La Directiva ALIAS:

El módulo String::Index de Jeff Pinyan provee funciones que permiten calcular el índice de aparición de un conjunto de caracteres en una cadena dada:

lhp@nereida:~/Lperl/src/XSUB/cpanexamples/String-Index-0.02$ perl -de 0
main::(-e:1):   0
  DB<1> use String::Index qw( cindex ncindex crindex ncrindex )
  DB<2> x $first_vowel    =   cindex("broadcast", "aeiouy")
0  2
  DB<3> x $last_vowel     =  crindex("broadcast", "aeiouy")
0  6
  DB<4> x $first_nonvowel =  ncindex("eerily",    "aeiouy")
0  2
  DB<5> x $last_nonvowel  = ncrindex("eerily",    "aeiouy")
0  4
  DB<6> x cindex("broadcast", "xyz")
0  '-1'

El módulo implanta las cuatro funciones usando una única función XSUB. Esta posibilidad la ofrece la directiva ALIAS: la cual permite asociar varios identificadores Perl con una XSUB. Permite además conocer con que nombre fué invocada la XSUB. A cada alias se le da un índice. Dentro de la XSUB es posible consultar dicho índice através de la variable predeclarada ix. Cuando la XSUB es llamada con su nombre oficial el valor de ix es 0.

lhp@nereida:~/Lperl/src/XSUB/cpanexamples/String-Index-0.02$ cat -n Index.xs
 1  #include "EXTERN.h"
 2  #include "perl.h"
 3  #include "XSUB.h"
 4
 5  #include "ppport.h"
 6
 7  #define SI_NOT  0x01
 8  #define SI_REV  0x02
 9
10
11  MODULE = String::Index          PACKAGE = String::Index
12
13
14  int
15  cindex(SV *str, SV *cc, ...)
16  PROTOTYPE: $$;$
17  ALIAS:
18    ncindex = 1
19    crindex = 2
20    ncrindex = 3
21  CODE:
22  {
23      STRLEN s_len;
24      STRLEN c_len;
25      char *s = SvPV(str,s_len);
26      char *c = SvPV(cc,c_len);
27      int seen_null = 0;
28      int p = (items == 3 ? (int)SvIV(ST(2)) : 0);
29      int i;
30
31      /* see if there is an INTERNAL null in the char str */
32      for (i = 0; i < c_len; ) {
33          if (c[i] == '\0' && (seen_null = 1)) c[i] = c[--c_len];
34          else ++i;
35      }
36      c[c_len] = '\0';
37
38      if (ix & SI_REV) {
39          s += (p ? p : s_len - 1);
40          for (i = p ? p : (s_len - 1); i >= 0; --i, --s)
41              if ((*s ? strchr(c, *s) > 0 : seen_null) != (ix & SI_NOT)) break;
42      }
43      else {
44          s += p;
45          for (i = p; i < s_len; ++i, ++s)
46              if ((*s ? strchr(c, *s) > 0 : seen_null) != (ix & SI_NOT)) break;
47      }
48
49      RETVAL = (i == ((ix & SI_REV) ? -1 : s_len) ? -1 : i);
50  }
51  OUTPUT:
52      RETVAL

  1. El prototipo de la línea 16 indica que el tercer argumento es opcional. La aparición de ; en un prototipo separa los argumentos requeridos de los argumentos opcionales. El tercer argumento es opcional ya que las funciones cindex tienen dos formatos de llamada:

    cindex(STR, CHARS, POSITION)
    cindex(STR, CHARS)
    

    POSITION indica en que posición se comienza la búsqueda. Si se omite se comienza desde el principio. La función retorna -1 si ninguno de los caracteres en CHARS es encontrado.

  2. El tipo STRLEN usado en las líneas 23 y 24 es un tipo entero lo suficientemente grande como para representar el tamaño de cualquier cadena que Perl pueda manejar:
    lhp@nereida:~/Lperl/src/perlcompilerssource/perl-5.8.8$ grep 'MEM_SIZE\>' perl.h
    #define MEM_SIZE Size_t
    typedef MEM_SIZE STRLEN;
    
  3. La macro SvPV tiene la sintáxis char* SvPV(SV* sv, STRLEN len). Devuelve un puntero a la cadena en sv o bien el resultado de convertir sv en una cadena (por ejemplo, si es una referencia o un objeto).

  4. La función strchr tiene por prototipo:
    char *strchr(const char *s, int c);
    
    La función devuelve un puntero a la primera ocurrencia del carácter c en la cadena de caracteres s.

Casiano Rodríguez León
2012-02-29