Exemplo n.º 1
0
static void
glob_like_ucs_nfd_common(sqlite3_context *context,
                         int argc, sqlite3_value **argv,
                         svn_boolean_t sql_like)
{
  svn_sqlite__db_t *const db = sqlite3_user_data(context);

  const char *const pattern = (void*)sqlite3_value_text(argv[0]);
  const apr_size_t pattern_len = sqlite3_value_bytes(argv[0]);
  const char *const string = (void*)sqlite3_value_text(argv[1]);
  const apr_size_t string_len = sqlite3_value_bytes(argv[1]);

  const char *escape = NULL;
  apr_size_t escape_len = 0;

  svn_boolean_t match;
  svn_error_t *err;

  if (pattern_len > SQLITE_MAX_LIKE_PATTERN_LENGTH)
    {
      sqlite3_result_error(context, "LIKE or GLOB pattern too complex", -1);
      return;
    }

  if (argc == 3 && sql_like)
    {
      escape = (void*)sqlite3_value_text(argv[2]);
      escape_len = sqlite3_value_bytes(argv[2]);
    }

  if (pattern && string)
    {
      err = svn_utf__glob(pattern, pattern_len, string, string_len,
                          escape, escape_len, sql_like,
                          &db->sqlext_buf1, &db->sqlext_buf2, &db->sqlext_buf3,
                          &match);

      if (err)
        {
          const char *errmsg;
          svn_membuf__ensure(&db->sqlext_buf1, 512);
          errmsg = svn_err_best_message(err,
                                        db->sqlext_buf1.data,
                                        db->sqlext_buf1.size - 1);
          svn_error_clear(err);
          sqlite3_result_error(context, errmsg, -1);
          return;
        }

      sqlite3_result_int(context, match);
    }
}
Exemplo n.º 2
0
unsigned int
svn_string__similarity(const svn_string_t *stringa,
                       const svn_string_t *stringb,
                       svn_membuf_t *buffer, apr_size_t *rlcs)
{
  const char *stra = stringa->data;
  const char *strb = stringb->data;
  const apr_size_t lena = stringa->len;
  const apr_size_t lenb = stringb->len;
  const apr_size_t total = lena + lenb;
  const char *enda = stra + lena;
  const char *endb = strb + lenb;
  apr_size_t lcs = 0;

  /* Skip the common prefix ... */
  while (stra < enda && strb < endb && *stra == *strb)
    {
      ++stra; ++strb;
      ++lcs;
    }

  /* ... and the common suffix */
  while (stra < enda && strb < endb)
    {
      --enda; --endb;
      if (*enda != *endb)
        {
          ++enda; ++endb;
          break;
        }

      ++lcs;
    }

  if (stra < enda && strb < endb)
    {
      const apr_size_t resta = enda - stra;
      const apr_size_t restb = endb - strb;
      const apr_size_t slots = (resta > restb ? restb : resta);
      apr_size_t *curr, *prev;
      const char *pstr;

      /* The outer loop must iterate on the longer string. */
      if (resta < restb)
        {
          pstr = stra;
          stra = strb;
          strb = pstr;

          pstr = enda;
          enda = endb;
          endb = pstr;
        }

      /* Allocate two columns in the LCS matrix
         ### Optimize this to (slots + 2) instesd of 2 * (slots + 1) */
      svn_membuf__ensure(buffer, 2 * (slots + 1) * sizeof(apr_size_t));
      svn_membuf__nzero(buffer, (slots + 2) * sizeof(apr_size_t));
      prev = buffer->data;
      curr = prev + slots + 1;

      /* Calculate LCS length of the remainder */
      for (pstr = stra; pstr < enda; ++pstr)
        {
          int i;
          for (i = 1; i <= slots; ++i)
            {
              if (*pstr == strb[i-1])
                curr[i] = prev[i-1] + 1;
              else
                curr[i] = (curr[i-1] > prev[i] ? curr[i-1] : prev[i]);
            }

          /* Swap the buffers, making the previous one current */
          {
            apr_size_t *const temp = prev;
            prev = curr;
            curr = temp;
          }
        }

      lcs += prev[slots];
    }

  if (rlcs)
    *rlcs = lcs;

  /* Return similarity ratio rounded to 4 significant digits */
  if (total)
    return(unsigned int)((2000 * lcs + total/2) / total);
  else
    return 1000;
}