1 Return-Path: <bremner@tethera.net>
\r
2 X-Original-To: notmuch@notmuchmail.org
\r
3 Delivered-To: notmuch@notmuchmail.org
\r
4 Received: from localhost (localhost [127.0.0.1])
\r
5 by arlo.cworth.org (Postfix) with ESMTP id 9A09E6DE01D0
\r
6 for <notmuch@notmuchmail.org>; Mon, 30 May 2016 04:50:20 -0700 (PDT)
\r
7 X-Virus-Scanned: Debian amavisd-new at cworth.org
\r
11 X-Spam-Status: No, score=-0.012 tagged_above=-999 required=5
\r
12 tests=[AWL=-0.001, SPF_PASS=-0.001, T_RP_MATCHES_RCVD=-0.01]
\r
14 Received: from arlo.cworth.org ([127.0.0.1])
\r
15 by localhost (arlo.cworth.org [127.0.0.1]) (amavisd-new, port 10024)
\r
16 with ESMTP id 3L7Li1OgWIgs for <notmuch@notmuchmail.org>;
\r
17 Mon, 30 May 2016 04:50:11 -0700 (PDT)
\r
18 Received: from fethera.tethera.net (fethera.tethera.net [198.245.60.197])
\r
19 by arlo.cworth.org (Postfix) with ESMTPS id 842D16DE0261
\r
20 for <notmuch@notmuchmail.org>; Mon, 30 May 2016 04:50:11 -0700 (PDT)
\r
21 Received: from remotemail by fethera.tethera.net with local (Exim 4.84)
\r
22 (envelope-from <bremner@tethera.net>)
\r
23 id 1b7Lhn-0000Oz-VM; Mon, 30 May 2016 07:50:00 -0400
\r
24 Received: (nullmailer pid 14850 invoked by uid 1000);
\r
25 Mon, 30 May 2016 11:50:06 -0000
\r
26 From: David Bremner <david@tethera.net>
\r
27 To: notmuch@notmuchmail.org
\r
28 Subject: [RFC2 Patch 2/5] lib: private string map (associative array) API
\r
29 Date: Mon, 30 May 2016 08:49:56 -0300
\r
30 Message-Id: <1464608999-14774-3-git-send-email-david@tethera.net>
\r
31 X-Mailer: git-send-email 2.8.1
\r
32 In-Reply-To: <1464608999-14774-1-git-send-email-david@tethera.net>
\r
33 References: <1463927339-5441-1-git-send-email-david@tethera.net>
\r
34 <1464608999-14774-1-git-send-email-david@tethera.net>
\r
36 Content-Type: text/plain; charset=UTF-8
\r
37 Content-Transfer-Encoding: 8bit
\r
38 X-BeenThere: notmuch@notmuchmail.org
\r
39 X-Mailman-Version: 2.1.20
\r
41 List-Id: "Use and development of the notmuch mail system."
\r
42 <notmuch.notmuchmail.org>
\r
43 List-Unsubscribe: <https://notmuchmail.org/mailman/options/notmuch>,
\r
44 <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>
\r
45 List-Archive: <http://notmuchmail.org/pipermail/notmuch/>
\r
46 List-Post: <mailto:notmuch@notmuchmail.org>
\r
47 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>
\r
48 List-Subscribe: <https://notmuchmail.org/mailman/listinfo/notmuch>,
\r
49 <mailto:notmuch-request@notmuchmail.org?subject=subscribe>
\r
50 X-List-Received-Date: Mon, 30 May 2016 11:50:20 -0000
\r
52 The choice of array implementation is deliberate, for future iterator support
\r
54 lib/Makefile.local | 1 +
\r
55 lib/notmuch-private.h | 11 ++++
\r
56 lib/string-map.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++++++
\r
57 3 files changed, 165 insertions(+)
\r
58 create mode 100644 lib/string-map.c
\r
60 diff --git a/lib/Makefile.local b/lib/Makefile.local
\r
61 index beb9635..9280880 100644
\r
62 --- a/lib/Makefile.local
\r
63 +++ b/lib/Makefile.local
\r
64 @@ -40,6 +40,7 @@ libnotmuch_c_srcs = \
\r
67 $(dir)/built-with.c \
\r
68 + $(dir)/string-map.c \
\r
71 libnotmuch_cxx_srcs = \
\r
72 diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h
\r
73 index 6f9af91..531b82f 100644
\r
74 --- a/lib/notmuch-private.h
\r
75 +++ b/lib/notmuch-private.h
\r
76 @@ -540,6 +540,17 @@ _notmuch_string_list_sort (notmuch_string_list_t *list);
\r
78 typedef struct _notmuch_string_map notmuch_string_map_t;
\r
80 +notmuch_string_map_t *
\r
81 +_notmuch_string_map_create (const void *ctx);
\r
84 +_notmuch_string_map_append (notmuch_string_map_t *map,
\r
86 + const char *value);
\r
89 +_notmuch_string_map_get (notmuch_string_map_t *map, const char *key);
\r
94 diff --git a/lib/string-map.c b/lib/string-map.c
\r
95 new file mode 100644
\r
96 index 0000000..0491a10
\r
98 +++ b/lib/string-map.c
\r
100 +/* string-map.c - associative arrays of strings
\r
103 + * Copyright © 2016 David Bremner
\r
105 + * This program is free software: you can redistribute it and/or modify
\r
106 + * it under the terms of the GNU General Public License as published by
\r
107 + * the Free Software Foundation, either version 3 of the License, or
\r
108 + * (at your option) any later version.
\r
110 + * This program is distributed in the hope that it will be useful,
\r
111 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
112 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
113 + * GNU General Public License for more details.
\r
115 + * You should have received a copy of the GNU General Public License
\r
116 + * along with this program. If not, see http://www.gnu.org/licenses/ .
\r
118 + * Author: David Bremner <david@tethera.net>
\r
121 +#include "notmuch-private.h"
\r
123 +/* Create a new notmuch_string_map_t object, with 'ctx' as its
\r
126 + * This function can return NULL in case of out-of-memory.
\r
129 +typedef struct _notmuch_string_pair_t {
\r
132 +} notmuch_string_pair_t;
\r
134 +struct _notmuch_string_map {
\r
135 + notmuch_bool_t sorted;
\r
137 + notmuch_string_pair_t *pairs;
\r
140 +notmuch_string_map_t *
\r
141 +_notmuch_string_map_create (const void *ctx)
\r
143 + notmuch_string_map_t *map;
\r
145 + map = talloc (ctx, notmuch_string_map_t);
\r
146 + if (unlikely (map == NULL))
\r
150 + map->pairs = NULL;
\r
151 + map->sorted = TRUE;
\r
157 +_notmuch_string_map_append (notmuch_string_map_t *map,
\r
159 + const char *value)
\r
163 + map->sorted = FALSE;
\r
166 + map->pairs = talloc_realloc (map, map->pairs, notmuch_string_pair_t, map->length + 1);
\r
168 + map->pairs = talloc_array (map, notmuch_string_pair_t, map->length + 1);
\r
170 + map->pairs[map->length - 1].key = talloc_strdup (map, key);
\r
171 + map->pairs[map->length - 1].value = talloc_strdup (map, value);
\r
173 + /* Add sentinel */
\r
174 + map->pairs[map->length].key = NULL;
\r
175 + map->pairs[map->length].value = NULL;
\r
180 +cmppair (const void *pa, const void *pb)
\r
182 + notmuch_string_pair_t *a = (notmuch_string_pair_t *) pa;
\r
183 + notmuch_string_pair_t *b = (notmuch_string_pair_t *) pb;
\r
185 + return strcmp (a->key, b->key);
\r
189 +_notmuch_string_map_sort (notmuch_string_map_t *map)
\r
191 + if (map->length == 0)
\r
197 + qsort (map->pairs, map->length, sizeof (notmuch_string_pair_t), cmppair);
\r
199 + map->sorted = TRUE;
\r
202 +static notmuch_bool_t
\r
203 +string_cmp (const char *a, const char *b, notmuch_bool_t exact)
\r
206 + return (strcmp (a, b));
\r
208 + return (strncmp (a, b, strlen (a)));
\r
211 +static notmuch_string_pair_t *
\r
212 +bsearch_first (notmuch_string_pair_t *array, size_t len, const char *key, notmuch_bool_t exact)
\r
214 + size_t first = 0;
\r
215 + size_t last = len - 1;
\r
221 + while (last > first) {
\r
222 + mid = (first + last) / 2;
\r
223 + int sign = string_cmp (key, array[mid].key, exact);
\r
232 + if (string_cmp (key, array[first].key, exact) == 0)
\r
233 + return array + first;
\r
240 +_notmuch_string_map_get (notmuch_string_map_t *map, const char *key)
\r
242 + notmuch_string_pair_t *pair;
\r
244 + /* this means that calling append invalidates iterators */
\r
245 + _notmuch_string_map_sort (map);
\r
247 + pair = bsearch_first (map->pairs, map->length, key, TRUE);
\r
251 + return pair->value;
\r