]> jfr.im git - solanum.git/blame - src/capability.c
Migrate capability negotiation code to new dynamic capability management API.
[solanum.git] / src / capability.c
CommitLineData
64b56afd
AC
1/*
2 * Copyright (c) 2012 William Pitcock <nenolod@dereferenced.org>.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice is present in all copies.
7 *
8 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
9 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
11 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
12 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
13 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
14 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
15 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
16 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
17 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
18 * POSSIBILITY OF SUCH DAMAGE.
19 */
20
21#include "stdinc.h"
22#include "capability.h"
23#include "irc_dictionary.h"
24
25struct CapabilityIndex {
26 struct Dictionary *cap_dict;
27 unsigned int highest_bit;
28};
29
30struct CapabilityEntry {
31 unsigned int orphaned;
32 unsigned int value;
33};
34
35unsigned int
36capability_get(struct CapabilityIndex *index, const char *cap)
37{
38 struct CapabilityEntry *entry;
39
40 s_assert(index != NULL);
41
42 entry = irc_dictionary_retrieve(index->cap_dict, cap);
43 if (entry != NULL && !entry->orphaned)
44 return entry->value;
45
46 return 0xFFFFFFFF;
47}
48
49unsigned int
50capability_put(struct CapabilityIndex *index, const char *cap)
51{
52 struct CapabilityEntry *entry;
53
54 s_assert(index != NULL);
55
56 if ((entry = irc_dictionary_retrieve(index->cap_dict, cap)) != NULL)
57 {
58 entry->orphaned = 0;
59 return entry->value;
60 }
61
62 entry = rb_malloc(sizeof(struct CapabilityEntry));
63 entry->orphaned = 0;
64 entry->value = index->highest_bit;
65
66 irc_dictionary_add(index->cap_dict, cap, entry);
67
68 index->highest_bit <<= 1;
69
70 /* hmm... not sure what to do here, so i guess we will abort for now... --nenolod */
71 if (index->highest_bit == 0)
72 abort();
73
74 return entry->value;
75}
76
77void
78capability_orphan(struct CapabilityIndex *index, const char *cap)
79{
80 struct CapabilityEntry *entry;
81
82 s_assert(index != NULL);
83
84 entry = irc_dictionary_retrieve(index->cap_dict, cap);
85 if (entry != NULL)
86 entry->orphaned = 1;
87}
88
89static void
90capability_destroy(struct DictionaryElement *delem, void *privdata)
91{
92 s_assert(delem != NULL);
93
94 rb_free(delem->data);
95}
96
97struct CapabilityIndex *
98capability_index_create(void)
99{
100 struct CapabilityIndex *index;
101
102 index = rb_malloc(sizeof(struct CapabilityIndex));
103 index->cap_dict = irc_dictionary_create(strcasecmp);
104 index->highest_bit = 1;
105
106 return index;
107}
108
109void
110capability_index_destroy(struct CapabilityIndex *index)
111{
112 s_assert(index != NULL);
113
114 irc_dictionary_destroy(index->cap_dict, capability_destroy, NULL);
115 rb_free(index);
116}
5e773521
AC
117
118const char *
119capability_index_list(struct CapabilityIndex *index, unsigned int cap_mask)
120{
121 struct DictionaryIter iter;
122 struct CapabilityEntry *entry;
123 static char buf[BUFSIZE];
124 char *t = buf;
125 int tl;
126
127 s_assert(index != NULL);
128
129 *t = '\0';
130
131 DICTIONARY_FOREACH(entry, &iter, index->cap_dict)
132 {
133 if (entry->value & cap_mask)
134 {
135 tl = rb_sprintf(t, "%s ", iter.cur->key);
136 t += tl;
137 }
138 }
139
140 t--;
141 *t = '\0';
142
143 return buf;
144}
ec3a9055
AC
145
146unsigned int
147capability_index_mask(struct CapabilityIndex *index)
148{
149 struct DictionaryIter iter;
150 struct CapabilityEntry *entry;
151 unsigned int mask = 0;
152
153 s_assert(index != NULL);
154
155 DICTIONARY_FOREACH(entry, &iter, index->cap_dict)
156 {
157 if (!entry->orphaned)
158 mask |= entry->value;
159 }
160
161 return mask;
162}