1 #ifndef REPLXX_HISTORY_HXX_INCLUDED
2 #define REPLXX_HISTORY_HXX_INCLUDED 1
3 
4 #include <list>
5 #include <unordered_map>
6 
7 #include "unicodestring.hxx"
8 #include "utf8string.hxx"
9 #include "conversion.hxx"
10 #include "util.hxx"
11 
12 namespace std {
13 template<>
14 struct hash<replxx::UnicodeString> {
operator ()std::hash15 	std::size_t operator()( replxx::UnicodeString const& us_ ) const {
16 		std::size_t h( 0 );
17 		char32_t const* p( us_.get() );
18 		char32_t const* e( p + us_.length() );
19 		while ( p != e ) {
20 			h *= 31;
21 			h += *p;
22 			++ p;
23 		}
24 		return ( h );
25 	}
26 };
27 }
28 
29 namespace replxx {
30 
31 class History {
32 public:
33 	class Entry {
34 		std::string _timestamp;
35 		UnicodeString _text;
36 	public:
Entry(std::string const & timestamp_,UnicodeString const & text_)37 		Entry( std::string const& timestamp_, UnicodeString const& text_ )
38 			: _timestamp( timestamp_ )
39 			, _text( text_ ) {
40 		}
timestamp(void) const41 		std::string const& timestamp( void ) const {
42 			return ( _timestamp );
43 		}
text(void) const44 		UnicodeString const& text( void ) const {
45 			return ( _text );
46 		}
operator <(Entry const & other_) const47 		bool operator < ( Entry const& other_ ) const {
48 			return ( _timestamp < other_._timestamp );
49 		}
50 	};
51 	typedef std::list<Entry> entries_t;
52 	typedef std::unordered_map<UnicodeString, entries_t::const_iterator> locations_t;
53 private:
54 	entries_t _entries;
55 	locations_t _locations;
56 	int _maxSize;
57 	entries_t::const_iterator _current;
58 	entries_t::const_iterator _yankPos;
59 	/*
60 	 * _previous and _recallMostRecent are used to allow
61 	 * HISTORY_NEXT action (a down-arrow key) to have a special meaning
62 	 * if invoked after a line from history was accepted without
63 	 * any modification.
64 	 * Special meaning is: a down arrow shall jump to the line one
65 	 * after previously accepted from history.
66 	 */
67 	entries_t::const_iterator _previous;
68 	bool _recallMostRecent;
69 	bool _unique;
70 public:
71 	History( void );
72 	void add( UnicodeString const& line, std::string const& when = now_ms_str() );
73 	bool save( std::string const& filename );
74 	bool load( std::string const& filename );
75 	void clear( void );
76 	void set_max_size( int len );
set_unique(bool unique_)77 	void set_unique( bool unique_ ) {
78 		_unique = unique_;
79 		remove_duplicates();
80 	}
81 	void reset_yank_iterator();
82 	bool next_yank_position( void );
reset_recall_most_recent(void)83 	void reset_recall_most_recent( void ) {
84 		_recallMostRecent = false;
85 	}
commit_index(void)86 	void commit_index( void ) {
87 		_previous = _current;
88 		_recallMostRecent = true;
89 	}
is_empty(void) const90 	bool is_empty( void ) const {
91 		return ( _entries.empty() );
92 	}
93 	void update_last( UnicodeString const& );
94 	void drop_last( void );
95 	bool is_last( void ) const;
96 	bool move( bool );
current(void) const97 	UnicodeString const& current( void ) const {
98 		return ( _current->text() );
99 	}
yank_line(void) const100 	UnicodeString const& yank_line( void ) const {
101 		return ( _yankPos->text() );
102 	}
103 	void jump( bool, bool = true );
104 	bool common_prefix_search( UnicodeString const&, int, bool );
size(void) const105 	int size( void ) const {
106 		return ( static_cast<int>( _entries.size() ) );
107 	}
108 	Replxx::HistoryScan::impl_t scan( void ) const;
109 	void save_pos( void );
110 	void restore_pos( void );
111 private:
112 	History( History const& ) = delete;
113 	History& operator = ( History const& ) = delete;
114 	bool move( entries_t::const_iterator&, int, bool = false ) const;
115 	entries_t::const_iterator moved( entries_t::const_iterator, int, bool = false ) const;
116 	void erase( entries_t::const_iterator );
117 	void trim_to_max_size( void );
118 	void remove_duplicate( UnicodeString const& );
119 	void remove_duplicates( void );
120 	bool do_load( std::string const& );
121 	entries_t::const_iterator last( void ) const;
122 	void sort( void );
123 };
124 
125 class Replxx::HistoryScanImpl {
126 	History::entries_t const& _entries;
127 	History::entries_t::const_iterator _it;
128 	mutable Utf8String _utf8Cache;
129 	mutable Replxx::HistoryEntry _entryCache;
130 	mutable bool _cacheValid;
131 public:
132 	HistoryScanImpl( History::entries_t const& );
133 	bool next( void );
134 	Replxx::HistoryEntry const& get( void ) const;
135 };
136 
137 }
138 
139 #endif
140 
141