version 0.1.14
[fms.git] / src / stringfunctions.cpp
1 #include "../include/stringfunctions.h"\r
2 \r
3 #include <algorithm>\r
4 \r
5 #ifdef XMEM\r
6         #include <xmem.h>\r
7 #endif\r
8 \r
9 namespace StringFunctions\r
10 {\r
11 \r
12 void LowerCase(const std::string &str, std::string &output)\r
13 {\r
14         output=str;\r
15         std::transform(str.begin(),str.end(),output.begin(),tolower);\r
16 }\r
17 \r
18 std::string Replace(const std::string &input, const std::string &find, const std::string &replace)\r
19 {\r
20         std::string returnstr=input;\r
21         std::string::size_type pos=returnstr.find(find);\r
22 \r
23         while(pos!=std::string::npos)\r
24         {\r
25                 returnstr.replace(pos,find.size(),replace);\r
26                 pos=returnstr.find(find,pos+replace.size());\r
27         }\r
28 \r
29         return returnstr;\r
30 \r
31 }\r
32 \r
33 void Split(const std::string &str, const std::string &delim, std::vector<std::string> &output)\r
34 {\r
35         std::string::size_type offset = 0;\r
36         std::string::size_type delimIndex = 0;\r
37     \r
38     delimIndex = str.find(delim, offset);\r
39 \r
40     while (delimIndex != std::string::npos)\r
41     {\r
42         output.push_back(str.substr(offset, delimIndex - offset));\r
43         offset += delimIndex - offset + delim.length();\r
44         delimIndex = str.find(delim, offset);\r
45     }\r
46 \r
47     output.push_back(str.substr(offset));\r
48 }\r
49 \r
50 void SplitMultiple(const std::string &str, const std::string &delim, std::vector<std::string> &output)\r
51 {\r
52         std::string::size_type offset = 0;\r
53         std::string::size_type delimIndex = 0;\r
54     \r
55     delimIndex = str.find_first_of(delim, offset);\r
56 \r
57     while (delimIndex != std::string::npos)\r
58     {\r
59         output.push_back(str.substr(offset, delimIndex - offset));\r
60         offset += delimIndex - offset + 1;\r
61         delimIndex = str.find_first_of(delim, offset);\r
62     }\r
63 \r
64     output.push_back(str.substr(offset));\r
65 }\r
66 \r
67 std::string TrimWhitespace(const std::string &str)\r
68 {\r
69         std::string returnstring=str;\r
70 \r
71         while(returnstring.size()>0 && returnstring.find_first_of(" \t\r\n")==0)\r
72         {\r
73                 returnstring.erase(0,1);\r
74         }\r
75         while(returnstring.size()>0 && returnstring.find_last_of(" \t\r\n")==returnstring.size()-1)\r
76         {\r
77                 returnstring.erase(returnstring.size()-1,1);\r
78         }\r
79 \r
80         return returnstring;\r
81 }\r
82 \r
83 void UpperCase(const std::string &str, std::string &output)\r
84 {\r
85         output=str;\r
86         std::transform(str.begin(),str.end(),output.begin(),toupper);\r
87 }\r
88 \r
89 std::string UriDecode(const std::string & sSrc)\r
90 {\r
91    // Note from RFC1630: "Sequences which start with a percent\r
92    // sign but are not followed by two hexadecimal characters\r
93    // (0-9, A-F) are reserved for future extension"\r
94    \r
95 static const char HEX2DEC[256] = \r
96 {\r
97     /*       0  1  2  3   4  5  6  7   8  9  A  B   C  D  E  F */\r
98     /* 0 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,\r
99     /* 1 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,\r
100     /* 2 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,\r
101     /* 3 */  0, 1, 2, 3,  4, 5, 6, 7,  8, 9,-1,-1, -1,-1,-1,-1,\r
102     \r
103     /* 4 */ -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1,\r
104     /* 5 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,\r
105     /* 6 */ -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1,\r
106     /* 7 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,\r
107     \r
108     /* 8 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,\r
109     /* 9 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,\r
110     /* A */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,\r
111     /* B */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,\r
112     \r
113     /* C */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,\r
114     /* D */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,\r
115     /* E */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,\r
116     /* F */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1\r
117 };\r
118 \r
119    const unsigned char * pSrc = (const unsigned char *)sSrc.c_str();\r
120    const int SRC_LEN = sSrc.length();\r
121    const unsigned char * const SRC_END = pSrc + SRC_LEN;\r
122    // last decodable '%'\r
123    const unsigned char * const SRC_LAST_DEC = SRC_END - 2;\r
124 \r
125    char * const pStart = new char[SRC_LEN];\r
126    char * pEnd = pStart;\r
127 \r
128    while (pSrc < SRC_LAST_DEC)\r
129    {\r
130       if (*pSrc == '%')\r
131       {\r
132          char dec1, dec2;\r
133          if (-1 != (dec1 = HEX2DEC[*(pSrc + 1)])\r
134             && -1 != (dec2 = HEX2DEC[*(pSrc + 2)]))\r
135          {\r
136             *pEnd++ = (dec1 << 4) + dec2;\r
137             pSrc += 3;\r
138             continue;\r
139          }\r
140       }\r
141 \r
142       *pEnd++ = *pSrc++;\r
143    }\r
144 \r
145    // the last 2- chars\r
146    while (pSrc < SRC_END)\r
147       *pEnd++ = *pSrc++;\r
148 \r
149    std::string sResult(pStart, pEnd);\r
150    delete [] pStart;\r
151    return sResult;\r
152 }\r
153 \r
154 std::string UriEncode(const std::string & sSrc)\r
155 {\r
156         \r
157 // Only alphanum is safe.\r
158 static const char SAFE[256] =\r
159 {\r
160     /*      0 1 2 3  4 5 6 7  8 9 A B  C D E F */\r
161     /* 0 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,\r
162     /* 1 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,\r
163     /* 2 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,\r
164     /* 3 */ 1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0,\r
165     \r
166     /* 4 */ 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1,\r
167     /* 5 */ 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0,\r
168     /* 6 */ 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1,\r
169     /* 7 */ 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0,\r
170     \r
171     /* 8 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,\r
172     /* 9 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,\r
173     /* A */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,\r
174     /* B */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,\r
175     \r
176     /* C */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,\r
177     /* D */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,\r
178     /* E */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,\r
179     /* F */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0\r
180 };\r
181         \r
182    const char DEC2HEX[16 + 1] = "0123456789ABCDEF";\r
183    const unsigned char * pSrc = (const unsigned char *)sSrc.c_str();\r
184    const int SRC_LEN = sSrc.length();\r
185    unsigned char * const pStart = new unsigned char[SRC_LEN * 3];\r
186    unsigned char * pEnd = pStart;\r
187    const unsigned char * const SRC_END = pSrc + SRC_LEN;\r
188 \r
189    for (; pSrc < SRC_END; ++pSrc)\r
190    {\r
191       if (SAFE[*pSrc])\r
192          *pEnd++ = *pSrc;\r
193       else\r
194       {\r
195          // escape this char\r
196          *pEnd++ = '%';\r
197          *pEnd++ = DEC2HEX[*pSrc >> 4];\r
198          *pEnd++ = DEC2HEX[*pSrc & 0x0F];\r
199       }\r
200    }\r
201 \r
202    std::string sResult((char *)pStart, (char *)pEnd);\r
203    delete [] pStart;\r
204    return sResult;\r
205 }\r
206 \r
207 }       // namespace\r