The R Project SVN R

Rev

Rev 65105 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

/*
  tre-match-utils.h - TRE matcher helper definitions

  This software is released under a BSD-style license.
  See the file LICENSE for details and copyright.

*/

#define str_source ((const tre_str_source*)string)

#ifdef TRE_WCHAR

#ifdef TRE_MULTIBYTE

/* Wide character and multibyte support. */

#define GET_NEXT_WCHAR()                              \
  do {                                        \
    prev_c = next_c;                                  \
    if (type == STR_BYTE)                             \
      {                                       \
    pos++;                                    \
    if (len >= 0 && pos >= len)                       \
      next_c = '\0';                              \
    else                                      \
      next_c = (unsigned char)(*str_byte++);                  \
      }                                       \
    else if (type == STR_WIDE)                            \
      {                                       \
    pos++;                                    \
    if (len >= 0 && pos >= len)                       \
      next_c = L'\0';                             \
    else                                      \
      next_c = *str_wide++;                           \
      }                                       \
    else if (type == STR_MBS)                             \
      {                                       \
        pos += pos_add_next;                                  \
    if (str_byte == NULL)                             \
      next_c = L'\0';                             \
    else                                      \
      {                                   \
        size_t w;                                 \
        int max;                                  \
        if (len >= 0)                             \
          max = len - pos;                            \
        else                                  \
          max = 32;                               \
        if (max <= 0)                             \
          {                                   \
        next_c = L'\0';                           \
        pos_add_next = 1;                         \
          }                                   \
        else                                  \
          {                                   \
        w = tre_mbrtowc(&next_c, str_byte, (size_t)max, &mbstate);    \
        if (w == (size_t)-1 || w == (size_t)-2)               \
          return REG_NOMATCH;                         \
        if (w == 0 && len >= 0)                       \
          {                               \
            pos_add_next = 1;                         \
            next_c = 0;                           \
            str_byte++;                           \
          }                               \
        else                                  \
          {                               \
            pos_add_next = (unsigned int)w;                       \
            str_byte += w;                        \
          }                               \
          }                                   \
      }                                   \
      }                                       \
    else if (type == STR_USER)                            \
      {                                       \
        pos += pos_add_next;                                  \
    str_user_end = str_source->get_next_char(&next_c, &pos_add_next,      \
                                                 str_source->context);        \
      }                                       \
  } while(/*CONSTCOND*/(void)0,0)

#else /* !TRE_MULTIBYTE */

/* Wide character support, no multibyte support. */

#define GET_NEXT_WCHAR()                              \
  do {                                        \
    prev_c = next_c;                                  \
    if (type == STR_BYTE)                             \
      {                                       \
    pos++;                                    \
    if (len >= 0 && pos >= len)                       \
      next_c = '\0';                              \
    else                                      \
      next_c = (unsigned char)(*str_byte++);                  \
      }                                       \
    else if (type == STR_WIDE)                            \
      {                                       \
    pos++;                                    \
    if (len >= 0 && pos >= len)                       \
      next_c = L'\0';                             \
    else                                      \
      next_c = *str_wide++;                           \
      }                                       \
    else if (type == STR_USER)                            \
      {                                       \
        pos += pos_add_next;                                  \
    str_user_end = str_source->get_next_char(&next_c, &pos_add_next,      \
                                                 str_source->context);        \
      }                                       \
  } while(/*CONSTCOND*/(void)0,0)

#endif /* !TRE_MULTIBYTE */

#else /* !TRE_WCHAR */

/* No wide character or multibyte support. */

#define GET_NEXT_WCHAR()                              \
  do {                                        \
    prev_c = next_c;                                  \
    if (type == STR_BYTE)                             \
      {                                       \
    pos++;                                    \
    if (len >= 0 && pos >= len)                       \
      next_c = '\0';                              \
    else                                      \
      next_c = (unsigned char)(*str_byte++);                  \
      }                                       \
    else if (type == STR_USER)                            \
      {                                       \
    pos += pos_add_next;                              \
    str_user_end = str_source->get_next_char(&next_c, &pos_add_next,      \
                         str_source->context);        \
      }                                       \
  } while(/*CONSTCOND*/(void)0,0)

#endif /* !TRE_WCHAR */



#define IS_WORD_CHAR(c)  ((c) == L'_' || tre_isalnum(c))

#define CHECK_ASSERTIONS(assertions)                          \
  (((assertions & ASSERT_AT_BOL)                          \
    && (pos > 0 || reg_notbol)                            \
    && (prev_c != L'\n' || !reg_newline))                     \
   || ((assertions & ASSERT_AT_EOL)                       \
       && (next_c != L'\0' || reg_noteol)                     \
       && (next_c != L'\n' || !reg_newline))                      \
   || ((assertions & ASSERT_AT_BOW)                       \
       && (IS_WORD_CHAR(prev_c) || !IS_WORD_CHAR(next_c)))                \
   || ((assertions & ASSERT_AT_EOW)                       \
       && (!IS_WORD_CHAR(prev_c) || IS_WORD_CHAR(next_c)))            \
   || ((assertions & ASSERT_AT_WB)                        \
       && (pos != 0 && next_c != L'\0'                        \
       && IS_WORD_CHAR(prev_c) == IS_WORD_CHAR(next_c)))              \
   || ((assertions & ASSERT_AT_WB_NEG)                        \
       && (pos == 0 || next_c == L'\0'                        \
       || IS_WORD_CHAR(prev_c) != IS_WORD_CHAR(next_c))))

#define CHECK_CHAR_CLASSES(trans_i, tnfa, eflags)                             \
  (((trans_i->assertions & ASSERT_CHAR_CLASS)                                 \
       && !(tnfa->cflags & REG_ICASE)                                         \
       && !tre_isctype((tre_cint_t)prev_c, trans_i->u.class))                 \
    || ((trans_i->assertions & ASSERT_CHAR_CLASS)                             \
        && (tnfa->cflags & REG_ICASE)                                         \
        && !tre_isctype(tre_tolower((tre_cint_t)prev_c),trans_i->u.class)     \
    && !tre_isctype(tre_toupper((tre_cint_t)prev_c),trans_i->u.class))    \
    || ((trans_i->assertions & ASSERT_CHAR_CLASS_NEG)                         \
        && tre_neg_char_classes_match(trans_i->neg_classes,(tre_cint_t)prev_c,\
                                      tnfa->cflags & REG_ICASE)))




/* Returns 1 if `t1' wins `t2', 0 otherwise. */
inline static int
tre_tag_order(int num_tags, tre_tag_direction_t *tag_directions,
          int *t1, int *t2)
{
  int i;
  for (i = 0; i < num_tags; i++)
    {
      if (tag_directions[i] == TRE_TAG_MINIMIZE)
    {
      if (t1[i] < t2[i])
        return 1;
      if (t1[i] > t2[i])
        return 0;
    }
      else
    {
      if (t1[i] > t2[i])
        return 1;
      if (t1[i] < t2[i])
        return 0;
    }
    }
  /*  assert(0);*/
  return 0;
}

inline static int
tre_neg_char_classes_match(tre_ctype_t *classes, tre_cint_t wc, int icase)
{
  DPRINT(("neg_char_classes_test: %p, %d, %d\n", classes, wc, icase));
  while (*classes != (tre_ctype_t)0)
    if ((!icase && tre_isctype(wc, *classes))
    || (icase && (tre_isctype(tre_toupper(wc), *classes)
              || tre_isctype(tre_tolower(wc), *classes))))
      return 1; /* Match. */
    else
      classes++;
  return 0; /* No match. */
}