[nemiver] Use a fuzzy matching scheme when searching an @
- From: Dodji Seketeli <dodji src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [nemiver] Use a fuzzy matching scheme when searching an @
- Date: Mon, 6 Sep 2010 19:53:01 +0000 (UTC)
commit 01e1bf2857d14462dd89692ba50914c376b5ef2a
Author: Dodji Seketeli <dodji redhat com>
Date: Sun Sep 5 18:11:07 2010 +0200
Use a fuzzy matching scheme when searching an @
* src/common/nmv-range.h (Range::ValueSearchResult): New enum.
* src/uicommon/nmv-source-editor.cc
(SourceEditor::Priv::get_smallest_range_containing_address): New
function.
(address_2_line): Use it. When asked the line matching an address
@, if @ is not present in the buffer, find the range of addresses
that encloses @, and return the line matching the uppper bound of
that address range.
src/common/nmv-range.h | 27 +++++++++++
src/uicommon/nmv-source-editor.cc | 89 ++++++++++++++++++++++++++++++++-----
2 files changed, 104 insertions(+), 12 deletions(-)
---
diff --git a/src/common/nmv-range.h b/src/common/nmv-range.h
index 2993520..aef1512 100644
--- a/src/common/nmv-range.h
+++ b/src/common/nmv-range.h
@@ -36,6 +36,33 @@ class Range {
size_t m_max;
public:
+
+ /// An enum representing the result of the searching of a range
+ /// around a value. E.g, suppose we have an ordered set of integer
+ /// values vi {v1, v2, v3 ...} that we name V.
+ /// Suppose we also have a particular integer N. And we want to
+ /// make the query expressed as: "What is the smallest range
+ /// R{vi,vi+p} that encloses N?".
+ /// If we had a function that would execute that query and return
+ /// an answer, this enum would help us know more about the how N
+ /// relates to the returned range.
+ /// VALUE_SEARCH_RESULT_EXACT means
+ /// that the N equals vi and equals vi+p. It means the range is
+ /// actually a single value, which is N.
+ /// VALUE_SEARCH_RESULT_WITHIN means that N is greater than vi
+ /// and less than vi+p. I means N is within the range.
+ /// VALUE_SEARCH_RESULT_BEFORE means that N is less then vi, and
+ /// so less than vi+p too. It means N is before the range.
+ /// VALUE_SEARCH_RESULT_AFTER means N is greater than vi+p, and so
+ /// greater than vi too. It means N is after the range.
+ enum ValueSearchResult {
+ VALUE_SEARCH_RESULT_EXACT = 0,
+ VALUE_SEARCH_RESULT_WITHIN,
+ VALUE_SEARCH_RESULT_BEFORE,
+ VALUE_SEARCH_RESULT_AFTER,
+ VALUE_SEARCH_RESULT_NONE // <-- must always be last.
+ };
+
Range (size_t a_min = 0, size_t a_max = 0) :
m_min (a_min),
m_max (a_max)
diff --git a/src/uicommon/nmv-source-editor.cc b/src/uicommon/nmv-source-editor.cc
index 06e0d45..fe8ca21 100644
--- a/src/uicommon/nmv-source-editor.cc
+++ b/src/uicommon/nmv-source-editor.cc
@@ -332,36 +332,101 @@ struct SourceEditor::Priv {
return 0;
}
- bool
- address_2_line (Glib::RefPtr<SourceBuffer> a_buf,
- const Address an_addr,
- int &a_line) const
+ typedef std::pair<Address, int> AddrLine;
+ typedef std::pair<AddrLine, AddrLine> AddrLineRange;
+
+ common::Range::ValueSearchResult
+ get_smallest_range_containing_address (Glib::RefPtr<SourceBuffer> a_buf,
+ const Address &an_addr,
+ AddrLineRange &a_range) const
+
{
- if (!a_buf)
- return false;
-
Gtk::TextBuffer::iterator it = a_buf->begin ();
size_t i;
std::string addr;
+ AddrLine lower_bound, upper_bound;
+
+ THROW_IF_FAIL (it.starts_line ());
+
while (!it.is_end ()) {
// We must always be at the beginning of a line here.
THROW_IF_FAIL (it.starts_line ());
addr.clear ();
for (i = 0;
!isspace (it.get_char ()) && it.ends_line () != true
- && i < an_addr.string_size ();
+ && i < an_addr.string_size ();
++it, ++i) {
addr += it.get_char ();
}
- bool match = (addr == an_addr.to_string ());
- if (match) {
- a_line = it.get_line () + 1;
- return true;
+
+ int match = (addr.compare (an_addr.to_string ()));
+
+ if (match < 0
+ && str_utils::string_is_hexa_number (addr)) {
+ lower_bound.first = addr;
+ lower_bound.second = it.get_line () + 1;
+ }
+
+ if (match > 0
+ && str_utils::string_is_hexa_number (addr)) {
+ if (lower_bound.first.empty ()) {
+ // So we are seing an @ that is greater than
+ // an_addr without having ever seen an @ that is
+ // lower than an_addr. That means all the @s of
+ // the buffer are greater than an_addr.
+ return common::Range::VALUE_SEARCH_RESULT_BEFORE;
+ } else {
+ // So the previous @ we saw was lower than
+ // a_address and this one is greater. it means we
+ // the buffer does not contain a_address, but
+ // rather contains at a range of @s that surrounds
+ // a_address. Return that range.
+ upper_bound.first = addr;
+ upper_bound.second = it.get_line () + 1;
+ a_range.first = lower_bound;
+ a_range.second = upper_bound;
+ return common::Range::VALUE_SEARCH_RESULT_WITHIN;
+ }
+ }
+
+ if (match == 0) {
+ a_range.first.first = an_addr;
+ a_range.first.second = it.get_line () + 1;
+ a_range.second = a_range.first;
+ return common::Range::VALUE_SEARCH_RESULT_EXACT;
} else {
// Go to next line.
it.forward_line ();
}
}
+
+ if (!lower_bound.first.empty ()) {
+ if (upper_bound.first.empty ())
+ return common::Range::VALUE_SEARCH_RESULT_AFTER;
+ else
+ THROW ("unreachable");
+ }
+
+ return common::Range::VALUE_SEARCH_RESULT_NONE;
+ }
+
+ bool
+ address_2_line (Glib::RefPtr<SourceBuffer> a_buf,
+ const Address an_addr,
+ int &a_line) const
+ {
+ if (!a_buf)
+ return false;
+
+ AddrLineRange range;
+ common::Range::ValueSearchResult s =
+ get_smallest_range_containing_address (a_buf, an_addr, range);
+
+ if (s == common::Range::VALUE_SEARCH_RESULT_EXACT
+ || s == common::Range::VALUE_SEARCH_RESULT_WITHIN) {
+ a_line = range.second.second;
+ return true;
+ }
return false;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]