-
Notifications
You must be signed in to change notification settings - Fork 42
/
Copy pathcollapse_object.c
53 lines (44 loc) · 1.29 KB
/
collapse_object.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <Rdefines.h>
#include <Rinternals.h>
#include <stdlib.h>
SEXP C_collapse_object(SEXP x, SEXP y) {
if (!isString(x) || !isString(y))
error("x and y must character vectors.");
int len = length(x);
if (len != length(y))
error("x and y must same length.");
size_t nchar_total = 0;
for (int i=0; i<len; i++) {
if(STRING_ELT(y, i) == NA_STRING) continue;
nchar_total += strlen(translateCharUTF8(STRING_ELT(x, i)));
nchar_total += strlen(translateCharUTF8(STRING_ELT(y, i)));
nchar_total += 2;
}
char *s = malloc(nchar_total + 3); //if len is 0, we need at least: '{}\0'
char *olds = s;
size_t size;
for (int i=0; i<len; i++) {
if(STRING_ELT(y, i) == NA_STRING) continue;
s[0] = ',';
//add x
size = strlen(translateCharUTF8(STRING_ELT(x, i)));
memcpy(++s, translateCharUTF8(STRING_ELT(x, i)), size);
s += size;
//add :
s[0] = ':';
//add y
size = strlen(translateCharUTF8(STRING_ELT(y, i)));
memcpy(++s, translateCharUTF8(STRING_ELT(y, i)), size);
s += size;
}
if(olds == s) s++;
olds[0] = '{';
s[0] = '}';
s[1] = '\0';
//get character encoding from first element
SEXP out = PROTECT(allocVector(STRSXP, 1));
SET_STRING_ELT(out, 0, mkCharCE(olds, CE_UTF8));
UNPROTECT(1);
free(olds);
return out;
}