mirror of
https://github.com/encounter/SDL.git
synced 2025-12-16 16:37:09 +00:00
os2: add port files for SDL2-2.0.4 from Andrey Vasilkin
only geniconv/iconv.h (was from LGPL libiconv) is replaced with a generic minimal iconv.h based on public knowledge.
This commit is contained in:
264
src/core/os2/geniconv/os2iconv.c
Normal file
264
src/core/os2/geniconv/os2iconv.c
Normal file
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
Implementation iconv via OS/2 conversion objects API.
|
||||
|
||||
Andrey Vasilkin.
|
||||
*/
|
||||
|
||||
#define ICONV_THREAD_SAFE 1
|
||||
//#undef ICONV_THREAD_SAFE
|
||||
|
||||
#include "iconv.h"
|
||||
#include <uconv.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef ICONV_THREAD_SAFE
|
||||
#define INCL_DOSSEMAPHORES
|
||||
#define INCL_DOSERRORS
|
||||
#include <os2.h>
|
||||
#endif
|
||||
#include "os2cp.h"
|
||||
|
||||
#define MAX_CP_NAME_LEN 64
|
||||
|
||||
typedef struct iuconv_obj {
|
||||
UconvObject uo_tocode;
|
||||
UconvObject uo_fromcode;
|
||||
int buf_len;
|
||||
UniChar *buf;
|
||||
#ifdef ICONV_THREAD_SAFE
|
||||
HMTX hMtx;
|
||||
#endif
|
||||
} iuconv_obj;
|
||||
|
||||
|
||||
static int _createUconvObj(const char *code, UconvObject *uobj)
|
||||
{
|
||||
UniChar uc_code[MAX_CP_NAME_LEN];
|
||||
int i;
|
||||
const char *ch = code;
|
||||
|
||||
if ( code == NULL )
|
||||
uc_code[0] = 0;
|
||||
else
|
||||
{
|
||||
for( i = 0; i < MAX_CP_NAME_LEN; i++ )
|
||||
{
|
||||
uc_code[i] = (unsigned short)*ch;
|
||||
if ( !(*ch) ) break;
|
||||
ch++;
|
||||
}
|
||||
}
|
||||
|
||||
return UniCreateUconvObject( &uc_code, uobj );
|
||||
}
|
||||
|
||||
static int uconv_open(const char *code, UconvObject *uobj)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if ( !stricmp( code, "UTF-16" ) )
|
||||
{
|
||||
*uobj = NULL;
|
||||
return ULS_SUCCESS;
|
||||
}
|
||||
|
||||
rc = _createUconvObj( code, uobj );
|
||||
if ( rc != ULS_SUCCESS )
|
||||
{
|
||||
unsigned long cp = os2cpFromName( (char *)code );
|
||||
char cp_name[16];
|
||||
|
||||
if ( cp != 0 && _snprintf( &cp_name, sizeof(cp_name), "IBM-%u", cp ) > 0 )
|
||||
rc = _createUconvObj( &cp_name, uobj );
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
extern iconv_t _System os2_iconv_open(const char* tocode, const char* fromcode)
|
||||
{
|
||||
UconvObject uo_tocode;
|
||||
UconvObject uo_fromcode;
|
||||
int rc;
|
||||
iuconv_obj *iuobj;
|
||||
|
||||
if ( tocode == NULL )
|
||||
tocode = "";
|
||||
|
||||
if ( fromcode == NULL )
|
||||
fromcode = "";
|
||||
|
||||
if ( stricmp(tocode, fromcode) != 0 )
|
||||
{
|
||||
rc = uconv_open( fromcode, &uo_fromcode );
|
||||
if ( rc != ULS_SUCCESS )
|
||||
{
|
||||
errno = EINVAL;
|
||||
return (iconv_t)(-1);
|
||||
}
|
||||
|
||||
rc = uconv_open( tocode, &uo_tocode );
|
||||
if ( rc != ULS_SUCCESS )
|
||||
{
|
||||
UniFreeUconvObject( uo_fromcode );
|
||||
errno = EINVAL;
|
||||
return (iconv_t)(-1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uo_tocode = NULL;
|
||||
uo_fromcode = NULL;
|
||||
}
|
||||
|
||||
iuobj = malloc( sizeof(iuconv_obj) );
|
||||
iuobj->uo_tocode = uo_tocode;
|
||||
iuobj->uo_fromcode = uo_fromcode;
|
||||
iuobj->buf_len = 0;
|
||||
iuobj->buf = NULL;
|
||||
#ifdef ICONV_THREAD_SAFE
|
||||
DosCreateMutexSem( NULL, &iuobj->hMtx, 0, FALSE );
|
||||
#endif
|
||||
|
||||
return iuobj;
|
||||
}
|
||||
|
||||
extern size_t _System os2_iconv(iconv_t cd, char* * inbuf,
|
||||
size_t *inbytesleft,
|
||||
char* * outbuf, size_t *outbytesleft)
|
||||
{
|
||||
UconvObject uo_tocode = ((iuconv_obj *)(cd))->uo_tocode;
|
||||
UconvObject uo_fromcode = ((iuconv_obj *)(cd))->uo_fromcode;
|
||||
size_t nonIdenticalConv = 0;
|
||||
UniChar *uc_buf;
|
||||
size_t uc_buf_len;
|
||||
UniChar **uc_str;
|
||||
size_t *uc_str_len;
|
||||
int rc;
|
||||
size_t ret = (size_t)(-1);
|
||||
|
||||
if ( uo_tocode == NULL && uo_fromcode == NULL )
|
||||
{
|
||||
uc_buf_len = min( *inbytesleft, *outbytesleft );
|
||||
memcpy( *outbuf, *inbuf, uc_buf_len );
|
||||
*inbytesleft -= uc_buf_len;
|
||||
*outbytesleft -= uc_buf_len;
|
||||
outbuf += uc_buf_len;
|
||||
inbuf += uc_buf_len;
|
||||
return uc_buf_len;
|
||||
}
|
||||
|
||||
#ifdef ICONV_THREAD_SAFE
|
||||
DosRequestMutexSem( ((iuconv_obj *)(cd))->hMtx, SEM_INDEFINITE_WAIT );
|
||||
#endif
|
||||
|
||||
if ( uo_tocode && uo_fromcode &&
|
||||
(( ((iuconv_obj *)(cd))->buf_len >> 1 ) < (*inbytesleft)) )
|
||||
{
|
||||
if ( ( ((iuconv_obj *)(cd))->buf ) != NULL )
|
||||
free( ((iuconv_obj *)(cd))->buf );
|
||||
((iuconv_obj *)(cd))->buf_len = *inbytesleft << 1;
|
||||
((iuconv_obj *)(cd))->buf = (UniChar *)malloc( ((iuconv_obj *)(cd))->buf_len );
|
||||
}
|
||||
|
||||
if ( uo_fromcode )
|
||||
{
|
||||
if ( uo_tocode )
|
||||
{
|
||||
uc_buf = ((iuconv_obj *)(cd))->buf;
|
||||
uc_buf_len = ((iuconv_obj *)(cd))->buf_len;
|
||||
uc_str = &uc_buf;
|
||||
}
|
||||
else {
|
||||
uc_str = (UniChar **)outbuf;
|
||||
uc_buf_len = *outbytesleft;
|
||||
}
|
||||
uc_buf_len = uc_buf_len >> 1;
|
||||
uc_str_len = &uc_buf_len;
|
||||
rc = UniUconvToUcs( uo_fromcode, (void **)inbuf, inbytesleft,
|
||||
uc_str, uc_str_len, &nonIdenticalConv );
|
||||
uc_buf_len = uc_buf_len << 1;
|
||||
if ( !uo_tocode )
|
||||
*outbytesleft = uc_buf_len;
|
||||
|
||||
if ( rc != ULS_SUCCESS )
|
||||
{
|
||||
errno = EILSEQ;
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
if ( *inbytesleft && !*uc_str_len )
|
||||
{
|
||||
errno = E2BIG;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ( !uo_tocode )
|
||||
return nonIdenticalConv;
|
||||
|
||||
uc_buf = ((iuconv_obj *)(cd))->buf;
|
||||
uc_buf_len = ((iuconv_obj *)(cd))->buf_len - uc_buf_len;
|
||||
uc_str = &uc_buf;
|
||||
uc_str_len = &uc_buf_len;
|
||||
}
|
||||
else {
|
||||
uc_str = (UniChar **)inbuf;
|
||||
uc_str_len = inbytesleft;
|
||||
}
|
||||
|
||||
*uc_str_len = *uc_str_len>>1;
|
||||
rc = UniUconvFromUcs( uo_tocode, uc_str, uc_str_len, (void **)outbuf,
|
||||
outbytesleft, &nonIdenticalConv );
|
||||
if ( rc != ULS_SUCCESS )
|
||||
{
|
||||
switch ( rc )
|
||||
{
|
||||
case ULS_BUFFERFULL:
|
||||
errno = E2BIG;
|
||||
break;
|
||||
case ULS_ILLEGALSEQUENCE:
|
||||
errno = EILSEQ;
|
||||
break;
|
||||
case ULS_INVALID:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
if ( *uc_str_len && !*outbytesleft )
|
||||
{
|
||||
errno = E2BIG;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = nonIdenticalConv;
|
||||
|
||||
done:
|
||||
|
||||
#ifdef ICONV_THREAD_SAFE
|
||||
DosReleaseMutexSem( ((iuconv_obj *)(cd))->hMtx );
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern int _System os2_iconv_close(iconv_t cd)
|
||||
{
|
||||
if ( !cd )
|
||||
return 0;
|
||||
|
||||
#ifdef ICONV_THREAD_SAFE
|
||||
DosCloseMutexSem( ((iuconv_obj *)(cd))->hMtx );
|
||||
#endif
|
||||
if ( ((iuconv_obj *)(cd))->uo_tocode != NULL )
|
||||
UniFreeUconvObject( ((iuconv_obj *)(cd))->uo_tocode );
|
||||
if ( ((iuconv_obj *)(cd))->uo_fromcode != NULL )
|
||||
UniFreeUconvObject( ((iuconv_obj *)(cd))->uo_fromcode );
|
||||
|
||||
if ( ( ((iuconv_obj *)(cd))->buf ) != NULL )
|
||||
free( ((iuconv_obj *)(cd))->buf );
|
||||
|
||||
free(cd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user