2012-05-16 75 views
3

讓我們假設有一段這樣的代碼:如何處理由字符的字符串字符的XS碼

my $str = 'some text'; 
    my $result = my_subroutine($str); 

my_subroutine()應該像Perl XS代碼來實現。例如,它可以返回(unicode)字符串的字節總和。

在XS碼,如何處理一個字符串的(a)炭由炭,作爲一般的方法,和(b)中逐字節,如果字符串是由ASCII碼的子集(一個內置-in函數將字符串的本機數據結構轉換爲char [])?

回答

3

在XS層,您將獲得字節或UTF-8字符串。在一般情況下,您的代碼可能會包含一個char *以指向字符串中的下一個項目,隨着它的增加而遞增。對於一組有用的UTF-8支持功能在XS使用,從http://cpansearch.perl.org/src/PEVANS/Tickit-0.15/lib/Tickit/Utils.xs

int textwidth(str) 
    SV *str 
    INIT: 
    STRLEN len; 
    const char *s, *e; 

    CODE: 
    RETVAL = 0; 

    if(!SvUTF8(str)) { 
     str = sv_mortalcopy(str); 
     sv_utf8_upgrade(str); 
    } 

    s = SvPV_const(str, len); 
    e = s + len; 

    while(s < e) { 
     UV ord = utf8n_to_uvchr(s, e-s, &len, (UTF8_DISALLOW_SURROGATE 
               |UTF8_WARN_SURROGATE 
               |UTF8_DISALLOW_FE_FF 
               |UTF8_WARN_FE_FF 
               |UTF8_WARN_NONCHAR)); 
     int width = wcwidth(ord); 
     if(width == -1) 
     XSRETURN_UNDEF; 

     s += len; 
     RETVAL += width; 
    } 

    OUTPUT: 
    RETVAL 

簡言之讀取的perlapi


礦的一個例子的"Unicode Support"部,該函數迭代給定的字符串一次一個Unicode字符,累積寬度如wcwidth()所示。

+0

有用的筆記,謝謝。但我仍然希望至少有一個基本的子程序框架(不是特別針對你)。我會等一段時間,如果沒有更好的表現,我會接受這個答案。 – ArtM

+0

好的。我會從我的代碼中挖出一些,併發布另一個答案,然後...... – LeoNerd

3

如果您期望字節:

STRLEN len; 
char* buf = SvPVbyte(sv, len); 

while (len--) { 
    char byte = *(buf++); 

    ... do something with byte ... 
} 

如果您期望文本或任何非字節字符:

STRLEN len; 
U8* buf = SvPVutf8(sv, len); 

while (len) { 
    STRLEN ch_len; 
    UV ch = utf8n_to_uvchr(buf, len, &ch_len, 0); 
    buf += ch_len; 
    len -= ch_len; 

    ... do something with ch ... 
}