1 /* SPDX-License-Identifier: BSD-3-Clause or GPL-2.0-only */
2
3 #include <stdlib.h>
4 #include <stdarg.h>
5
6 #include "kv_pair.h"
7
8 /* Internal variable for output style. Use accessors to get/set style. */
9 static enum kv_pair_style _style;
10
kv_pair_set_style(enum kv_pair_style style)11 void kv_pair_set_style(enum kv_pair_style style)
12 {
13 _style = style;
14 }
15
kv_pair_get_style(void)16 enum kv_pair_style kv_pair_get_style(void)
17 {
18 return _style;
19 }
20
kv_pair_new(void)21 struct kv_pair *kv_pair_new(void)
22 {
23 struct kv_pair *kv;
24
25 kv = calloc(1, sizeof(*kv));
26 if (!kv)
27 return NULL;
28
29 return kv;
30 }
31
kv_pair_add(struct kv_pair * kv_list,const char * key,const char * value)32 struct kv_pair *kv_pair_add(struct kv_pair *kv_list,
33 const char *key, const char *value)
34 {
35 struct kv_pair *kv_new;
36 struct kv_pair *kv_ptr;
37
38 kv_new = kv_pair_new();
39 if (!kv_new)
40 return NULL;
41
42 /* save key=value strings if provided */
43 if (key) {
44 kv_new->key = strdup(key);
45 if (!kv_new->key)
46 goto kv_pair_add_failed;
47 }
48 if (value) {
49 kv_new->value = strdup(value);
50 if (!kv_new->value)
51 goto kv_pair_add_failed;
52 }
53
54 /* first in the list if no list provided */
55 if (kv_list) {
56 /* find the end of list */
57 for (kv_ptr = kv_list; kv_ptr->next != NULL;
58 kv_ptr = kv_ptr->next)
59 ;
60
61 /* link in the new pair at the end */
62 kv_ptr->next = kv_new;
63 }
64
65 /* return pointer to the new pair */
66 return kv_new;
67
68 kv_pair_add_failed:
69 kv_pair_free(kv_new);
70 return NULL;
71 }
72
kv_pair_add_bool(struct kv_pair * kv_list,const char * key,int value)73 struct kv_pair *kv_pair_add_bool(struct kv_pair *kv_list,
74 const char *key, int value)
75 {
76 const char *str;
77
78 if (value) {
79 str = "yes";
80 } else {
81 str = "no";
82 }
83 return kv_pair_add(kv_list, key, str);
84 }
85
kv_pair_fmt(struct kv_pair * kv_list,const char * kv_key,const char * format,...)86 struct kv_pair *kv_pair_fmt(struct kv_pair *kv_list,
87 const char *kv_key, const char *format, ...)
88 {
89 char kv_value[KV_PAIR_MAX_VALUE_LEN];
90 va_list vptr;
91
92 memset(kv_value, 0, sizeof(kv_value));
93
94 va_start(vptr, format);
95 vsnprintf(kv_value, sizeof(kv_value), format, vptr);
96 va_end(vptr);
97
98 return kv_pair_add(kv_list, kv_key, kv_value);
99 }
100
kv_pair_free(struct kv_pair * kv_list)101 void kv_pair_free(struct kv_pair *kv_list)
102 {
103 struct kv_pair *kv_ptr = kv_list;
104 struct kv_pair *kv_next;
105
106 while (kv_ptr != NULL) {
107 /* free key/value strings */
108 if (kv_ptr->key)
109 free(kv_ptr->key);
110 if (kv_ptr->value)
111 free(kv_ptr->value);
112
113 /* free current pair move to next */
114 kv_next = kv_ptr->next;
115 free(kv_ptr);
116 kv_ptr = kv_next;
117 }
118 }
119
kv_pair_print_to_file(FILE * fp,struct kv_pair * kv_list,enum kv_pair_style style)120 void kv_pair_print_to_file(FILE* fp, struct kv_pair *kv_list,
121 enum kv_pair_style style)
122 {
123 struct kv_pair *kv_ptr;
124
125 switch (style) {
126 case KV_STYLE_PAIR:
127 for (kv_ptr = kv_list; kv_ptr != NULL; kv_ptr = kv_ptr->next) {
128 if (kv_ptr->key && kv_ptr->value) {
129 fprintf(fp, "%s=\"%s\" ",
130 kv_ptr->key, kv_ptr->value);
131 }
132 }
133 break;
134
135 case KV_STYLE_VALUE:
136 for (kv_ptr = kv_list; kv_ptr != NULL; kv_ptr = kv_ptr->next) {
137 if (kv_ptr->value) {
138 fprintf(fp, "%s", kv_ptr->value);
139 if (kv_ptr->next)
140 fprintf(fp, " | ");
141 }
142 }
143 break;
144
145 case KV_STYLE_LONG:
146 for (kv_ptr = kv_list; kv_ptr != NULL; kv_ptr = kv_ptr->next) {
147 if (kv_ptr->key && kv_ptr->value)
148 fprintf(fp, "%-20s | %s\n",
149 kv_ptr->key, kv_ptr->value);
150 }
151 break;
152 }
153
154 fprintf(fp, "\n");
155 }
156
kv_pair_print(struct kv_pair * kv_list)157 void kv_pair_print(struct kv_pair *kv_list)
158 {
159 kv_pair_print_to_file(stdout, kv_list, kv_pair_get_style());
160 }
161
kv_pair_get_value(struct kv_pair * kv_list,const char * kv_key)162 const char *kv_pair_get_value(struct kv_pair *kv_list, const char *kv_key)
163 {
164 const char *kv_value = NULL;
165 struct kv_pair *kv_ptr;
166
167 for (kv_ptr = kv_list; kv_ptr != NULL; kv_ptr = kv_ptr->next) {
168 if (kv_ptr->key && strcmp(kv_ptr->key, kv_key) == 0) {
169 kv_value = kv_ptr->value;
170 break;
171 }
172 }
173 return kv_value;
174 }
175
kv_pair_size(struct kv_pair * kv_list)176 int kv_pair_size(struct kv_pair *kv_list) {
177 struct kv_pair *kv_ptr;
178 int count;
179
180 count = 0;
181 for (kv_ptr = kv_list; kv_ptr != NULL; kv_ptr = kv_ptr->next) {
182 if (kv_ptr->key) {
183 count++;
184 }
185 }
186 return count;
187 }
188