Subversion Repositories pentevo

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1186 savelij 1
/* striter.c */
2
/*****************************************************************************/
3
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
4
/*                                                                           */
5
/* AS                                                                        */
6
/*                                                                           */
7
/* String Iteration                                                          */
8
/*                                                                           */
9
/*****************************************************************************/
10
 
11
#include "striter.h"
12
 
13
/* iterator state variables, used in loop */
14
 
15
typedef struct
16
{
17
  Boolean this_escaped, next_escaped;
18
} iter_data_t;
19
 
20
/*!------------------------------------------------------------------------
21
 * \fn     iterate_quote_core(const char *p_run, as_quoted_iterator_cb_data_t *p_cb_data, iter_data_t *p_iter_data)
22
 * \brief  common quoting/escaping character handling while iterating string
23
 * \param  p_run current position in string
24
 * \param  p_cb_data, p_iter_data iteration callback
25
 * \return True if this was a special character
26
 * ------------------------------------------------------------------------ */
27
 
28
static Boolean iterate_quote_core(const char *p_run, as_quoted_iterator_cb_data_t *p_cb_data, iter_data_t *p_iter_data)
29
{
30
  p_iter_data->next_escaped = False;
31
  switch(*p_run)
32
  {
33
    case '\\':
34
      if ((p_cb_data->in_single_quote || p_cb_data->in_double_quote) && !p_iter_data->this_escaped)
35
        p_iter_data->next_escaped = True;
36
      return True;
37
    case '\'':
38
      if (p_cb_data->in_double_quote) { }
39
      else if (!p_cb_data->in_single_quote && (!p_cb_data->qualify_quote || p_cb_data->qualify_quote(p_cb_data->p_str, p_run)))
40
        p_cb_data->in_single_quote = True;
41
      else if (!p_iter_data->this_escaped) /* skip escaped ' in '...' */
42
        p_cb_data->in_single_quote = False;
43
      return True;
44
    case '"':
45
      if (p_cb_data->in_single_quote) { }
46
      else if (!p_cb_data->in_double_quote)
47
        p_cb_data->in_double_quote = True;
48
      else if (!p_iter_data->this_escaped) /* skip escaped " in "..." */
49
        p_cb_data->in_double_quote = False;
50
      return True;
51
    default:
52
      return False;
53
  }
54
}
55
 
56
/*!------------------------------------------------------------------------
57
 * \fn     as_iterate_str(const char *p_str, as_quoted_iterator_cb_t callback, as_quoted_iterator_cb_data_t *p_cb_data)
58
 * \brief  iterate through string, detecting quoted areas
59
 * \param  p_str string to iterate through
60
 * \param  callback is called for all characters outside quoted areas
61
 * \param  p_cb_data callback data
62
 * ------------------------------------------------------------------------ */
63
 
64
void as_iterate_str(const char *p_str, as_quoted_iterator_cb_t callback, as_quoted_iterator_cb_data_t *p_cb_data)
65
{
66
  iter_data_t iter_data;
67
  int n_extra_skip;
68
  const char *p_run;
69
 
70
  p_cb_data->p_str = p_str;
71
  p_cb_data->in_single_quote =
72
  p_cb_data->in_double_quote = False;
73
 
74
  for (p_run = p_str, iter_data.this_escaped = False;
75
       *p_run;
76
       p_run += (1 + n_extra_skip), iter_data.this_escaped = iter_data.next_escaped)
77
  {
78
    n_extra_skip = 0;
79
 
80
    (void)iterate_quote_core(p_run, p_cb_data, &iter_data);
81
    n_extra_skip = callback(p_run, p_cb_data);
82
    if (n_extra_skip < 0)
83
      return;
84
  }
85
}
86
 
87
/*!------------------------------------------------------------------------
88
 * \fn     as_iterate_str_quoted(const char *p_str, as_quoted_iterator_cb_t callback, as_quoted_iterator_cb_data_t *p_cb_data)
89
 * \brief  iterate through string, skipping quoted areas
90
 * \param  p_str string to iterate through
91
 * \param  callback is called for all characters outside quoted areas
92
 * \param  p_cb_data callback data
93
 * ------------------------------------------------------------------------ */
94
 
95
void as_iterate_str_quoted(const char *p_str, as_quoted_iterator_cb_t callback, as_quoted_iterator_cb_data_t *p_cb_data)
96
{
97
  iter_data_t iter_data;
98
  int n_extra_skip;
99
  const char *p_run;
100
 
101
  p_cb_data->p_str = p_str;
102
  p_cb_data->in_single_quote =
103
  p_cb_data->in_double_quote = False;
104
 
105
  for (p_run = p_str, iter_data.this_escaped = False;
106
       *p_run;
107
       p_run += (1 + n_extra_skip), iter_data.this_escaped = iter_data.next_escaped)
108
  {
109
    if (p_cb_data->callback_before && !p_cb_data->in_single_quote && !p_cb_data->in_double_quote)
110
    {
111
      n_extra_skip = callback(p_run, p_cb_data);
112
      if (n_extra_skip < 0)
113
        return;
114
    }
115
    else
116
      n_extra_skip = 0;
117
 
118
    if (!iterate_quote_core(p_run, p_cb_data, &iter_data)
119
     && !p_cb_data->callback_before
120
     && !p_cb_data->in_single_quote
121
     && !p_cb_data->in_double_quote)
122
    {
123
      n_extra_skip = callback(p_run, p_cb_data);
124
      if (n_extra_skip < 0)
125
        return;
126
    }
127
  }
128
}