OpenVPN 3 Core Library
Loading...
Searching...
No Matches
split.hpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2012- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11
12// General string-splitting methods. These methods along with lexical analyzer
13// classes (such as those defined in lex.hpp and OptionList::LexComment) can be
14// used as a basis for parsers.
15
16#ifndef OPENVPN_COMMON_SPLIT_H
17#define OPENVPN_COMMON_SPLIT_H
18
19#include <string>
20#include <vector>
21#include <utility>
22
26
27
28using namespace openvpn::numeric_util;
29
30namespace openvpn::Split {
31
32enum
33{
35 TRIM_SPECIAL = (1 << 1), // trims quotes (but respects their content)
36};
37
39{
40 void add_term()
41 {
42 }
43};
44
45// Split a string using a character (such as ',') as a separator.
46// Types:
47// V : string vector of return data
48// LEX : lexical analyzer class such as StandardLex
49// LIM : limit class such as OptionList::Limits
50// Args:
51// ret : return data -- a list of strings
52// input : input string to be split
53// split_by : separator
54// flags : TRIM_LEADING_SPACES, TRIM_SPECIAL
55// max_terms : the size of the returned string list will be, at most, this value + 1. Pass
56// ~0 to disable.
57// lim : an optional limits object such as OptionList::Limits
58template <typename V, typename LEX, typename LIM>
59inline void by_char_void(V &ret, const std::string &input, const char split_by, const unsigned int flags = 0, const unsigned int max_terms = ~0, LIM *lim = nullptr)
60{
61 LEX lex;
62 unsigned int nterms = 0;
63 std::string term;
64 for (std::string::const_iterator i = input.begin(); i != input.end(); ++i)
65 {
66 const char c = *i;
67 lex.put(c);
68 if (!lex.in_quote() && c == split_by && nterms < max_terms)
69 {
70 if (lim)
71 lim->add_term();
72 ret.push_back(std::move(term));
73 ++nterms;
74 term = "";
75 }
76 else if ((!(flags & TRIM_SPECIAL) || lex.available())
77 && (!(flags & TRIM_LEADING_SPACES) || !term.empty() || !SpaceMatch::is_space(c)))
78 term += c;
79 }
80 if (lim)
81 lim->add_term();
82 ret.push_back(std::move(term));
83}
84
85// convenience method that returns data rather than modifying an in-place argument
86template <typename V, typename LEX, typename LIM>
87inline V by_char(const std::string &input, const char split_by, const unsigned int flags = 0, const unsigned int max_terms = ~0, LIM *lim = nullptr)
88{
89 V ret;
90 by_char_void<V, LEX, LIM>(ret, input, split_by, flags, max_terms, lim);
91 return ret;
92}
93
94// Split a string using spaces as a separator.
95// Types:
96// V : string vector of return data
97// LEX : lexical analyzer class such as StandardLex
98// SPACE : class that we use to differentiate between space and non-space chars
99// LIM : limit class such as OptionList::Limits
100// Args:
101// ret : return data -- a list of strings
102// input : input string to be split
103// lim : an optional limits object such as OptionList::Limits
104template <typename V, typename LEX, typename SPACE, typename LIM>
105inline void by_space_void(V &ret, const std::string &input, LIM *lim = nullptr)
106{
107 LEX lex;
108
109 std::string term;
110 bool defined = false;
111 for (std::string::const_iterator i = input.begin(); i != input.end(); ++i)
112 {
113 const char c = *i;
114 lex.put(c);
115 if (lex.in_quote())
116 defined = true;
117 if (lex.available())
118 {
119 const char tc = clamp_to_default<char>(lex.get(), '?');
120 if (!SPACE::is_space(tc) || lex.in_quote())
121 {
122 defined = true;
123 term += tc;
124 }
125 else if (defined)
126 {
127 if (lim)
128 lim->add_term();
129 ret.push_back(std::move(term));
130 term = "";
131 defined = false;
132 }
133 }
134 }
135 if (defined)
136 {
137 if (lim)
138 lim->add_term();
139 ret.push_back(std::move(term));
140 }
141}
142
143// convenience method that returns data rather than modifying an in-place argument
144template <typename V, typename LEX, typename SPACE, typename LIM>
145inline V by_space(const std::string &input, LIM *lim = nullptr)
146{
147 V ret;
148 by_space_void<V, LEX, SPACE, LIM>(ret, input, lim);
149 return ret;
150}
151} // namespace openvpn::Split
152
153#endif // OPENVPN_COMMON_SPLIT_H
void by_space_void(V &ret, const std::string &input, LIM *lim=nullptr)
Definition split.hpp:105
@ TRIM_LEADING_SPACES
Definition split.hpp:34
V by_char(const std::string &input, const char split_by, const unsigned int flags=0, const unsigned int max_terms=~0, LIM *lim=nullptr)
Definition split.hpp:87
void by_char_void(V &ret, const std::string &input, const char split_by, const unsigned int flags=0, const unsigned int max_terms=~0, LIM *lim=nullptr)
Definition split.hpp:59
V by_space(const std::string &input, LIM *lim=nullptr)
Definition split.hpp:145
static bool is_space(char c)
Definition lex.hpp:25
reroute_gw flags
std::string ret
static const char * input[]