Bug Summary

File:/home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/models/ElevationModel.cpp
Warning:line 173, column 9
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ElevationModel.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/home/gilles/devel/GIT/8.x/build.scan/core/utilities/geolocation/engine -fcoverage-compilation-dir=/home/gilles/devel/GIT/8.x/build.scan/core/utilities/geolocation/engine -resource-dir /usr/lib/llvm-18/lib/clang/18 -D CMS_NO_REGISTER_KEYWORD=1 -D HAVE_FFMPEG_VERSION5 -D LIBPGF_DISABLE_OPENMP -D MAGICKCORE_HDRI_ENABLE=0 -D MAGICKCORE_QUANTUM_DEPTH=16 -D QT_DEPRECATED_WARNINGS -D QT_DEPRECATED_WARNINGS_SINCE=0x060000 -D QT_DISABLE_DEPRECATED_BEFORE=0x050E00 -D QT_NO_CAST_FROM_ASCII -D QT_NO_CAST_FROM_BYTEARRAY -D QT_NO_CAST_TO_ASCII -D QT_NO_KEYWORDS -D QT_NO_NARROWING_CONVERSIONS_IN_CONNECT -D QT_NO_URL_CAST_FROM_STRING -D QT_STRICT_ITERATORS -D QT_USE_QSTRINGBUILDER -D TRANSLATION_DOMAIN="digikam" -D USE_JASPER -D USE_JPEG -D USE_JPEG8 -D _GNU_SOURCE -D _LARGEFILE64_SOURCE -D digikamcore_EXPORTS -I /home/gilles/devel/GIT/8.x/build.scan/core/utilities/geolocation/engine -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine -I /home/gilles/devel/GIT/8.x/build.scan/core/utilities/geolocation/engine/core_marble_obj_autogen/include -I /home/gilles/devel/GIT/8.x/core/libs/video/player/qtmm -I /home/gilles/devel/GIT/8.x/core/libs/album/engine -I /home/gilles/devel/GIT/8.x/core/libs/album/manager -I /home/gilles/devel/GIT/8.x/core/libs/album/treeview -I /home/gilles/devel/GIT/8.x/core/libs/album/widgets -I /home/gilles/devel/GIT/8.x/core/libs/database/collection -I /home/gilles/devel/GIT/8.x/core/libs/database/coredb -I /home/gilles/devel/GIT/8.x/core/libs/database/dbjobs -I /home/gilles/devel/GIT/8.x/core/libs/database/engine -I /home/gilles/devel/GIT/8.x/core/libs/database/haar -I /home/gilles/devel/GIT/8.x/core/libs/database/history -I /home/gilles/devel/GIT/8.x/core/libs/database/item/containers -I /home/gilles/devel/GIT/8.x/core/libs/database/item/lister -I /home/gilles/devel/GIT/8.x/core/libs/database/item/query -I /home/gilles/devel/GIT/8.x/core/libs/database/item/scanner -I /home/gilles/devel/GIT/8.x/core/libs/database/models -I /home/gilles/devel/GIT/8.x/core/libs/database/server -I /home/gilles/devel/GIT/8.x/core/libs/database/similaritydb -I /home/gilles/devel/GIT/8.x/core/libs/database/tags -I /home/gilles/devel/GIT/8.x/core/libs/database/thumbsdb -I /home/gilles/devel/GIT/8.x/core/libs/database/utils/ifaces -I /home/gilles/devel/GIT/8.x/core/libs/database/utils/scan -I /home/gilles/devel/GIT/8.x/core/libs/database/utils/widgets -I /home/gilles/devel/GIT/8.x/core/libs/dialogs -I /home/gilles/devel/GIT/8.x/core/libs/dimg/color -I /home/gilles/devel/GIT/8.x/core/libs/dimg -I /home/gilles/devel/GIT/8.x/core/libs/dimg/filters/auto -I /home/gilles/devel/GIT/8.x/core/libs/dimg/filters/bcg -I /home/gilles/devel/GIT/8.x/core/libs/dimg/filters/bw -I /home/gilles/devel/GIT/8.x/core/libs/dimg/filters/cb -I /home/gilles/devel/GIT/8.x/core/libs/dimg/filters/curves -I /home/gilles/devel/GIT/8.x/core/libs/dimg/filters/decorate -I /home/gilles/devel/GIT/8.x/core/libs/dimg/filters -I /home/gilles/devel/GIT/8.x/core/libs/dimg/filters/film -I /home/gilles/devel/GIT/8.x/core/libs/dimg/filters/fx -I /home/gilles/devel/GIT/8.x/core/libs/dimg/filters/greycstoration/cimg -I /home/gilles/devel/GIT/8.x/core/libs/dimg/filters/greycstoration -I /home/gilles/devel/GIT/8.x/core/libs/dimg/filters/hotpixels -I /home/gilles/devel/GIT/8.x/core/libs/dimg/filters/hsl -I /home/gilles/devel/GIT/8.x/core/libs/dimg/filters/icc -I /home/gilles/devel/GIT/8.x/core/libs/dimg/filters/lc -I /home/gilles/devel/GIT/8.x/core/libs/dimg/filters/lens -I /home/gilles/devel/GIT/8.x/core/libs/dimg/filters/levels -I /home/gilles/devel/GIT/8.x/core/libs/dimg/filters/nr -I /home/gilles/devel/GIT/8.x/core/libs/dimg/filters/raw -I /home/gilles/devel/GIT/8.x/core/libs/dimg/filters/redeye -I /home/gilles/devel/GIT/8.x/core/libs/dimg/filters/sharp -I /home/gilles/devel/GIT/8.x/core/libs/dimg/filters/transform -I /home/gilles/devel/GIT/8.x/core/libs/dimg/filters/wb -I /home/gilles/devel/GIT/8.x/core/libs/dimg/history -I /home/gilles/devel/GIT/8.x/core/libs/dimg/loaders -I /home/gilles/devel/GIT/8.x/core/libs/dngwriter -I /home/gilles/devel/GIT/8.x/core/libs/dplugins/core -I /home/gilles/devel/GIT/8.x/core/libs/dplugins/iface -I /home/gilles/devel/GIT/8.x/core/libs/dplugins/setup -I /home/gilles/devel/GIT/8.x/core/libs/dplugins/webservices -I /home/gilles/devel/GIT/8.x/core/libs/dplugins/widgets -I /home/gilles/devel/GIT/8.x/core/libs/dragdrop -I /home/gilles/devel/GIT/8.x/core/libs/dtrash -I /home/gilles/devel/GIT/8.x/core/libs/facesengine/common -I /home/gilles/devel/GIT/8.x/core/libs/facesengine/detection -I /home/gilles/devel/GIT/8.x/core/libs/facesengine/detection/opencv-dnn -I /home/gilles/devel/GIT/8.x/core/libs/facesengine/facedb -I /home/gilles/devel/GIT/8.x/core/libs/facesengine/preprocessing -I /home/gilles/devel/GIT/8.x/core/libs/facesengine/preprocessing/recognition -I /home/gilles/devel/GIT/8.x/core/libs/facesengine/preprocessing/shape-predictor -I /home/gilles/devel/GIT/8.x/core/libs/facesengine/recognition -I /home/gilles/devel/GIT/8.x/core/libs/facesengine/recognition/opencv-dnn -I /home/gilles/devel/GIT/8.x/core/libs/fileactionmanager -I /home/gilles/devel/GIT/8.x/core/libs/filters -I /home/gilles/devel/GIT/8.x/core/libs/imgqsort/detectors -I /home/gilles/devel/GIT/8.x/core/libs/imgqsort -I /home/gilles/devel/GIT/8.x/core/libs/iojobs -I /home/gilles/devel/GIT/8.x/core/libs/jpegutils -I /home/gilles/devel/GIT/8.x/core/libs/metadataengine/containers -I /home/gilles/devel/GIT/8.x/core/libs/metadataengine/dmetadata -I /home/gilles/devel/GIT/8.x/core/libs/metadataengine/engine -I /home/gilles/devel/GIT/8.x/core/libs/metadataengine/exiftool -I /home/gilles/devel/GIT/8.x/core/libs/metadataengine/focuspoint -I /home/gilles/devel/GIT/8.x/core/libs/models -I /home/gilles/devel/GIT/8.x/core/libs/networkmanager -I /home/gilles/devel/GIT/8.x/core/libs/notificationmanager -I /home/gilles/devel/GIT/8.x/core/libs/onlineversion -I /home/gilles/devel/GIT/8.x/core/libs/pgfutils -I /home/gilles/devel/GIT/8.x/core/libs/progressmanager -I /home/gilles/devel/GIT/8.x/core/libs/properties/captions -I /home/gilles/devel/GIT/8.x/core/libs/properties/geolocation -I /home/gilles/devel/GIT/8.x/core/libs/properties/history -I /home/gilles/devel/GIT/8.x/core/libs/properties/import -I /home/gilles/devel/GIT/8.x/core/libs/properties -I /home/gilles/devel/GIT/8.x/core/libs/rawengine -I /home/gilles/devel/GIT/8.x/core/libs/settings -I /home/gilles/devel/GIT/8.x/core/libs/tags/autoassignment -I /home/gilles/devel/GIT/8.x/core/libs/tags/autoassignment/model -I /home/gilles/devel/GIT/8.x/core/libs/tags/engine -I /home/gilles/devel/GIT/8.x/core/libs/tags/manager/models -I /home/gilles/devel/GIT/8.x/core/libs/tags/manager -I /home/gilles/devel/GIT/8.x/core/libs/tags/widgets -I /home/gilles/devel/GIT/8.x/core/libs/template -I /home/gilles/devel/GIT/8.x/core/libs/threadimageio/engine -I /home/gilles/devel/GIT/8.x/core/libs/threadimageio/fileio -I /home/gilles/devel/GIT/8.x/core/libs/threadimageio/preview -I /home/gilles/devel/GIT/8.x/core/libs/threadimageio/thumb -I /home/gilles/devel/GIT/8.x/core/libs/threadimageio/video -I /home/gilles/devel/GIT/8.x/core/libs/threads -I /home/gilles/devel/GIT/8.x/core/libs/timeadjust -I /home/gilles/devel/GIT/8.x/core/libs/transitionmngr -I /home/gilles/devel/GIT/8.x/core/libs/versionmanager -I /home/gilles/devel/GIT/8.x/core/libs/video -I /home/gilles/devel/GIT/8.x/core/libs/video/manager -I /home/gilles/devel/GIT/8.x/core/libs/video/osd -I /home/gilles/devel/GIT/8.x/core/libs/video/player -I /home/gilles/devel/GIT/8.x/core/libs/widgets/colors -I /home/gilles/devel/GIT/8.x/core/libs/widgets/combo -I /home/gilles/devel/GIT/8.x/core/libs/widgets/files -I /home/gilles/devel/GIT/8.x/core/libs/widgets/fonts -I /home/gilles/devel/GIT/8.x/core/libs/widgets/graphicsview -I /home/gilles/devel/GIT/8.x/core/libs/widgets/history -I /home/gilles/devel/GIT/8.x/core/libs/widgets/iccprofiles -I /home/gilles/devel/GIT/8.x/core/libs/widgets/itemview -I /home/gilles/devel/GIT/8.x/core/libs/widgets/layout -I /home/gilles/devel/GIT/8.x/core/libs/widgets/mainview -I /home/gilles/devel/GIT/8.x/core/libs/widgets/metadata/config -I /home/gilles/devel/GIT/8.x/core/libs/widgets/metadata/exiftool -I /home/gilles/devel/GIT/8.x/core/libs/widgets/metadata/exiv2 -I /home/gilles/devel/GIT/8.x/core/libs/widgets/metadata/labels -I /home/gilles/devel/GIT/8.x/core/libs/widgets/metadata/utils -I /home/gilles/devel/GIT/8.x/core/libs/widgets/range -I /home/gilles/devel/GIT/8.x/core/libs/widgets/text -I /home/gilles/devel/GIT/8.x/core/libs/jpegutils/libjpeg/84 -I /home/gilles/devel/GIT/8.x/core/app/utils -I /home/gilles/devel/GIT/8.x/build.scan/core/app/utils -I /home/gilles/devel/GIT/8.x/core/utilities/advancedrename -I /home/gilles/devel/GIT/8.x/core/utilities/advancedrename/common -I /home/gilles/devel/GIT/8.x/core/utilities/advancedrename/parser -I /home/gilles/devel/GIT/8.x/core/utilities/advancedrename/parser/modifiers -I /home/gilles/devel/GIT/8.x/core/utilities/advancedrename/parser/options -I /home/gilles/devel/GIT/8.x/core/utilities/advancedrename/parser/options/database -I /home/gilles/devel/GIT/8.x/core/utilities/advancedrename/parser/options/database/keys -I /home/gilles/devel/GIT/8.x/core/utilities/extrasupport/addressbook -I /home/gilles/devel/GIT/8.x/core/utilities/extrasupport/filesindexer -I /home/gilles/devel/GIT/8.x/core/utilities/facemanagement/bench -I /home/gilles/devel/GIT/8.x/core/utilities/facemanagement/database -I /home/gilles/devel/GIT/8.x/core/utilities/facemanagement/items -I /home/gilles/devel/GIT/8.x/core/utilities/facemanagement/threads -I /home/gilles/devel/GIT/8.x/core/utilities/facemanagement/widgets -I /home/gilles/devel/GIT/8.x/core/utilities/facemanagement/workers -I /home/gilles/devel/GIT/8.x/core/utilities/firstrun -I /home/gilles/devel/GIT/8.x/core/utilities/focuspointmanagement -I /home/gilles/devel/GIT/8.x/core/utilities/fuzzysearch -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/astro -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/blendings -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/core -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/geodata/data -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/geodata/graphicsitem -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/geodata/handlers/dgml -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/geodata/handlers/kml -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/geodata/parser -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/geodata/scene -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/geodata/writer -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/geodata/writers/dgml -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/geodata/writers/kml -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/graphicsview -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/layers -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/models -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/osm -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/plugins -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/plugins/render/atmosphere -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/plugins/render/compass -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/plugins/render/crosshairs -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/plugins/render/graticule -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/plugins/render/mapscale -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/plugins/render/measure -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/plugins/render/navigation -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/plugins/render/overviewmap -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/plugins/render/progress -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/plugins/runner/cache -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/plugins/runner/gpsbabel -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/plugins/runner/gpx -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/plugins/runner/gpx/handlers -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/plugins/runner/json -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/plugins/runner/kml -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/plugins/runner/nominatim-reversegeocoding -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/plugins/runner/osm -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/plugins/runner/osm/o5mreader -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/plugins/runner/osm/translators -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/plugins/runner/osm/writers -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/plugins/runner/pn2 -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/plugins/runner/pnt -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/projections -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/runners -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/settings -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/storage -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/tile -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/geoiface/backends -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/geoiface/bookmark -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/geoiface/core -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/geoiface/correlator -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/geoiface/dragdrop -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/geoiface/items -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/geoiface/lookup -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/geoiface/reversegeocoding -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/geoiface/tiles -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/geoiface/tracks -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/geoiface/widgets -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/geomapwrapper -I /home/gilles/devel/GIT/8.x/core/utilities/geolocation/mapsearches -I /home/gilles/devel/GIT/8.x/core/utilities/imageeditor/core -I /home/gilles/devel/GIT/8.x/core/utilities/imageeditor/dialogs -I /home/gilles/devel/GIT/8.x/core/utilities/imageeditor/editor -I /home/gilles/devel/GIT/8.x/core/utilities/imageeditor/main -I /home/gilles/devel/GIT/8.x/core/utilities/imageeditor/widgets -I /home/gilles/devel/GIT/8.x/core/utilities/import/backend -I /home/gilles/devel/GIT/8.x/core/utilities/import/dialogs -I /home/gilles/devel/GIT/8.x/core/utilities/import/items -I /home/gilles/devel/GIT/8.x/core/utilities/import/main -I /home/gilles/devel/GIT/8.x/core/utilities/import/models -I /home/gilles/devel/GIT/8.x/core/utilities/import/views -I /home/gilles/devel/GIT/8.x/core/utilities/import/widgets -I /home/gilles/devel/GIT/8.x/core/utilities/lighttable -I /home/gilles/devel/GIT/8.x/core/utilities/maintenance/main -I /home/gilles/devel/GIT/8.x/core/utilities/maintenance/manager -I /home/gilles/devel/GIT/8.x/core/utilities/maintenance/tools/autotags -I /home/gilles/devel/GIT/8.x/core/utilities/maintenance/tools/dbcleaner -I /home/gilles/devel/GIT/8.x/core/utilities/maintenance/tools/dbscan -I /home/gilles/devel/GIT/8.x/core/utilities/maintenance/tools/duplicates -I /home/gilles/devel/GIT/8.x/core/utilities/maintenance/tools/facesmanagement -I /home/gilles/devel/GIT/8.x/core/utilities/maintenance/tools/fingerprints -I /home/gilles/devel/GIT/8.x/core/utilities/maintenance/tools/imgqsort -I /home/gilles/devel/GIT/8.x/core/utilities/maintenance/tools/metaremover -I /home/gilles/devel/GIT/8.x/core/utilities/maintenance/tools/metasync -I /home/gilles/devel/GIT/8.x/core/utilities/maintenance/tools/thumbs -I /home/gilles/devel/GIT/8.x/core/utilities/maintenance/utils -I /home/gilles/devel/GIT/8.x/core/utilities/queuemanager/dplugins -I /home/gilles/devel/GIT/8.x/core/utilities/queuemanager/main -I /home/gilles/devel/GIT/8.x/core/utilities/queuemanager/manager -I /home/gilles/devel/GIT/8.x/core/utilities/queuemanager/views -I /home/gilles/devel/GIT/8.x/core/utilities/searchwindow -I /home/gilles/devel/GIT/8.x/core/utilities/setup/album -I /home/gilles/devel/GIT/8.x/core/utilities/setup/camera -I /home/gilles/devel/GIT/8.x/core/utilities/setup/collections -I /home/gilles/devel/GIT/8.x/core/utilities/setup/downloader -I /home/gilles/devel/GIT/8.x/core/utilities/setup/editor -I /home/gilles/devel/GIT/8.x/core/utilities/setup/metadata -I /home/gilles/devel/GIT/8.x/core/utilities/setup/misc -I /home/gilles/devel/GIT/8.x/core/utilities/setup -I /home/gilles/devel/GIT/8.x/core/app/main -I /home/gilles/devel/GIT/8.x/core/app/date -I /home/gilles/devel/GIT/8.x/core/app/dragdrop -I /home/gilles/devel/GIT/8.x/core/app/views/stack -I /home/gilles/devel/GIT/8.x/core/app/views/utils -I /home/gilles/devel/GIT/8.x/core/app/views/sidebar -I /home/gilles/devel/GIT/8.x/core/app/items/utils -I /home/gilles/devel/GIT/8.x/core/app/items/overlays -I /home/gilles/devel/GIT/8.x/core/app/items/views -I /home/gilles/devel/GIT/8.x/core/app/items/thumbbar -I /home/gilles/devel/GIT/8.x/core/app/views/preview -I /usr/include/opencv4 -I /usr/include/ImageMagick-6 -I /usr/include/x86_64-linux-gnu/ImageMagick-6 -I /opt/qt6/include/QtMultimedia -I /opt/qt6/include -I /opt/qt6/include/QtCore -I /opt/qt6/mkspecs/linux-g++ -I /opt/qt6/include/QtGui -I /opt/qt6/include/QtNetwork -I /opt/qt6/include/QtMultimediaWidgets -I /opt/qt6/include/QtWidgets -I /opt/qt6/include/QtXml -I /opt/qt6/include/QtSvg -I /opt/qt6/include/QtConcurrent -I /opt/qt6/include/KF6/KI18n -I /opt/qt6/include/KF6/KConfig -I /opt/qt6/include/KF6/KConfigCore -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/x86_64-linux-gnu/c++/13 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/backward -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-long-long -Wno-deprecated-copy -std=c++20 -fdeprecated-macro -ferror-limit 19 -fvisibility=hidden -fvisibility-inlines-hidden -fno-operator-names -fopenmp -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fcxx-exceptions -fexceptions -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /mnt/data2/devel/GIT/8.x/project/reports/report.scan/2024-07-24-085343-476556-1 -x c++ /home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/models/ElevationModel.cpp

/home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/models/ElevationModel.cpp

1/* ============================================================
2 *
3 * This file is a part of digiKam project
4 * https://www.digikam.org
5 *
6 * Date : 2023-05-15
7 * Description : geolocation engine based on Marble.
8 * (c) 2007-2022 Marble Team
9 * https://invent.kde.org/education/marble/-/raw/master/data/credits_authors.html
10 *
11 * SPDX-FileCopyrightText: 2023-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
12 *
13 * SPDX-License-Identifier: LGPL-2.1-or-later
14 *
15 * ============================================================ */
16
17#include "ElevationModel.h"
18
19// Qt includes
20
21#include <QCache>
22#include <QImage>
23#include <qmath.h>
24
25// Local includes
26
27#include "GeoSceneHead.h"
28#include "GeoSceneLayer.h"
29#include "GeoSceneMap.h"
30#include "GeoSceneDocument.h"
31#include "GeoSceneTextureTileDataset.h"
32#include "HttpDownloadManager.h"
33#include "Tile.h"
34#include "TileLoader.h"
35#include "TileLoaderHelper.h"
36#include "MapThemeManager.h"
37#include "TileId.h"
38#include "PluginManager.h"
39#include "digikam_debug.h"
40
41namespace Marble
42{
43
44class Q_DECL_HIDDEN__attribute__((visibility("hidden"))) ElevationModelPrivate
45{
46public:
47
48 ElevationModelPrivate(ElevationModel* _q, HttpDownloadManager* downloadManager, PluginManager* pluginManager)
49 : q(_q),
50 m_tileLoader(downloadManager, pluginManager),
51 m_textureLayer(nullptr),
52 m_srtmTheme(nullptr)
53 {
54 m_cache.setMaxCost(10); //keep 10 tiles in memory (~17MB)
55
56 m_srtmTheme = MapThemeManager::loadMapTheme(QString::fromUtf8("earth/srtm2/srtm2.dgml"));
57
58 if (!m_srtmTheme)
59 {
60 qCDebug(DIGIKAM_MARBLE_LOG)for (QLoggingCategoryMacroHolder<QtDebugMsg> qt_category
((DIGIKAM_MARBLE_LOG)()); qt_category; qt_category.control = false
) QMessageLogger(static_cast<const char *>("/home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/models/ElevationModel.cpp"
), 60, static_cast<const char *>(__PRETTY_FUNCTION__), qt_category
.name()).debug()
<< "Failed to load map theme earth/srtm2/srtm2.dgml. Check your installation. No elevation will be returned.";
61 return;
62 }
63
64 const GeoSceneHead* head = m_srtmTheme->head();
65
66 Q_ASSERT(head)((head) ? static_cast<void>(0) : qt_assert("head", "/home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/models/ElevationModel.cpp"
, 66))
;
67
68 const GeoSceneMap* map = m_srtmTheme->map();
69
70 Q_ASSERT(map)((map) ? static_cast<void>(0) : qt_assert("map", "/home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/models/ElevationModel.cpp"
, 70))
;
71
72 const GeoSceneLayer* sceneLayer = map->layer(head->theme());
73
74 if (!sceneLayer)
75 {
76 qCDebug(DIGIKAM_MARBLE_LOG)for (QLoggingCategoryMacroHolder<QtDebugMsg> qt_category
((DIGIKAM_MARBLE_LOG)()); qt_category; qt_category.control = false
) QMessageLogger(static_cast<const char *>("/home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/models/ElevationModel.cpp"
), 76, static_cast<const char *>(__PRETTY_FUNCTION__), qt_category
.name()).debug()
<< "Failed to instantiate elevation map. No elevation will be returned.";
77 return;
78 }
79
80 Q_ASSERT(sceneLayer)((sceneLayer) ? static_cast<void>(0) : qt_assert("sceneLayer"
, "/home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/models/ElevationModel.cpp"
, 80))
;
81
82 m_textureLayer = dynamic_cast<GeoSceneTextureTileDataset*>(sceneLayer->datasets().first());
83
84 Q_ASSERT(m_textureLayer)((m_textureLayer) ? static_cast<void>(0) : qt_assert("m_textureLayer"
, "/home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/models/ElevationModel.cpp"
, 84))
;
85 }
86
87 ~ElevationModelPrivate()
88 {
89 delete m_srtmTheme;
90 }
91
92 void tileCompleted(const TileId& tileId, const QImage& image)
93 {
94 m_cache.insert(tileId, new QImage(image));
95
96 Q_EMIT q->updateAvailable();
97 }
98
99public:
100
101 ElevationModel* q = nullptr;
102
103 TileLoader m_tileLoader;
104 const GeoSceneTextureTileDataset* m_textureLayer = nullptr;
105 QCache<TileId, const QImage> m_cache;
106 GeoSceneDocument* m_srtmTheme = nullptr;
107};
108
109ElevationModel::ElevationModel(HttpDownloadManager* downloadManager, PluginManager* pluginManager, QObject* parent) :
110 QObject(parent),
111 d(new ElevationModelPrivate(this, downloadManager, pluginManager))
112{
113 connect(&d->m_tileLoader, SIGNAL(tileCompleted(TileId,QImage))qFlagLocation("2" "tileCompleted(TileId,QImage)" "\0" "/home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/models/ElevationModel.cpp"
":" "113")
,
114 this, SLOT(tileCompleted(TileId,QImage))qFlagLocation("1" "tileCompleted(TileId,QImage)" "\0" "/home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/models/ElevationModel.cpp"
":" "114")
);
115}
116
117ElevationModel::~ElevationModel()
118{
119 delete d;
120}
121
122qreal ElevationModel::height(qreal lon, qreal lat) const
123{
124 if (!d->m_textureLayer
9.1
Field 'm_textureLayer' is non-null
9.1
Field 'm_textureLayer' is non-null
)
10
Taking false branch
125 {
126 return invalidElevationData;
127 }
128
129 const int tileZoomLevel = TileLoader::maximumTileLevel(*(d->m_textureLayer));
130
131 Q_ASSERT(tileZoomLevel == 9)((tileZoomLevel == 9) ? static_cast<void>(0) : qt_assert
("tileZoomLevel == 9", "/home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/models/ElevationModel.cpp"
, 131))
;
11
Assuming 'tileZoomLevel' is equal to 9
12
'?' condition is true
132
133 const int width = d->m_textureLayer->tileSize().width();
134 const int height = d->m_textureLayer->tileSize().height();
135
136 const int numTilesX = TileLoaderHelper::levelToColumn(d->m_textureLayer->levelZeroColumns(), tileZoomLevel);
137 const int numTilesY = TileLoaderHelper::levelToRow(d->m_textureLayer->levelZeroRows(), tileZoomLevel);
138
139 Q_ASSERT(numTilesX > 0)((numTilesX > 0) ? static_cast<void>(0) : qt_assert(
"numTilesX > 0", "/home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/models/ElevationModel.cpp"
, 139))
;
13
Assuming 'numTilesX' is > 0
14
'?' condition is true
140 Q_ASSERT(numTilesY > 0)((numTilesY > 0) ? static_cast<void>(0) : qt_assert(
"numTilesY > 0", "/home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/models/ElevationModel.cpp"
, 140))
;
15
Assuming 'numTilesY' is > 0
16
'?' condition is true
141
142 qreal textureX = 180 + lon;
143 textureX *= numTilesX * width / 360;
144
145 qreal textureY = 90 - lat;
146 textureY *= numTilesY * height / 180;
147
148 qreal ret = 0;
149 bool hasHeight = false;
150 qreal noData = 0;
151
152 for (int i = 0 ; i < 4 ; ++i)
17
Loop condition is true. Entering loop body
153 {
154 const int x = static_cast<int>(textureX + (i % 2));
155 const int y = static_cast<int>(textureY + (i / 2));
156
157 //qCDebug(DIGIKAM_MARBLE_LOG) << "x" << x << ( x / width );
158 //qCDebug(DIGIKAM_MARBLE_LOG) << "y" << y << ( y / height );
159
160 const TileId id(0, tileZoomLevel, (x % (numTilesX * width)) / width, (y % (numTilesY * height)) / height);
161
162 //qCDebug(DIGIKAM_MARBLE_LOG) << "LAT" << lat << "LON" << lon << "tile" << ( x % ( numTilesX * width ) ) / width << ( y % ( numTilesY * height ) ) / height;
163
164 const QImage* image = d->m_cache[id];
165
166 if (image == nullptr)
18
Taking true branch
167 {
168 image = new QImage(d->m_tileLoader.loadTileImage(d->m_textureLayer, id, DownloadBrowse));
19
Memory is allocated
169 d->m_cache.insert(id, image);
20
Calling 'QCache::insert'
24
Returning; memory was released via 2nd parameter
170 }
171
172 Q_ASSERT(image)((image) ? static_cast<void>(0) : qt_assert("image", "/home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/models/ElevationModel.cpp"
, 172))
;
25
'?' condition is true
173 Q_ASSERT(!image->isNull())((!image->isNull()) ? static_cast<void>(0) : qt_assert
("!image->isNull()", "/home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/models/ElevationModel.cpp"
, 173))
;
26
Use of memory after it is freed
174 Q_ASSERT(width == image->width())((width == image->width()) ? static_cast<void>(0) : qt_assert
("width == image->width()", "/home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/models/ElevationModel.cpp"
, 174))
;
175 Q_ASSERT(height == image->height())((height == image->height()) ? static_cast<void>(0) :
qt_assert("height == image->height()", "/home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/models/ElevationModel.cpp"
, 175))
;
176
177 const qreal dx = (textureX > (qreal)x) ? textureX - (qreal)x : (qreal)x - textureX;
178 const qreal dy = (textureY > (qreal)y) ? textureY - (qreal)y : (qreal)y - textureY;
179
180 Q_ASSERT(0 <= dx && dx <= 1)((0 <= dx && dx <= 1) ? static_cast<void>
(0) : qt_assert("0 <= dx && dx <= 1", "/home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/models/ElevationModel.cpp"
, 180))
;
181 Q_ASSERT(0 <= dy && dy <= 1)((0 <= dy && dy <= 1) ? static_cast<void>
(0) : qt_assert("0 <= dy && dy <= 1", "/home/gilles/devel/GIT/8.x/core/utilities/geolocation/engine/models/ElevationModel.cpp"
, 181))
;
182
183 unsigned int pixel = image->pixel(x % width, y % height) & 0xffff; // 16 valid bits
184 short int elevation = (short int) pixel; // and signed type, so just cast it
185
186 //qCDebug(DIGIKAM_MARBLE_LOG) << "(1-dx)" << (1-dx) << "(1-dy)" << (1-dy);
187
188 if (pixel != invalidElevationData) //no data?
189 {
190 //qCDebug(DIGIKAM_MARBLE_LOG) << "got at x" << x % width << "y" << y % height << "a height of" << pixel << "** RGB" << qRed(pixel) << qGreen(pixel) << qBlue(pixel);
191
192 ret += (qreal)elevation * (1 - dx) * (1 - dy);
193 hasHeight = true;
194 }
195 else
196 {
197 //qCDebug(DIGIKAM_MARBLE_LOG) << "no data at" << x % width << "y" << y % height;
198
199 noData += (1 - dx) * (1 - dy);
200 }
201 }
202
203 if (!hasHeight)
204 {
205 ret = invalidElevationData; //no data
206 }
207 else
208 {
209 if (noData)
210 {
211 //qCDebug(DIGIKAM_MARBLE_LOG) << "NO DATA" << noData;
212
213 ret += (ret / (1 - noData)) * noData;
214 }
215 }
216
217 //qCDebug(DIGIKAM_MARBLE_LOG) << ">>>" << lat << lon << "returning an elevation of" << ret;
218
219 return ret;
220}
221
222QVector<GeoDataCoordinates> ElevationModel::heightProfile(qreal fromLon, qreal fromLat, qreal toLon, qreal toLat) const
223{
224 if (!d->m_textureLayer)
1
Assuming field 'm_textureLayer' is non-null
2
Taking false branch
225 {
226 return QVector<GeoDataCoordinates>();
227 }
228
229 const int tileZoomLevel = TileLoader::maximumTileLevel(*(d->m_textureLayer));
230 const int width = d->m_textureLayer->tileSize().width();
231 const int numTilesX = TileLoaderHelper::levelToColumn(d->m_textureLayer->levelZeroColumns(), tileZoomLevel);
232 qreal distPerPixel = (qreal)360 / (width * numTilesX);
233
234 //qCDebug(DIGIKAM_MARBLE_LOG) << "heightProfile" << fromLat << fromLon << toLat << toLon << "distPerPixel" << distPerPixel;
235
236 qreal lat = fromLat;
237 qreal lon = fromLon;
238 char dirLat = fromLat < toLat ? 1 : -1;
3
Assuming 'fromLat' is >= 'toLat'
4
'?' condition is false
239 char dirLon = fromLon < toLon ? 1 : -1;
5
Assuming 'fromLon' is >= 'toLon'
6
'?' condition is false
240 qreal k = qAbs((fromLat - toLat) / (fromLon - toLon));
241
242 //qCDebug(DIGIKAM_MARBLE_LOG) << "fromLon" << fromLon << "fromLat" << fromLat;
243 //qCDebug(DIGIKAM_MARBLE_LOG) << "diff lon" << ( fromLon - toLon ) << "diff lat" << ( fromLat - toLat );
244 //qCDebug(DIGIKAM_MARBLE_LOG) << "dirLon" << QString::number(dirLon) << "dirLat" << QString::number(dirLat) << "k" << k;
245
246 QVector<GeoDataCoordinates> ret;
247
248 while (lat * dirLat <= toLat * dirLat && lon * dirLon <= toLon * dirLon)
7
Assuming the condition is true
8
Loop condition is true. Entering loop body
249 {
250 //qCDebug(DIGIKAM_MARBLE_LOG) << lat << lon;
251
252 qreal h = height(lon, lat);
9
Calling 'ElevationModel::height'
253
254 if (h < 32000)
255 {
256 ret << GeoDataCoordinates(lon, lat, h, GeoDataCoordinates::Degree);
257 }
258
259 if (k < 0.5)
260 {
261 //qCDebug(DIGIKAM_MARBLE_LOG) << "lon(x) += distPerPixel";
262
263 lat += distPerPixel * k * dirLat;
264 lon += distPerPixel * dirLon;
265 }
266 else
267 {
268 //qCDebug(DIGIKAM_MARBLE_LOG) << "lat(y) += distPerPixel";
269
270 lat += distPerPixel * dirLat;
271 lon += distPerPixel / k * dirLon;
272 }
273 }
274
275 //qCDebug(DIGIKAM_MARBLE_LOG) << ret;
276
277 return ret;
278}
279
280} // namespace Marble
281
282#include "moc_ElevationModel.cpp"

/opt/qt6/include/QtCore/qcache.h

1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QCACHE_H
5#define QCACHE_H
6
7#include <QtCore/qhash.h>
8
9QT_BEGIN_NAMESPACE
10
11
12template <class Key, class T>
13class QCache
14{
15 struct Value
16 {
17 T *t = nullptr;
18 qsizetype cost = 0;
19 Value() noexcept = default;
20 Value(T *tt, qsizetype c) noexcept
21 : t(tt), cost(c)
22 {}
23 Value(Value &&other) noexcept
24 : t(other.t),
25 cost(other.cost)
26 {
27 other.t = nullptr;
28 }
29 Value &operator=(Value &&other) noexcept
30 {
31 qt_ptr_swap(t, other.t);
32 std::swap(cost, other.cost);
33 return *this;
34 }
35 ~Value() { delete t; }
36
37 private:
38 Q_DISABLE_COPY(Value)Value(const Value &) = delete; Value &operator=(const
Value &) = delete;
39 };
40
41 struct Chain
42 {
43 Chain() noexcept : prev(this), next(this) { }
44 Chain *prev;
45 Chain *next;
46 };
47
48 struct Node : public Chain
49 {
50 using KeyType = Key;
51 using ValueType = Value;
52
53 Key key;
54 Value value;
55
56 Node(const Key &k, Value &&t) noexcept(std::is_nothrow_move_assignable_v<Key>)
57 : Chain(),
58 key(k),
59 value(std::move(t))
60 {
61 }
62 Node(Key &&k, Value &&t) noexcept(std::is_nothrow_move_assignable_v<Key>)
63 : Chain(),
64 key(std::move(k)),
65 value(std::move(t))
66 {
67 }
68 static void createInPlace(Node *n, const Key &k, T *o, qsizetype cost)
69 {
70 new (n) Node{ Key(k), Value(o, cost) };
71 }
72 void emplace(T *o, qsizetype cost)
73 {
74 value = Value(o, cost);
75 }
76
77 Node(Node &&other)
78 : Chain(other),
79 key(std::move(other.key)),
80 value(std::move(other.value))
81 {
82 Q_ASSERT(this->prev)((this->prev) ? static_cast<void>(0) : qt_assert("this->prev"
, "/opt/qt6/include/QtCore/qcache.h", 82))
;
83 Q_ASSERT(this->next)((this->next) ? static_cast<void>(0) : qt_assert("this->next"
, "/opt/qt6/include/QtCore/qcache.h", 83))
;
84 this->prev->next = this;
85 this->next->prev = this;
86 }
87 private:
88 Q_DISABLE_COPY(Node)Node(const Node &) = delete; Node &operator=(const Node
&) = delete;
89 };
90
91 using Data = QHashPrivate::Data<Node>;
92
93 mutable Chain chain;
94 Data d;
95 qsizetype mx = 0;
96 qsizetype total = 0;
97
98 void unlink(Node *n) noexcept(std::is_nothrow_destructible_v<Node>)
99 {
100 Q_ASSERT(n->prev)((n->prev) ? static_cast<void>(0) : qt_assert("n->prev"
, "/opt/qt6/include/QtCore/qcache.h", 100))
;
101 Q_ASSERT(n->next)((n->next) ? static_cast<void>(0) : qt_assert("n->next"
, "/opt/qt6/include/QtCore/qcache.h", 101))
;
102 n->prev->next = n->next;
103 n->next->prev = n->prev;
104 total -= n->value.cost;
105 auto it = d.findBucket(n->key);
106 d.erase(it);
107 }
108 T *relink(const Key &key) const noexcept
109 {
110 if (isEmpty())
111 return nullptr;
112 Node *n = d.findNode(key);
113 if (!n)
114 return nullptr;
115
116 if (chain.next != n) {
117 Q_ASSERT(n->prev)((n->prev) ? static_cast<void>(0) : qt_assert("n->prev"
, "/opt/qt6/include/QtCore/qcache.h", 117))
;
118 Q_ASSERT(n->next)((n->next) ? static_cast<void>(0) : qt_assert("n->next"
, "/opt/qt6/include/QtCore/qcache.h", 118))
;
119 n->prev->next = n->next;
120 n->next->prev = n->prev;
121 n->next = chain.next;
122 chain.next->prev = n;
123 n->prev = &chain;
124 chain.next = n;
125 }
126 return n->value.t;
127 }
128
129 void trim(qsizetype m) noexcept(std::is_nothrow_destructible_v<Node>)
130 {
131 while (chain.prev != &chain && total > m) {
132 Node *n = static_cast<Node *>(chain.prev);
133 unlink(n);
134 }
135 }
136
137
138 Q_DISABLE_COPY(QCache)QCache(const QCache &) = delete; QCache &operator=(const
QCache &) = delete;
139
140public:
141 inline explicit QCache(qsizetype maxCost = 100) noexcept
142 : mx(maxCost)
143 {
144 }
145 inline ~QCache()
146 {
147 static_assert(std::is_nothrow_destructible_v<Key>, "Types with throwing destructors are not supported in Qt containers.");
148 static_assert(std::is_nothrow_destructible_v<T>, "Types with throwing destructors are not supported in Qt containers.");
149
150 clear();
151 }
152
153 inline qsizetype maxCost() const noexcept { return mx; }
154 void setMaxCost(qsizetype m) noexcept(std::is_nothrow_destructible_v<Node>)
155 {
156 mx = m;
157 trim(mx);
158 }
159 inline qsizetype totalCost() const noexcept { return total; }
160
161 inline qsizetype size() const noexcept { return qsizetype(d.size); }
162 inline qsizetype count() const noexcept { return qsizetype(d.size); }
163 inline bool isEmpty() const noexcept { return !d.size; }
164 inline QList<Key> keys() const
165 {
166 QList<Key> k;
167 if (size()) {
168 k.reserve(size());
169 for (auto it = d.begin(); it != d.end(); ++it)
170 k << it.node()->key;
171 }
172 Q_ASSERT(k.size() == size())((k.size() == size()) ? static_cast<void>(0) : qt_assert
("k.size() == size()", "/opt/qt6/include/QtCore/qcache.h", 172
))
;
173 return k;
174 }
175
176 void clear() noexcept(std::is_nothrow_destructible_v<Node>)
177 {
178 d.clear();
179 total = 0;
180 chain.next = &chain;
181 chain.prev = &chain;
182 }
183
184 bool insert(const Key &key, T *object, qsizetype cost = 1)
185 {
186 if (cost > mx) {
21
Assuming 'cost' is > field 'mx'
22
Taking true branch
187 remove(key);
188 delete object;
23
Memory is released
189 return false;
190 }
191 trim(mx - cost);
192 auto result = d.findOrInsert(key);
193 Node *n = result.it.node();
194 if (result.initialized) {
195 auto prevCost = n->value.cost;
196 result.it.node()->emplace(object, cost);
197 cost -= prevCost;
198 relink(key);
199 } else {
200 Node::createInPlace(n, key, object, cost);
201 n->prev = &chain;
202 n->next = chain.next;
203 chain.next->prev = n;
204 chain.next = n;
205 }
206 total += cost;
207 return true;
208 }
209 T *object(const Key &key) const noexcept
210 {
211 return relink(key);
212 }
213 T *operator[](const Key &key) const noexcept
214 {
215 return relink(key);
216 }
217 inline bool contains(const Key &key) const noexcept
218 {
219 return !isEmpty() && d.findNode(key) != nullptr;
220 }
221
222 bool remove(const Key &key) noexcept(std::is_nothrow_destructible_v<Node>)
223 {
224 if (isEmpty())
225 return false;
226 Node *n = d.findNode(key);
227 if (!n) {
228 return false;
229 } else {
230 unlink(n);
231 return true;
232 }
233 }
234
235 T *take(const Key &key) noexcept(std::is_nothrow_destructible_v<Key>)
236 {
237 if (isEmpty())
238 return nullptr;
239 Node *n = d.findNode(key);
240 if (!n)
241 return nullptr;
242
243 T *t = n->value.t;
244 n->value.t = nullptr;
245 unlink(n);
246 return t;
247 }
248
249};
250
251QT_END_NAMESPACE
252
253#endif // QCACHE_H