So I made this encode object of mine to hide differences between windows & linux, I went to the
effort of setting up my custom printf handler to support UTF-16, UTF-32 & TCHAR plus a a "largest character type" (pawjc) and the encoder was responsible for passing the pointers over to the system handlers, trouble is I'm somehow getting 0 bytes written to the destination according to the output length, yet the string is definitely copied over according to the debugger so I'm at a loss as to what I did wrong that resulted in "0 characters" converted despite it actually getting in the destination.
Triggered by:
Code:
pawd test__Printf( paws ARGS, paws VA, paws args, pawhhs arghhs, ... )
{
#define CHK_MAX 511
pawd did = -1;
pawd len = -1;
va_list one, two;
pawSTR Got = NULL;
pawc chk[CHK_MAX+1] = {0};
va_start( one, arghhs );
va_copy( two, one );
len = vsnprintf( chk, CHK_MAX, args, one );
Got = pawMakeStringv( arghhs, &two );
printf( "vsnprintf( %s, %s ): %s\n", ARGS, VA, chk );
printf( "pawPrintf( %s, %s ): ", ARGS, VA );
...
}
...
switch ( *mod )
{
case 'h':
if ( len > 1 )
paw_cpy( dst, src, sizeof(pawhhc) * did );
else
did = pawhs2hhs( dst, cap, src, len );
break;
case 'l':
did = (len > 1)
? pawlls2hhs( dst, cap, src, did )
: pawls2hhs( dst, cap, src, did );
break;
case 't': did = pawts2hhs( dst, cap, src, did ); break;
case 'j': did = pawjs2hhs( dst, cap, src, did ); break;
default: did = paws2hhs( dst, cap, src, did ); // here
}
...
PAW_API pawzd paws2hhs( pawhhc *dst, pawd max, paws src, pawd len )
{
return paw_encode
(
PAWHHC_ENCODING, dst, max, sizeof(pawhhc),
PAWC_ENCODING, src, len, sizeof(pawc)
);
}
...
PAW_API pawzd paw_encode
(
paws DST, void *dst, pawd max, pawzd perDN,
paws SRC, pawp src, pawd len, pawzd perSN
)
{
if ( dst && max > 0 && perDN > 0 && src && len >= 0 && perSN > 0 )
{
pawENC enc = pawMakeEncoder( DST, SRC );
pawhhu *D = (pawhhu*)dst;
if ( !enc )
return -1;
len = pawEncodeText
( enc, dst, perDN * --max, src, perSN * len );
pawVoidEncoder( enc );
paw_set( D + perDN * max, 0, perDN );
return (len > 0) ? len / perDN : len;
}
return -1;
}
Code:
#include "std.h"
#include <stdlib.h>
PAW_API pawzd pawEncodeCB_notsup( pawENC enc )
{ (void)enc; errno = ENOSYS; return -1; }
PAW_API pawzd pawEncodeCB_rawcpy( pawENC enc )
{
pawzd bytes = PawToLower( enc->dleft, enc->sleft );
paw_cpy( enc->daddr, enc->saddr, bytes );
enc->daddr += bytes;
enc->saddr += bytes;
enc->dleft -= bytes;
enc->sleft -= bytes;
return bytes;
}
#ifdef PAW_ON_WINDOWS
PAW_API paws pawCharEncoding() { return "UTF-8"; }
PAW_API pawzd pawEncodeCB_MultiByteToWideChar( pawENC enc )
{
pawzd did = WideCharToMultiByte
(
enc->dstcp, 0,
enc->saddr,
enc->sleft,
enc->daddr,
enc->dleft,
NULL,
NULL
);
if ( did < 0 )
return -1;
return did;
}
PAW_API pawzd pawEncodeCB_MultiByteToWideChar( pawENC enc )
{
pawzd did = MultiByteToWideChar
(
enc->dstcp, 0,
enc->saddr,
enc->sleft,
enc->daddr,
enc->dleft
);
if ( did < 0 )
return -1;
return did;
}
#else
PAW_API paws pawCharEncoding()
{
paws info = getenv("LC_TYPE"), conv;
if ( !info ) info = getenv("LANG");
conv = strchr( info, '.' );
conv = conv ? conv + 1 : PAWC_LAST_RESORT_ENCODING_ASSUMPTION;
return conv;
}
PAW_API void pawVoidEncoder( pawENC enc )
{
if ( enc->dname )
iconv_close( enc->iconv );
PawGet( enc, 0 );
}
PAW_API pawENC pawMakeEncoder( paws dst, paws src )
{
pawENC enc = PawGetUD( sizeof(pawENC) );
if ( enc )
{
if ( !dst || !(dst[0]) ) dst = pawCharEncoding();
if ( !src || !(src[0]) ) src = pawCharEncoding();
if ( dst == src || paws_icmp( dst, src ) < 0 ) // footnote at bottom about this
{
enc->encodeCB = pawEncodeCB_rawcpy;
enc->iconv = (iconv_t)-1;
return enc;
}
enc->iconv = iconv_open( dst, src );
if ( enc->iconv == (iconv_t)-1 )
{
PawGet( enc, 0 );
return NULL;
}
enc->dname = dst;
enc->sname = src;
enc->encodeCB = pawEncodeCB_iconv;
}
return enc;
}
PAW_API pawzd pawEncodeCB_iconv( pawENC enc )
{
pawzu dleft = enc->dleft;
pawzu sleft = enc->sleft;
pawc* daddr = (pawc*)(enc->daddr);
pawc* saddr = (pawc*)(enc->saddr);
pawzd bytes = iconv( enc->iconv, &saddr, &sleft, &daddr, &dleft );
enc->daddr = daddr;
enc->dleft = dleft;
enc->saddr = saddr;
enc->sleft = sleft;
return bytes;
}
#endif
PAW_API pawzd pawEncodeText
( pawENC enc, void *dst, pawzd cap, pawp src, pawzd has )
{
enc->daddr = dst;
enc->dleft = cap;
enc->saddr = src;
enc->sleft = has;
return enc->encodeCB( enc );
}
As an extra I also found I had made a mistake somewhere with my paw_icmp function, not seeing what though, only realised it because a comparison between "UTF-8" & "UTF-8" did not yield -1 as I was expecting it to, if anyone's inclined to look, here it is:
Code:
PAW_API pawd paw_icmp( pawp a, pawp b, pawzd perN )
{
pawd i = 0;
pawzd n = 0, N = 0;
pawhhu const *A = (pawhhu const*)a;
pawhhu const *B = (pawhhu const*)b;
if ( !a || !b || a == b )
return -(a == b);
for ( N = paw_is0( A, perN ); N < 0; N = paw_is0( A + n, perN ) )
{
N = paw_cmp( A + n, B + n, perN );
if ( N > 0 || toupper(A[n]) != toupper(B[n]) )
return i;
n += perN;
++i;
}
N = paw_is0( B + n, perN );
return (N < 0) ? -1 : n + N;
}