SDL  2.0
os2iconv.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 
22 /*
23  Implementation iconv via OS/2 conversion objects API.
24 
25  Andrey Vasilkin.
26 */
27 
28 #define ICONV_THREAD_SAFE 1
29 
30 #include "geniconv.h"
31 #define _ULS_CALLCONV_
32 #define CALLCONV _System
33 #include <uconv.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #ifdef ICONV_THREAD_SAFE
38 #define INCL_DOSSEMAPHORES
39 #define INCL_DOSERRORS
40 #include <os2.h>
41 #endif
42 #include "os2cp.h"
43 
44 #if !defined(min)
45 #define min(a, b) (((a) < (b)) ? (a) : (b))
46 #endif
47 
48 #define MAX_CP_NAME_LEN 64
49 
50 typedef struct iuconv_obj {
51  UconvObject uo_tocode;
52  UconvObject uo_fromcode;
53  int buf_len;
54  UniChar *buf;
55 #ifdef ICONV_THREAD_SAFE
56  HMTX hMtx;
57 #endif
58 } iuconv_obj;
59 
60 
61 static int _createUconvObj(const char *code, UconvObject *uobj)
62 {
63  UniChar uc_code[MAX_CP_NAME_LEN];
64  int i;
65  const char *ch = code;
66 
67  if (code == NULL)
68  uc_code[0] = 0;
69  else {
70  for (i = 0; i < MAX_CP_NAME_LEN; i++) {
71  uc_code[i] = (unsigned short)*ch;
72  if (! (*ch))
73  break;
74  ch++;
75  }
76  }
77 
78  return UniCreateUconvObject(uc_code, uobj);
79 }
80 
81 static int uconv_open(const char *code, UconvObject *uobj)
82 {
83  int rc;
84 
85  if (!stricmp(code, "UTF-16")) {
86  *uobj = NULL;
87  return ULS_SUCCESS;
88  }
89 
90  rc = _createUconvObj(code, uobj);
91  if (rc != ULS_SUCCESS) {
92  unsigned long cp = os2cpFromName((char *)code);
93  char cp_name[16];
94 
95  if (cp != 0 && _snprintf(cp_name, sizeof(cp_name), "IBM-%u", cp) > 0)
96  rc = _createUconvObj(cp_name, uobj);
97  }
98 
99  return rc;
100 }
101 
102 
103 extern iconv_t _System os2_iconv_open(const char* tocode, const char* fromcode)
104 {
105  UconvObject uo_tocode;
106  UconvObject uo_fromcode;
107  int rc;
108  iuconv_obj *iuobj;
109 
110  if (tocode == NULL)
111  tocode = "";
112 
113  if (fromcode == NULL)
114  fromcode = "";
115 
116  if (stricmp(tocode, fromcode) != 0) {
117  rc = uconv_open(fromcode, &uo_fromcode);
118  if (rc != ULS_SUCCESS) {
119  errno = EINVAL;
120  return (iconv_t)(-1);
121  }
122 
123  rc = uconv_open(tocode, &uo_tocode);
124  if (rc != ULS_SUCCESS) {
125  UniFreeUconvObject(uo_fromcode);
126  errno = EINVAL;
127  return (iconv_t)(-1);
128  }
129  } else {
130  uo_tocode = NULL;
131  uo_fromcode = NULL;
132  }
133 
134  iuobj = (iuconv_obj *) malloc(sizeof(iuconv_obj));
135  iuobj->uo_tocode = uo_tocode;
136  iuobj->uo_fromcode = uo_fromcode;
137  iuobj->buf_len = 0;
138  iuobj->buf = NULL;
139 #ifdef ICONV_THREAD_SAFE
140  DosCreateMutexSem(NULL, &iuobj->hMtx, 0, FALSE);
141 #endif
142 
143  return iuobj;
144 }
145 
146 extern size_t _System os2_iconv(iconv_t cd, char* * inbuf,
147  size_t *inbytesleft,
148  char* * outbuf, size_t *outbytesleft)
149 {
150  UconvObject uo_tocode = ((iuconv_obj *)(cd))->uo_tocode;
151  UconvObject uo_fromcode = ((iuconv_obj *)(cd))->uo_fromcode;
152  size_t nonIdenticalConv = 0;
153  UniChar *uc_buf;
154  size_t uc_buf_len;
155  UniChar **uc_str;
156  size_t *uc_str_len;
157  int rc;
158  size_t ret = (size_t)(-1);
159 
160  if (uo_tocode == NULL && uo_fromcode == NULL) {
161  uc_buf_len = min(*inbytesleft, *outbytesleft);
162  memcpy(*outbuf, *inbuf, uc_buf_len);
163  *inbytesleft -= uc_buf_len;
164  *outbytesleft -= uc_buf_len;
165  outbuf += uc_buf_len;
166  inbuf += uc_buf_len;
167  return uc_buf_len;
168  }
169 
170 #ifdef ICONV_THREAD_SAFE
171  DosRequestMutexSem(((iuconv_obj *)(cd))->hMtx, SEM_INDEFINITE_WAIT);
172 #endif
173 
174  if (uo_tocode && uo_fromcode &&
175  (((iuconv_obj *)cd)->buf_len >> 1) < *inbytesleft) {
176  if (((iuconv_obj *)cd)->buf != NULL)
177  free(((iuconv_obj *)cd)->buf);
178  ((iuconv_obj *)cd)->buf_len = *inbytesleft << 1;
179  ((iuconv_obj *)cd)->buf = (UniChar *)malloc(((iuconv_obj *)cd)->buf_len);
180  }
181 
182  if (uo_fromcode) {
183  if (uo_tocode) {
184  uc_buf = ((iuconv_obj *)cd)->buf;
185  uc_buf_len = ((iuconv_obj *)cd)->buf_len;
186  uc_str = &uc_buf;
187  } else {
188  uc_str = (UniChar **)outbuf;
189  uc_buf_len = *outbytesleft;
190  }
191  uc_buf_len = uc_buf_len >> 1;
192  uc_str_len = &uc_buf_len;
193  rc = UniUconvToUcs(uo_fromcode, (void **)inbuf, inbytesleft,
194  uc_str, uc_str_len, &nonIdenticalConv);
195  uc_buf_len = uc_buf_len << 1;
196  if (!uo_tocode)
197  *outbytesleft = uc_buf_len;
198 
199  if (rc != ULS_SUCCESS) {
200  errno = EILSEQ;
201  goto done;
202  } else if (*inbytesleft && !*uc_str_len) {
203  errno = E2BIG;
204  goto done;
205  }
206 
207  if (!uo_tocode)
208  return nonIdenticalConv;
209 
210  uc_buf = ((iuconv_obj *)cd)->buf;
211  uc_buf_len = ((iuconv_obj *)cd)->buf_len - uc_buf_len;
212  uc_str = &uc_buf;
213  uc_str_len = &uc_buf_len;
214  } else {
215  uc_str = (UniChar **)inbuf;
216  uc_str_len = inbytesleft;
217  }
218 
219  *uc_str_len = *uc_str_len>>1;
220  rc = UniUconvFromUcs(uo_tocode, uc_str, uc_str_len, (void **)outbuf,
221  outbytesleft, &nonIdenticalConv);
222  if (rc != ULS_SUCCESS) {
223  switch (rc) {
224  case ULS_BUFFERFULL:
225  errno = E2BIG;
226  break;
227  case ULS_ILLEGALSEQUENCE:
228  errno = EILSEQ;
229  break;
230  case ULS_INVALID:
231  errno = EINVAL;
232  break;
233  }
234  goto done;
235  } else if (*uc_str_len && !*outbytesleft) {
236  errno = E2BIG;
237  goto done;
238  }
239 
240  ret = nonIdenticalConv;
241 
242 done:
243 
244 #ifdef ICONV_THREAD_SAFE
245  DosReleaseMutexSem(((iuconv_obj *)cd)->hMtx);
246 #endif
247  return ret;
248 }
249 
250 int _System os2_iconv_close(iconv_t cd)
251 {
252  if (!cd) return 0;
253 
254 #ifdef ICONV_THREAD_SAFE
255  DosCloseMutexSem(((iuconv_obj *)cd)->hMtx);
256 #endif
257  if (((iuconv_obj *)cd)->uo_tocode != NULL)
258  UniFreeUconvObject(((iuconv_obj *)cd)->uo_tocode);
259  if (((iuconv_obj *)cd)->uo_fromcode != NULL)
260  UniFreeUconvObject(((iuconv_obj *)cd)->uo_fromcode);
261 
262  if (((iuconv_obj *)cd)->buf != NULL)
263  free(((iuconv_obj *)cd)->buf);
264 
265  free(cd);
266 
267  return 0;
268 }
269 
270 /* vi: set ts=4 sw=4 expandtab: */
unsigned int size_t
SDL_EventEntry * free
Definition: SDL_events.c:89
#define memcpy
Definition: SDL_malloc.c:630
GLenum GLuint GLenum GLsizei const GLchar * buf
#define malloc
Definition: SDL_qsort.c:46
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
#define NULL
Definition: begin_code.h:163
int done
Definition: checkkeys.c:28
static const double cp
Definition: e_pow.c:96
#define FALSE
Definition: edid-parse.c:34
void * iconv_t
Definition: iconv.h:7
unsigned long os2cpFromName(char *cp)
Definition: os2cp.c:340
int _System os2_iconv_close(iconv_t cd)
Definition: os2iconv.c:250
static int uconv_open(const char *code, UconvObject *uobj)
Definition: os2iconv.c:81
#define MAX_CP_NAME_LEN
Definition: os2iconv.c:48
iconv_t _System os2_iconv_open(const char *tocode, const char *fromcode)
Definition: os2iconv.c:103
#define min(a, b)
Definition: os2iconv.c:45
size_t _System os2_iconv(iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft)
Definition: os2iconv.c:146
static int _createUconvObj(const char *code, UconvObject *uobj)
Definition: os2iconv.c:61
int buf_len
Definition: os2iconv.c:53
HMTX hMtx
Definition: os2iconv.c:56
UniChar * buf
Definition: os2iconv.c:54
UconvObject uo_tocode
Definition: os2iconv.c:51
UconvObject uo_fromcode
Definition: os2iconv.c:52