Coverage Report

Created: 2026-03-28 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/trafficserver/include/proxy/hdrs/HdrUtils.h
Line
Count
Source
1
/** @file
2
3
  A brief file description
4
5
  @section license License
6
7
  Licensed to the Apache Software Foundation (ASF) under one
8
  or more contributor license agreements.  See the NOTICE file
9
  distributed with this work for additional information
10
  regarding copyright ownership.  The ASF licenses this file
11
  to you under the Apache License, Version 2.0 (the
12
  "License"); you may not use this file except in compliance
13
  with the License.  You may obtain a copy of the License at
14
15
      http://www.apache.org/licenses/LICENSE-2.0
16
17
  Unless required by applicable law or agreed to in writing, software
18
  distributed under the License is distributed on an "AS IS" BASIS,
19
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
  See the License for the specific language governing permissions and
21
  limitations under the License.
22
 */
23
24
/****************************************************************************
25
26
   HdrUtils.h
27
28
   Description: Convenience routines for dealing with hdrs and
29
                 values
30
31
32
 ****************************************************************************/
33
34
#pragma once
35
36
#include "swoc/TextView.h"
37
#include "tscore/ParseRules.h"
38
#include "proxy/hdrs/MIME.h"
39
40
/** Accessor class to iterate over values in a multi-valued field.
41
 *
42
 * This implements the logic for quoted strings as specified in the RFC.
43
 */
44
class HdrCsvIter
45
{
46
  using TextView = swoc::TextView;
47
48
public:
49
  /** Construct the iterator in the initial state.
50
   *
51
   * @param s The separator character for sub-values.
52
   */
53
1.41k
  HdrCsvIter(char s = ',') : m_separator(s) {}
54
55
  /** Get the first sub-value.
56
   *
57
   * @param m The multi-valued field.
58
   * @param follow_dups Continue on to duplicate fields flag.
59
   * @return A view of the first sub-value in multi-valued data.
60
   */
61
  TextView    get_first(const MIMEField *m, bool follow_dups = true);
62
  const char *get_first(const MIMEField *m, int *len, bool follow_dups = true);
63
64
  /** Get the next sub-value.
65
   *
66
   * @return A view of the next subvalue, or an empty view if no more values.
67
   *
68
   * If @a follow_dups was set in the constructor, this will continue on to additional fields
69
   * if those fields have the same name as the original field (e.g, are duplicates).
70
   */
71
  TextView    get_next();
72
  const char *get_next(int *len);
73
74
  /** Get the current sub-value.
75
   *
76
   * @return A view of the current subvalue, or an empty view if no more values.
77
   *
78
   * The state of the iterator is not modified.
79
   */
80
  TextView    get_current();
81
  const char *get_current(int *len);
82
83
  int count_values(MIMEField *field, bool follow_dups = true);
84
85
  /** Get the first sub-value as an integer.
86
   *
87
   * @param m Field with the value.
88
   * @param result [out] Set to the integer sub-value.
89
   * @return @c true if there was an integer and @a result was set, @c false otherwise.
90
   */
91
  bool get_first_int(MIMEField *m, int &result);
92
93
  /** Get the next subvalue as an integer.
94
   *
95
   * @param result [out] Set to the integer sub-value.
96
   * @return @c true if there was an integer and @a result was set, @c false otherwise.
97
   */
98
  bool get_next_int(int &result);
99
100
private:
101
  void find_csv();
102
103
  /// The current field value.
104
  TextView m_value;
105
106
  /// Whether duplicates are being followed.
107
  bool m_follow_dups = false;
108
109
  /// The current sub-value.
110
  TextView m_csv;
111
112
  /// The field containing the current sub-value.
113
  const MIMEField *m_cur_field = nullptr;
114
115
  /// Separator for sub-values.
116
  /// for the Cookie/Set-cookie headers, the separator is ';'
117
  const char m_separator; // required constructor parameter, no initialization here.
118
119
  void field_init(const MIMEField *m);
120
};
121
122
inline void
123
HdrCsvIter::field_init(const MIMEField *m)
124
11.6k
{
125
11.6k
  m_cur_field = m;
126
11.6k
  m_value.assign(m->m_ptr_value, m->m_len_value);
127
11.6k
}
128
129
inline const char *
130
HdrCsvIter::get_first(const MIMEField *m, int *len, bool follow_dups)
131
1.41k
{
132
1.41k
  auto tv = this->get_first(m, follow_dups);
133
1.41k
  *len    = static_cast<int>(tv.size());
134
1.41k
  return tv.data();
135
1.41k
}
136
137
inline swoc::TextView
138
HdrCsvIter::get_first(const MIMEField *m, bool follow_dups)
139
1.41k
{
140
1.41k
  field_init(m);
141
1.41k
  m_follow_dups = follow_dups;
142
1.41k
  this->find_csv();
143
1.41k
  return m_csv;
144
1.41k
}
145
146
inline swoc::TextView
147
HdrCsvIter::get_next()
148
5.25k
{
149
5.25k
  this->find_csv();
150
5.25k
  return m_csv;
151
5.25k
}
152
153
inline const char *
154
HdrCsvIter::get_next(int *len)
155
5.25k
{
156
5.25k
  auto tv = this->get_next();
157
5.25k
  *len    = static_cast<int>(tv.size());
158
5.25k
  return tv.data();
159
5.25k
}
160
161
inline swoc::TextView
162
HdrCsvIter::get_current()
163
0
{
164
0
  return m_csv;
165
0
}
166
167
inline const char *
168
HdrCsvIter::get_current(int *len)
169
0
{
170
0
  *len = static_cast<int>(m_csv.size());
171
0
  return m_csv.data();
172
0
}
173
174
inline bool
175
HdrCsvIter::get_first_int(MIMEField *m, int &result)
176
0
{
177
0
  auto val = this->get_first(m);
178
0
179
0
  if (val) {
180
0
    TextView parsed;
181
0
    int      n = swoc::svtoi(val, &parsed);
182
0
    if (parsed) {
183
0
      result = n;
184
0
      return true;
185
0
    }
186
0
  }
187
0
  return false;
188
0
}
189
190
inline bool
191
HdrCsvIter::get_next_int(int &result)
192
0
{
193
0
  auto val = this->get_next();
194
0
195
0
  if (val) {
196
0
    TextView parsed;
197
0
    int      n = swoc::svtoi(val, &parsed);
198
0
    if (parsed) {
199
0
      result = n;
200
0
      return true;
201
0
    }
202
0
  }
203
0
  return false;
204
0
}