Deep-Encode

 view release on metacpan or  search on metacpan

Encode.xs  view on Meta::CPAN

inline bool is_utf8(char *z, STRLEN m){
    return _is_utf8( (U8 *)(z), (U8*)(z + m));
}

typedef struct pp_args{
    char  type;
    char  fastinit;

    int   noskip;
    int   argc;
    int   str_pos;
    int   counter;
    char *method;
    CV   *meth1;
    CV   *meth2;
    p_callback callback;    
    SV* argv[10 + 2];
} *pp_func;

void utf8_check_encoding_cb( pp_func pf, SV *data){
    char *ptr;
    STRLEN data_len;
    if (!pf->counter)
	return;
    ptr = SvPV( data, data_len);
    if (!is_utf8( ptr, data_len ))
	pf->counter = 0;

}

void utf8_upgrade_cb( pp_func pf, SV * data){
    if (!SvUTF8(data)){
	(void) sv_utf8_upgrade( data );
	++(pf->counter);
    };
}

void utf8_downgrade_cb( pp_func pf, SV * data){
    if (SvUTF8(data)){
	(void) sv_utf8_downgrade( data , 0);
	++(pf->counter);
    };
}

void utf8_off_cb( pp_func pf, SV * data){
    if (SvUTF8(data)){
	SvUTF8_off(data);
	++(pf->counter);
    };
}

void utf8_on_cb( pp_func pf, SV * data){
    if (!SvUTF8(data)){
		SvUTF8_on(data);
		++(pf->counter);
	}
}

void from_to_cb( pp_func pf, SV * data){
    int ret_list_size;
    SV *decoded_sv;
    dSP;
    ENTER;
    SAVETMPS;

    if ( !  pf->fastinit ){
	GV * method_glob;
	HV * encoding_stash;
	pf->meth1 = 0;
	pf->meth2 = 0;
	pf->fastinit = -1;

	encoding_stash = SvSTASH( SvRV( pf->argv[0] ) );
	method_glob = gv_fetchmeth( encoding_stash, "decode", 6, 0 );
	pf->meth1 = GvCV( method_glob );
	

	encoding_stash = SvSTASH( SvRV( pf->argv[1] ) );
	method_glob = gv_fetchmeth( encoding_stash, "encode", 6, 0 );
	pf->meth2 = GvCV( method_glob );

	if ( pf->meth1 && pf->meth2 ){
	    pf->fastinit = 1;
	};
    };

    PUSHMARK(SP);
    XPUSHs( pf->argv[0] ); /*first encoding */
    XPUSHs( data );
    PUTBACK;

    if ( pf->fastinit == 1 ){
    	ret_list_size = call_sv( (SV *) pf->meth1, G_SCALAR);
    }
    else {
    	ret_list_size = call_method("decode", G_SCALAR);
    };

    SPAGAIN;
    if (ret_list_size != 1){
	croak( "A big trouble");
    }
    decoded_sv = POPs;
    PUTBACK;

    PUSHMARK(SP);
    XPUSHs( pf->argv[1] );
    XPUSHs( decoded_sv );
    PUTBACK;


    if ( pf->fastinit == 1 ){
    	ret_list_size = call_sv( (SV *) pf->meth2, G_SCALAR);
    }
    else {
	ret_list_size = call_method("encode", G_SCALAR);
    }
    SPAGAIN;
    if (ret_list_size != 1){
	croak( "A big trouble");
    }
    decoded_sv = POPs;
    sv_setsv( data , decoded_sv );
    PUTBACK;
    FREETMPS;
    LEAVE;
}

void from_to_cb_00( pp_func pf, SV * data){
    int ret_list_size;
    SV *decoded_sv;
    dSP;
    ENTER;
    SAVETMPS;

    PUSHMARK(SP);
    XPUSHs( pf->argv[0] ); /*first encoding */
    XPUSHs( data );

    PUTBACK;

    ret_list_size = call_method("decode", G_SCALAR);
    SPAGAIN;
    if (ret_list_size != 1){
	croak( "A big trouble");
    }
    decoded_sv = POPs;
    PUTBACK;

    PUSHMARK(SP);
    XPUSHs( pf->argv[1] );
    XPUSHs( decoded_sv );
    PUTBACK;


    ret_list_size = call_method("encode", G_SCALAR);
    SPAGAIN;
    if (ret_list_size != 1){
	croak( "A big trouble");
    }
    decoded_sv = POPs;
    sv_setsv( data , decoded_sv );
    PUTBACK;
    FREETMPS;
    LEAVE;
}

/*static U8* good_encoding=",cp1251,latin1,utf8,windows1251,cp866,"; */
SV *find_encoding(pp_func pfunc, SV* encoding )
{
    int ret_list;
    SV *enc_obj;
    dSP;
    enc_obj = 0;

    if ( SvROK(encoding) &&  sv_isobject( encoding )) {
	enc_obj = encoding;
    };
    if ( !enc_obj ) {
	PUSHMARK(SP);
	XPUSHs(encoding);
	PUTBACK;

	ret_list = call_pv("Encode::find_encoding", G_SCALAR);
	SPAGAIN;
	if (ret_list != 1)
	    croak( "Big trouble with Encode::find_encoding");
	enc_obj = POPs;	    

	if (!SvOK(enc_obj)) {
	    if ( SvPOK(encoding) )
		croak("Unknown encoding '%.*s'", SvCUR(encoding), SvPV_nolen(encoding));
	    else 
		croak("Unknown encoding ??? (is not string)");
	};
	PUTBACK;
    };
    if (! pfunc->noskip ){
	SV *name_sv;
	char *name;
	STRLEN name_len;

	PUSHMARK(SP);
	XPUSHs(enc_obj);
	PUTBACK;

	ret_list = call_method("name", G_SCALAR);
	SPAGAIN;
	if (ret_list != 1)
	    croak( "Big trouble with Encode::find_encoding");
	name_sv = POPs;	    
	PUTBACK;
	name = SvPV(name_sv, name_len);
	switch( name_len ){
	    case 6:
		if (strEQ("cp1251", name ))
		    return enc_obj;
		break;
	    case 5:
		if (strEQ("cp866", name ))
		    return enc_obj;
		break;



( run in 0.558 second using v1.01-cache-2.11-cpan-2398b32b56e )