TString      T_STROKA
TUtf16String      T_WTROKA
TUtf8String T_USTRING
TLemma*     T_PTROBJ
TLangMask   T_LANGMASK
TLangMask*  T_PTROBJ
ELanguage T_DOCLANG
ELanguage* T_PTROBJ

INPUT
T_STROKA
    $var = ($arg && SvUTF8($arg)) ? RecodeToYandex(CODES_UTF8, SvPV_nolen($arg)) : SvPV_nolen($arg);

T_USTRING
    $var = SvPV_nolen($arg);

T_WTROKA
    if ($arg) {
        STRLEN stringSize = 0;
        char* stringData = SvPV($arg, stringSize);
        size_t inRead = 0, outWritten = 0;
        bool utf8 = SvUTF8($arg);
        size_t outSize = utf8 ? sv_len_utf8($arg) : stringSize;
        $var.resize(outSize);
        RECODE_RESULT res = RecodeToUnicode(utf8 ? CODES_UTF8 : CODES_YANDEX, stringData, $var.begin(), stringSize, outSize, inRead, outWritten);
        $var.resize(outWritten);
        if (res != RECODE_OK) {
            warn(\"RecodeToUnicode failed\");
        }
    }

T_LANGMASK
    if (SvROK($arg)) {
        if (sv_derived_from($arg, \"TLangMaskPtr\")) {
            $var = *INT2PTR(${type}*, SvIV((SV*)SvRV($arg)));
        } else {
            croak(\"%s is not of type %s\", \"$var\", \"$ntype\");
        }
    } else {
        const char* s = SvPV_nolen($arg);
        $var = ParseLangString(s);
    }

T_DOCLANG
   if (SvROK($arg)) {
       if (sv_derived_from($arg, \"docLanguagePtr\")) {
           $var = *INT2PTR(${type}*, SvIV((SV*)SvRV($arg)));
        } else {
            croak(\"%s is not of type %s\", \"$var\", \"$ntype\");
        }
    } else {
       const char* s = SvPV_nolen($arg);
       $var = LanguageByName(s);
       if ($var == LANG_UNK) {
           croak(\"Unable to parse language: %s\", s);
       }
    }

OUTPUT
T_STROKA
    sv_setpv((SV*)$arg, RecodeFromYandex(CODES_UTF8, $var).c_str());
    SvUTF8_on((SV*)$arg);

T_USTRING
    sv_setpv((SV*)$arg, $var.c_str());
    SvUTF8_on((SV*)$arg);

T_WTROKA
    sv_setpv((SV*)$arg, WideToUTF8($var.c_str(), $var.size()).c_str());
    SvUTF8_on((SV*)$arg);
