]>
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
;