如何在XS代码中通过char处理字符串char

时间:2012-05-16 16:19:12

标签: c perl perl-xs

我们假设有一段这样的代码:

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

my_subroutine()应该实现为Perl XS代码。例如,它可以返回(unicode)字符串的字节总和。

在XS代码中,如何通过char处理字符串(a)作为一般方法,如果是字符串,则逐字节处理(b)是由ASCII代码子集(一个内置函数,从字符串的原生数据结构转换为char [])?

2 个答案:

答案 0 :(得分:3)

在XS层,您将获得字节或UTF-8字符串。在一般情况下,您的代码可能包含一个char *来指向字符串中的下一个项目,并在其前进时递增它。有关在XS中使用的一组有用的UTF-8支持函数,请阅读perlapi的{​​{3}}部分


我的一个例子来自"Unicode Support"

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

简而言之,此函数一次迭代给定字符串一个Unicode字符,累加wcwidth()给出的宽度。

答案 1 :(得分: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 ...
}