All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bartosz Golaszewski <brgl@bgdev.pl>
To: Kent Gibson <warthog618@gmail.com>,
	Andy Shevchenko <andriy.shevchenko@linux.intel.com>,
	Geert Uytterhoeven <geert@linux-m68k.org>,
	Jack Winch <sunt.un.morcov@gmail.com>,
	Helmut Grohne <helmut.grohne@intenta.de>,
	Linus Walleij <linus.walleij@linaro.org>
Cc: linux-gpio@vger.kernel.org,
	Bartosz Golaszewski <bgolaszewski@baylibre.com>
Subject: [libgpiod][PATCH 05/14] core: drop line iterators
Date: Thu, 10 Dec 2020 14:23:06 +0100	[thread overview]
Message-ID: <20201210132315.5785-6-brgl@bgdev.pl> (raw)
In-Reply-To: <20201210132315.5785-1-brgl@bgdev.pl>

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

Hand-crafted iterators don't make much sense in C and impose an
additional layer of memory allocation and resource releasing. Remove
the line iterators from the core C library.

We're leaving the iterators where they make sense: in C++ and Python
bindings but we convert them to using other means of keeping track of
lines.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 bindings/cxx/gpiod.hpp        |  1 -
 bindings/cxx/iter.cpp         | 28 +++++---------------
 bindings/python/gpiodmodule.c | 21 +++++----------
 include/gpiod.h               | 36 --------------------------
 lib/helpers.c                 | 32 ++++++++++-------------
 lib/iter.c                    | 48 -----------------------------------
 tests/gpiod-test.h            |  2 --
 tests/tests-iter.c            | 23 -----------------
 tools/gpioinfo.c              | 14 ++++------
 9 files changed, 33 insertions(+), 172 deletions(-)

diff --git a/bindings/cxx/gpiod.hpp b/bindings/cxx/gpiod.hpp
index 8c8e6c9..0f1d9b2 100644
--- a/bindings/cxx/gpiod.hpp
+++ b/bindings/cxx/gpiod.hpp
@@ -1083,7 +1083,6 @@ public:
 
 private:
 
-	::std::shared_ptr<::gpiod_line_iter> _m_iter;
 	line _m_current;
 };
 
diff --git a/bindings/cxx/iter.cpp b/bindings/cxx/iter.cpp
index 7985910..15c3925 100644
--- a/bindings/cxx/iter.cpp
+++ b/bindings/cxx/iter.cpp
@@ -17,23 +17,6 @@ void chip_iter_deleter(::gpiod_chip_iter* iter)
 	::gpiod_chip_iter_free_noclose(iter);
 }
 
-void line_iter_deleter(::gpiod_line_iter* iter)
-{
-	::gpiod_line_iter_free(iter);
-}
-
-::gpiod_line_iter* make_line_iter(::gpiod_chip* chip)
-{
-	::gpiod_line_iter* iter;
-
-	iter = ::gpiod_line_iter_new(chip);
-	if (!iter)
-		throw ::std::system_error(errno, ::std::system_category(),
-					  "error creating GPIO line iterator");
-
-	return iter;
-}
-
 } /* namespace */
 
 chip_iter make_chip_iter(void)
@@ -105,17 +88,20 @@ line_iter end(const line_iter&) noexcept
 }
 
 line_iter::line_iter(const chip& owner)
-	: _m_iter(make_line_iter(owner._m_chip.get()), line_iter_deleter),
-	  _m_current(line(::gpiod_line_iter_next(this->_m_iter.get()), owner))
+	: _m_current(owner.get_line(0))
 {
 
 }
 
 line_iter& line_iter::operator++(void)
 {
-	::gpiod_line* next = ::gpiod_line_iter_next(this->_m_iter.get());
+	unsigned int offset = this->_m_current.offset() + 1;
+	chip owner = this->_m_current.get_chip();
 
-	this->_m_current = next ? line(next, this->_m_current._m_owner) : line();
+	if (offset == owner.num_lines())
+		this->_m_current = line(); /* Last element */
+	else
+		this->_m_current = owner.get_line(offset);
 
 	return *this;
 }
diff --git a/bindings/python/gpiodmodule.c b/bindings/python/gpiodmodule.c
index b9b5770..11d1407 100644
--- a/bindings/python/gpiodmodule.c
+++ b/bindings/python/gpiodmodule.c
@@ -41,7 +41,7 @@ typedef struct {
 
 typedef struct {
 	PyObject_HEAD
-	struct gpiod_line_iter *iter;
+	unsigned int offset;
 	gpiod_ChipObject *owner;
 } gpiod_LineIterObject;
 
@@ -2621,14 +2621,7 @@ static int gpiod_LineIter_init(gpiod_LineIterObject *self,
 	if (gpiod_ChipIsClosed(chip_obj))
 		return -1;
 
-	Py_BEGIN_ALLOW_THREADS;
-	self->iter = gpiod_line_iter_new(chip_obj->chip);
-	Py_END_ALLOW_THREADS;
-	if (!self->iter) {
-		PyErr_SetFromErrno(PyExc_OSError);
-		return -1;
-	}
-
+	self->offset = 0;
 	self->owner = chip_obj;
 	Py_INCREF(chip_obj);
 
@@ -2637,9 +2630,6 @@ static int gpiod_LineIter_init(gpiod_LineIterObject *self,
 
 static void gpiod_LineIter_dealloc(gpiod_LineIterObject *self)
 {
-	if (self->iter)
-		gpiod_line_iter_free(self->iter);
-
 	PyObject_Del(self);
 }
 
@@ -2647,10 +2637,13 @@ static gpiod_LineObject *gpiod_LineIter_next(gpiod_LineIterObject *self)
 {
 	struct gpiod_line *line;
 
-	line = gpiod_line_iter_next(self->iter);
-	if (!line)
+	if (self->offset == gpiod_chip_num_lines(self->owner->chip))
 		return NULL; /* Last element. */
 
+	line = gpiod_chip_get_line(self->owner->chip, self->offset++);
+	if (!line)
+		return (gpiod_LineObject *)PyErr_SetFromErrno(PyExc_OSError);
+
 	return gpiod_MakeLineObject(self->owner, line);
 }
 
diff --git a/include/gpiod.h b/include/gpiod.h
index 9ffb446..b5965ed 100644
--- a/include/gpiod.h
+++ b/include/gpiod.h
@@ -40,7 +40,6 @@ extern "C" {
 struct gpiod_chip;
 struct gpiod_line;
 struct gpiod_chip_iter;
-struct gpiod_line_iter;
 struct gpiod_line_bulk;
 
 /**
@@ -1202,41 +1201,6 @@ gpiod_chip_iter_next_noclose(struct gpiod_chip_iter *iter) GPIOD_API;
 	     (chip);							\
 	     (chip) = gpiod_chip_iter_next_noclose(iter))
 
-/**
- * @brief Create a new line iterator.
- * @param chip Active gpiochip handle over the lines of which we want
- *             to iterate.
- * @return New line iterator or NULL if an error occurred.
- */
-struct gpiod_line_iter *
-gpiod_line_iter_new(struct gpiod_chip *chip) GPIOD_API;
-
-/**
- * @brief Free all resources associated with a GPIO line iterator.
- * @param iter Line iterator object.
- */
-void gpiod_line_iter_free(struct gpiod_line_iter *iter) GPIOD_API;
-
-/**
- * @brief Get the next GPIO line handle.
- * @param iter The GPIO line iterator object.
- * @return Pointer to the next GPIO line handle or NULL if there are no more
- *         lines left.
- */
-struct gpiod_line *
-gpiod_line_iter_next(struct gpiod_line_iter *iter) GPIOD_API;
-
-/**
- * @brief Iterate over all GPIO lines of a single chip.
- * @param iter An initialized GPIO line iterator.
- * @param line Pointer to a GPIO line handle - on each iteration, the
- *             next GPIO line will be assigned to this argument.
- */
-#define gpiod_foreach_line(iter, line)					\
-	for ((line) = gpiod_line_iter_next(iter);			\
-	     (line);							\
-	     (line) = gpiod_line_iter_next(iter))
-
 /**
  * @}
  *
diff --git a/lib/helpers.c b/lib/helpers.c
index a343f71..3b7428b 100644
--- a/lib/helpers.c
+++ b/lib/helpers.c
@@ -124,24 +124,23 @@ gpiod_chip_get_lines(struct gpiod_chip *chip,
 
 struct gpiod_line_bulk *gpiod_chip_get_all_lines(struct gpiod_chip *chip)
 {
-	struct gpiod_line_iter *iter;
 	struct gpiod_line_bulk *bulk;
 	struct gpiod_line *line;
+	unsigned int offset;
 
 	bulk = gpiod_line_bulk_new(gpiod_chip_num_lines(chip));
 	if (!bulk)
 		return NULL;
 
-	iter = gpiod_line_iter_new(chip);
-	if (!iter) {
-		gpiod_line_bulk_free(bulk);
-		return NULL;
-	}
+	for (offset = 0; offset < gpiod_chip_num_lines(chip); offset++) {
+		line = gpiod_chip_get_line(chip, offset);
+		if (!line) {
+			gpiod_line_bulk_free(bulk);
+			return NULL;
+		}
 
-	gpiod_foreach_line(iter, line)
 		gpiod_line_bulk_add_line(bulk, line);
-
-	gpiod_line_iter_free(iter);
+	}
 
 	return bulk;
 }
@@ -149,24 +148,21 @@ struct gpiod_line_bulk *gpiod_chip_get_all_lines(struct gpiod_chip *chip)
 struct gpiod_line *
 gpiod_chip_find_line(struct gpiod_chip *chip, const char *name)
 {
-	struct gpiod_line_iter *iter;
 	struct gpiod_line *line;
+	unsigned int offset;
 	const char *tmp;
 
-	iter = gpiod_line_iter_new(chip);
-	if (!iter)
-		return NULL;
+	for (offset = 0; offset < gpiod_chip_num_lines(chip); offset++) {
+		line = gpiod_chip_get_line(chip, offset);
+		if (!line)
+			return NULL;
 
-	gpiod_foreach_line(iter, line) {
 		tmp = gpiod_line_name(line);
-		if (tmp && strcmp(tmp, name) == 0) {
-			gpiod_line_iter_free(iter);
+		if (tmp && strcmp(tmp, name) == 0)
 			return line;
-		}
 	}
 
 	errno = ENOENT;
-	gpiod_line_iter_free(iter);
 
 	return NULL;
 }
diff --git a/lib/iter.c b/lib/iter.c
index bfd2852..2ff767c 100644
--- a/lib/iter.c
+++ b/lib/iter.c
@@ -17,12 +17,6 @@ struct gpiod_chip_iter {
 	unsigned int offset;
 };
 
-struct gpiod_line_iter {
-	struct gpiod_line **lines;
-	unsigned int num_lines;
-	unsigned int offset;
-};
-
 static int dir_filter(const struct dirent *dir)
 {
 	return !strncmp(dir->d_name, "gpiochip", 8);
@@ -127,45 +121,3 @@ struct gpiod_chip *gpiod_chip_iter_next_noclose(struct gpiod_chip_iter *iter)
 	return iter->offset < (iter->num_chips)
 					? iter->chips[iter->offset++] : NULL;
 }
-
-struct gpiod_line_iter *gpiod_line_iter_new(struct gpiod_chip *chip)
-{
-	struct gpiod_line_iter *iter;
-	unsigned int i;
-
-	iter = malloc(sizeof(*iter));
-	if (!iter)
-		return NULL;
-
-	iter->num_lines = gpiod_chip_num_lines(chip);
-	iter->offset = 0;
-
-	iter->lines = calloc(iter->num_lines, sizeof(*iter->lines));
-	if (!iter->lines) {
-		free(iter);
-		return NULL;
-	}
-
-	for (i = 0; i < iter->num_lines; i++) {
-		iter->lines[i] = gpiod_chip_get_line(chip, i);
-		if (!iter->lines[i]) {
-			free(iter->lines);
-			free(iter);
-			return NULL;
-		}
-	}
-
-	return iter;
-}
-
-void gpiod_line_iter_free(struct gpiod_line_iter *iter)
-{
-	free(iter->lines);
-	free(iter);
-}
-
-struct gpiod_line *gpiod_line_iter_next(struct gpiod_line_iter *iter)
-{
-	return iter->offset < (iter->num_lines)
-					? iter->lines[iter->offset++] : NULL;
-}
diff --git a/tests/gpiod-test.h b/tests/gpiod-test.h
index a43109a..df9f0c7 100644
--- a/tests/gpiod-test.h
+++ b/tests/gpiod-test.h
@@ -26,12 +26,10 @@
 typedef struct gpiod_chip gpiod_chip_struct;
 typedef struct gpiod_line_bulk gpiod_line_bulk_struct;
 typedef struct gpiod_chip_iter gpiod_chip_iter_struct;
-typedef struct gpiod_line_iter gpiod_line_iter_struct;
 
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(gpiod_chip_struct, gpiod_chip_close);
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(gpiod_line_bulk_struct, gpiod_line_bulk_free);
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(gpiod_chip_iter_struct, gpiod_chip_iter_free);
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(gpiod_line_iter_struct, gpiod_line_iter_free);
 
 /* These are private definitions and should not be used directly. */
 typedef void (*_gpiod_test_func)(void);
diff --git a/tests/tests-iter.c b/tests/tests-iter.c
index 8deee8e..163a820 100644
--- a/tests/tests-iter.c
+++ b/tests/tests-iter.c
@@ -98,26 +98,3 @@ GPIOD_TEST_CASE(chip_iter_break, 0, { 8, 8, 8, 8, 8 })
 
 	g_assert_cmpuint(i, ==, 3);
 }
-
-GPIOD_TEST_CASE(line_iter, 0, { 8 })
-{
-	g_autoptr(gpiod_line_iter_struct) iter = NULL;
-	g_autoptr(gpiod_chip_struct) chip = NULL;
-	struct gpiod_line *line;
-	guint i = 0;
-
-	chip = gpiod_chip_open(gpiod_test_chip_path(0));
-	g_assert_nonnull(chip);
-	gpiod_test_return_if_failed();
-
-	iter = gpiod_line_iter_new(chip);
-	g_assert_nonnull(iter);
-	gpiod_test_return_if_failed();
-
-	gpiod_foreach_line(iter, line) {
-		g_assert_cmpuint(i, ==, gpiod_line_offset(line));
-		i++;
-	}
-
-	g_assert_cmpuint(i, ==, 8);
-}
diff --git a/tools/gpioinfo.c b/tools/gpioinfo.c
index 67be379..dd4a388 100644
--- a/tools/gpioinfo.c
+++ b/tools/gpioinfo.c
@@ -116,22 +116,20 @@ static PRINTF(3, 4) void prinfo(bool *of,
 
 static void list_lines(struct gpiod_chip *chip)
 {
-	struct gpiod_line_iter *iter;
 	int direction, active_state;
 	const char *name, *consumer;
 	struct gpiod_line *line;
 	unsigned int i, offset;
 	bool flag_printed, of;
 
-	iter = gpiod_line_iter_new(chip);
-	if (!iter)
-		die_perror("error creating line iterator");
-
 	printf("%s - %u lines:\n",
 	       gpiod_chip_name(chip), gpiod_chip_num_lines(chip));
 
-	gpiod_foreach_line(iter, line) {
-		offset = gpiod_line_offset(line);
+	for (offset = 0; offset < gpiod_chip_num_lines(chip); offset++) {
+		line = gpiod_chip_get_line(chip, offset);
+		if (!line)
+			die_perror("unable to retrieve the line object from chip");
+
 		name = gpiod_line_name(line);
 		consumer = gpiod_line_consumer(line);
 		direction = gpiod_line_direction(line);
@@ -178,8 +176,6 @@ static void list_lines(struct gpiod_chip *chip)
 
 		printf("\n");
 	}
-
-	gpiod_line_iter_free(iter);
 }
 
 int main(int argc, char **argv)
-- 
2.29.1


  parent reply	other threads:[~2020-12-10 13:24 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-12-10 13:23 [libgpiod][PATCH 00/14] treewide: start shaving off cruft for v2.0 Bartosz Golaszewski
2020-12-10 13:23 ` [libgpiod][PATCH 01/14] bindings: cxx: check for error from gpiod_line_bulk_new() Bartosz Golaszewski
2020-12-10 13:23 ` [libgpiod][PATCH 02/14] build: drop the message about tests having been built successfully Bartosz Golaszewski
2020-12-10 13:23 ` [libgpiod][PATCH 03/14] core: export gpiod_is_gpiochip_device() Bartosz Golaszewski
2020-12-10 13:23 ` [libgpiod][PATCH 04/14] bulk: drop the limit on the max number of lines Bartosz Golaszewski
2020-12-10 13:23 ` Bartosz Golaszewski [this message]
2020-12-10 13:23 ` [libgpiod][PATCH 06/14] treewide: kill opening chips by label Bartosz Golaszewski
2020-12-10 13:23 ` [libgpiod][PATCH 07/14] API: move gpiod_line_get_chip() to line attributes section Bartosz Golaszewski
2020-12-10 13:23 ` [libgpiod][PATCH 08/14] core: kill gpiod_line_close_chip() Bartosz Golaszewski
2020-12-10 13:23 ` [libgpiod][PATCH 09/14] core: kill gpiod_line_get() Bartosz Golaszewski
2020-12-10 13:23 ` [libgpiod][PATCH 10/14] treewide: kill global line lookup Bartosz Golaszewski
2020-12-10 13:23 ` [libgpiod][PATCH 11/14] treewide: kill find_lines() Bartosz Golaszewski
2020-12-10 13:23 ` [libgpiod][PATCH 12/14] core: rework gpiod_chip_find_line() Bartosz Golaszewski
2020-12-10 13:23 ` [libgpiod][PATCH 13/14] build: add a configure switch for building examples Bartosz Golaszewski
2020-12-10 13:23 ` [libgpiod][PATCH 14/14] core: kill chip iterators Bartosz Golaszewski
2020-12-10 13:56 ` [libgpiod][PATCH 00/14] treewide: start shaving off cruft for v2.0 Andy Shevchenko
2020-12-11  8:38   ` Bartosz Golaszewski
2020-12-11 14:31     ` Andy Shevchenko
2020-12-11 14:33       ` Bartosz Golaszewski
2020-12-11 14:58         ` Andy Shevchenko
2020-12-11 15:06           ` Bartosz Golaszewski
2020-12-14 15:02   ` Bartosz Golaszewski

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=20201210132315.5785-6-brgl@bgdev.pl \
    --to=brgl@bgdev.pl \
    --cc=andriy.shevchenko@linux.intel.com \
    --cc=bgolaszewski@baylibre.com \
    --cc=geert@linux-m68k.org \
    --cc=helmut.grohne@intenta.de \
    --cc=linus.walleij@linaro.org \
    --cc=linux-gpio@vger.kernel.org \
    --cc=sunt.un.morcov@gmail.com \
    --cc=warthog618@gmail.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.