| /** @file |
| |
| A brief file description |
| |
| @section license License |
| |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| */ |
| |
| /**************************************************************************** |
| |
| HdrUtils.h |
| |
| Description: Convenience routines for dealing with hdrs and |
| values |
| |
| |
| ****************************************************************************/ |
| |
| #pragma once |
| |
| #include "tscpp/util/TextView.h" |
| #include "tscore/ParseRules.h" |
| #include "MIME.h" |
| |
| /** Accessor class to iterate over values in a multi-valued field. |
| * |
| * This implements the logic for quoted strings as specified in the RFC. |
| */ |
| class HdrCsvIter |
| { |
| using TextView = ts::TextView; |
| |
| public: |
| /** Construct the iterator in the initial state. |
| * |
| * @param s The separator character for sub-values. |
| */ |
| HdrCsvIter(char s = ',') : m_separator(s) {} |
| |
| /** Get the first sub-value. |
| * |
| * @param m The multi-valued field. |
| * @param follow_dups Continue on to duplicate fields flag. |
| * @return A view of the first sub-value in multi-valued data. |
| */ |
| TextView get_first(const MIMEField *m, bool follow_dups = true); |
| const char *get_first(const MIMEField *m, int *len, bool follow_dups = true); |
| |
| /** Get the next sub-value. |
| * |
| * @return A view of the next subvalue, or an empty view if no more values. |
| * |
| * If @a follow_dups was set in the constructor, this will continue on to additional fields |
| * if those fields have the same name as the original field (e.g, are duplicates). |
| */ |
| TextView get_next(); |
| const char *get_next(int *len); |
| |
| /** Get the current sub-value. |
| * |
| * @return A view of the current subvalue, or an empty view if no more values. |
| * |
| * The state of the iterator is not modified. |
| */ |
| TextView get_current(); |
| const char *get_current(int *len); |
| |
| /** Get the @a nth sub-value in the field @a m. |
| * |
| * @param m Field. |
| * @param nth Index of the target sub-value. |
| * @param follow_dups Follow duplicate fields if necessary. |
| * @return The subvalue at index @a n, or an empty view if that does not exist. |
| */ |
| TextView get_nth(MIMEField *m, int nth, bool follow_dups = true); |
| const char *get_nth(MIMEField *m, int *len, int n, bool follow_dups = true); |
| |
| int count_values(MIMEField *field, bool follow_dups = true); |
| |
| /** Get the first sub-value as an integer. |
| * |
| * @param m Field with the value. |
| * @param result [out] Set to the integer sub-value. |
| * @return @c true if there was an integer and @a result was set, @c false otherwise. |
| */ |
| bool get_first_int(MIMEField *m, int &result); |
| |
| /** Get the next subvalue as an integer. |
| * |
| * @param result [out] Set to the integer sub-value. |
| * @return @c true if there was an integer and @a result was set, @c false otherwise. |
| */ |
| bool get_next_int(int &result); |
| |
| private: |
| void find_csv(); |
| |
| /// The current field value. |
| TextView m_value; |
| |
| /// Whether duplicates are being followed. |
| bool m_follow_dups = false; |
| |
| /// The current sub-value. |
| TextView m_csv; |
| |
| /// The field containing the current sub-value. |
| const MIMEField *m_cur_field = nullptr; |
| |
| /// Separator for sub-values. |
| /// for the Cookie/Set-cookie headers, the separator is ';' |
| const char m_separator; // required constructor parameter, no initialization here. |
| |
| void field_init(const MIMEField *m); |
| }; |
| |
| inline void |
| HdrCsvIter::field_init(const MIMEField *m) |
| { |
| m_cur_field = m; |
| m_value.assign(m->m_ptr_value, m->m_len_value); |
| } |
| |
| inline const char * |
| HdrCsvIter::get_first(const MIMEField *m, int *len, bool follow_dups) |
| { |
| auto tv = this->get_first(m, follow_dups); |
| *len = static_cast<int>(tv.size()); |
| return tv.data(); |
| } |
| |
| inline ts::TextView |
| HdrCsvIter::get_first(const MIMEField *m, bool follow_dups) |
| { |
| field_init(m); |
| m_follow_dups = follow_dups; |
| this->find_csv(); |
| return m_csv; |
| } |
| |
| inline ts::TextView |
| HdrCsvIter::get_next() |
| { |
| this->find_csv(); |
| return m_csv; |
| } |
| |
| inline const char * |
| HdrCsvIter::get_next(int *len) |
| { |
| auto tv = this->get_next(); |
| *len = static_cast<int>(tv.size()); |
| return tv.data(); |
| } |
| |
| inline ts::TextView |
| HdrCsvIter::get_current() |
| { |
| return m_csv; |
| } |
| |
| inline const char * |
| HdrCsvIter::get_current(int *len) |
| { |
| *len = static_cast<int>(m_csv.size()); |
| return m_csv.data(); |
| } |
| |
| inline bool |
| HdrCsvIter::get_first_int(MIMEField *m, int &result) |
| { |
| auto val = this->get_first(m); |
| |
| if (val) { |
| TextView parsed; |
| int n = ts::svtoi(val, &parsed); |
| if (parsed) { |
| result = n; |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| inline bool |
| HdrCsvIter::get_next_int(int &result) |
| { |
| auto val = this->get_next(); |
| |
| if (val) { |
| TextView parsed; |
| int n = ts::svtoi(val, &parsed); |
| if (parsed) { |
| result = n; |
| return true; |
| } |
| } |
| return false; |
| } |