+/* The result of a successful completion match. When doing symbol
+ comparison, we use the symbol search name for the symbol name match
+ check, but the matched name that is shown to the user may be
+ different. For example, Ada uses encoded names for lookup, but
+ then wants to decode the symbol name to show to the user, and also
+ in some cases wrap the matched name in "<sym>" (meaning we can't
+ always use the symbol's print name). */
+
+class completion_match
+{
+public:
+ /* Get the completion match result. See m_match/m_storage's
+ descriptions. */
+ const char *match ()
+ { return m_match; }
+
+ /* Set the completion match result. See m_match/m_storage's
+ descriptions. */
+ void set_match (const char *match)
+ { m_match = match; }
+
+ /* Get temporary storage for generating a match result, dynamically.
+ The built string is only good until the next clear() call. I.e.,
+ good until the next symbol comparison. */
+ std::string &storage ()
+ { return m_storage; }
+
+ /* Prepare for another completion matching sequence. */
+ void clear ()
+ {
+ m_match = NULL;
+ m_storage.clear ();
+ }
+
+private:
+ /* The completion match result. This can either be a pointer into
+ M_STORAGE string, or it can be a pointer into the some other
+ string that outlives the completion matching sequence (usually, a
+ pointer to a symbol's name). */
+ const char *m_match;
+
+ /* Storage a symbol comparison routine can use for generating a
+ match result, dynamically. The built string is only good until
+ the next clear() call. I.e., good until the next symbol
+ comparison. */
+ std::string m_storage;
+};
+
+/* The result of a successful completion match, but for least common
+ denominator (LCD) computation. Some completers provide matches
+ that don't start with the completion "word". E.g., completing on
+ "b push_ba" on a C++ program usually completes to
+ std::vector<...>::push_back, std::string::push_back etc. In such
+ case, the symbol comparison routine will set the LCD match to point
+ into the "push_back" substring within the symbol's name string.
+ Also, in some cases, the symbol comparison routine will want to
+ ignore parts of the symbol name for LCD purposes, such as for
+ example symbols with abi tags in C++. In such cases, the symbol
+ comparison routine will set MARK_IGNORED_RANGE to mark the ignored
+ substrings of the matched string. The resulting LCD string with
+ the ignored parts stripped out is computed at the end of a
+ completion match sequence iff we had a positive match. */
+
+class completion_match_for_lcd
+{
+public:
+ /* Get the resulting LCD, after a successful match. */
+ const char *match ()
+ { return m_match; }
+
+ /* Set the match for LCD. See m_match's description. */
+ void set_match (const char *match)
+ { m_match = match; }
+
+ /* Mark the range between [BEGIN, END) as ignored. */
+ void mark_ignored_range (const char *begin, const char *end)
+ { m_ignored_ranges.emplace_back (begin, end); }
+
+ /* Get the resulting LCD, after a successful match. If there are
+ ignored ranges, then this builds a new string with the ignored
+ parts removed (and stores it internally). As such, the result of
+ this call is only good for the current completion match
+ sequence. */
+ const char *finish ()
+ {
+ if (m_ignored_ranges.empty ())
+ return m_match;
+ else
+ {
+ m_finished_storage.clear ();
+
+ const char *prev = m_match;
+ for (const auto &range : m_ignored_ranges)
+ {
+ m_finished_storage.append (prev, range.first);
+ prev = range.second;
+ }
+ m_finished_storage.append (prev);
+
+ return m_finished_storage.c_str ();
+ }
+ }
+
+ /* Prepare for another completion matching sequence. */
+ void clear ()
+ {
+ m_match = NULL;
+ m_ignored_ranges.clear ();
+ }
+
+private:
+ /* The completion match result for LCD. This is usually either a
+ pointer into to a substring within a symbol's name, or to the
+ storage of the pairing completion_match object. */
+ const char *m_match;
+
+ /* The ignored substring ranges within M_MATCH. E.g., if we were
+ looking for completion matches for C++ functions starting with
+ "functio"
+ and successfully match:
+ "function[abi:cxx11](int)"
+ the ignored ranges vector will contain an entry that delimits the
+ "[abi:cxx11]" substring, such that calling finish() results in:
+ "function(int)"
+ */
+ std::vector<std::pair<const char *, const char *>> m_ignored_ranges;
+
+ /* Storage used by the finish() method, if it has to compute a new
+ string. */
+ std::string m_finished_storage;
+};
+
+/* Convenience aggregate holding info returned by the symbol name
+ matching routines (see symbol_name_matcher_ftype). */
+struct completion_match_result
+{
+ /* The completion match candidate. */
+ completion_match match;
+
+ /* The completion match, for LCD computation purposes. */
+ completion_match_for_lcd match_for_lcd;
+
+ /* Convenience that sets both MATCH and MATCH_FOR_LCD. M_FOR_LCD is
+ optional. If not specified, defaults to M. */
+ void set_match (const char *m, const char *m_for_lcd = NULL)
+ {
+ match.set_match (m);
+ if (m_for_lcd == NULL)
+ match_for_lcd.set_match (m);
+ else
+ match_for_lcd.set_match (m_for_lcd);
+ }
+};
+