Change trailer API to return a simple array
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
diff --git a/include/git2/message.h b/include/git2/message.h
index a74dcc2..e3c9fe7 100644
--- a/include/git2/message.h
+++ b/include/git2/message.h
@@ -38,7 +38,18 @@ GIT_BEGIN_DECL
*/
GIT_EXTERN(int) git_message_prettify(git_buf *out, const char *message, int strip_comments, char comment_char);
-typedef int(*git_message_trailer_cb)(const char *key, const char *value, void *payload);
+typedef struct {
+ const char *key;
+ const char *value;
+} git_message_trailer;
+
+typedef struct {
+ git_message_trailer *trailers;
+ size_t count;
+
+ /* private */
+ char *_trailer_block;
+} git_message_trailer_array;
/**
* Parse trailers out of a message, calling a callback once for each trailer.
@@ -48,15 +59,14 @@ typedef int(*git_message_trailer_cb)(const char *key, const char *value, void *p
* Trailers are key/value pairs in the last paragraph of a message, not
* including any patches or conflicts that may be present.
*
+ * @param arr A pre-allocated git_message_trailer_array struct to be filled in
+ * with any trailers found during parsing.
* @param message The message to be parsed
- * @param cb The callback to call for each trailer found in the message. The
- * key and value arguments are pointers to NUL-terminated C strings. These
- * pointers are only guaranteed to be valid until the callback returns.
- * User code must make a copy of this data should it need to be retained
- * @param payload Pointer to callback data (optional)
* @return 0 on success, or non-zero callback return value.
*/
-GIT_EXTERN(int) git_message_trailers(const char *message, git_message_trailer_cb cb, void *payload);
+GIT_EXTERN(int) git_message_trailers(git_message_trailer_array *arr, const char *message);
+
+GIT_EXTERN(void) git_message_trailer_array_free(git_message_trailer_array *arr);
/** @} */
GIT_END_DECL
diff --git a/src/trailer.c b/src/trailer.c
index cfefc53..79db9a4 100644
--- a/src/trailer.c
+++ b/src/trailer.c
@@ -4,6 +4,7 @@
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
+#include "array.h"
#include "common.h"
#include "git2/message.h"
@@ -279,13 +280,16 @@ enum trailer_state {
#define NEXT(st) { state = (st); ptr++; continue; }
#define GOTO(st) { state = (st); continue; }
-int git_message_trailers(const char *message, git_message_trailer_cb cb, void *payload)
+typedef git_array_t(git_message_trailer) git_array_trailer_t;
+
+int git_message_trailers(git_message_trailer_array *trailer_arr, const char *message)
{
enum trailer_state state = S_START;
int rc = 0;
char *ptr;
char *key = NULL;
char *value = NULL;
+ git_array_trailer_t arr = GIT_ARRAY_INIT;
size_t trailer_len;
char *trailer = find_trailer(message, &trailer_len);
@@ -373,9 +377,10 @@ int git_message_trailers(const char *message, git_message_trailer_cb cb, void *p
GOTO(S_VALUE_END);
}
case S_VALUE_END: {
- if ((rc = cb(key, value, payload))) {
- goto ret;
- }
+ git_message_trailer *t = git_array_alloc(arr);
+
+ t->key = key;
+ t->value = value;
key = NULL;
value = NULL;
@@ -397,6 +402,15 @@ int git_message_trailers(const char *message, git_message_trailer_cb cb, void *p
}
ret:
- git__free(trailer);
+ trailer_arr->_trailer_block = trailer;
+ trailer_arr->trailers = arr.ptr;
+ trailer_arr->count = arr.size;
+
return rc;
}
+
+void git_message_trailer_array_free(git_message_trailer_array *arr)
+{
+ git__free(arr->_trailer_block);
+ git__free(arr->trailers);
+}
diff --git a/tests/message/trailer.c b/tests/message/trailer.c
index 83fc778..77ad710 100644
--- a/tests/message/trailer.c
+++ b/tests/message/trailer.c
@@ -6,32 +6,22 @@ struct trailer {
const char *value;
};
-struct cb_state {
- struct trailer *trailer;
-};
-
-static int trailer_cb(const char *key, const char *value, void *st_)
-{
- struct cb_state *st = st_;
-
- cl_assert_equal_s(st->trailer->key, key);
- cl_assert_equal_s(st->trailer->value, value);
-
- st->trailer++;
-
- return 0;
-}
-
static void assert_trailers(const char *message, struct trailer *trailers)
{
- struct cb_state st = { trailers };
+ git_message_trailer_array arr;
- int rc = git_message_trailers(message, trailer_cb, &st);
+ int rc = git_message_trailers(&arr, message);
- cl_assert_equal_s(NULL, st.trailer->key);
- cl_assert_equal_s(NULL, st.trailer->value);
+ cl_assert_equal_i(0, rc);
+
+ for(size_t i=0; i<arr.count; i++) {
+ cl_assert_equal_s(arr.trailers[i].key, trailers[i].key);
+ cl_assert_equal_s(arr.trailers[i].value, trailers[i].value);
+ }
cl_assert_equal_i(0, rc);
+
+ git_message_trailer_array_free(&arr);
}
void test_message_trailer__simple(void)