/** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * 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. * * Neither the name of Timothy Stack 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 REGENTS 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 REGENTS OR CONTRIBUTORS 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. * * @file bookmarks.hh */ #ifndef bookmarks_hh #define bookmarks_hh #include #include #include #include #include #include "base/lnav_log.hh" struct bookmark_metadata { static std::set KNOWN_TAGS; std::string bm_name; std::string bm_comment; std::vector bm_tags; void add_tag(const std::string& tag) { if (std::find(this->bm_tags.begin(), this->bm_tags.end(), tag) == this->bm_tags.end()) { this->bm_tags.push_back(tag); } }; bool remove_tag(const std::string& tag) { auto iter = std::find(this->bm_tags.begin(), this->bm_tags.end(), tag); bool retval = false; if (iter != this->bm_tags.end()) { this->bm_tags.erase(iter); retval = true; } return retval; }; bool empty() const { return this->bm_name.empty() && this->bm_comment.empty() && this->bm_tags.empty(); }; void clear() { this->bm_comment.clear(); this->bm_tags.clear(); }; }; /** * Extension of the STL vector that is used to store bookmarks for * files being viewed, where a bookmark is just a particular line in * the file(s). The value-added over the standard vector are some * methods for doing content-wise iteration. In other words, given a * value that may or may not be in the vector, find the next or * previous value that is in the vector. * * @param LineType The type used to store line numbers. (e.g. * vis_line_t or content_line_t) * * @note The vector is expected to be sorted. */ template class bookmark_vector : public std::vector { typedef std::vector base_vector; public: typedef typename base_vector::size_type size_type; typedef typename base_vector::iterator iterator; typedef typename base_vector::const_iterator const_iterator; /** * Insert a bookmark into this vector, but only if it is not already in the * vector. * * @param vl The line to bookmark. */ iterator insert_once(LineType vl) { iterator lb, retval; require(vl >= 0); lb = std::lower_bound(this->begin(), this->end(), vl); if (lb == this->end() || *lb != vl) { this->insert(lb, vl); retval = this->end(); } else { retval = lb; } return retval; }; std::pair equal_range(LineType start, LineType stop) { auto lb = std::lower_bound(this->begin(), this->end(), start); if (stop == LineType(-1)) { return std::make_pair(lb, this->end()); } else { auto up = std::upper_bound(this->begin(), this->end(), stop); return std::make_pair(lb, up); } }; /** * @param start The value to start the search for the next bookmark. * @return The next bookmark value in the vector or -1 if there are * no more remaining bookmarks. If the 'start' value is a bookmark, * the next bookmark is returned. If the 'start' value is not a * bookmark, the next highest value in the vector is returned. */ LineType next(LineType start) const; /** * @param start The value to start the search for the previous * bookmark. * @return The previous bookmark value in the vector or -1 if there * are no more prior bookmarks. * @see next */ LineType prev(LineType start) const; }; /** * Dummy type whose instances are used to distinguish between * bookmarks maintained by different source modules. */ class bookmark_type_t { public: typedef std::vector::iterator type_iterator; static type_iterator type_begin() { return get_all_types().begin(); }; static type_iterator type_end() { return get_all_types().end(); }; static bookmark_type_t* find_type(const std::string& name) { auto iter = find_if(type_begin(), type_end(), mark_eq(name)); bookmark_type_t* retval = nullptr; if (iter != type_end()) { retval = (*iter); } return retval; }; static std::vector& get_all_types() { static std::vector all_types; return all_types; }; explicit bookmark_type_t(std::string name) : bt_name(std::move(name)) { get_all_types().push_back(this); }; const std::string& get_name() const { return this->bt_name; }; private: struct mark_eq { explicit mark_eq(const std::string& name) : me_name(name){}; bool operator()(bookmark_type_t* bt) { return bt->bt_name == this->me_name; }; const std::string& me_name; }; const std::string bt_name; }; template LineType bookmark_vector::next(LineType start) const { LineType retval(-1); require(start >= -1); auto ub = upper_bound(this->cbegin(), this->cend(), start); if (ub != this->cend()) { retval = *ub; } ensure(retval == -1 || start < retval); return retval; } template LineType bookmark_vector::prev(LineType start) const { LineType retval(-1); require(start >= 0); auto lb = lower_bound(this->cbegin(), this->cend(), start); if (lb != this->cbegin()) { lb -= 1; retval = *lb; } ensure(retval < start); return retval; } /** * Map of bookmark types to bookmark vectors. */ template struct bookmarks { typedef std::map > type; }; #endif