]> pilppa.org Git - libcharencoding.git/blob - src/internal/charencoding_internal.c
libcharencoding: initial version
[libcharencoding.git] / src / internal / charencoding_internal.c
1 /**
2   * Copyright (c) 2009-2010 Mika Laitio <lamikr@pilppa.org>
3   *
4   * This file and library is covered by the LGPL version 3, read LICENSE for details.
5   *
6   * History:
7   * - Created charencoding_internal.c on: Nov 25, 2009
8   */
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <stdbool.h>
13 #include <locale.h>
14 #include <langinfo.h>
15 #include <stdarg.h>
16 #include <errno.h>
17 #include <iconv.h>
18 #include <limits.h>
19 #include <iconv.h>
20 #include <time.h>
21 #include <ctype.h>
22
23 #define SIZE_CALCULATION_TEMP_BUFFER_SIZE       8
24
25 static bool _locale_charset_initialized                 = false;
26
27 const char *get_locale_charset_alias()
28 {
29         if (_locale_charset_initialized == false) {
30                 setlocale(LC_ALL, "");
31                 _locale_charset_initialized = true;
32         }
33         return nl_langinfo(CODESET);
34 }
35
36 size_t calculate_target_charset_bytecount(iconv_t conversion_desc,
37                                         const char *src,
38                                         size_t bcount_src)
39 {
40         size_t          ret_val;
41         size_t          err_flg;
42         size_t          bcount_trgt;
43         const char      *p_src;
44         char            *p_trgt;
45         char            tmp_buf[SIZE_CALCULATION_TEMP_BUFFER_SIZE];
46
47         ret_val         = 0;
48         err_flg         = 0;
49         // reset conversion descriptor to initial state
50         iconv(conversion_desc,
51                 NULL,
52                 NULL,
53                 NULL,
54                 NULL);
55         p_src   = src;
56         while (bcount_src > 0) {
57                 p_trgt          = tmp_buf;
58                 bcount_trgt     = SIZE_CALCULATION_TEMP_BUFFER_SIZE;
59                 err_flg         = iconv(conversion_desc,
60                                         (char **)&p_src,
61                                         &bcount_src,
62                                         &p_trgt,
63                                         &bcount_trgt);
64                 if (err_flg == (size_t)(-1)) {
65                         if (errno == E2BIG) {
66                                 // too small tmp_buf error can be skipped
67                                 err_flg = 0;
68                         }
69                         else {
70                                 err_flg = -1;
71                                 break;
72                         }
73                 }
74                 ret_val = ret_val + SIZE_CALCULATION_TEMP_BUFFER_SIZE - bcount_trgt;
75         }
76         if (err_flg != 0) {
77                 ret_val =-1;
78         }
79         printf("size: %d\n", ret_val);
80         return ret_val;
81 }
82
83 char *str_iconv_encode(iconv_t conversion_desc,
84                 const char *src,
85                 size_t bcount_src,
86                 size_t *p_bcount,
87                 int *err_flg)
88 {
89         char            *ret_val;
90         char            *p_ret_val;
91         const char      *p_src;
92         size_t          bcount_src_left;
93         size_t          bcount_trgt_left;
94         size_t          ic_ret_val;
95
96         ret_val         = NULL;
97         *err_flg        = 0;
98         *p_bcount       = calculate_target_charset_bytecount(conversion_desc,
99                                                 src,
100                                                 bcount_src);
101         if (*p_bcount >= 0) {
102                 ret_val = (char *)calloc(1, *p_bcount + 1);
103                 if (ret_val != NULL) {
104                         // reset conversion descriptor to initial state
105                         iconv(conversion_desc,
106                                 NULL,
107                                 NULL,
108                                 NULL,
109                                 NULL);
110                         p_src                   = src;
111                         bcount_src_left         = bcount_src;
112                         p_ret_val               = ret_val;
113                         bcount_trgt_left        = *p_bcount;
114                         while (bcount_src_left > 0) {
115                                 errno           = 0;
116                                 ic_ret_val      = iconv(conversion_desc,
117                                                         (char **)&p_src,
118                                                         &bcount_src_left,
119                                                         &p_ret_val,
120                                                         &bcount_trgt_left);
121                                 if (ic_ret_val == (size_t)(-1)) {
122                                         free(ret_val);
123                                         ret_val         = NULL;
124                                         *err_flg        = -1;
125                                         break;
126                                 }
127                         }
128                 }
129                 else {
130                         *err_flg        = -1;
131                 }
132         }
133         else {
134                 // could not calculate the byte count
135                 *err_flg        = -1;
136         }
137         if (*err_flg != 0) {
138                 *p_bcount       = -1;
139         }
140         return ret_val;
141 }