56aa774f62aa5a905f755fcfc1cac47a435acd2d
[folly.git] / folly / gen / String.h
1 /*
2  * Copyright 2014 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #ifndef FOLLY_GEN_STRING_H
18 #define FOLLY_GEN_STRING_H
19
20 #include "folly/Range.h"
21 #include "folly/gen/Base.h"
22
23 namespace folly {
24 namespace gen {
25
26 namespace detail {
27 class StringResplitter;
28
29 template<class Delimiter>
30 class SplitStringSource;
31
32 template<class Delimiter, class Output>
33 class Unsplit;
34
35 template<class Delimiter, class OutputBuffer>
36 class UnsplitBuffer;
37
38 template<class TargetContainer,
39          class Delimiter,
40          class... Targets>
41 class SplitTo;
42
43 }  // namespace detail
44
45 /**
46  * Split the output from a generator into StringPiece "lines" delimited by
47  * the given delimiter.  Delimters are NOT included in the output.
48  *
49  * resplit() behaves as if the input strings were concatenated into one long
50  * string and then split.
51  */
52 // make this a template so we don't require StringResplitter to be complete
53 // until use
54 template <class S=detail::StringResplitter>
55 S resplit(char delimiter) {
56   return S(delimiter);
57 }
58
59 template <class S = detail::SplitStringSource<char>>
60 S split(const StringPiece& source, char delimiter) {
61   return S(source, delimiter);
62 }
63
64 template <class S = detail::SplitStringSource<StringPiece>>
65 S split(StringPiece source, StringPiece delimiter) {
66   return S(source, delimiter);
67 }
68
69 /**
70  * EOL terms ("\r", "\n", or "\r\n").
71  */
72 class MixedNewlines {};
73
74 /**
75  * Split by EOL ("\r", "\n", or "\r\n").
76  * @see split().
77  */
78 template <class S = detail::SplitStringSource<MixedNewlines>>
79 S lines(StringPiece source) {
80   return S(source, MixedNewlines{});
81 }
82
83 /*
84  * Joins a sequence of tokens into a string, with the chosen delimiter.
85  *
86  * E.G.
87  *   fbstring result = split("a,b,c", ",") | unsplit(",");
88  *   assert(result == "a,b,c");
89  *
90  *   std::string result = split("a,b,c", ",") | unsplit<std::string>(" ");
91  *   assert(result == "a b c");
92  */
93
94
95 // NOTE: The template arguments are reversed to allow the user to cleanly
96 // specify the output type while still inferring the type of the delimiter.
97 template<class Output = folly::fbstring,
98          class Delimiter,
99          class Unsplit = detail::Unsplit<Delimiter, Output>>
100 Unsplit unsplit(const Delimiter& delimiter) {
101   return Unsplit(delimiter);
102 }
103
104 template<class Output = folly::fbstring,
105          class Unsplit = detail::Unsplit<fbstring, Output>>
106 Unsplit unsplit(const char* delimiter) {
107   return Unsplit(delimiter);
108 }
109
110 /*
111  * Joins a sequence of tokens into a string, appending them to the output
112  * buffer.  If the output buffer is empty, an initial delimiter will not be
113  * inserted at the start.
114  *
115  * E.G.
116  *   std::string buffer;
117  *   split("a,b,c", ",") | unsplit(",", &buffer);
118  *   assert(buffer == "a,b,c");
119  *
120  *   std::string anotherBuffer("initial");
121  *   split("a,b,c", ",") | unsplit(",", &anotherbuffer);
122  *   assert(anotherBuffer == "initial,a,b,c");
123  */
124 template<class Delimiter,
125          class OutputBuffer,
126          class UnsplitBuffer = detail::UnsplitBuffer<Delimiter, OutputBuffer>>
127 UnsplitBuffer unsplit(Delimiter delimiter, OutputBuffer* outputBuffer) {
128   return UnsplitBuffer(delimiter, outputBuffer);
129 }
130
131 template<class OutputBuffer,
132          class UnsplitBuffer = detail::UnsplitBuffer<fbstring, OutputBuffer>>
133 UnsplitBuffer unsplit(const char* delimiter, OutputBuffer* outputBuffer) {
134   return UnsplitBuffer(delimiter, outputBuffer);
135 }
136
137
138 template<class... Targets>
139 detail::Map<detail::SplitTo<std::tuple<Targets...>, char, Targets...>>
140 eachToTuple(char delim) {
141   return detail::Map<
142     detail::SplitTo<std::tuple<Targets...>, char, Targets...>>(
143     detail::SplitTo<std::tuple<Targets...>, char, Targets...>(delim));
144 }
145
146 template<class... Targets>
147 detail::Map<detail::SplitTo<std::tuple<Targets...>, fbstring, Targets...>>
148 eachToTuple(StringPiece delim) {
149   return detail::Map<
150     detail::SplitTo<std::tuple<Targets...>, fbstring, Targets...>>(
151     detail::SplitTo<std::tuple<Targets...>, fbstring, Targets...>(delim));
152 }
153
154 template<class First, class Second>
155 detail::Map<detail::SplitTo<std::pair<First, Second>, char, First, Second>>
156 eachToPair(char delim) {
157   return detail::Map<
158     detail::SplitTo<std::pair<First, Second>, char, First, Second>>(
159     detail::SplitTo<std::pair<First, Second>, char, First, Second>(delim));
160 }
161
162 template<class First, class Second>
163 detail::Map<detail::SplitTo<std::pair<First, Second>, fbstring, First, Second>>
164 eachToPair(StringPiece delim) {
165   return detail::Map<
166     detail::SplitTo<std::pair<First, Second>, fbstring, First, Second>>(
167     detail::SplitTo<std::pair<First, Second>, fbstring, First, Second>(
168       to<fbstring>(delim)));
169 }
170
171 }  // namespace gen
172 }  // namespace folly
173
174 #include "folly/gen/String-inl.h"
175
176 #endif // FOLLY_GEN_STRING_H