xref: /aosp_15_r20/external/coreboot/util/cbfstool/flashmap/kv_pair.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
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