e4b02d9adfe18ecfa8d93b4be5e63cfc91902ba5
[folly.git] / folly / experimental / StringGen.h
1 /*
2  * Copyright 2013 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_STRINGGEN_H_
18 #define FOLLY_STRINGGEN_H_
19
20 #include "folly/Range.h"
21 #include "folly/experimental/Gen.h"
22
23 namespace folly {
24 namespace gen {
25
26 namespace detail {
27 class StringResplitter;
28 class SplitStringSource;
29
30 template<class Delimiter, class Output>
31 class Unsplit;
32
33 template<class Delimiter, class OutputBuffer>
34 class UnsplitBuffer;
35
36 template<class TargetContainer,
37          class Delimiter,
38          class... Targets>
39 class SplitTo;
40
41 }  // namespace detail
42
43 /**
44  * Split the output from a generator into StringPiece "lines" delimited by
45  * the given delimiter.  Delimters are NOT included in the output.
46  *
47  * resplit() behaves as if the input strings were concatenated into one long
48  * string and then split.
49  */
50 // make this a template so we don't require StringResplitter to be complete
51 // until use
52 template <class S=detail::StringResplitter>
53 S resplit(char delimiter) {
54   return S(delimiter);
55 }
56
57 template <class S=detail::SplitStringSource>
58 S split(const StringPiece& source, char delimiter) {
59   return S(source, delimiter);
60 }
61
62 /*
63  * Joins a sequence of tokens into a string, with the chosen delimiter.
64  *
65  * E.G.
66  *   fbstring result = split("a,b,c", ",") | unsplit(",");
67  *   assert(result == "a,b,c");
68  *
69  *   std::string result = split("a,b,c", ",") | unsplit<std::string>(" ");
70  *   assert(result == "a b c");
71  */
72
73
74 // NOTE: The template arguments are reversed to allow the user to cleanly
75 // specify the output type while still inferring the type of the delimiter.
76 template<class Output = folly::fbstring,
77          class Delimiter,
78          class Unsplit = detail::Unsplit<Delimiter, Output>>
79 Unsplit unsplit(const Delimiter& delimiter) {
80   return Unsplit(delimiter);
81 }
82
83 template<class Output = folly::fbstring,
84          class Unsplit = detail::Unsplit<fbstring, Output>>
85 Unsplit unsplit(const char* delimiter) {
86   return Unsplit(delimiter);
87 }
88
89 /*
90  * Joins a sequence of tokens into a string, appending them to the output
91  * buffer.  If the output buffer is empty, an initial delimiter will not be
92  * inserted at the start.
93  *
94  * E.G.
95  *   std::string buffer;
96  *   split("a,b,c", ",") | unsplit(",", &buffer);
97  *   assert(buffer == "a,b,c");
98  *
99  *   std::string anotherBuffer("initial");
100  *   split("a,b,c", ",") | unsplit(",", &anotherbuffer);
101  *   assert(anotherBuffer == "initial,a,b,c");
102  */
103 template<class Delimiter,
104          class OutputBuffer,
105          class UnsplitBuffer = detail::UnsplitBuffer<Delimiter, OutputBuffer>>
106 UnsplitBuffer unsplit(Delimiter delimiter, OutputBuffer* outputBuffer) {
107   return UnsplitBuffer(delimiter, outputBuffer);
108 }
109
110 template<class OutputBuffer,
111          class UnsplitBuffer = detail::UnsplitBuffer<fbstring, OutputBuffer>>
112 UnsplitBuffer unsplit(const char* delimiter, OutputBuffer* outputBuffer) {
113   return UnsplitBuffer(delimiter, outputBuffer);
114 }
115
116
117 template<class... Targets>
118 detail::Map<detail::SplitTo<std::tuple<Targets...>, char, Targets...>>
119 eachToTuple(char delim) {
120   return detail::Map<
121     detail::SplitTo<std::tuple<Targets...>, char, Targets...>>(
122     detail::SplitTo<std::tuple<Targets...>, char, Targets...>(delim));
123 }
124
125 template<class... Targets>
126 detail::Map<detail::SplitTo<std::tuple<Targets...>, fbstring, Targets...>>
127 eachToTuple(StringPiece delim) {
128   return detail::Map<
129     detail::SplitTo<std::tuple<Targets...>, fbstring, Targets...>>(
130     detail::SplitTo<std::tuple<Targets...>, fbstring, Targets...>(delim));
131 }
132
133 template<class First, class Second>
134 detail::Map<detail::SplitTo<std::pair<First, Second>, char, First, Second>>
135 eachToPair(char delim) {
136   return detail::Map<
137     detail::SplitTo<std::pair<First, Second>, char, First, Second>>(
138     detail::SplitTo<std::pair<First, Second>, char, First, Second>(delim));
139 }
140
141 template<class First, class Second>
142 detail::Map<detail::SplitTo<std::pair<First, Second>, fbstring, First, Second>>
143 eachToPair(StringPiece delim) {
144   return detail::Map<
145     detail::SplitTo<std::pair<First, Second>, fbstring, First, Second>>(
146     detail::SplitTo<std::pair<First, Second>, fbstring, First, Second>(
147       to<fbstring>(delim)));
148 }
149
150 }  // namespace gen
151 }  // namespace folly
152
153 #include "folly/experimental/StringGen-inl.h"
154
155 #endif /* FOLLY_STRINGGEN_H_ */
156