Skip to content

Commit f1083cc

Browse files
committed
feat(implode): add implode implementation ✨
1 parent e33ec9c commit f1083cc

File tree

7 files changed

+140
-1
lines changed

7 files changed

+140
-1
lines changed

demo/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ list(APPEND _ALL_DEMO
88
words_count
99
parse_int
1010
index_of
11-
explode)
11+
explode
12+
implode
13+
)
1214

1315
foreach (d ${_ALL_DEMO})
1416

demo/implode.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#include <explode.h>
2+
#include <implode.h>
3+
#include <stdio.h>
4+
5+
int main() {
6+
explode_s list = explode_make("hello world hello C", ' ');
7+
8+
const char *value = implode_make((const char **)list.values, "<=>");
9+
10+
printf("output: %s\n", value);
11+
12+
implode_clean((char *)value);
13+
14+
explode_clean(&list);
15+
}

src/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ add_library(${PROJECT_NAME}
4545
include/explode.h
4646
explode.c
4747

48+
include/implode.h
49+
implode.c
50+
4851
include/concat.h
4952
concat.c)
5053

src/implode.c

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#include "include/implode.h"
2+
#include <stdio.h>
3+
#include <stdlib.h>
4+
5+
typedef struct {
6+
size_t size;
7+
char *data;
8+
const char **list;
9+
} state;
10+
11+
size_t _len(const char *input) {
12+
size_t i = 0;
13+
while (input[i] != '\0') {
14+
i++;
15+
}
16+
return i;
17+
}
18+
19+
void _copy(char *dist, const char *source, size_t len) {
20+
for (int i = 0; i < len; i++) {
21+
dist[i] = source[i];
22+
}
23+
}
24+
25+
char *implode_make(const char **list, const char *separator) {
26+
if (list == NULL) {
27+
return NULL;
28+
}
29+
30+
state s = {
31+
.list = list,
32+
.size = 0,
33+
.data = NULL,
34+
};
35+
36+
const char **pointer = list;
37+
38+
const char hasSep = separator != NULL;
39+
40+
size_t sepLen = hasSep ? _len(separator) : 0;
41+
42+
char *out = NULL;
43+
size_t i = 0;
44+
45+
while (s.list[i] != NULL) {
46+
size_t itemLength = _len(s.list[i]);
47+
size_t newSize = itemLength + sepLen;
48+
out = realloc(out, s.size + newSize);
49+
_copy(out + s.size, s.list[i], itemLength);
50+
if (hasSep)
51+
_copy(out + s.size + itemLength, separator, sepLen);
52+
s.size += newSize;
53+
i++;
54+
}
55+
56+
if (hasSep)
57+
out[s.size - sepLen] = 0;
58+
59+
return out;
60+
}
61+
62+
void implode_clean(const char *value) { free(value); }

src/include/implode.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#ifndef INDEX_OF_H
2+
#define INDEX_OF_H
3+
4+
#include "common.h"
5+
6+
BEGIN_DECL
7+
8+
char *implode_make(const char **list, const char *separator);
9+
void implode_clean(const char *value);
10+
11+
END_DECL
12+
13+
#endif // INDEX_OF_H

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ target_sources(${PROJECT_NAME} PRIVATE
2626
start_with.test.cpp
2727
end_with.test.cpp
2828
explode.test.cpp
29+
implode.test.cpp
2930
concat.test.cpp
3031
)
3132

tests/implode.test.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#include <catch2/catch.hpp>
2+
#include <implode.h>
3+
4+
TEST_CASE("implode_make") {
5+
SECTION("can implode_make an array to a string #1") {
6+
const char *input[] = {"abc", "def", NULL};
7+
const char *r = implode_make(input, ",");
8+
REQUIRE(r != NULL);
9+
REQUIRE_THAT(r, Catch::Matchers::Equals("abc,def"));
10+
implode_clean(r);
11+
}
12+
13+
SECTION("can implode_make an array to a string with different length") {
14+
const char *input[] = {"1234", "12", "1", "12345", NULL};
15+
const char *r = implode_make(input, ",");
16+
REQUIRE(r != NULL);
17+
REQUIRE_THAT(r, Catch::Matchers::Equals("1234,12,1,12345"));
18+
implode_clean(r);
19+
}
20+
21+
SECTION("can implode_make an array to a string with separator that has "
22+
"multiple chars") {
23+
const char *input[] = {"1234", "12", "1", "12345", NULL};
24+
const char *r = implode_make(input, "|===| ");
25+
REQUIRE(r != NULL);
26+
REQUIRE_THAT(r, Catch::Matchers::Equals("1234|===| 12|===| 1|===| 12345"));
27+
implode_clean(r);
28+
}
29+
30+
SECTION("can implode_make to a string with no seperator") {
31+
const char *input[] = {"1234", "12", "1", "12345", NULL};
32+
const char *r = implode_make(input, NULL);
33+
REQUIRE(r != NULL);
34+
REQUIRE_THAT(r, Catch::Matchers::Equals("123412112345"));
35+
implode_clean(r);
36+
}
37+
38+
SECTION("returns NULL when input is NULLL") {
39+
const char *r = implode_make(NULL, ",");
40+
REQUIRE(r == NULL);
41+
implode_clean(r);
42+
}
43+
}

0 commit comments

Comments
 (0)