~ubuntu-branches/ubuntu/quantal/mysql-workbench/quantal

« back to all changes in this revision

Viewing changes to ext/scintilla/lexlib/PropSetSimple.cxx

  • Committer: Package Import Robot
  • Author(s): Dmitry Smirnov
  • Date: 2012-03-01 21:57:30 UTC
  • Revision ID: package-import@ubuntu.com-20120301215730-o7y8av8y38n162ro
Tags: upstream-5.2.38+dfsg
ImportĀ upstreamĀ versionĀ 5.2.38+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// SciTE - Scintilla based Text Editor
 
2
/** @file PropSetSimple.cxx
 
3
 ** A Java style properties file module.
 
4
 **/
 
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.
 
7
 
 
8
// Maintain a dictionary of properties
 
9
 
 
10
#include <stdlib.h>
 
11
#include <string.h>
 
12
#include <stdio.h>
 
13
 
 
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
 
18
 
 
19
#include <string>
 
20
#include <map>
 
21
 
 
22
#include "PropSetSimple.h"
 
23
 
 
24
#ifdef SCI_NAMESPACE
 
25
using namespace Scintilla;
 
26
#endif
 
27
 
 
28
typedef std::map<std::string, std::string> mapss;
 
29
 
 
30
PropSetSimple::PropSetSimple() {
 
31
        mapss *props = new mapss;
 
32
        impl = static_cast<void *>(props);
 
33
}
 
34
 
 
35
PropSetSimple::~PropSetSimple() {
 
36
        mapss *props = static_cast<mapss *>(impl);
 
37
        delete props;
 
38
        impl = 0;
 
39
}
 
40
 
 
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
 
44
                return;
 
45
        if (lenKey == -1)
 
46
                lenKey = static_cast<int>(strlen(key));
 
47
        if (lenVal == -1)
 
48
                lenVal = static_cast<int>(strlen(val));
 
49
        (*props)[std::string(key, lenKey)] = std::string(val, lenVal);
 
50
}
 
51
 
 
52
static bool IsASpaceCharacter(unsigned int ch) {
 
53
    return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d));
 
54
}
 
55
 
 
56
void PropSetSimple::Set(const char *keyVal) {
 
57
        while (IsASpaceCharacter(*keyVal))
 
58
                keyVal++;
 
59
        const char *endVal = keyVal;
 
60
        while (*endVal && (*endVal != '\n'))
 
61
                endVal++;
 
62
        const char *eqAt = strchr(keyVal, '=');
 
63
        if (eqAt) {
 
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);
 
68
        }
 
69
}
 
70
 
 
71
void PropSetSimple::SetMultiple(const char *s) {
 
72
        const char *eol = strchr(s, '\n');
 
73
        while (eol) {
 
74
                Set(s);
 
75
                s = eol + 1;
 
76
                eol = strchr(s, '\n');
 
77
        }
 
78
        Set(s);
 
79
}
 
80
 
 
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();
 
86
        } else {
 
87
                return "";
 
88
        }
 
89
}
 
90
 
 
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.
 
95
 
 
96
struct VarChain {
 
97
        VarChain(const char *var_=NULL, const VarChain *link_=NULL): var(var_), link(link_) {}
 
98
 
 
99
        bool contains(const char *testVar) const {
 
100
                return (var && (0 == strcmp(var, testVar)))
 
101
                        || (link && link->contains(testVar));
 
102
        }
 
103
 
 
104
        const char *var;
 
105
        const VarChain *link;
 
106
};
 
107
 
 
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) {
 
113
                        break;
 
114
                }
 
115
 
 
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);
 
122
                }
 
123
 
 
124
                std::string var(withVars.c_str(), varStart + 2, varEnd - varStart - 2);
 
125
                std::string val = props.Get(var.c_str());
 
126
 
 
127
                if (blankVars.contains(var.c_str())) {
 
128
                        val = ""; // treat blankVar as an empty string (e.g. to block self-reference)
 
129
                }
 
130
 
 
131
                if (--maxExpands >= 0) {
 
132
                        maxExpands = ExpandAllInPlace(props, val, maxExpands, VarChain(var.c_str(), &blankVars));
 
133
                }
 
134
 
 
135
                withVars.erase(varStart, varEnd-varStart+1);
 
136
                withVars.insert(varStart, val.c_str(), val.length());
 
137
 
 
138
                varStart = withVars.find("$(");
 
139
        }
 
140
 
 
141
        return maxExpands;
 
142
}
 
143
 
 
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());
 
149
        return ret;
 
150
}
 
151
 
 
152
int PropSetSimple::GetExpanded(const char *key, char *result) const {
 
153
        char *val = Expanded(key);
 
154
        const int n = static_cast<int>(strlen(val));
 
155
        if (result) {
 
156
                strcpy(result, val);
 
157
        }
 
158
        delete []val;
 
159
        return n;       // Not including NUL
 
160
}
 
161
 
 
162
int PropSetSimple::GetInt(const char *key, int defaultValue) const {
 
163
        char *val = Expanded(key);
 
164
        if (val) {
 
165
                int retVal = val[0] ? atoi(val) : defaultValue;
 
166
                delete []val;
 
167
                return retVal;
 
168
        }
 
169
        return defaultValue;
 
170
}