-
Notifications
You must be signed in to change notification settings - Fork 42
/
expand.h
63 lines (57 loc) · 1.77 KB
/
expand.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#ifndef EXPAND_H
#define EXPAND_H
#include <vector>
#include <string>
#include <streambuf>
#include <sstream>
#include <algorithm>
#include <iterator>
/*
* - ${VAR} evaluates to variable VAR's value
* - ${VAR&word} evaluates to ${VAR} if ${VAR} is empty,
* otherwise word
* - ${VAR|word} evaluates to ${VAR} if ${VAR} is not empty,
* otherwise word
*/
template <typename CharT, typename Iterator, typename Func>
std::basic_string<CharT>
process1(Iterator &begin, Iterator end, Func lookup, int delim);
template <typename CharT, typename Iterator, typename Func>
std::basic_string<CharT> expand(Iterator &begin, Iterator end, Func lookup)
{
std::basic_string<CharT> name, value, value2;
CharT c;
while (begin < end && (c = *begin++) != '&' && c != '|' && c != '}')
name.push_back(c);
value = lookup(name);
if (c != '&' && c != '|')
return value;
// XXX: not short-circuit
value2 = process1<CharT>(begin, end, lookup, '}');
if (c == '&')
return value.empty() ? value : value2;
else
return value.empty() ? value2 : value;
}
template <typename CharT, typename Iterator, typename Func>
std::basic_string<CharT>
process1(Iterator &begin, Iterator end, Func lookup, int delim)
{
std::basic_string<CharT> result;
CharT c;
while (begin < end && (c = *begin++) != delim) {
if (c == '$' && begin < end && *begin == '{')
result += expand<CharT>(++begin, end, lookup);
else
result.push_back(c);
}
return result;
}
template <typename CharT, typename Func>
std::basic_string<CharT>
process_template(const std::basic_string<CharT> &s, Func lookup)
{
typename std::basic_string<CharT>::const_iterator it = s.begin();
return process1<CharT>(it, s.end(), lookup, 0);
}
#endif