Motr  M0
slist.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2013-2020 Seagate Technology LLC and/or its Affiliates
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * For any questions about this software or licensing,
18  * please email opensource@seagate.com or cortx-questions@seagate.com.
19  *
20  */
21 
22 
23 #include "lib/misc.h" /* M0_SET0 */
24 #include "lib/memory.h" /* M0_ALLOC_ARR */
25 #include "lib/errno.h" /* ENOMEM */
26 
27 #include "motr/magic.h" /* M0_NET_TEST_SLIST_MAGIC */
28 
29 #include "net/test/slist.h"
30 
38 static bool slist_alloc(struct m0_net_test_slist *slist,
39  size_t string_nr,
40  size_t arr_len)
41 {
42  M0_ALLOC_ARR(slist->ntsl_list, string_nr);
43  if (slist->ntsl_list != NULL) {
44  M0_ALLOC_ARR(slist->ntsl_str, arr_len);
45  if (slist->ntsl_str == NULL)
46  m0_free(slist->ntsl_list);
47  }
48  return slist->ntsl_list != NULL && slist->ntsl_str != NULL;
49 }
50 
51 static void slist_free(struct m0_net_test_slist *slist)
52 {
53  m0_free(slist->ntsl_list);
54  m0_free(slist->ntsl_str);
55 }
56 
58  const char *str,
59  char delim)
60 {
61  const char *str1;
62  char *str2;
63  size_t len = 0;
64  size_t i = 0;
65  bool allocated;
66 
67  M0_PRE(slist != NULL);
68  M0_PRE(str != NULL);
69  M0_PRE(delim != '\0');
70 
71  M0_SET0(slist);
72 
73  len = strlen(str);
74  if (len != 0) {
75  for (str1 = str; str1 != NULL; str1 = strchr(str1, delim)) {
76  ++str1;
77  ++slist->ntsl_nr;
78  }
79  allocated = slist_alloc(slist, slist->ntsl_nr, len + 1);
80  if (!allocated)
81  return -ENOMEM;
82 
83  strncpy(slist->ntsl_str, str, len + 1);
84  str2 = slist->ntsl_str;
85  for ( ; str2 != NULL; str2 = strchr(str2, delim)) {
86  if (str2 != slist->ntsl_str) {
87  *str2 = '\0';
88  ++str2;
89  }
90  slist->ntsl_list[i++] = str2;
91  }
92  }
94  return 0;
95 }
96 
98 {
99  size_t i;
100 
101  if (slist == NULL)
102  return false;
103  if (slist->ntsl_nr == 0)
104  return true;
105  if (slist->ntsl_list == NULL)
106  return false;
107  if (slist->ntsl_str == NULL)
108  return false;
109 
110  /* check all pointers in ntsl_list */
111  if (slist->ntsl_list[0] != slist->ntsl_str)
112  return false;
113  for (i = 1; i < slist->ntsl_nr; ++i)
114  if (slist->ntsl_list[i - 1] >= slist->ntsl_list[i] ||
115  slist->ntsl_list[i] <= slist->ntsl_str)
116  return false;
117  return true;
118 }
119 
121 {
123 
124  if (slist->ntsl_nr > 0)
125  slist_free(slist);
126  M0_SET0(slist);
127 }
128 
130 {
131  size_t i;
132  size_t j;
133 
135 
136  for (i = 0; i < slist->ntsl_nr; ++i)
137  for (j = i + 1; j < slist->ntsl_nr; ++j)
138  if (strcmp(slist->ntsl_list[i],
139  slist->ntsl_list[j]) == 0)
140  return false;
141  return true;
142 }
143 
144 struct slist_params {
145  uint64_t sp_magic;
146  size_t sp_nr;
147  size_t sp_len;
148 };
149 
151  FIELD_DESCR(struct slist_params, sp_magic),
152  FIELD_DESCR(struct slist_params, sp_nr),
153  FIELD_DESCR(struct slist_params, sp_len),
154 };
155 
157  struct m0_bufvec *bv,
159 {
160  struct slist_params sp;
161  m0_bcount_t len;
162  m0_bcount_t len_total;
163 
164  sp.sp_nr = slist->ntsl_nr;
165  sp.sp_len = slist->ntsl_nr == 0 ? 0 :
166  slist->ntsl_list[slist->ntsl_nr - 1] -
167  slist->ntsl_list[0] +
168  strlen(slist->ntsl_list[slist->ntsl_nr - 1]) + 1;
170 
173  if (len == 0 || slist->ntsl_nr == 0)
174  return len;
175  len_total = net_test_len_accumulate(0, len);
176 
178  sp.sp_len, true,
179  bv, offset + len_total);
180  len_total = net_test_len_accumulate(len_total, len);
181  return len_total;
182 }
183 
185  struct m0_bufvec *bv,
187 {
188  struct slist_params sp;
189  m0_bcount_t len;
190  m0_bcount_t len_total;
191  size_t i;
192  bool allocated;
193 
194 
197  bv, offset);
198  if (len == 0 || sp.sp_magic != M0_NET_TEST_SLIST_MAGIC)
199  return 0;
200  len_total = net_test_len_accumulate(0, len);
201 
202  M0_SET0(slist);
203  slist->ntsl_nr = sp.sp_nr;
204  /* zero-size string list */
205  if (slist->ntsl_nr == 0)
206  return len_total;
207 
208  allocated = slist_alloc(slist, sp.sp_nr, sp.sp_len + 1);
209  if (!allocated)
210  return 0;
211 
213  slist->ntsl_str, sp.sp_len, true,
214  bv, offset + len_total);
215  if (len == 0)
216  goto failed;
217  len_total = net_test_len_accumulate(len_total, len);
218 
219  slist->ntsl_list[0] = slist->ntsl_str;
220  /* additional check if received string doesn't contains '\0' */
221  slist->ntsl_str[sp.sp_len] = '\0';
222  for (i = 1; i < slist->ntsl_nr; ++i) {
223  slist->ntsl_list[i] = slist->ntsl_list[i - 1] +
224  strlen(slist->ntsl_list[i - 1]) + 1;
225  if (slist->ntsl_list[i] - slist->ntsl_list[0] >= sp.sp_len)
226  goto failed;
227  }
228 
229  return len_total;
230 failed:
231  slist_free(slist);
232  return 0;
233 }
234 
236  struct m0_net_test_slist *slist,
237  struct m0_bufvec *bv,
239 {
240  M0_PRE(slist != NULL);
242 
243  return op == M0_NET_TEST_SERIALIZE ? slist_encode(slist, bv, offset) :
244  slist_decode(slist, bv, offset);
245 }
246 
251 /*
252  * Local variables:
253  * c-indentation-style: "K&R"
254  * c-basic-offset: 8
255  * tab-width: 8
256  * fill-column: 79
257  * scroll-step: 1
258  * End:
259  */
#define M0_PRE(cond)
#define M0_ALLOC_ARR(arr, nr)
Definition: memory.h:84
#define NULL
Definition: misc.h:38
static m0_bcount_t slist_decode(struct m0_net_test_slist *slist, struct m0_bufvec *bv, m0_bcount_t offset)
Definition: slist.c:184
m0_bcount_t m0_net_test_serialize(enum m0_net_test_serialize_op op, void *obj, const struct m0_net_test_descr descr[], size_t descr_nr, struct m0_bufvec *bv, m0_bcount_t bv_offset)
Definition: serialize.c:176
size_t sp_len
Definition: slist.c:147
TYPE_DESCR(slist_params)
uint64_t m0_bcount_t
Definition: types.h:77
static m0_bcount_t net_test_len_accumulate(m0_bcount_t accumulator, m0_bcount_t addend)
Definition: serialize.h:122
#define M0_SET0(obj)
Definition: misc.h:64
int m0_net_test_slist_init(struct m0_net_test_slist *slist, const char *str, char delim)
Definition: slist.c:57
static struct m0_atomic64 allocated
Definition: memory.c:101
op
Definition: libdemo.c:64
bool m0_net_test_slist_unique(const struct m0_net_test_slist *slist)
Definition: slist.c:129
int i
Definition: dir.c:1033
static bool slist_alloc(struct m0_net_test_slist *slist, size_t string_nr, size_t arr_len)
Definition: slist.c:38
uint64_t sp_magic
Definition: slist.c:145
void m0_net_test_slist_fini(struct m0_net_test_slist *slist)
Definition: slist.c:120
size_t ntsl_nr
Definition: slist.h:49
#define FIELD_DESCR(type, field)
Definition: serialize.h:63
#define M0_POST(cond)
char * ntsl_str
Definition: slist.h:58
static m0_bindex_t offset
Definition: dump.c:173
bool m0_net_test_slist_invariant(const struct m0_net_test_slist *slist)
Definition: slist.c:97
m0_net_test_serialize_op
Definition: serialize.h:42
m0_bcount_t m0_net_test_slist_serialize(enum m0_net_test_serialize_op op, struct m0_net_test_slist *slist, struct m0_bufvec *bv, m0_bcount_t offset)
Definition: slist.c:235
static m0_bcount_t slist_encode(struct m0_net_test_slist *slist, struct m0_bufvec *bv, m0_bcount_t offset)
Definition: slist.c:156
static void slist_free(struct m0_net_test_slist *slist)
Definition: slist.c:51
void m0_free(void *data)
Definition: memory.c:146
m0_bcount_t m0_net_test_serialize_data(enum m0_net_test_serialize_op op, void *data, m0_bcount_t data_len, bool plain_data, struct m0_bufvec *bv, m0_bcount_t bv_offset)
Definition: serialize.c:163
#define USE_TYPE_DESCR(type_name)
Definition: serialize.h:57
size_t sp_nr
Definition: slist.c:146
char ** ntsl_list
Definition: slist.h:53
Definition: vec.h:145