mirror of
https://github.com/MidnightCommander/mc
synced 2025-01-26 21:22:03 +03:00
Merge branch '1882_esc_seq_in_replace_field'
* 1882_esc_seq_in_replace_field: Remove replace_prepare_t type and use defined constants for use just one type (int) in functions Despite of the fact that algorithm now ignores the absence of closing curly brace '}' (which probably isn't 100% correct), this should be checked in tests for replace_handle_esc_seq function, not process_escape_sequence - it is the replace_handle_esq_seq who decides whether it is an escape sequence or not. added tests for mc_search_regex__replace_handle_esc_seq() function str_isutf8() function now returns gboolean value Ticket #1882: PCRE search: escape sequence support in replacements, UTF8 support (just a flag for libPCRE)
This commit is contained in:
commit
ba09144ce5
@ -598,6 +598,7 @@ if test x$enable_tests != xno; then
|
||||
AC_CONFIG_FILES([
|
||||
lib/tests/Makefile
|
||||
lib/tests/mcconfig/Makefile
|
||||
lib/tests/search/Makefile
|
||||
lib/tests/vfs/Makefile
|
||||
])
|
||||
|
||||
|
@ -91,6 +91,7 @@ typedef struct mc_search_struct
|
||||
off_t start_buffer;
|
||||
/* some data for regexp */
|
||||
int num_results;
|
||||
gboolean is_utf8;
|
||||
mc_search_matchinfo_t *regex_match_info;
|
||||
GString *regex_buffer;
|
||||
#ifdef SEARCH_TYPE_PCRE
|
||||
|
@ -5,7 +5,8 @@
|
||||
Copyright (C) 2009 The Free Software Foundation, Inc.
|
||||
|
||||
Written by:
|
||||
Slava Zanko <slavazanko@gmail.com>, 2009.
|
||||
Slava Zanko <slavazanko@gmail.com>, 2009,2010,2011
|
||||
Vitaliy Filippov <vitalif@yourcmc.ru>, 2011
|
||||
|
||||
This file is part of the Midnight Commander.
|
||||
|
||||
@ -42,6 +43,10 @@
|
||||
|
||||
/*** file scope macro definitions ****************************************************************/
|
||||
|
||||
#define REPLACE_PREPARE_T_NOTHING_SPECIAL -1
|
||||
#define REPLACE_PREPARE_T_REPLACE_FLAG -2
|
||||
#define REPLACE_PREPARE_T_ESCAPE_SEQ -3
|
||||
|
||||
/*** file scope type declarations ****************************************************************/
|
||||
|
||||
typedef enum
|
||||
@ -53,6 +58,7 @@ typedef enum
|
||||
REPLACE_T_LOW_TRANSFORM = 8
|
||||
} replace_transform_type_t;
|
||||
|
||||
|
||||
/*** file scope variables ************************************************************************/
|
||||
|
||||
/*** file scope functions ************************************************************************/
|
||||
@ -374,6 +380,85 @@ mc_search_regex__get_token_by_num (const mc_search_t * lc_mc_search, gsize lc_in
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static gboolean
|
||||
mc_search_regex__replace_handle_esc_seq (const GString * replace_str, const gsize current_pos,
|
||||
gsize * skip_len, int *ret)
|
||||
{
|
||||
char *curr_str = &(replace_str->str[current_pos]);
|
||||
char c = *(curr_str + 1);
|
||||
|
||||
if (replace_str->len > current_pos + 2)
|
||||
{
|
||||
if (c == '{')
|
||||
{
|
||||
for (*skip_len = 2; /* \{ */
|
||||
current_pos + *skip_len < replace_str->len
|
||||
&& *(curr_str + *skip_len) >= '0'
|
||||
&& *(curr_str + *skip_len) <= '7'; (*skip_len)++);
|
||||
if (current_pos + *skip_len < replace_str->len && *(curr_str + *skip_len) == '}')
|
||||
{
|
||||
(*skip_len)++;
|
||||
*ret = REPLACE_PREPARE_T_ESCAPE_SEQ;
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
*ret = REPLACE_PREPARE_T_NOTHING_SPECIAL;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (c == 'x')
|
||||
{
|
||||
*skip_len = 2; /* \x */
|
||||
c = *(curr_str + 2);
|
||||
if (c == '{')
|
||||
{
|
||||
for (*skip_len = 3; /* \x{ */
|
||||
current_pos + *skip_len < replace_str->len
|
||||
&& g_ascii_isxdigit ((guchar) * (curr_str + *skip_len)); (*skip_len)++);
|
||||
if (current_pos + *skip_len < replace_str->len && *(curr_str + *skip_len) == '}')
|
||||
{
|
||||
(*skip_len)++;
|
||||
*ret = REPLACE_PREPARE_T_ESCAPE_SEQ;
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
*ret = REPLACE_PREPARE_T_NOTHING_SPECIAL;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else if (!g_ascii_isxdigit ((guchar) c))
|
||||
{
|
||||
*skip_len = 2; /* \x without number behind */
|
||||
*ret = REPLACE_PREPARE_T_NOTHING_SPECIAL;
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = *(curr_str + 3);
|
||||
if (!g_ascii_isxdigit ((guchar) c))
|
||||
*skip_len = 3; /* \xH */
|
||||
else
|
||||
*skip_len = 4; /* \xHH */
|
||||
*ret = REPLACE_PREPARE_T_ESCAPE_SEQ;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (strchr ("ntvbrfa", c) != NULL)
|
||||
{
|
||||
*skip_len = 2;
|
||||
*ret = REPLACE_PREPARE_T_ESCAPE_SEQ;
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
mc_search_regex__process_replace_str (const GString * replace_str, const gsize current_pos,
|
||||
gsize * skip_len, replace_transform_type_t * replace_flags)
|
||||
@ -383,16 +468,17 @@ mc_search_regex__process_replace_str (const GString * replace_str, const gsize c
|
||||
const char *curr_str = &(replace_str->str[current_pos]);
|
||||
|
||||
if (current_pos > replace_str->len)
|
||||
return -1;
|
||||
return REPLACE_PREPARE_T_NOTHING_SPECIAL;
|
||||
|
||||
*skip_len = 0;
|
||||
|
||||
if (*curr_str == '$' && *(curr_str + 1) == '{' && (*(curr_str + 2) & (char) 0xf0) == 0x30)
|
||||
if ((*curr_str == '$') && (*(curr_str + 1) == '{') && ((*(curr_str + 2) & (char) 0xf0) == 0x30)
|
||||
&& (replace_str->len > current_pos + 2))
|
||||
{
|
||||
if (strutils_is_char_escaped (replace_str->str, curr_str))
|
||||
{
|
||||
*skip_len = 1;
|
||||
return -1;
|
||||
return REPLACE_PREPARE_T_NOTHING_SPECIAL;
|
||||
}
|
||||
|
||||
for (*skip_len = 0;
|
||||
@ -400,34 +486,38 @@ mc_search_regex__process_replace_str (const GString * replace_str, const gsize c
|
||||
&& (*(curr_str + 2 + *skip_len) & (char) 0xf0) == 0x30; (*skip_len)++);
|
||||
|
||||
if (*(curr_str + 2 + *skip_len) != '}')
|
||||
return -1;
|
||||
return REPLACE_PREPARE_T_NOTHING_SPECIAL;
|
||||
|
||||
tmp_str = g_strndup (curr_str + 2, *skip_len);
|
||||
if (tmp_str == NULL)
|
||||
return -1;
|
||||
return REPLACE_PREPARE_T_NOTHING_SPECIAL;
|
||||
|
||||
ret = atoi (tmp_str);
|
||||
g_free (tmp_str);
|
||||
|
||||
*skip_len += 3; /* ${} */
|
||||
return ret;
|
||||
return ret; /* capture buffer index >= 0 */
|
||||
}
|
||||
|
||||
if (*curr_str == '\\')
|
||||
if ((*curr_str == '\\') && (replace_str->len > current_pos + 1))
|
||||
{
|
||||
if (strutils_is_char_escaped (replace_str->str, curr_str))
|
||||
{
|
||||
*skip_len = 1;
|
||||
return -1;
|
||||
return REPLACE_PREPARE_T_NOTHING_SPECIAL;
|
||||
}
|
||||
|
||||
if (g_ascii_isdigit (*(curr_str + 1)))
|
||||
{
|
||||
ret = g_ascii_digit_value (*(curr_str + 1));
|
||||
ret = g_ascii_digit_value (*(curr_str + 1)); /* capture buffer index >= 0 */
|
||||
*skip_len = 2; /* \\ and one digit */
|
||||
return ret;
|
||||
}
|
||||
ret = -2;
|
||||
|
||||
if (!mc_search_regex__replace_handle_esc_seq (replace_str, current_pos, skip_len, &ret))
|
||||
return ret;
|
||||
|
||||
ret = REPLACE_PREPARE_T_REPLACE_FLAG;
|
||||
*skip_len += 2;
|
||||
switch (*(curr_str + 1))
|
||||
{
|
||||
@ -449,13 +539,15 @@ mc_search_regex__process_replace_str (const GString * replace_str, const gsize c
|
||||
*replace_flags = REPLACE_T_NO_TRANSFORM;
|
||||
break;
|
||||
default:
|
||||
ret = -1;
|
||||
ret = REPLACE_PREPARE_T_NOTHING_SPECIAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
mc_search_regex__process_append_str (GString * dest_str, const char *from, gsize len,
|
||||
replace_transform_type_t * replace_flags)
|
||||
@ -517,7 +609,111 @@ mc_search_regex__process_append_str (GString * dest_str, const char *from, gsize
|
||||
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
mc_search_regex__process_escape_sequence (GString * dest_str, const char *from, gsize len,
|
||||
replace_transform_type_t * replace_flags,
|
||||
gboolean is_utf8)
|
||||
{
|
||||
gsize i = 0;
|
||||
unsigned int c = 0;
|
||||
char b;
|
||||
|
||||
if (len == (gsize) (-1))
|
||||
len = strlen (from);
|
||||
if (len == 0)
|
||||
return;
|
||||
if (from[i] == '{')
|
||||
i++;
|
||||
if (i >= len)
|
||||
return;
|
||||
|
||||
if (from[i] == 'x')
|
||||
{
|
||||
i++;
|
||||
if (i < len && from[i] == '{')
|
||||
i++;
|
||||
for (; i < len; i++)
|
||||
{
|
||||
if (from[i] >= '0' && from[i] <= '9')
|
||||
c = c * 16 + from[i] - '0';
|
||||
else if (from[i] >= 'a' && from[i] <= 'f')
|
||||
c = c * 16 + 10 + from[i] - 'a';
|
||||
else if (from[i] >= 'A' && from[i] <= 'F')
|
||||
c = c * 16 + 10 + from[i] - 'A';
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (from[i] >= '0' && from[i] <= '7')
|
||||
for (; i < len && from[i] >= '0' && from[i] <= '7'; i++)
|
||||
c = c * 8 + from[i] - '0';
|
||||
else
|
||||
{
|
||||
switch (from[i])
|
||||
{
|
||||
case 'n':
|
||||
c = '\n';
|
||||
break;
|
||||
case 't':
|
||||
c = '\t';
|
||||
break;
|
||||
case 'v':
|
||||
c = '\v';
|
||||
break;
|
||||
case 'b':
|
||||
c = '\b';
|
||||
break;
|
||||
case 'r':
|
||||
c = '\r';
|
||||
break;
|
||||
case 'f':
|
||||
c = '\f';
|
||||
break;
|
||||
case 'a':
|
||||
c = '\a';
|
||||
break;
|
||||
default:
|
||||
mc_search_regex__process_append_str (dest_str, from, len, replace_flags);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (c < 0x80 || !is_utf8)
|
||||
g_string_append_c (dest_str, (char) c);
|
||||
else if (c < 0x800)
|
||||
{
|
||||
b = 0xC0 | (c >> 6);
|
||||
g_string_append_c (dest_str, b);
|
||||
b = 0x80 | (c & 0x3F);
|
||||
g_string_append_c (dest_str, b);
|
||||
}
|
||||
else if (c < 0x10000)
|
||||
{
|
||||
b = 0xE0 | (c >> 12);
|
||||
g_string_append_c (dest_str, b);
|
||||
b = 0x80 | ((c >> 6) & 0x3F);
|
||||
g_string_append_c (dest_str, b);
|
||||
b = 0x80 | (c & 0x3F);
|
||||
g_string_append_c (dest_str, b);
|
||||
}
|
||||
else if (c < 0x10FFFF)
|
||||
{
|
||||
b = 0xF0 | (c >> 16);
|
||||
g_string_append_c (dest_str, b);
|
||||
b = 0x80 | ((c >> 12) & 0x3F);
|
||||
g_string_append_c (dest_str, b);
|
||||
b = 0x80 | ((c >> 6) & 0x3F);
|
||||
g_string_append_c (dest_str, b);
|
||||
b = 0x80 | (c & 0x3F);
|
||||
g_string_append_c (dest_str, b);
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/*** public functions ****************************************************************************/
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
mc_search__cond_struct_new_init_regex (const char *charset, mc_search_t * lc_mc_search,
|
||||
@ -525,10 +721,6 @@ mc_search__cond_struct_new_init_regex (const char *charset, mc_search_t * lc_mc_
|
||||
{
|
||||
#ifdef SEARCH_TYPE_GLIB
|
||||
GError *error = NULL;
|
||||
#else /* SEARCH_TYPE_GLIB */
|
||||
const char *error;
|
||||
int erroffset;
|
||||
#endif /* SEARCH_TYPE_GLIB */
|
||||
|
||||
if (!lc_mc_search->is_case_sensitive)
|
||||
{
|
||||
@ -538,10 +730,9 @@ mc_search__cond_struct_new_init_regex (const char *charset, mc_search_t * lc_mc_
|
||||
mc_search_cond->str = mc_search__cond_struct_new_regex_ci_str (charset, tmp);
|
||||
g_string_free (tmp, TRUE);
|
||||
}
|
||||
#ifdef SEARCH_TYPE_GLIB
|
||||
mc_search_cond->regex_handle =
|
||||
g_regex_new (mc_search_cond->str->str, G_REGEX_OPTIMIZE | G_REGEX_RAW | G_REGEX_DOTALL, 0,
|
||||
&error);
|
||||
g_regex_new (mc_search_cond->str->str, G_REGEX_OPTIMIZE | G_REGEX_RAW | G_REGEX_DOTALL,
|
||||
0, &error);
|
||||
|
||||
if (error != NULL)
|
||||
{
|
||||
@ -551,8 +742,30 @@ mc_search__cond_struct_new_init_regex (const char *charset, mc_search_t * lc_mc_
|
||||
return;
|
||||
}
|
||||
#else /* SEARCH_TYPE_GLIB */
|
||||
const char *error;
|
||||
int erroffset;
|
||||
int pcre_options = PCRE_EXTRA | PCRE_MULTILINE;
|
||||
|
||||
if (str_isutf8 (charset))
|
||||
{
|
||||
pcre_options |= PCRE_UTF8;
|
||||
if (lc_mc_search->is_case_sensitive)
|
||||
pcre_options |= PCRE_CASELESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!lc_mc_search->is_case_sensitive)
|
||||
{
|
||||
GString *tmp;
|
||||
|
||||
tmp = mc_search_cond->str;
|
||||
mc_search_cond->str = mc_search__cond_struct_new_regex_ci_str (charset, tmp);
|
||||
g_string_free (tmp, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
mc_search_cond->regex_handle =
|
||||
pcre_compile (mc_search_cond->str->str, PCRE_EXTRA, &error, &erroffset, NULL);
|
||||
pcre_compile (mc_search_cond->str->str, pcre_options, &error, &erroffset, NULL);
|
||||
if (mc_search_cond->regex_handle == NULL)
|
||||
{
|
||||
lc_mc_search->error = MC_SEARCH_E_REGEX_COMPILE;
|
||||
@ -572,6 +785,7 @@ mc_search__cond_struct_new_init_regex (const char *charset, mc_search_t * lc_mc_
|
||||
}
|
||||
}
|
||||
#endif /* SEARCH_TYPE_GLIB */
|
||||
lc_mc_search->is_utf8 = str_isutf8 (charset);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -708,7 +922,7 @@ mc_search_regex_prepare_replace_str (mc_search_t * lc_mc_search, GString * repla
|
||||
{
|
||||
lc_index = mc_search_regex__process_replace_str (replace_str, loop, &len, &replace_flags);
|
||||
|
||||
if (lc_index == -1)
|
||||
if (lc_index == REPLACE_PREPARE_T_NOTHING_SPECIAL)
|
||||
{
|
||||
if (len != 0)
|
||||
{
|
||||
@ -723,7 +937,7 @@ mc_search_regex_prepare_replace_str (mc_search_t * lc_mc_search, GString * repla
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lc_index == -2)
|
||||
if (lc_index == REPLACE_PREPARE_T_REPLACE_FLAG)
|
||||
{
|
||||
if (loop)
|
||||
mc_search_regex__process_append_str (ret, prev_str,
|
||||
@ -734,6 +948,21 @@ mc_search_regex_prepare_replace_str (mc_search_t * lc_mc_search, GString * repla
|
||||
continue;
|
||||
}
|
||||
|
||||
/* escape sequence */
|
||||
if (lc_index == REPLACE_PREPARE_T_ESCAPE_SEQ)
|
||||
{
|
||||
mc_search_regex__process_append_str (ret, prev_str,
|
||||
replace_str->str + loop - prev_str,
|
||||
&replace_flags);
|
||||
/* call process_escape_sequence without starting '\\' */
|
||||
mc_search_regex__process_escape_sequence (ret, replace_str->str + loop + 1, len - 1,
|
||||
&replace_flags, lc_mc_search->is_utf8);
|
||||
prev_str = replace_str->str + loop + len;
|
||||
loop += len - 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* invalid capture buffer number */
|
||||
if (lc_index > lc_mc_search->num_results)
|
||||
{
|
||||
g_string_free (ret, TRUE);
|
||||
|
@ -511,10 +511,10 @@ int str_key_collate (const char *t1, const char *t2, int case_sen);
|
||||
*/
|
||||
void str_release_key (char *key, int case_sen);
|
||||
|
||||
/* return 1 if codeset_name is utf8 or utf-8
|
||||
/* return TRUE if codeset_name is utf8 or utf-8
|
||||
* I
|
||||
*/
|
||||
int str_isutf8 (const char *codeset_name);
|
||||
gboolean str_isutf8 (const char *codeset_name);
|
||||
|
||||
const char *str_detect_termencoding (void);
|
||||
|
||||
|
@ -354,15 +354,10 @@ str_choose_str_functions (void)
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
gboolean
|
||||
str_isutf8 (const char *codeset_name)
|
||||
{
|
||||
int result = 0;
|
||||
if (str_test_encoding_class (codeset_name, str_utf8_encodings))
|
||||
{
|
||||
result = 1;
|
||||
}
|
||||
return result;
|
||||
return (str_test_encoding_class (codeset_name, str_utf8_encodings) != 0);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1,4 +1,4 @@
|
||||
SUBDIRS = . mcconfig vfs
|
||||
SUBDIRS = . mcconfig search vfs
|
||||
|
||||
AM_CFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir) @CHECK_CFLAGS@
|
||||
LIBS=@CHECK_LIBS@ $(top_builddir)/lib/libmc.la
|
||||
|
14
lib/tests/search/Makefile.am
Normal file
14
lib/tests/search/Makefile.am
Normal file
@ -0,0 +1,14 @@
|
||||
AM_CFLAGS = -I$(top_srcdir)/lib/search $(GLIB_CFLAGS) -I$(top_srcdir) @CHECK_CFLAGS@
|
||||
LIBS=@CHECK_LIBS@ $(top_builddir)/lib/libmc.la
|
||||
|
||||
TESTS = \
|
||||
regex_replace_esc_seq \
|
||||
regex_process_escape_sequence
|
||||
|
||||
check_PROGRAMS = $(TESTS)
|
||||
|
||||
regex_replace_esc_seq_SOURCES = \
|
||||
regex_replace_esc_seq.c
|
||||
|
||||
regex_process_escape_sequence_SOURCES = \
|
||||
regex_process_escape_sequence.c
|
82
lib/tests/search/regex_process_escape_sequence.c
Normal file
82
lib/tests/search/regex_process_escape_sequence.c
Normal file
@ -0,0 +1,82 @@
|
||||
/* libmc - checks for processing esc sequences in replace string
|
||||
|
||||
Copyright (C) 2011 Free Software Foundation, Inc.
|
||||
|
||||
Written by:
|
||||
Slava Zanko <slavazanko@gmail.com>, 2011
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License
|
||||
as published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#define TEST_SUITE_NAME "lib/search/regex"
|
||||
|
||||
#include <check.h>
|
||||
|
||||
#include "regex.c" /* for testing static functions*/
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
#define test_helper_valid_data(from, etalon, dest_str, replace_flags, utf) { \
|
||||
dest_str = g_string_new(""); \
|
||||
mc_search_regex__process_escape_sequence (dest_str, from, -1, &replace_flags, utf); \
|
||||
fail_if (strcmp(dest_str->str, etalon), "dest_str(%s) != %s", dest_str->str, etalon); \
|
||||
g_string_free(dest_str, TRUE); \
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
START_TEST (test_regex_process_escape_sequence_valid)
|
||||
{
|
||||
GString *dest_str;
|
||||
replace_transform_type_t replace_flags = REPLACE_T_NO_TRANSFORM;
|
||||
|
||||
test_helper_valid_data("{101}", "A", dest_str, replace_flags, FALSE);
|
||||
test_helper_valid_data("x42", "B", dest_str, replace_flags, FALSE);
|
||||
test_helper_valid_data("x{444}", "D", dest_str, replace_flags, FALSE);
|
||||
test_helper_valid_data("x{444}", "ф", dest_str, replace_flags, TRUE);
|
||||
|
||||
test_helper_valid_data("n", "\n", dest_str, replace_flags, FALSE);
|
||||
test_helper_valid_data("t", "\t", dest_str, replace_flags, FALSE);
|
||||
test_helper_valid_data("v", "\v", dest_str, replace_flags, FALSE);
|
||||
test_helper_valid_data("b", "\b", dest_str, replace_flags, FALSE);
|
||||
test_helper_valid_data("r", "\r", dest_str, replace_flags, FALSE);
|
||||
test_helper_valid_data("f", "\f", dest_str, replace_flags, FALSE);
|
||||
test_helper_valid_data("a", "\a", dest_str, replace_flags, FALSE);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
int number_failed;
|
||||
|
||||
Suite *s = suite_create (TEST_SUITE_NAME);
|
||||
TCase *tc_core = tcase_create ("Core");
|
||||
SRunner *sr;
|
||||
|
||||
/* Add new tests here: *************** */
|
||||
tcase_add_test (tc_core, test_regex_process_escape_sequence_valid);
|
||||
/* *********************************** */
|
||||
|
||||
suite_add_tcase (s, tc_core);
|
||||
sr = srunner_create (s);
|
||||
srunner_run_all (sr, CK_NORMAL);
|
||||
number_failed = srunner_ntests_failed (sr);
|
||||
srunner_free (sr);
|
||||
return (number_failed == 0) ? 0 : 1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
118
lib/tests/search/regex_replace_esc_seq.c
Normal file
118
lib/tests/search/regex_replace_esc_seq.c
Normal file
@ -0,0 +1,118 @@
|
||||
/* libmc - checks for processing esc sequences in replace string
|
||||
|
||||
Copyright (C) 2011 Free Software Foundation, Inc.
|
||||
|
||||
Written by:
|
||||
Slava Zanko <slavazanko@gmail.com>, 2011
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License
|
||||
as published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#define TEST_SUITE_NAME "lib/search/regex"
|
||||
|
||||
#include <check.h>
|
||||
|
||||
#include "regex.c" /* for testing static functions*/
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
#define test_helper_check_valid_data( a, b, c, d, e, f ) \
|
||||
{ \
|
||||
fail_unless( a == b, "ret_value != %s", (b) ? "TRUE": "FALSE" ); \
|
||||
fail_unless( c == d, "skip_len(%d) != %d", c, d ); \
|
||||
if (f!=0) fail_unless( e == f, "ret(%d) != %d", e, f ); \
|
||||
}
|
||||
|
||||
#define test_helper_handle_esc_seq( pos, r, skip, flag ) \
|
||||
{ \
|
||||
skip_len = 0;\
|
||||
test_helper_check_valid_data(\
|
||||
mc_search_regex__replace_handle_esc_seq( replace_str, pos, &skip_len, &ret ), r,\
|
||||
skip_len, skip,\
|
||||
ret, flag\
|
||||
); \
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
START_TEST (test_regex_replace_esc_seq_prepare_valid)
|
||||
{
|
||||
GString *replace_str;
|
||||
gsize skip_len;
|
||||
int ret;
|
||||
|
||||
replace_str = g_string_new("bla-bla\\{123}bla-bla\\xabc234 bla-bla\\x{456abcd}bla-bla\\xtre\\n\\t\\v\\b\\r\\f\\a");
|
||||
|
||||
test_helper_handle_esc_seq( 7, FALSE, 6, REPLACE_PREPARE_T_ESCAPE_SEQ ); /* \\{123} */
|
||||
test_helper_handle_esc_seq( 20, FALSE, 4, REPLACE_PREPARE_T_ESCAPE_SEQ ); /* \\xab */
|
||||
test_helper_handle_esc_seq( 36, FALSE, 11, REPLACE_PREPARE_T_ESCAPE_SEQ ); /* \\x{456abcd} */
|
||||
test_helper_handle_esc_seq( 54, FALSE, 2, REPLACE_PREPARE_T_NOTHING_SPECIAL ); /* \\xtre */
|
||||
test_helper_handle_esc_seq( 59, FALSE, 2, REPLACE_PREPARE_T_ESCAPE_SEQ ); /* \\n */
|
||||
test_helper_handle_esc_seq( 61, FALSE, 2, REPLACE_PREPARE_T_ESCAPE_SEQ ); /* \\t */
|
||||
test_helper_handle_esc_seq( 63, FALSE, 2, REPLACE_PREPARE_T_ESCAPE_SEQ ); /* \\v */
|
||||
test_helper_handle_esc_seq( 65, FALSE, 2, REPLACE_PREPARE_T_ESCAPE_SEQ ); /* \\b */
|
||||
test_helper_handle_esc_seq( 67, FALSE, 2, REPLACE_PREPARE_T_ESCAPE_SEQ ); /* \\r */
|
||||
test_helper_handle_esc_seq( 69, FALSE, 2, REPLACE_PREPARE_T_ESCAPE_SEQ ); /* \\f */
|
||||
test_helper_handle_esc_seq( 71, FALSE, 2, REPLACE_PREPARE_T_ESCAPE_SEQ ); /* \\a */
|
||||
|
||||
g_string_free(replace_str, TRUE);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
START_TEST (test_regex_replace_esc_seq_prepare_invalid)
|
||||
{
|
||||
|
||||
GString *replace_str;
|
||||
gsize skip_len;
|
||||
int ret;
|
||||
|
||||
replace_str = g_string_new("\\{123 \\x{qwerty} \\12} \\x{456a-bcd}bla-bla\\satre");
|
||||
|
||||
test_helper_handle_esc_seq( 0, TRUE, 5, REPLACE_PREPARE_T_NOTHING_SPECIAL ); /* \\{123 */
|
||||
test_helper_handle_esc_seq( 6, TRUE, 3, REPLACE_PREPARE_T_NOTHING_SPECIAL ); /* \\x{qwerty} */
|
||||
test_helper_handle_esc_seq( 17, TRUE, 0, REPLACE_PREPARE_T_NOTHING_SPECIAL ); /* \\12} */
|
||||
test_helper_handle_esc_seq( 22, TRUE, 7, REPLACE_PREPARE_T_NOTHING_SPECIAL ); /* \\x{456a-bcd} */
|
||||
test_helper_handle_esc_seq( 41, TRUE, 0, REPLACE_PREPARE_T_NOTHING_SPECIAL ); /* \\satre */
|
||||
|
||||
g_string_free(replace_str, TRUE);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
int number_failed;
|
||||
|
||||
Suite *s = suite_create (TEST_SUITE_NAME);
|
||||
TCase *tc_core = tcase_create ("Core");
|
||||
SRunner *sr;
|
||||
|
||||
/* Add new tests here: *************** */
|
||||
tcase_add_test (tc_core, test_regex_replace_esc_seq_prepare_valid);
|
||||
tcase_add_test (tc_core, test_regex_replace_esc_seq_prepare_invalid);
|
||||
/* *********************************** */
|
||||
|
||||
suite_add_tcase (s, tc_core);
|
||||
sr = srunner_create (s);
|
||||
srunner_run_all (sr, CK_NORMAL);
|
||||
number_failed = srunner_ntests_failed (sr);
|
||||
srunner_free (sr);
|
||||
return (number_failed == 0) ? 0 : 1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
Loading…
Reference in New Issue
Block a user