/src/readstat/src/readstat_convert.c
Line | Count | Source |
1 | | |
2 | | #include <errno.h> |
3 | | #include "readstat.h" |
4 | | #include "readstat_iconv.h" |
5 | | #include "readstat_convert.h" |
6 | | |
7 | 10.4M | readstat_error_t readstat_convert(char *dst, size_t dst_len, const char *src, size_t src_len, iconv_t converter) { |
8 | | /* strip off spaces from the input because the programs use ASCII space |
9 | | * padding even with non-ASCII encoding. */ |
10 | 36.8M | while (src_len && (src[src_len-1] == ' ' || src[src_len-1] == '\0')) { |
11 | 26.3M | src_len--; |
12 | 26.3M | } |
13 | 10.4M | if (dst_len == 0) { |
14 | 0 | return READSTAT_ERROR_CONVERT_LONG_STRING; |
15 | 10.4M | } else if (converter) { |
16 | 1.64M | size_t dst_left = dst_len - 1; |
17 | 1.64M | char *dst_end = dst; |
18 | 1.64M | size_t status = iconv(converter, (readstat_iconv_inbuf_t)&src, &src_len, &dst_end, &dst_left); |
19 | 1.64M | if (status == (size_t)-1) { |
20 | 3.47k | if (errno == E2BIG) { |
21 | 7 | return READSTAT_ERROR_CONVERT_LONG_STRING; |
22 | 3.46k | } else if (errno == EILSEQ) { |
23 | 1.98k | return READSTAT_ERROR_CONVERT_BAD_STRING; |
24 | 1.98k | } else if (errno != EINVAL) { /* EINVAL indicates improper truncation; accept it */ |
25 | 0 | return READSTAT_ERROR_CONVERT; |
26 | 0 | } |
27 | 3.47k | } |
28 | 1.64M | dst[dst_len - dst_left - 1] = '\0'; |
29 | 8.84M | } else if (src_len + 1 > dst_len) { |
30 | 85 | return READSTAT_ERROR_CONVERT_LONG_STRING; |
31 | 8.84M | } else { |
32 | 8.84M | memcpy(dst, src, src_len); |
33 | 8.84M | dst[src_len] = '\0'; |
34 | 8.84M | } |
35 | 10.4M | return READSTAT_OK; |
36 | 10.4M | } |