Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Matthieu Longo <matthieu.longo@arm.com>
To: <gdb-patches@sourceware.org>
Cc: Andrew Burgess <aburgess@redhat.com>, Tom Tromey <tom@tromey.com>,
	Matthieu Longo <matthieu.longo@arm.com>
Subject: [PATCH v3 4/8] gdbsupport: add extract_next_field helper
Date: Tue, 22 Sep 2026 14:50:46 +0100	[thread overview]
Message-ID: <20260922135050.236941-5-matthieu.longo@arm.com> (raw)
In-Reply-To: <20260922135050.236941-1-matthieu.longo@arm.com>

Add extract_next_field, a helper for extracting a view from a buffer
up to a given separator. The helper also returns an iterator to the
beginning of the next entry, skipping consecutive separators.

The helper supports views whose value type is 'char', such as
gdb::array_view<char> and std::string_view (from c++20).
---
 gdb/unittests/common-utils-selftests.c | 32 +++++++++++++++++
 gdbsupport/common-utils.h              | 50 ++++++++++++++++++++++++++
 2 files changed, 82 insertions(+)

diff --git a/gdb/unittests/common-utils-selftests.c b/gdb/unittests/common-utils-selftests.c
index eb9c83616f0..bbd8b00a2de 100644
--- a/gdb/unittests/common-utils-selftests.c
+++ b/gdb/unittests/common-utils-selftests.c
@@ -19,6 +19,8 @@
 
 #include "gdbsupport/selftest.h"
 
+#include "gdbsupport/array-view.h"
+
 namespace selftests {
 
 /* Type of both 'string_printf' and the 'format' function below.  Used
@@ -125,6 +127,34 @@ string_vappendf_tests ()
   test_appendf_func (string_vappendf_wrapper);
 }
 
+static void
+extract_next_field_tests ()
+{
+  auto bytewise_match = [] (const auto &s1, const auto &s2) -> bool
+  {
+    return std::equal (s1.begin (), s1.end (), s2.begin (), s2.end ());
+  };
+
+  std::string s = "\n1234\nabc\n\ndef";
+  std::vector<std::string> expected = { "1234", "abc", "def" };
+  {
+    using view_t = gdb::array_view<char>;
+    std::vector<view_t> lines;
+    view_t buffer (s.data (), s.size ());
+    for (auto it = buffer.begin (); it != buffer.end ();)
+      {
+	auto [line, next_line_begin]
+	  = extract_next_field (buffer, it, '\n');
+	lines.emplace_back (line);
+	it = next_line_begin;
+      }
+
+    SELF_CHECK (expected.size () == lines.size ());
+    for (auto i = 0; i < expected.size () && i < lines.size (); ++i)
+      SELF_CHECK (bytewise_match (expected[i], lines[i]));
+  }
+}
+
 } /* namespace selftests */
 
 INIT_GDB_FILE (common_utils_selftests)
@@ -134,4 +164,6 @@ INIT_GDB_FILE (common_utils_selftests)
   selftests::register_test ("string_appendf", selftests::string_appendf_tests);
   selftests::register_test ("string_vappendf",
 			    selftests::string_vappendf_tests);
+  selftests::register_test ("extract_next_field",
+			    selftests::extract_next_field_tests);
 }
diff --git a/gdbsupport/common-utils.h b/gdbsupport/common-utils.h
index de83a715ac4..a4042b24644 100644
--- a/gdbsupport/common-utils.h
+++ b/gdbsupport/common-utils.h
@@ -279,4 +279,54 @@ struct string_view_hash
 
 } /* namespace gdb */
 
+/* Extract a view from BUFFER starting at START.
+
+   Leading occurrences of SEPARATOR at START are skipped.  The returned view
+   extends from the first non-separator character to the next occurrence of
+   SEPARATOR, or to BUFFER.end () if no separator is found.
+
+   Return the extracted view together with an iterator pointing to the first
+   non-separator character after the extracted view.  Successive separators
+   are skipped.  If there is no following non-separator character, the returned
+   iterator is BUFFER.end ().
+
+   If START does not point into BUFFER, return an empty view and BUFFER.end ().
+
+   ViewT may be gdb::array_view<char> or std::string_view.  The later requires
+   C++20, which added the constructor taking the range [first, last).  */
+
+template <class ViewT>
+std::pair<ViewT, typename ViewT::iterator>
+extract_next_field (ViewT buffer,
+		    typename ViewT::iterator start,
+		    char separator = '\0')
+{
+  static_assert (!std::is_reference_v <ViewT>);
+  static_assert (std::is_same_v <typename ViewT::value_type, char>);
+
+  auto next_start = buffer.end ();
+
+  /* Reject a START iterator that does not point into BUFFER.  */
+  if (start < buffer.begin () || start >= buffer.end ())
+    return {ViewT (), next_start};
+
+  /* Skip leading occurrences of the separator.  */
+  while (start != buffer.end () && *start == separator)
+    ++start;
+
+  auto it = std::find (start, buffer.end (), separator);
+
+  /* If no separator is found, the remainder of BUFFER is the final string.  */
+  if (it != buffer.end ())
+    {
+      /* Otherwise, skip successive separators so that NEXT_START points to
+	 the beginning of the next string, if any.  */
+      for (next_start = std::next (it);
+	   next_start != buffer.end () && *next_start == separator;
+	   next_start = std::next (next_start));
+    }
+
+  return {ViewT (start, it), next_start};
+}
+
 #endif /* GDBSUPPORT_COMMON_UTILS_H */
-- 
2.55.0


  parent reply	other threads:[~2026-09-22 13:53 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-22 13:50 [PATCH v3 0/8] gdb: introduce file_reader_t to read procfs files Matthieu Longo
2026-09-22 13:50 ` [PATCH v3 1/8] gdb support: add gdb::ranges::replace algorithm Matthieu Longo
2026-09-22 13:50 ` [PATCH v3 2/8] gdb/linux: remove redundant struct prefixes from smaps_data Matthieu Longo
2026-09-22 13:50 ` [PATCH v3 3/8] gdb/linux: style filenames in /proc warning messages Matthieu Longo
2026-09-22 13:50 ` Matthieu Longo [this message]
2026-09-22 13:50 ` [PATCH v3 5/8] gdb/linux: refactor /proc mapping parsing to use array_view Matthieu Longo
2026-09-22 13:50 ` [PATCH v3 6/8] gdb: introduce helper class target_file_reader Matthieu Longo
2026-09-22 13:50 ` [PATCH v3 7/8] gdb/linux-tdep: use target_file_reader for procfs parsing Matthieu Longo
2026-09-22 13:50 ` [PATCH v3 8/8] gdb/linux-tdep: remove legacy parse_smaps_data overload Matthieu Longo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260922135050.236941-5-matthieu.longo@arm.com \
    --to=matthieu.longo@arm.com \
    --cc=aburgess@redhat.com \
    --cc=gdb-patches@sourceware.org \
    --cc=tom@tromey.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox