mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-05-30 09:20:07 +02:00
New functions: g_regex_ref(), g_regex_unref() which replaces
2007-06-03 Yevgen Muntyan <muntyan@tamu.edu> * glib/gregex.c: * glib/gregex.h: New functions: g_regex_ref(), g_regex_unref() which replaces g_regex_free(); g_match_info_get_regex(), g_match_info_get_string(); g_regex_check_replacement(). Made g_match_info_expand_references() accept NULL; changed GRegexEvalCallback to take only arguments which are likely to be actualy used. * docs/reference/glib/glib-sections.txt: * glib/glib.symbols: Added new functions. * tests/regex-test.c: Test them. * docs/reference/glib/tmpl/gregex.sgml: Updated GRegexEvalCallback docs. svn path=/trunk/; revision=5524
This commit is contained in:
parent
458c58ae43
commit
904c42896f
16
ChangeLog
16
ChangeLog
@ -1,3 +1,19 @@
|
||||
2007-06-03 Yevgen Muntyan <muntyan@tamu.edu>
|
||||
|
||||
* glib/gregex.c:
|
||||
* glib/gregex.h: New functions: g_regex_ref(), g_regex_unref() which
|
||||
replaces g_regex_free(); g_match_info_get_regex(), g_match_info_get_string();
|
||||
g_regex_check_replacement().
|
||||
Made g_match_info_expand_references() accept NULL; changed GRegexEvalCallback
|
||||
to take only arguments which are likely to be actualy used.
|
||||
|
||||
* docs/reference/glib/glib-sections.txt:
|
||||
* glib/glib.symbols: Added new functions.
|
||||
|
||||
* tests/regex-test.c: Test them.
|
||||
|
||||
* docs/reference/glib/tmpl/gregex.sgml: Updated GRegexEvalCallback docs.
|
||||
|
||||
2007-05-31 Matthias Clasen <mclasen@redhat.com>
|
||||
|
||||
* README.win32: Fix a typo. (#423708, Olivier Delhomme)
|
||||
|
@ -873,7 +873,8 @@ GRegexMatchFlags
|
||||
GRegex
|
||||
GRegexEvalCallback
|
||||
g_regex_new
|
||||
g_regex_free
|
||||
g_regex_ref
|
||||
g_regex_unref
|
||||
g_regex_get_pattern
|
||||
g_regex_get_max_backref
|
||||
g_regex_get_capture_count
|
||||
@ -890,7 +891,10 @@ g_regex_split_full
|
||||
g_regex_replace
|
||||
g_regex_replace_literal
|
||||
g_regex_replace_eval
|
||||
g_regex_check_replacement
|
||||
GMatchInfo
|
||||
g_match_info_get_regex
|
||||
g_match_info_get_string
|
||||
g_match_info_free
|
||||
g_match_info_next
|
||||
g_match_info_get_match_count
|
||||
|
@ -203,15 +203,16 @@ structure is opaque and its fields cannot be accessed directly.
|
||||
<!-- ##### USER_FUNCTION GRegexEvalCallback ##### -->
|
||||
<para>
|
||||
Specifies the type of the function passed to g_regex_replace_eval().
|
||||
It is called for each occurance of the pattern @regex in @string, and it
|
||||
should append the replacement to @result.
|
||||
It is called for each occurance of the pattern in the string passed
|
||||
to g_regex_replace_eval(), and it should append the replacement to
|
||||
@result.
|
||||
</para>
|
||||
|
||||
@Param1: the #GRegex passed to g_regex_replace_eval()
|
||||
@Param2: the #GMatchInfo generated by the match
|
||||
@Param3: the string used to perform matches against
|
||||
@Param4: a #GString containing the new string
|
||||
@Param5: user data passed to g_regex_replace_eval()
|
||||
@Param1: the #GMatchInfo generated by the match. Use g_match_info_get_regex()
|
||||
and g_match_info_get_string() if you need the #GRegex or the matched
|
||||
string.
|
||||
@Param2: a #GString containing the new string
|
||||
@Param3: user data passed to g_regex_replace_eval()
|
||||
@Returns: %FALSE to continue the replacement process, %TRUE to stop it
|
||||
@Since: 2.14
|
||||
|
||||
|
@ -1427,7 +1427,8 @@ g_get_codeset
|
||||
#if IN_FILE(__G_REGEX_C__)
|
||||
g_regex_error_quark
|
||||
g_regex_new
|
||||
g_regex_free
|
||||
g_regex_ref
|
||||
g_regex_unref
|
||||
g_regex_get_pattern
|
||||
g_regex_get_max_backref
|
||||
g_regex_get_capture_count
|
||||
@ -1444,6 +1445,9 @@ g_regex_split_full
|
||||
g_regex_replace
|
||||
g_regex_replace_literal
|
||||
g_regex_replace_eval
|
||||
g_regex_check_replacement
|
||||
g_match_info_get_regex
|
||||
g_match_info_get_string
|
||||
g_match_info_free
|
||||
g_match_info_next
|
||||
g_match_info_matches
|
||||
|
240
glib/gregex.c
240
glib/gregex.c
@ -98,13 +98,9 @@ struct _GRegex
|
||||
/* TRUE if ret is an error code, FALSE otherwise. */
|
||||
#define IS_PCRE_ERROR(ret) ((ret) < PCRE_ERROR_NOMATCH && (ret) != PCRE_ERROR_PARTIAL)
|
||||
|
||||
static GRegex *regex_ref (GRegex *regex);
|
||||
static void regex_unref (GRegex *regex);
|
||||
|
||||
typedef struct _InterpolationData InterpolationData;
|
||||
static gboolean interpolate_replacement (const GRegex *regex,
|
||||
const GMatchInfo *match_info,
|
||||
const gchar *string,
|
||||
static gboolean interpolation_list_needs_match (GList *list);
|
||||
static gboolean interpolate_replacement (const GMatchInfo *match_info,
|
||||
GString *result,
|
||||
gpointer data);
|
||||
static GList *split_replacement (const gchar *replacement,
|
||||
@ -195,7 +191,7 @@ match_info_new (const GRegex *regex,
|
||||
string_len = strlen (string);
|
||||
|
||||
match_info = g_new0 (GMatchInfo, 1);
|
||||
match_info->regex = regex_ref ((GRegex *)regex);
|
||||
match_info->regex = g_regex_ref ((GRegex *)regex);
|
||||
match_info->string = string;
|
||||
match_info->string_len = string_len;
|
||||
match_info->matches = PCRE_ERROR_NOMATCH;
|
||||
@ -222,6 +218,44 @@ match_info_new (const GRegex *regex,
|
||||
return match_info;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_match_info_get_regex:
|
||||
* @match_info: a #GMatchInfo
|
||||
*
|
||||
* Returns #GRegex object used in @match_info. It belongs to glib
|
||||
* and must not be freed. Use g_regex_ref() if you need to keep it
|
||||
* after you free @match_info object.
|
||||
*
|
||||
* Returns: #GRegex object used in @match_info
|
||||
*
|
||||
* Since: 2.14
|
||||
*/
|
||||
GRegex *
|
||||
g_match_info_get_regex (const GMatchInfo *match_info)
|
||||
{
|
||||
g_return_val_if_fail (match_info != NULL, NULL);
|
||||
return match_info->regex;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_match_info_get_string:
|
||||
* @match_info: a #GMatchInfo
|
||||
*
|
||||
* Returns the string searched with @match_info. This is the
|
||||
* string passed to g_regex_match() or g_regex_replace() so
|
||||
* you may not free it before calling this function.
|
||||
*
|
||||
* Returns: the string searched with @match_info
|
||||
*
|
||||
* Since: 2.14
|
||||
*/
|
||||
const gchar *
|
||||
g_match_info_get_string (const GMatchInfo *match_info)
|
||||
{
|
||||
g_return_val_if_fail (match_info != NULL, NULL);
|
||||
return match_info->string;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_match_info_free:
|
||||
* @match_info: a #GMatchInfo
|
||||
@ -233,10 +267,13 @@ match_info_new (const GRegex *regex,
|
||||
void
|
||||
g_match_info_free (GMatchInfo *match_info)
|
||||
{
|
||||
regex_unref (match_info->regex);
|
||||
g_free (match_info->offsets);
|
||||
g_free (match_info->workspace);
|
||||
g_free (match_info);
|
||||
if (match_info)
|
||||
{
|
||||
g_regex_unref (match_info->regex);
|
||||
g_free (match_info->offsets);
|
||||
g_free (match_info->workspace);
|
||||
g_free (match_info);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -403,13 +440,14 @@ g_match_info_is_partial_match (const GMatchInfo *match_info)
|
||||
|
||||
/**
|
||||
* g_match_info_expand_references:
|
||||
* @match_info: a #GMatchInfo
|
||||
* @match_info: a #GMatchInfo or %NULL
|
||||
* @string_to_expand: the string to expand
|
||||
* @error: location to store the error occuring, or %NULL to ignore errors
|
||||
*
|
||||
* Returns a new string containing the text in @string_to_expand with
|
||||
* references expanded. References refer to the last match done with
|
||||
* @string against @regex and have the same syntax used by g_regex_replace().
|
||||
* references and escape sequences expanded. References refer to the last
|
||||
* match done with @string against @regex and have the same syntax used by
|
||||
* g_regex_replace().
|
||||
*
|
||||
* The @string_to_expand must be UTF-8 encoded even if #G_REGEX_RAW was
|
||||
* passed to g_regex_new().
|
||||
@ -417,6 +455,13 @@ g_match_info_is_partial_match (const GMatchInfo *match_info)
|
||||
* The backreferences are extracted from the string passed to the match
|
||||
* function, so you cannot call this function after freeing the string.
|
||||
*
|
||||
* @match_info may be %NULL in which case @string_to_expand must not
|
||||
* contain references. For instance "foo\n" does not refer to an actual
|
||||
* pattern and '\n' merely will be replaced with \n character,
|
||||
* while to expand "\0" (whole match) one needs the result of a match.
|
||||
* Use g_regex_check_replacement() to find out whether @string_to_expand
|
||||
* contains references.
|
||||
*
|
||||
* Returns: the expanded string, or %NULL if an error occurred
|
||||
*
|
||||
* Since: 2.14
|
||||
@ -430,7 +475,6 @@ g_match_info_expand_references (const GMatchInfo *match_info,
|
||||
GList *list;
|
||||
GError *tmp_error = NULL;
|
||||
|
||||
g_return_val_if_fail (match_info != NULL, NULL);
|
||||
g_return_val_if_fail (string_to_expand != NULL, NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
@ -441,9 +485,16 @@ g_match_info_expand_references (const GMatchInfo *match_info,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!match_info && interpolation_list_needs_match (list))
|
||||
{
|
||||
g_critical ("String '%s' contains references to the match, can't "
|
||||
"expand references without GMatchInfo object",
|
||||
string_to_expand);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = g_string_sized_new (strlen (string_to_expand));
|
||||
interpolate_replacement (match_info->regex, match_info,
|
||||
match_info->string, result, list);
|
||||
interpolate_replacement (match_info, result, list);
|
||||
|
||||
g_list_foreach (list, (GFunc)free_interpolation_data, NULL);
|
||||
g_list_free (list);
|
||||
@ -724,16 +775,38 @@ g_regex_error_quark (void)
|
||||
return error_quark;
|
||||
}
|
||||
|
||||
static GRegex *
|
||||
regex_ref (GRegex *regex)
|
||||
/**
|
||||
* g_regex_ref:
|
||||
* @regex: a #GRegex
|
||||
*
|
||||
* Increases reference count of @regex by 1.
|
||||
*
|
||||
* Returns: @regex
|
||||
*
|
||||
* Since: 2.14
|
||||
*/
|
||||
GRegex *
|
||||
g_regex_ref (GRegex *regex)
|
||||
{
|
||||
g_return_val_if_fail (regex != NULL, NULL);
|
||||
g_atomic_int_inc ((gint*) ®ex->ref_count);
|
||||
return regex;
|
||||
}
|
||||
|
||||
static void
|
||||
regex_unref (GRegex *regex)
|
||||
/**
|
||||
* g_regex_unref:
|
||||
* @regex: a #GRegex
|
||||
*
|
||||
* Decreases reference count of @regex by 1. When reference count drops
|
||||
* to zero, it frees all the memory associated with the regex structure.
|
||||
*
|
||||
* Since: 2.14
|
||||
*/
|
||||
void
|
||||
g_regex_unref (GRegex *regex)
|
||||
{
|
||||
g_return_if_fail (regex != NULL);
|
||||
|
||||
if (g_atomic_int_exchange_and_add ((gint *) ®ex->ref_count, -1) - 1 == 0)
|
||||
{
|
||||
g_free (regex->pattern);
|
||||
@ -755,7 +828,8 @@ regex_unref (GRegex *regex)
|
||||
* Compiles the regular expression to an internal form, and does the initial
|
||||
* setup of the #GRegex structure.
|
||||
*
|
||||
* Returns: a #GRegex structure
|
||||
* Returns: a #GRegex structure. Call g_regex_unref() when you are done
|
||||
* with it.
|
||||
*
|
||||
* Since: 2.14
|
||||
*/
|
||||
@ -873,23 +947,6 @@ g_regex_new (const gchar *pattern,
|
||||
return regex;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_regex_free:
|
||||
* @regex: a #GRegex
|
||||
*
|
||||
* Frees all the memory associated with the regex structure.
|
||||
*
|
||||
* Since: 2.14
|
||||
*/
|
||||
void
|
||||
g_regex_free (GRegex *regex)
|
||||
{
|
||||
if (regex == NULL)
|
||||
return;
|
||||
|
||||
regex_unref (regex);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_regex_get_pattern:
|
||||
* @regex: a #GRegex structure
|
||||
@ -988,7 +1045,7 @@ g_regex_match_simple (const gchar *pattern,
|
||||
if (!regex)
|
||||
return FALSE;
|
||||
result = g_regex_match_full (regex, string, -1, 0, match_options, NULL, NULL);
|
||||
g_regex_free (regex);
|
||||
g_regex_unref (regex);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1006,7 +1063,9 @@ g_regex_match_simple (const gchar *pattern,
|
||||
* structures.
|
||||
*
|
||||
* A #GMatchInfo structure, used to get information on the match, is stored
|
||||
* in @match_info if not %NULL.
|
||||
* in @match_info if not %NULL. Note that if @match_info is not %NULL then
|
||||
* it is created even if the function returns %FALSE, i.e. you must free it
|
||||
* regardless if regular expression actually matched.
|
||||
*
|
||||
* To retrieve all the non-overlapping matches of the pattern in string you
|
||||
* can use g_match_info_next().
|
||||
@ -1029,7 +1088,7 @@ g_regex_match_simple (const gchar *pattern,
|
||||
* g_match_info_next (match_info, NULL);
|
||||
* }
|
||||
* g_match_info_free (match_info);
|
||||
* g_regex_free (regex);
|
||||
* g_regex_unref (regex);
|
||||
* }
|
||||
* </programlisting></informalexample>
|
||||
*
|
||||
@ -1068,7 +1127,13 @@ g_regex_match (const GRegex *regex,
|
||||
* with any kind of lookbehind assertion, such as "\b".
|
||||
*
|
||||
* A #GMatchInfo structure, used to get information on the match, is stored
|
||||
* in @match_info if not %NULL.
|
||||
* in @match_info if not %NULL. Note that if @match_info is not %NULL then
|
||||
* it is created even if the function returns %FALSE, i.e. you must free it
|
||||
* regardless if regular expression actually matched.
|
||||
*
|
||||
* @string is not copied and is used in #GMatchInfo internally. If you use
|
||||
* any #GMatchInfo method (except g_match_info_free()) after freeing or
|
||||
* modifying @string then the behaviour is undefined.
|
||||
*
|
||||
* To retrieve all the non-overlapping matches of the pattern in string you
|
||||
* can use g_match_info_next().
|
||||
@ -1092,7 +1157,7 @@ g_regex_match (const GRegex *regex,
|
||||
* g_match_info_next (match_info, &error);
|
||||
* }
|
||||
* g_match_info_free (match_info);
|
||||
* g_regex_free (regex);
|
||||
* g_regex_unref (regex);
|
||||
* if (error != NULL)
|
||||
* {
|
||||
* g_printerr ("Error while matching: %s\n", error->message);
|
||||
@ -1148,7 +1213,9 @@ g_regex_match_full (const GRegex *regex,
|
||||
* For more documentation see g_regex_match_all_full().
|
||||
*
|
||||
* A #GMatchInfo structure, used to get information on the match, is stored
|
||||
* in @match_info if not %NULL.
|
||||
* in @match_info if not %NULL. Note that if @match_info is not %NULL then
|
||||
* it is created even if the function returns %FALSE, i.e. you must free it
|
||||
* regardless if regular expression actually matched.
|
||||
*
|
||||
* Returns: %TRUE is the string matched, %FALSE otherwise
|
||||
*
|
||||
@ -1203,7 +1270,9 @@ g_regex_match_all (const GRegex *regex,
|
||||
* with any kind of lookbehind assertion, such as "\b".
|
||||
*
|
||||
* A #GMatchInfo structure, used to get information on the match, is stored
|
||||
* in @match_info if not %NULL.
|
||||
* in @match_info if not %NULL. Note that if @match_info is not %NULL then
|
||||
* it is created even if the function returns %FALSE, i.e. you must free it
|
||||
* regardless if regular expression actually matched.
|
||||
*
|
||||
* Returns: %TRUE is the string matched, %FALSE otherwise
|
||||
*
|
||||
@ -1353,7 +1422,7 @@ g_regex_split_simple (const gchar *pattern,
|
||||
if (!regex)
|
||||
return NULL;
|
||||
result = g_regex_split_full (regex, string, -1, 0, match_options, 0, NULL);
|
||||
g_regex_free (regex);
|
||||
g_regex_unref (regex);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1955,9 +2024,7 @@ string_append (GString *string,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
interpolate_replacement (const GRegex *regex,
|
||||
const GMatchInfo *match_info,
|
||||
const gchar *string,
|
||||
interpolate_replacement (const GMatchInfo *match_info,
|
||||
GString *result,
|
||||
gpointer data)
|
||||
{
|
||||
@ -2004,6 +2071,28 @@ interpolate_replacement (const GRegex *regex,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* whether actual match_info is needed for replacement, i.e.
|
||||
* whether there are references
|
||||
*/
|
||||
static gboolean
|
||||
interpolation_list_needs_match (GList *list)
|
||||
{
|
||||
while (list != NULL)
|
||||
{
|
||||
InterpolationData *data = list->data;
|
||||
|
||||
if (data->type == REPL_TYPE_SYMBOLIC_REFERENCE ||
|
||||
data->type == REPL_TYPE_NUMERIC_REFERENCE)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_regex_replace:
|
||||
* @regex: a #GRegex structure
|
||||
@ -2108,9 +2197,7 @@ g_regex_replace (const GRegex *regex,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
literal_replacement (const GRegex *regex,
|
||||
const GMatchInfo *match_info,
|
||||
const gchar *string,
|
||||
literal_replacement (const GMatchInfo *match_info,
|
||||
GString *result,
|
||||
gpointer data)
|
||||
{
|
||||
@ -2217,7 +2304,7 @@ g_regex_replace_eval (const GRegex *regex,
|
||||
g_string_append_len (result,
|
||||
string + str_pos,
|
||||
match_info->offsets[0] - str_pos);
|
||||
done = (*eval) (regex, match_info, string, result, user_data);
|
||||
done = (*eval) (match_info, result, user_data);
|
||||
str_pos = match_info->offsets[1];
|
||||
g_match_info_next (match_info, &tmp_error);
|
||||
}
|
||||
@ -2233,6 +2320,51 @@ g_regex_replace_eval (const GRegex *regex,
|
||||
return g_string_free (result, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_regex_check_replacement:
|
||||
* @replacement: the replacement string
|
||||
* @has_references: location to store information about
|
||||
* references in @replacement or %NULL
|
||||
* @error: location to store error
|
||||
*
|
||||
* Checks whether @replacement is a valid replacement string (see g_regex_replace()),
|
||||
* i.e. that all escape sequences in it are valid.
|
||||
*
|
||||
* If @has_references is not %NULL then @replacement is checked for
|
||||
* pattern references. For instance, replacement text 'foo\n'
|
||||
* does not contain references and may be evaluated without information
|
||||
* about actual match, but '\0\1' (whole match followed by first subpattern)
|
||||
* requires valid #GMatchInfo object.
|
||||
*
|
||||
* Returns: whether @replacement is a valid replacement string
|
||||
*
|
||||
* Since: 2.14
|
||||
*/
|
||||
gboolean
|
||||
g_regex_check_replacement (const gchar *replacement,
|
||||
gboolean *has_references,
|
||||
GError **error)
|
||||
{
|
||||
GList *list;
|
||||
GError *tmp = NULL;
|
||||
|
||||
list = split_replacement (replacement, &tmp);
|
||||
|
||||
if (tmp)
|
||||
{
|
||||
g_propagate_error (error, tmp);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (has_references)
|
||||
*has_references = interpolation_list_needs_match (list);
|
||||
|
||||
g_list_foreach (list, (GFunc) free_interpolation_data, NULL);
|
||||
g_list_free (list);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_regex_escape_string:
|
||||
* @string: the string to escape
|
||||
|
@ -77,18 +77,17 @@ typedef enum
|
||||
typedef struct _GRegex GRegex;
|
||||
typedef struct _GMatchInfo GMatchInfo;
|
||||
|
||||
typedef gboolean (*GRegexEvalCallback) (const GRegex *,
|
||||
const GMatchInfo *,
|
||||
const gchar *,
|
||||
GString *,
|
||||
gpointer);
|
||||
typedef gboolean (*GRegexEvalCallback) (const GMatchInfo *match_info,
|
||||
GString *result,
|
||||
gpointer user_data);
|
||||
|
||||
|
||||
GRegex *g_regex_new (const gchar *pattern,
|
||||
GRegexCompileFlags compile_options,
|
||||
GRegexMatchFlags match_options,
|
||||
GError **error);
|
||||
void g_regex_free (GRegex *regex);
|
||||
GRegex *g_regex_ref (GRegex *regex);
|
||||
void g_regex_unref (GRegex *regex);
|
||||
const gchar *g_regex_get_pattern (const GRegex *regex);
|
||||
gint g_regex_get_max_backref (const GRegex *regex);
|
||||
gint g_regex_get_capture_count (const GRegex *regex);
|
||||
@ -164,8 +163,14 @@ gchar *g_regex_replace_eval (const GRegex *regex,
|
||||
GRegexEvalCallback eval,
|
||||
gpointer user_data,
|
||||
GError **error);
|
||||
gboolean g_regex_check_replacement (const gchar *replacement,
|
||||
gboolean *has_references,
|
||||
GError **error);
|
||||
|
||||
/* Match info */
|
||||
GRegex *g_match_info_get_regex (const GMatchInfo *match_info);
|
||||
const gchar *g_match_info_get_string (const GMatchInfo *match_info);
|
||||
|
||||
void g_match_info_free (GMatchInfo *match_info);
|
||||
gboolean g_match_info_next (GMatchInfo *match_info,
|
||||
GError **error);
|
||||
|
@ -112,13 +112,11 @@ test_new (const gchar *pattern,
|
||||
{
|
||||
g_print ("failed \t(pattern: \"%s\")\n",
|
||||
pattern);
|
||||
g_regex_free (regex);
|
||||
g_regex_unref (regex);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_regex_free (regex);
|
||||
/* Free a null string. */
|
||||
g_regex_free (NULL);
|
||||
g_regex_unref (regex);
|
||||
|
||||
verbose ("passed\n");
|
||||
return TRUE;
|
||||
@ -146,7 +144,7 @@ test_new_fail (const gchar *pattern,
|
||||
{
|
||||
g_print ("failed \t(pattern: \"%s\", compile: %d)\n",
|
||||
pattern, compile_opts);
|
||||
g_regex_free (regex);
|
||||
g_regex_unref (regex);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -220,7 +218,7 @@ test_match (const gchar *pattern,
|
||||
g_print ("failed \t(unexpected %s) '%s' against '%s'\n", match ? "match" : "mismatch", e1, e2);
|
||||
g_free (e1);
|
||||
g_free (e2);
|
||||
g_regex_free (regex);
|
||||
g_regex_unref (regex);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -231,12 +229,12 @@ test_match (const gchar *pattern,
|
||||
{
|
||||
g_print ("failed \t(pattern: \"%s\", string: \"%s\")\n",
|
||||
pattern, string);
|
||||
g_regex_free (regex);
|
||||
g_regex_unref (regex);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
g_regex_free (regex);
|
||||
g_regex_unref (regex);
|
||||
|
||||
verbose ("passed (%s)\n", match ? "match" : "nomatch");
|
||||
return TRUE;
|
||||
@ -319,6 +317,8 @@ test_match_next (const gchar *pattern,
|
||||
matches = g_slist_prepend (matches, match);
|
||||
g_match_info_next (match_info, NULL);
|
||||
}
|
||||
g_assert (regex == g_match_info_get_regex (match_info));
|
||||
g_assert (string == g_match_info_get_string (match_info));
|
||||
g_match_info_free (match_info);
|
||||
matches = g_slist_reverse (matches);
|
||||
|
||||
@ -366,7 +366,7 @@ exit:
|
||||
verbose ("passed (%d %s)\n", count, count == 1 ? "match" : "matches");
|
||||
}
|
||||
|
||||
g_regex_free (regex);
|
||||
g_regex_unref (regex);
|
||||
g_slist_foreach (expected, free_match, NULL);
|
||||
g_slist_free (expected);
|
||||
g_slist_foreach (matches, free_match, NULL);
|
||||
@ -450,7 +450,7 @@ test_match_count (const gchar *pattern,
|
||||
}
|
||||
|
||||
g_match_info_free (match_info);
|
||||
g_regex_free (regex);
|
||||
g_regex_unref (regex);
|
||||
|
||||
verbose ("passed\n");
|
||||
return TRUE;
|
||||
@ -481,26 +481,26 @@ test_partial (const gchar *pattern,
|
||||
if (expected != g_match_info_is_partial_match (match_info))
|
||||
{
|
||||
g_print ("failed \t(got %d, expected: %d)\n", !expected, expected);
|
||||
g_regex_free (regex);
|
||||
g_regex_unref (regex);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (expected && g_match_info_fetch_pos (match_info, 0, NULL, NULL))
|
||||
{
|
||||
g_print ("failed \t(got sub-pattern 0)\n");
|
||||
g_regex_free (regex);
|
||||
g_regex_unref (regex);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (expected && g_match_info_fetch_pos (match_info, 1, NULL, NULL))
|
||||
{
|
||||
g_print ("failed \t(got sub-pattern 1)\n");
|
||||
g_regex_free (regex);
|
||||
g_regex_unref (regex);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_match_info_free (match_info);
|
||||
g_regex_free (regex);
|
||||
g_regex_unref (regex);
|
||||
|
||||
verbose ("passed\n");
|
||||
return TRUE;
|
||||
@ -540,7 +540,7 @@ test_sub_pattern (const gchar *pattern,
|
||||
g_print ("failed \t(got \"%s\", expected \"%s\")\n",
|
||||
sub_expr, expected_sub);
|
||||
g_free (sub_expr);
|
||||
g_regex_free (regex);
|
||||
g_regex_unref (regex);
|
||||
return FALSE;
|
||||
}
|
||||
g_free (sub_expr);
|
||||
@ -550,12 +550,12 @@ test_sub_pattern (const gchar *pattern,
|
||||
{
|
||||
g_print ("failed \t(got [%d, %d], expected [%d, %d])\n",
|
||||
start, end, expected_start, expected_end);
|
||||
g_regex_free (regex);
|
||||
g_regex_unref (regex);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_match_info_free (match_info);
|
||||
g_regex_free (regex);
|
||||
g_regex_unref (regex);
|
||||
|
||||
verbose ("passed\n");
|
||||
return TRUE;
|
||||
@ -598,7 +598,7 @@ test_named_sub_pattern (const gchar *pattern,
|
||||
g_print ("failed \t(got \"%s\", expected \"%s\")\n",
|
||||
sub_expr, expected_sub);
|
||||
g_free (sub_expr);
|
||||
g_regex_free (regex);
|
||||
g_regex_unref (regex);
|
||||
return FALSE;
|
||||
}
|
||||
g_free (sub_expr);
|
||||
@ -608,12 +608,12 @@ test_named_sub_pattern (const gchar *pattern,
|
||||
{
|
||||
g_print ("failed \t(got [%d, %d], expected [%d, %d])\n",
|
||||
start, end, expected_start, expected_end);
|
||||
g_regex_free (regex);
|
||||
g_regex_unref (regex);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_match_info_free (match_info);
|
||||
g_regex_free (regex);
|
||||
g_regex_unref (regex);
|
||||
|
||||
verbose ("passed\n");
|
||||
return TRUE;
|
||||
@ -704,7 +704,7 @@ test_fetch_all (const gchar *pattern,
|
||||
|
||||
exit:
|
||||
g_match_info_free (match_info);
|
||||
g_regex_free (regex);
|
||||
g_regex_unref (regex);
|
||||
g_slist_foreach (expected, (GFunc)g_free, NULL);
|
||||
g_slist_free (expected);
|
||||
g_strfreev (matches);
|
||||
@ -907,7 +907,7 @@ test_split_full (const gchar *pattern,
|
||||
token_count == 1 ? "token" : "tokens");
|
||||
|
||||
exit:
|
||||
g_regex_free (regex);
|
||||
g_regex_unref (regex);
|
||||
g_slist_foreach (expected, (GFunc)g_free, NULL);
|
||||
g_slist_free (expected);
|
||||
g_strfreev (tokens);
|
||||
@ -976,7 +976,7 @@ test_split (const gchar *pattern,
|
||||
token_count == 1 ? "token" : "tokens");
|
||||
|
||||
exit:
|
||||
g_regex_free (regex);
|
||||
g_regex_unref (regex);
|
||||
g_slist_foreach (expected, (GFunc)g_free, NULL);
|
||||
g_slist_free (expected);
|
||||
g_strfreev (tokens);
|
||||
@ -1048,6 +1048,44 @@ exit:
|
||||
} \
|
||||
}
|
||||
|
||||
static gboolean
|
||||
test_check_replacement (const gchar *string_to_expand,
|
||||
gboolean expected,
|
||||
gboolean expected_refs)
|
||||
{
|
||||
gboolean result;
|
||||
gboolean has_refs;
|
||||
|
||||
verbose ("checking replacement string \"%s\" \t", string_to_expand);
|
||||
|
||||
result = g_regex_check_replacement (string_to_expand, &has_refs, NULL);
|
||||
if (expected != result)
|
||||
{
|
||||
g_print ("failed \t(got \"%s\", expected \"%s\")\n",
|
||||
result ? "TRUE" : "FALSE",
|
||||
expected ? "TRUE" : "FALSE");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (expected && expected_refs != has_refs)
|
||||
{
|
||||
g_print ("failed \t(got has_references \"%s\", expected \"%s\")\n",
|
||||
has_refs ? "TRUE" : "FALSE",
|
||||
expected_refs ? "TRUE" : "FALSE");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
verbose ("passed\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#define TEST_CHECK_REPLACEMENT(string_to_expand, expected, expected_refs) { \
|
||||
total++; \
|
||||
if (test_check_replacement (string_to_expand, expected, expected_refs)) \
|
||||
PASS; \
|
||||
else \
|
||||
FAIL; \
|
||||
}
|
||||
static gboolean
|
||||
test_expand (const gchar *pattern,
|
||||
const gchar *string,
|
||||
@ -1055,27 +1093,33 @@ test_expand (const gchar *pattern,
|
||||
gboolean raw,
|
||||
const gchar *expected)
|
||||
{
|
||||
GRegex *regex;
|
||||
GMatchInfo *match_info;
|
||||
GRegex *regex = NULL;
|
||||
GMatchInfo *match_info = NULL;
|
||||
gchar *res;
|
||||
|
||||
verbose ("expanding the references in \"%s\" (pattern: \"%s\", string: \"%s\") \t",
|
||||
string_to_expand, pattern, string);
|
||||
|
||||
regex = g_regex_new (pattern, raw ? G_REGEX_RAW : 0, 0, NULL);
|
||||
g_regex_match (regex, string, 0, &match_info);
|
||||
if (pattern)
|
||||
{
|
||||
regex = g_regex_new (pattern, raw ? G_REGEX_RAW : 0, 0, NULL);
|
||||
g_regex_match (regex, string, 0, &match_info);
|
||||
}
|
||||
|
||||
res = g_match_info_expand_references (match_info, string_to_expand, NULL);
|
||||
if (!streq (res, expected))
|
||||
{
|
||||
g_print ("failed \t(got \"%s\", expected \"%s\")\n", res, expected);
|
||||
g_free (res);
|
||||
g_regex_free (regex);
|
||||
g_match_info_free (match_info);
|
||||
g_regex_unref (regex);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_free (res);
|
||||
g_match_info_free (match_info);
|
||||
g_regex_free (regex);
|
||||
if (regex)
|
||||
g_regex_unref (regex);
|
||||
|
||||
verbose ("passed\n");
|
||||
return TRUE;
|
||||
@ -1108,12 +1152,12 @@ test_replace (const gchar *pattern,
|
||||
{
|
||||
g_print ("failed \t(got \"%s\", expected \"%s\")\n", res, expected);
|
||||
g_free (res);
|
||||
g_regex_free (regex);
|
||||
g_regex_unref (regex);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_free (res);
|
||||
g_regex_free (regex);
|
||||
g_regex_unref (regex);
|
||||
|
||||
verbose ("passed\n");
|
||||
return TRUE;
|
||||
@ -1147,12 +1191,12 @@ test_replace_lit (const gchar *pattern,
|
||||
{
|
||||
g_print ("failed \t(got \"%s\", expected \"%s\")\n", res, expected);
|
||||
g_free (res);
|
||||
g_regex_free (regex);
|
||||
g_regex_unref (regex);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_free (res);
|
||||
g_regex_free (regex);
|
||||
g_regex_unref (regex);
|
||||
|
||||
verbose ("passed\n");
|
||||
return TRUE;
|
||||
@ -1179,7 +1223,7 @@ test_get_string_number (const gchar *pattern,
|
||||
|
||||
regex = g_regex_new (pattern, 0, 0, NULL);
|
||||
num = g_regex_get_string_number (regex, name);
|
||||
g_regex_free (regex);
|
||||
g_regex_unref (regex);
|
||||
|
||||
if (num != expected_num)
|
||||
{
|
||||
@ -1336,7 +1380,7 @@ exit:
|
||||
}
|
||||
|
||||
g_match_info_free (match_info);
|
||||
g_regex_free (regex);
|
||||
g_regex_unref (regex);
|
||||
g_slist_foreach (expected, free_match, NULL);
|
||||
g_slist_free (expected);
|
||||
|
||||
@ -1442,7 +1486,7 @@ exit:
|
||||
}
|
||||
|
||||
g_match_info_free (match_info);
|
||||
g_regex_free (regex);
|
||||
g_regex_unref (regex);
|
||||
g_slist_foreach (expected, free_match, NULL);
|
||||
g_slist_free (expected);
|
||||
|
||||
@ -1852,6 +1896,17 @@ main (int argc, char *argv[])
|
||||
TEST_SPLIT3(" *", "ab c", 0, 3, "a", "b", "c");
|
||||
TEST_SPLIT3(" *", "ab c", 0, 4, "a", "b", "c");
|
||||
|
||||
/* TEST_CHECK_REPLACEMENT(string_to_expand, expected, expected_refs) */
|
||||
TEST_CHECK_REPLACEMENT("", TRUE, FALSE);
|
||||
TEST_CHECK_REPLACEMENT("a", TRUE, FALSE);
|
||||
TEST_CHECK_REPLACEMENT("\\t\\n\\v\\r\\f\\a\\b\\\\\\x{61}", TRUE, FALSE);
|
||||
TEST_CHECK_REPLACEMENT("\\0", TRUE, TRUE);
|
||||
TEST_CHECK_REPLACEMENT("\\n\\2", TRUE, TRUE);
|
||||
TEST_CHECK_REPLACEMENT("\\g<foo>", TRUE, TRUE);
|
||||
/* Invalid strings */
|
||||
TEST_CHECK_REPLACEMENT("\\Q", FALSE, FALSE);
|
||||
TEST_CHECK_REPLACEMENT("x\\Ay", FALSE, FALSE);
|
||||
|
||||
/* TEST_EXPAND(pattern, string, string_to_expand, raw, expected) */
|
||||
TEST_EXPAND("a", "a", "", FALSE, "");
|
||||
TEST_EXPAND("a", "a", "\\0", FALSE, "a");
|
||||
@ -1918,6 +1973,12 @@ main (int argc, char *argv[])
|
||||
TEST_EXPAND("", "", "\\", FALSE, NULL);
|
||||
TEST_EXPAND("a", "a", "\\x{61", FALSE, NULL);
|
||||
TEST_EXPAND("a", "a", "\\x6X", FALSE, NULL);
|
||||
/* Pattern-less. */
|
||||
TEST_EXPAND(NULL, NULL, "", FALSE, "");
|
||||
TEST_EXPAND(NULL, NULL, "\\n", FALSE, "\n");
|
||||
/* Invalid strings */
|
||||
TEST_EXPAND(NULL, NULL, "\\Q", FALSE, NULL);
|
||||
TEST_EXPAND(NULL, NULL, "x\\Ay", FALSE, NULL);
|
||||
|
||||
/* TEST_REPLACE(pattern, string, start_position, replacement, expected) */
|
||||
TEST_REPLACE("a", "ababa", 0, "A", "AbAbA");
|
||||
|
Loading…
x
Reference in New Issue
Block a user