]>
git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/lexlib/PropSetSimple.cxx
1 // SciTE - Scintilla based Text Editor
2 /** @file PropSetSimple.cxx
3 ** A Java style properties file module.
5 // Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
6 // The License.txt file describes the conditions under which this software may be distributed.
8 // Maintain a dictionary of properties
15 // Visual C++ doesn't like unreachable code in its own headers.
16 #pragma warning(disable: 4018 4100 4245 4511 4512 4663 4702)
22 #include "PropSetSimple.h"
25 using namespace Scintilla
;
28 typedef std::map
<std::string
, std::string
> mapss
;
30 PropSetSimple::PropSetSimple() {
31 mapss
*props
= new mapss
;
32 impl
= static_cast<void *>(props
);
35 PropSetSimple::~PropSetSimple() {
36 mapss
*props
= static_cast<mapss
*>(impl
);
41 void PropSetSimple::Set(const char *key
, const char *val
, int lenKey
, int lenVal
) {
42 mapss
*props
= static_cast<mapss
*>(impl
);
43 if (!*key
) // Empty keys are not supported
46 lenKey
= static_cast<int>(strlen(key
));
48 lenVal
= static_cast<int>(strlen(val
));
49 (*props
)[std::string(key
, lenKey
)] = std::string(val
, lenVal
);
52 static bool IsASpaceCharacter(unsigned int ch
) {
53 return (ch
== ' ') || ((ch
>= 0x09) && (ch
<= 0x0d));
56 void PropSetSimple::Set(const char *keyVal
) {
57 while (IsASpaceCharacter(*keyVal
))
59 const char *endVal
= keyVal
;
60 while (*endVal
&& (*endVal
!= '\n'))
62 const char *eqAt
= strchr(keyVal
, '=');
64 Set(keyVal
, eqAt
+ 1, static_cast<int>(eqAt
-keyVal
),
65 static_cast<int>(endVal
- eqAt
- 1));
66 } else if (*keyVal
) { // No '=' so assume '=1'
67 Set(keyVal
, "1", static_cast<int>(endVal
-keyVal
), 1);
71 void PropSetSimple::SetMultiple(const char *s
) {
72 const char *eol
= strchr(s
, '\n');
76 eol
= strchr(s
, '\n');
81 const char *PropSetSimple::Get(const char *key
) const {
82 mapss
*props
= static_cast<mapss
*>(impl
);
83 mapss::const_iterator keyPos
= props
->find(std::string(key
));
84 if (keyPos
!= props
->end()) {
85 return keyPos
->second
.c_str();
91 // There is some inconsistency between GetExpanded("foo") and Expand("$(foo)").
92 // A solution is to keep a stack of variables that have been expanded, so that
93 // recursive expansions can be skipped. For now I'll just use the C++ stack
94 // for that, through a recursive function and a simple chain of pointers.
97 VarChain(const char *var_
=NULL
, const VarChain
*link_
=NULL
): var(var_
), link(link_
) {}
99 bool contains(const char *testVar
) const {
100 return (var
&& (0 == strcmp(var
, testVar
)))
101 || (link
&& link
->contains(testVar
));
105 const VarChain
*link
;
108 static int ExpandAllInPlace(const PropSetSimple
&props
, std::string
&withVars
, int maxExpands
, const VarChain
&blankVars
) {
109 size_t varStart
= withVars
.find("$(");
110 while ((varStart
!= std::string::npos
) && (maxExpands
> 0)) {
111 size_t varEnd
= withVars
.find(")", varStart
+2);
112 if (varEnd
== std::string::npos
) {
116 // For consistency, when we see '$(ab$(cde))', expand the inner variable first,
117 // regardless whether there is actually a degenerate variable named 'ab$(cde'.
118 size_t innerVarStart
= withVars
.find("$(", varStart
+2);
119 while ((innerVarStart
!= std::string::npos
) && (innerVarStart
> varStart
) && (innerVarStart
< varEnd
)) {
120 varStart
= innerVarStart
;
121 innerVarStart
= withVars
.find("$(", varStart
+2);
124 std::string
var(withVars
.c_str(), varStart
+ 2, varEnd
- varStart
- 2);
125 std::string val
= props
.Get(var
.c_str());
127 if (blankVars
.contains(var
.c_str())) {
128 val
= ""; // treat blankVar as an empty string (e.g. to block self-reference)
131 if (--maxExpands
>= 0) {
132 maxExpands
= ExpandAllInPlace(props
, val
, maxExpands
, VarChain(var
.c_str(), &blankVars
));
135 withVars
.erase(varStart
, varEnd
-varStart
+1);
136 withVars
.insert(varStart
, val
.c_str(), val
.length());
138 varStart
= withVars
.find("$(");
144 char *PropSetSimple::Expanded(const char *key
) const {
145 std::string val
= Get(key
);
146 ExpandAllInPlace(*this, val
, 100, VarChain(key
));
147 char *ret
= new char [val
.size() + 1];
148 strcpy(ret
, val
.c_str());
152 int PropSetSimple::GetExpanded(const char *key
, char *result
) const {
153 char *val
= Expanded(key
);
154 const int n
= static_cast<int>(strlen(val
));
159 return n
; // Not including NUL
162 int PropSetSimple::GetInt(const char *key
, int defaultValue
) const {
163 char *val
= Expanded(key
);
165 int retVal
= val
[0] ? atoi(val
) : defaultValue
;