substitute.h
1//-*-C++-*-
2/***************************************************************************
3 *
4 * Copyright (C) 2006 by Willem van Straten
5 * Licensed under the Academic Free License version 2.1
6 *
7 ***************************************************************************/
8// psrchive/Util/units/substitute.h
9
10#ifndef __UTILS_UNITS_SUBSTITUTE_H
11#define __UTILS_UNITS_SUBSTITUTE_H
12
13#include "TextInterfaceName.h"
14#include "Functor.h"
15
16#include <string>
17#include <algorithm>
18#include <functional>
19#include <ctype.h>
20
22template<class Pred> std::string::size_type
23find_first_if (const std::string& text, Pred pred, std::string::size_type pos)
24{
25 std::string::const_iterator iter;
26 iter = std::find_if (text.begin()+pos, text.end(), pred);
27 if (iter == text.end())
28 return std::string::npos;
29 else
30 return iter - text.begin();
31}
32
34template<class Pred> std::string::size_type
35find_last_if (const std::string& text, Pred pred)
36{
37 auto iter = std::find_if (text.rbegin(), text.rend(), pred);
38 if (iter == text.rend())
39 return std::string::npos;
40 else
41 return text.length() - (iter - text.rbegin());
42}
43
44template<class T>
45std::string substitute (const std::string& text, T* resolver,
46 char substitution = '$',
47 Functor< bool(char) > in_name =
48 Functor< bool(char) > (TextInterface::Name(),
50try
51{
52 if (!resolver)
53 throw Error (InvalidState, "substitute", "resolver = NULL");
54
55 std::string remain = text;
56 std::string result;
57
58 std::string::size_type start;
59
60 while ( (start = remain.find(substitution)) != std::string::npos ) {
61
62 // string preceding the variable substitution
63 std::string before = remain.substr (0, start);
64
65 // ignore the substitution symbol
66 start ++;
67
68 // repeated substitution symbol strings are simply decreased by one symbol
69 std::string::size_type name_start = start;
70 while (name_start < remain.length() && remain[name_start] == substitution)
71 name_start ++;
72
73 // check for commands to send to resolver without substitution
74 while (remain[name_start] == '<')
75 {
76 std::string::size_type command_start = name_start + 1;
77 std::string::size_type command_end = remain.find('>',name_start);
78 if (command_end == std::string::npos)
79 throw Error (InvalidState, "substitute", "command opening '<' without closing '>'");
80
81 std::string command = remain.substr (command_start, command_end - command_start);
82
83 resolver->process (command);
84 start = name_start = command_end + 1;
85 }
86
87 // find the end of the variable name
88 std::string::size_type end;
89 end = find_first_if (remain, std::not1(in_name), name_start);
90
91 // length to end of variable name
92 std::string::size_type length = std::string::npos;
93
94 if (end != std::string::npos)
95 length = end - start;
96
97 // the variable name
98 std::string name = remain.substr (start, length);
99
100 if (start == name_start)
101 // perform the substitution and add to the result
102 result += before + resolver->get_value(name);
103 else
104 result += before + name;
105
106 // remainder of string following the variable name
107 if (end != std::string::npos)
108 remain = remain.substr (end);
109 else
110 remain.erase();
111 }
112
113 return result + remain;
114}
115 catch (Error& error)
116 {
117 throw error += "substitute (text=\"" + text + "\",parser=" +
118 resolver->get_interface_name() + ")";
119 }
120
121#endif
A convenient exception handling class.
Definition Error.h:54
Implements an adaptable function object in compliance with the STL.
Definition Functor.h:39
Defines the sequence of characters that constitute a valid name.
Definition TextInterfaceName.h:20
bool valid(char c) const
Return true if c is the next character in a valid name.
Definition TextInterfaceName.C:22

Generated using doxygen 1.14.0