273 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			273 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#ifndef OSMIUM_OSM_DIFF_OBJECT_HPP
 | 
						|
#define OSMIUM_OSM_DIFF_OBJECT_HPP
 | 
						|
 | 
						|
/*
 | 
						|
 | 
						|
This file is part of Osmium (http://osmcode.org/libosmium).
 | 
						|
 | 
						|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
 | 
						|
 | 
						|
Boost Software License - Version 1.0 - August 17th, 2003
 | 
						|
 | 
						|
Permission is hereby granted, free of charge, to any person or organization
 | 
						|
obtaining a copy of the software and accompanying documentation covered by
 | 
						|
this license (the "Software") to use, reproduce, display, distribute,
 | 
						|
execute, and transmit the Software, and to prepare derivative works of the
 | 
						|
Software, and to permit third-parties to whom the Software is furnished to
 | 
						|
do so, all subject to the following:
 | 
						|
 | 
						|
The copyright notices in the Software and this entire statement, including
 | 
						|
the above license grant, this restriction and the following disclaimer,
 | 
						|
must be included in all copies of the Software, in whole or in part, and
 | 
						|
all derivative works of the Software, unless such copies or derivative
 | 
						|
works are solely in the form of machine-executable object code generated by
 | 
						|
a source language processor.
 | 
						|
 | 
						|
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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
 | 
						|
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
 | 
						|
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
 | 
						|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 | 
						|
DEALINGS IN THE SOFTWARE.
 | 
						|
 | 
						|
*/
 | 
						|
 | 
						|
#include <cassert>
 | 
						|
 | 
						|
#include <osmium/fwd.hpp>
 | 
						|
#include <osmium/osm/item_type.hpp>
 | 
						|
#include <osmium/osm/object.hpp>
 | 
						|
#include <osmium/osm/timestamp.hpp>
 | 
						|
#include <osmium/osm/types.hpp>
 | 
						|
 | 
						|
namespace osmium {
 | 
						|
 | 
						|
    /**
 | 
						|
     * A DiffObject holds pointers to three OSMObjects, the current object,
 | 
						|
     * the previous, and the next. They always have the same type (Node, Way,
 | 
						|
     * or Relation) and the same ID, but may have different versions.
 | 
						|
     *
 | 
						|
     * It is used when iterating over OSM files with history data to make
 | 
						|
     * working with versioned OSM objects easier. Because you have access to
 | 
						|
     * the previous and next objects as well as the current one, comparisons
 | 
						|
     * between object versions is easy.
 | 
						|
     *
 | 
						|
     * If the current object is the first version available, the previous
 | 
						|
     * pointer must be the same as the current one. If the current object is
 | 
						|
     * the last version available, the next pointer must be the same as the
 | 
						|
     * current one.
 | 
						|
     *
 | 
						|
     * DiffObjects are immutable.
 | 
						|
     */
 | 
						|
    class DiffObject {
 | 
						|
 | 
						|
        const osmium::OSMObject* m_prev;
 | 
						|
        const osmium::OSMObject* m_curr;
 | 
						|
        const osmium::OSMObject* m_next;
 | 
						|
 | 
						|
    public:
 | 
						|
 | 
						|
        /**
 | 
						|
         * Default construct an empty DiffObject. Most methods of this class
 | 
						|
         * can not be called on empty DiffObjects.
 | 
						|
         */
 | 
						|
        DiffObject() noexcept :
 | 
						|
            m_prev(nullptr),
 | 
						|
            m_curr(nullptr),
 | 
						|
            m_next(nullptr) {
 | 
						|
        }
 | 
						|
 | 
						|
        /**
 | 
						|
         * Construct a non-empty DiffObject from the given OSMObjects. All
 | 
						|
         * OSMObjects must be of the same type (Node, Way, or Relation) and
 | 
						|
         * have the same ID.
 | 
						|
         */
 | 
						|
        DiffObject(const osmium::OSMObject& prev, const osmium::OSMObject& curr, const osmium::OSMObject& next) noexcept :
 | 
						|
            m_prev(&prev),
 | 
						|
            m_curr(&curr),
 | 
						|
            m_next(&next) {
 | 
						|
            assert(prev.type() == curr.type() && curr.type() == next.type());
 | 
						|
            assert(prev.id()   == curr.id()   && curr.id()   == next.id());
 | 
						|
        }
 | 
						|
 | 
						|
        /**
 | 
						|
         * Check whether the DiffObject was created empty.
 | 
						|
         */
 | 
						|
        bool empty() const noexcept {
 | 
						|
            return m_prev == nullptr;
 | 
						|
        }
 | 
						|
 | 
						|
        /**
 | 
						|
         * Get the previous object stored.
 | 
						|
         *
 | 
						|
         * @pre DiffObject must not be empty.
 | 
						|
         */
 | 
						|
        const osmium::OSMObject& prev() const noexcept {
 | 
						|
            assert(m_prev && m_curr && m_next);
 | 
						|
            return *m_prev;
 | 
						|
        }
 | 
						|
 | 
						|
        /**
 | 
						|
         * Get the current object stored.
 | 
						|
         *
 | 
						|
         * @pre DiffObject must not be empty.
 | 
						|
         */
 | 
						|
        const osmium::OSMObject& curr() const noexcept {
 | 
						|
            assert(m_prev && m_curr && m_next);
 | 
						|
            return *m_curr;
 | 
						|
        }
 | 
						|
 | 
						|
        /**
 | 
						|
         * Get the next object stored.
 | 
						|
         *
 | 
						|
         * @pre DiffObject must not be empty.
 | 
						|
         */
 | 
						|
        const osmium::OSMObject& next() const noexcept {
 | 
						|
            assert(m_prev && m_curr && m_next);
 | 
						|
            return *m_next;
 | 
						|
        }
 | 
						|
 | 
						|
        /**
 | 
						|
         * Is the current object version the first (with this type and ID)?
 | 
						|
         *
 | 
						|
         * @pre DiffObject must not be empty.
 | 
						|
         */
 | 
						|
        bool first() const noexcept {
 | 
						|
            assert(m_prev && m_curr && m_next);
 | 
						|
            return m_prev == m_curr;
 | 
						|
        }
 | 
						|
 | 
						|
        /**
 | 
						|
         * Is the current object version the last (with this type and ID)?
 | 
						|
         *
 | 
						|
         * @pre DiffObject must not be empty.
 | 
						|
         */
 | 
						|
        bool last() const noexcept {
 | 
						|
            assert(m_prev && m_curr && m_next);
 | 
						|
            return m_curr == m_next;
 | 
						|
        }
 | 
						|
 | 
						|
        /**
 | 
						|
         * Return the type of the current object.
 | 
						|
         *
 | 
						|
         * @pre DiffObject must not be empty.
 | 
						|
         */
 | 
						|
        osmium::item_type type() const noexcept {
 | 
						|
            assert(m_prev && m_curr && m_next);
 | 
						|
            return m_curr->type();
 | 
						|
        }
 | 
						|
 | 
						|
        /**
 | 
						|
         * Return the ID of the current object.
 | 
						|
         *
 | 
						|
         * @pre DiffObject must not be empty.
 | 
						|
         */
 | 
						|
        osmium::object_id_type id() const noexcept {
 | 
						|
            assert(m_prev && m_curr && m_next);
 | 
						|
            return m_curr->id();
 | 
						|
        }
 | 
						|
 | 
						|
        /**
 | 
						|
         * Return the version of the current object.
 | 
						|
         *
 | 
						|
         * @pre DiffObject must not be empty.
 | 
						|
         */
 | 
						|
        osmium::object_version_type version() const noexcept {
 | 
						|
            assert(m_prev && m_curr && m_next);
 | 
						|
            return m_curr->version();
 | 
						|
        }
 | 
						|
 | 
						|
        /**
 | 
						|
         * Return the changeset ID of the current object.
 | 
						|
         *
 | 
						|
         * @pre DiffObject must not be empty.
 | 
						|
         */
 | 
						|
        osmium::changeset_id_type changeset() const noexcept {
 | 
						|
            assert(m_prev && m_curr && m_next);
 | 
						|
            return m_curr->changeset();
 | 
						|
        }
 | 
						|
 | 
						|
        /**
 | 
						|
         * Return the timestamp when the current object version was created.
 | 
						|
         *
 | 
						|
         * @pre DiffObject must not be empty.
 | 
						|
         */
 | 
						|
        const osmium::Timestamp start_time() const noexcept {
 | 
						|
            assert(m_prev && m_curr && m_next);
 | 
						|
            return m_curr->timestamp();
 | 
						|
        }
 | 
						|
 | 
						|
        /**
 | 
						|
         * Return the timestamp when the current version of the object is
 | 
						|
         * not valid any more, ie the time when the next version of the object
 | 
						|
         * is valid. If this is the last version of the object, this will
 | 
						|
         * return a special "end of time" timestamp that is guaranteed to
 | 
						|
         * be larger than any normal timestamp.
 | 
						|
         *
 | 
						|
         * @pre DiffObject must not be empty.
 | 
						|
         */
 | 
						|
        const osmium::Timestamp end_time() const noexcept {
 | 
						|
            assert(m_prev && m_curr && m_next);
 | 
						|
            return last() ? osmium::end_of_time() : m_next->timestamp();
 | 
						|
        }
 | 
						|
 | 
						|
        /**
 | 
						|
         * Current object version is valid between time "from" (inclusive) and
 | 
						|
         * time "to" (not inclusive).
 | 
						|
         *
 | 
						|
         * This is a bit more complex than you'd think, because we have to
 | 
						|
         * handle the case properly where the start_time() == end_time().
 | 
						|
         *
 | 
						|
         * @pre DiffObject must not be empty.
 | 
						|
         */
 | 
						|
        bool is_between(const osmium::Timestamp& from, const osmium::Timestamp& to) const noexcept {
 | 
						|
            assert(m_prev && m_curr && m_next);
 | 
						|
            return start_time() < to &&
 | 
						|
                   ((start_time() != end_time() && end_time() >  from) ||
 | 
						|
                    (start_time() == end_time() && end_time() >= from));
 | 
						|
        }
 | 
						|
 | 
						|
        /**
 | 
						|
         * Current object version is visible at the given timestamp.
 | 
						|
         *
 | 
						|
         * @pre DiffObject must not be empty.
 | 
						|
         */
 | 
						|
        bool is_visible_at(const osmium::Timestamp& timestamp) const noexcept {
 | 
						|
            assert(m_prev && m_curr && m_next);
 | 
						|
            return start_time() <= timestamp && end_time() > timestamp && m_curr->visible();
 | 
						|
        }
 | 
						|
 | 
						|
    }; // class DiffObject
 | 
						|
 | 
						|
    template <typename T>
 | 
						|
    class DiffObjectDerived : public DiffObject {
 | 
						|
 | 
						|
    public:
 | 
						|
 | 
						|
        DiffObjectDerived(const T& prev, const T& curr, const T& next) noexcept :
 | 
						|
            DiffObject(prev, curr, next) {
 | 
						|
        }
 | 
						|
 | 
						|
        const T& prev() const noexcept {
 | 
						|
            return static_cast<const T&>(DiffObject::prev());
 | 
						|
        }
 | 
						|
 | 
						|
        const T& curr() const noexcept {
 | 
						|
            return static_cast<const T&>(DiffObject::curr());
 | 
						|
        }
 | 
						|
 | 
						|
        const T& next() const noexcept {
 | 
						|
            return static_cast<const T&>(DiffObject::next());
 | 
						|
        }
 | 
						|
 | 
						|
    }; // class DiffObjectDerived
 | 
						|
 | 
						|
    using DiffNode     = DiffObjectDerived<osmium::Node>;
 | 
						|
    using DiffWay      = DiffObjectDerived<osmium::Way>;
 | 
						|
    using DiffRelation = DiffObjectDerived<osmium::Relation>;
 | 
						|
 | 
						|
} // namespace osmium
 | 
						|
 | 
						|
#endif // OSMIUM_OSM_DIFF_OBJECT_HPP
 |