profiler: bgo#633018 crash in Anjuta IDE: misuse of xmlCleanupParser
[anjuta-extras.git] / plugins / scintilla / scintilla / PropSet.cxx
blob9936c39d12779879f0ae737f8e959b74f3b9e308
1 // SciTE - Scintilla based Text Editor
2 /** @file PropSet.cxx
3 ** A Java style properties file module.
4 **/
5 // Copyright 1998-2003 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
10 #include <stdlib.h>
11 #include <string.h>
12 #include <stdio.h>
14 #ifdef _MSC_VER
15 // Visual C++ doesn't like unreachable code or long decorated names in its own headers.
16 #pragma warning(disable: 4018 4100 4245 4511 4512 4663 4702 4786)
17 #endif
19 #include <string>
20 #include <map>
22 #include "Platform.h"
24 #include "PropSet.h"
25 #include "PropSetSimple.h"
27 #ifdef SCI_NAMESPACE
28 using namespace Scintilla;
29 #endif
31 typedef std::map<std::string, std::string> mapss;
33 PropSetSimple::PropSetSimple() {
34 mapss *props = new mapss;
35 impl = static_cast<void *>(props);
38 PropSetSimple::~PropSetSimple() {
39 mapss *props = static_cast<mapss *>(impl);
40 delete props;
41 impl = 0;
44 void PropSetSimple::Set(const char *key, const char *val, int lenKey, int lenVal) {
45 mapss *props = static_cast<mapss *>(impl);
46 if (!*key) // Empty keys are not supported
47 return;
48 if (lenKey == -1)
49 lenKey = static_cast<int>(strlen(key));
50 if (lenVal == -1)
51 lenVal = static_cast<int>(strlen(val));
52 (*props)[std::string(key, lenKey)] = std::string(val, lenVal);
55 static bool IsASpaceCharacter(unsigned int ch) {
56 return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d));
59 void PropSetSimple::Set(const char *keyVal) {
60 while (IsASpaceCharacter(*keyVal))
61 keyVal++;
62 const char *endVal = keyVal;
63 while (*endVal && (*endVal != '\n'))
64 endVal++;
65 const char *eqAt = strchr(keyVal, '=');
66 if (eqAt) {
67 Set(keyVal, eqAt + 1, eqAt-keyVal, endVal - eqAt - 1);
68 } else if (*keyVal) { // No '=' so assume '=1'
69 Set(keyVal, "1", endVal-keyVal, 1);
73 void PropSetSimple::SetMultiple(const char *s) {
74 const char *eol = strchr(s, '\n');
75 while (eol) {
76 Set(s);
77 s = eol + 1;
78 eol = strchr(s, '\n');
80 Set(s);
83 const char *PropSetSimple::Get(const char *key) const {
84 mapss *props = static_cast<mapss *>(impl);
85 mapss::const_iterator keyPos = props->find(std::string(key));
86 if (keyPos != props->end()) {
87 return keyPos->second.c_str();
88 } else {
89 return "";
93 // There is some inconsistency between GetExpanded("foo") and Expand("$(foo)").
94 // A solution is to keep a stack of variables that have been expanded, so that
95 // recursive expansions can be skipped. For now I'll just use the C++ stack
96 // for that, through a recursive function and a simple chain of pointers.
98 struct VarChain {
99 VarChain(const char*var_=NULL, const VarChain *link_=NULL): var(var_), link(link_) {}
101 bool contains(const char *testVar) const {
102 return (var && (0 == strcmp(var, testVar)))
103 || (link && link->contains(testVar));
106 const char *var;
107 const VarChain *link;
110 static int ExpandAllInPlace(const PropSetSimple &props, std::string &withVars, int maxExpands, const VarChain &blankVars) {
111 size_t varStart = withVars.find("$(");
112 while ((varStart != std::string::npos) && (maxExpands > 0)) {
113 size_t varEnd = withVars.find(")", varStart+2);
114 if (varEnd == std::string::npos) {
115 break;
118 // For consistency, when we see '$(ab$(cde))', expand the inner variable first,
119 // regardless whether there is actually a degenerate variable named 'ab$(cde'.
120 size_t innerVarStart = withVars.find("$(", varStart+2);
121 while ((innerVarStart != std::string::npos) && (innerVarStart > varStart) && (innerVarStart < varEnd)) {
122 varStart = innerVarStart;
123 innerVarStart = withVars.find("$(", varStart+2);
126 std::string var(withVars.c_str(), varStart + 2, varEnd - varStart - 2);
127 std::string val = props.Get(var.c_str());
129 if (blankVars.contains(var.c_str())) {
130 val = ""; // treat blankVar as an empty string (e.g. to block self-reference)
133 if (--maxExpands >= 0) {
134 maxExpands = ExpandAllInPlace(props, val, maxExpands, VarChain(var.c_str(), &blankVars));
137 withVars.erase(varStart, varEnd-varStart+1);
138 withVars.insert(varStart, val.c_str(), val.length());
140 varStart = withVars.find("$(");
143 return maxExpands;
146 char *PropSetSimple::Expanded(const char *key) const {
147 std::string val = Get(key);
148 ExpandAllInPlace(*this, val, 100, VarChain(key));
149 char *ret = new char [val.size() + 1];
150 strcpy(ret, val.c_str());
151 return ret;
154 char *PropSetSimple::ToString() const {
155 mapss *props = static_cast<mapss *>(impl);
156 std::string sval;
157 for (mapss::const_iterator it=props->begin(); it != props->end(); it++) {
158 sval += it->first;
159 sval += "=";
160 sval += it->second;
161 sval += "\n";
163 char *ret = new char [sval.size() + 1];
164 strcpy(ret, sval.c_str());
165 return ret;
168 int PropSetSimple::GetInt(const char *key, int defaultValue) const {
169 char *val = Expanded(key);
170 if (val) {
171 int retVal = val[0] ? atoi(val) : defaultValue;
172 delete []val;
173 return retVal;
175 return defaultValue;