iterators: improve error handling of line iterators
authorBartosz Golaszewski <bartekgola@gmail.com>
Wed, 11 Jan 2017 10:34:14 +0000 (11:34 +0100)
committerBartosz Golaszewski <bartekgola@gmail.com>
Wed, 11 Jan 2017 10:34:14 +0000 (11:34 +0100)
As was done for chip iterators: extend the API to include functions
that allow to check if an error occured while iterating over lines
and use them in the foreach macro and in gpioinfo.

Signed-off-by: Bartosz Golaszewski <bartekgola@gmail.com>
gpiod.h
gpioinfo.c

diff --git a/gpiod.h b/gpiod.h
index 4d2e7bc9953cc7face0a63ba70e4a388612a7c6b..d8e9789f963c5832cc1832e35925286adffd6a58 100644 (file)
--- a/gpiod.h
+++ b/gpiod.h
@@ -736,6 +736,18 @@ bool gpiod_chip_iter_iserr(struct gpiod_chip_iter *iter) GPIOD_API;
 const char *
 gpiod_chip_iter_failed_chip(struct gpiod_chip_iter *iter) GPIOD_API;
 
+/**
+ * @brief Possible states of a line iterator.
+ */
+enum {
+       GPIOD_LINE_ITER_INIT = 0,
+       /**< Line iterator is initiated or iterating over lines. */
+       GPIOD_LINE_ITER_DONE,
+       /**< Line iterator is done with all lines on this chip. */
+       GPIOD_LINE_ITER_ERR,
+       /**< There was an error retrieving info for a line. */
+};
+
 /**
  * @brief GPIO line iterator structure.
  *
@@ -747,13 +759,20 @@ struct gpiod_line_iter {
        /**< Current line offset. */
        struct gpiod_chip *chip;
        /**< GPIO chip whose line we're iterating over. */
+       int state;
+       /**< Current state of the iterator. */
 };
 
 /**
  * @brief Static initializer for line iterators.
  * @param chip The gpiochip object whose lines we want to iterate over.
  */
-#define GPIOD_LINE_ITER_INITIALIZER(chip)      { 0, (chip) }
+#define GPIOD_LINE_ITER_INITIALIZER(chip)                              \
+       {                                                               \
+               .offset = 0,                                            \
+               .chip = (chip),                                         \
+               state = GPIOD_LINE_ITER_INIT,                           \
+       }
 
 /**
  * @brief Initialize a GPIO line iterator.
@@ -765,6 +784,7 @@ static inline void gpiod_line_iter_init(struct gpiod_line_iter *iter,
 {
        iter->offset = 0;
        iter->chip = chip;
+       iter->state = GPIOD_LINE_ITER_INIT;
 }
 
 /**
@@ -776,10 +796,53 @@ static inline void gpiod_line_iter_init(struct gpiod_line_iter *iter,
 static inline struct gpiod_line *
 gpiod_line_iter_next(struct gpiod_line_iter *iter)
 {
-       if (iter->offset >= gpiod_chip_num_lines(iter->chip))
+       struct gpiod_line *line;
+
+       if (iter->offset >= gpiod_chip_num_lines(iter->chip)) {
+               iter->state = GPIOD_LINE_ITER_DONE;
                return NULL;
+       }
+
+       iter->state = GPIOD_LINE_ITER_INIT;
+       line = gpiod_chip_get_line(iter->chip, iter->offset++);
+       if (!line)
+               iter->state = GPIOD_LINE_ITER_ERR;
+
+       return line;
+}
+
+/**
+ * @brief Check if we're done iterating over lines on this iterator.
+ * @param iter The GPIO line iterator object.
+ * @return True if we've iterated over all lines, false otherwise.
+ */
+static inline bool gpiod_line_iter_done(const struct gpiod_line_iter *iter)
+{
+       return iter->state == GPIOD_LINE_ITER_DONE;
+}
 
-       return gpiod_chip_get_line(iter->chip, iter->offset++);
+/**
+ * @brief Check if we've encountered an error condition while retrieving
+ *        info for a line.
+ * @param iter The GPIO line iterator object.
+ * @return True if there was an error retrieving info about a GPIO line,
+ *         false otherwise.
+ */
+static inline bool gpiod_line_iter_err(const struct gpiod_line_iter *iter)
+{
+       return iter->state == GPIOD_LINE_ITER_ERR;
+}
+
+/**
+ * @brief Get the offset of the last line we tried to open.
+ * @param iter The GPIO line iterator object.
+ * @return The offset of the last line we tried to open - whether we failed
+ *         or succeeded to do so.
+ */
+static inline unsigned int
+gpiod_line_iter_last_offset(const struct gpiod_line_iter *iter)
+{
+       return iter->offset - 1;
 }
 
 /**
@@ -790,7 +853,7 @@ gpiod_line_iter_next(struct gpiod_line_iter *iter)
  */
 #define gpiod_foreach_line(iter, line)                                 \
        for ((line) = gpiod_line_iter_next(iter);                       \
-            (line);                                                    \
+            !gpiod_line_iter_done(iter);                               \
             (line) = gpiod_line_iter_next(iter))
 
 /**
index b403a966170cfb3861e8c4dde93c9604cbe10af8..2d88e62bf7700b1cd46acb7b77bf0c905479ba24 100644 (file)
@@ -100,6 +100,10 @@ static void list_lines(struct gpiod_chip *chip)
 
        gpiod_line_iter_init(&iter, chip);
        gpiod_foreach_line(&iter, line) {
+               if (gpiod_line_iter_err(&iter))
+                       die_perror("error retrieving info for line %u",
+                                  gpiod_line_iter_last_offset(&iter));
+
                offset = gpiod_line_offset(line);
                name = gpiod_line_name(line);
                consumer = gpiod_line_consumer(line);