~ubuntu-branches/debian/sid/fluxbox/sid

« back to all changes in this revision

Viewing changes to .pc/fix-home-detection.patch/src/FbTk/StringUtil.cc

  • Committer: Package Import Robot
  • Author(s): Paul Tagliamonte, Paul Tagliamonte, Andreas Beckmann
  • Date: 2014-02-24 22:56:46 UTC
  • Revision ID: package-import@ubuntu.com-20140224225646-kc5c7yxhn1ei4ql5
Tags: 1.3.5-2
[Paul Tagliamonte]
* Check for $HOME before blindly using it in fluxbox-update_configs.
  (Closes: #715911)

[Andreas Beckmann]
* preinst, prerm: Do not test for the existence of update-alternatives
  (this is part of dpkg).  (Closes: #720136)
* Do not remove+reinstall the current alternative on upgrades as that could
  override local customization.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// StringUtil.cc for fluxbox
 
2
// Copyright (c) 2001 - 2006 Henrik Kinnunen (fluxgen at fluxbox dot org)
 
3
//
 
4
// Permission is hereby granted, free of charge, to any person obtaining a
 
5
// copy of this software and associated documentation files (the "Software"),
 
6
// to deal in the Software without restriction, including without limitation
 
7
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
 
8
// and/or sell copies of the Software, and to permit persons to whom the
 
9
// Software is furnished to do so, subject to the following conditions:
 
10
//
 
11
// The above copyright notice and this permission notice shall be included in
 
12
// all copies or substantial portions of the Software.
 
13
//
 
14
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
15
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
16
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 
17
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
18
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 
19
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 
20
// DEALINGS IN THE SOFTWARE.
 
21
 
 
22
#include "StringUtil.hh"
 
23
 
 
24
#include "../defaults.hh"
 
25
 
 
26
#ifdef HAVE_CSTDIO
 
27
  #include <cstdio>
 
28
#else
 
29
  #include <stdio.h>
 
30
#endif
 
31
#ifdef HAVE_CSTDLIB
 
32
  #include <cstdlib>
 
33
#else
 
34
  #include <stdlib.h>
 
35
#endif
 
36
#ifdef HAVE_CCTYPE
 
37
  #include <cctype>
 
38
#else
 
39
  #include <ctype.h>
 
40
#endif
 
41
#ifdef HAVE_CASSERT
 
42
  #include <cassert>
 
43
#else
 
44
  #include <assert.h>
 
45
#endif
 
46
#ifdef HAVE_CSTRING
 
47
  #include <cstring>
 
48
#else
 
49
  #include <string.h>
 
50
#endif
 
51
 
 
52
#ifdef HAVE_CERRNO
 
53
  #include <cerrno>
 
54
#else
 
55
  #include <errno.h>
 
56
#endif
 
57
 
 
58
#include <memory>
 
59
#include <algorithm>
 
60
#include <string>
 
61
#include <iostream>
 
62
 
 
63
using std::string;
 
64
using std::transform;
 
65
 
 
66
namespace {
 
67
 
 
68
template <typename T>
 
69
int extractBigNumber(const char* in, T (*extractFunc)(const char*, char**, int), T& out) {
 
70
 
 
71
    errno = 0;
 
72
 
 
73
    int ret = 0;
 
74
    char* end = 0;
 
75
    T result = extractFunc(in, &end, 0);
 
76
 
 
77
    if (errno == 0 && end != in) {
 
78
        out = result;
 
79
        ret = 1;
 
80
    }
 
81
 
 
82
    return ret;
 
83
}
 
84
 
 
85
template<typename T>
 
86
int extractSignedNumber(const std::string& in, T& out) {
 
87
 
 
88
    long long int result = 0;
 
89
 
 
90
    if (::extractBigNumber(in.c_str(), strtoll, result)) {
 
91
        out = static_cast<T>(result);
 
92
        return 1;
 
93
    }
 
94
 
 
95
    return 0;
 
96
}
 
97
 
 
98
template<typename T>
 
99
int extractUnsignedNumber(const std::string& in, T& out) {
 
100
 
 
101
    unsigned long long int result = 0;
 
102
 
 
103
    if (::extractBigNumber(in.c_str(), strtoull, result)) {
 
104
        out = static_cast<T>(result);
 
105
        return 1;
 
106
    }
 
107
 
 
108
    return 0;
 
109
}
 
110
 
 
111
 
 
112
 
 
113
}
 
114
 
 
115
 
 
116
namespace FbTk {
 
117
 
 
118
namespace StringUtil {
 
119
 
 
120
int extractNumber(const std::string& in, int& out) {
 
121
    return ::extractSignedNumber<int>(in, out);
 
122
}
 
123
 
 
124
int extractNumber(const std::string& in, unsigned int& out) {
 
125
    return ::extractUnsignedNumber<unsigned int>(in, out);
 
126
}
 
127
 
 
128
int extractNumber(const std::string& in, long& out) {
 
129
    return ::extractSignedNumber<long>(in, out);
 
130
}
 
131
 
 
132
int extractNumber(const std::string& in, unsigned long& out) {
 
133
    return ::extractUnsignedNumber<unsigned long>(in, out);
 
134
}
 
135
 
 
136
int extractNumber(const std::string& in, long long& out) {
 
137
    return ::extractSignedNumber<long long>(in, out);
 
138
}
 
139
 
 
140
int extractNumber(const std::string& in, unsigned long long& out) {
 
141
    return ::extractUnsignedNumber<unsigned long long>(in, out);
 
142
}
 
143
 
 
144
 
 
145
 
 
146
std::string number2String(long long num) {
 
147
    char s[128];
 
148
    snprintf(s, sizeof(s), "%lld", num);
 
149
    return std::string(s);
 
150
}
 
151
 
 
152
std::string number2HexString(long long num) {
 
153
    char s[17];
 
154
    snprintf(s, sizeof(s), "%lx", num);
 
155
    return std::string(s);
 
156
}
 
157
 
 
158
 
 
159
/**
 
160
   Tries to find a string in another and
 
161
   ignoring the case of the characters
 
162
   Returns 0 on failure else pointer to str.
 
163
*/
 
164
const char *strcasestr(const char *str, const char *ptn) {
 
165
    const char *s2, *p2;
 
166
    for( ; *str; str++) {
 
167
        for(s2=str, p2=ptn; ; s2++,p2++) {
 
168
            // check if we reached the end of ptn, if so, return str
 
169
            if (!*p2)
 
170
                return str;
 
171
            // check if the chars match(ignoring case)
 
172
            if (toupper(*s2) != toupper(*p2))
 
173
                break;
 
174
        }
 
175
    }
 
176
    return 0;
 
177
}
 
178
 
 
179
 
 
180
#ifdef _WIN32
 
181
 
 
182
#include <string>
 
183
#define WIN32_LEAN_AND_MEAN 1
 
184
#define NOMINMAX
 
185
#include <windows.h>
 
186
 
 
187
static void removeTrailingPathSeparators(std::string & path) {
 
188
        // Remove any trailing path separators
 
189
        size_t beforeLastPathSep = path.find_last_not_of("/\\");
 
190
        if (beforeLastPathSep != path.size() - 1) {
 
191
            path.erase(beforeLastPathSep + 1);
 
192
        }
 
193
}
 
194
 
 
195
static std::string getFluxboxPrefix() {
 
196
    static std::string ret;
 
197
    static bool init = false;
 
198
    if (!init) {
 
199
        char buffer[1024];
 
200
        HMODULE module = GetModuleHandle(NULL);
 
201
        DWORD size = GetModuleFileName(module, buffer, sizeof(buffer));
 
202
        if (sizeof(buffer) > 0)
 
203
        {
 
204
          buffer[sizeof(buffer) - 1] = 0;
 
205
        }
 
206
        static const char slash = '/';
 
207
        static const char backslash = '\\';
 
208
        char * lastslash = std::find_end(buffer, buffer+size, &slash, &slash + 1);
 
209
        char * lastbackslash = std::find_end(buffer, buffer+size, &backslash, &backslash + 1);
 
210
        ret.assign(buffer);
 
211
 
 
212
        // Remove the filename
 
213
        size_t lastPathSep = ret.find_last_of("/\\");
 
214
        if (lastPathSep != std::string::npos) {
 
215
            ret.erase(lastPathSep);
 
216
        }
 
217
 
 
218
        removeTrailingPathSeparators(ret);
 
219
 
 
220
        // If the last directory is bin, remove that too.
 
221
        lastPathSep = ret.find_last_of("/\\");
 
222
        if (lastPathSep != std::string::npos && ret.substr(lastPathSep + 1) == "bin") {
 
223
            ret.erase(lastPathSep);
 
224
        }
 
225
 
 
226
        removeTrailingPathSeparators(ret);
 
227
    }
 
228
    return ret;
 
229
}
 
230
 
 
231
#endif // _WIN32
 
232
 
 
233
/**
 
234
   if ~ then expand it to home of user
 
235
   if /DUMMYPREFIX on Windows then expand it to the prefix relative to the
 
236
   executable on Windows.
 
237
   returns expanded filename
 
238
*/
 
239
string expandFilename(const string &filename) {
 
240
    string retval;
 
241
    size_t pos = filename.find_first_not_of(" \t");
 
242
    if (pos != string::npos && filename[pos] == '~') {
 
243
#ifdef _WIN32
 
244
        retval = getenv("USERPROFILE");
 
245
#else
 
246
        retval = getenv("HOME");
 
247
#endif
 
248
        if (pos + 1 < filename.size()) {
 
249
            // copy from the character after '~'
 
250
            retval += static_cast<const char *>(filename.c_str() + pos + 1);
 
251
        }
 
252
    } else {
 
253
        retval = filename; //return unmodified value
 
254
    }
 
255
 
 
256
#if defined(_WIN32) && defined(DUMMYPREFIX)
 
257
    if (retval.find(DUMMYPREFIX) == 0) {
 
258
      static const std::string dummyPrefix = DUMMYPREFIX;
 
259
      retval.replace(0, dummyPrefix.size(), getFluxboxPrefix());
 
260
    }
 
261
#endif
 
262
 
 
263
    return retval;
 
264
}
 
265
 
 
266
/**
 
267
   @return string from last "." to end of string
 
268
*/
 
269
string findExtension(const string &filename) {
 
270
    //get start of extension
 
271
    string::size_type start_pos = filename.find_last_of(".");
 
272
    if (start_pos == string::npos && start_pos != filename.size())
 
273
        return "";
 
274
    // return from last . to end of string
 
275
    return filename.substr(start_pos + 1);
 
276
}
 
277
 
 
278
string::size_type findCharFromAlphabetAfterTrigger(const std::string& in, char trigger, const char alphabet[], size_t len_alphabet, size_t* found) {
 
279
    for (const char* s = in.c_str(); *s != '\0'; ) {
 
280
        if (*s++ == trigger && *s != '\0') {
 
281
            for (const char* a = alphabet; (a - alphabet) < static_cast<ssize_t>(len_alphabet); ++a) {
 
282
                if (*s == *a) {
 
283
                    if (found) {
 
284
                        *found = a - alphabet;
 
285
                    }
 
286
                    return s - in.c_str() - 1;
 
287
                }
 
288
            }
 
289
            s++;
 
290
        }
 
291
    }
 
292
    return string::npos;
 
293
}
 
294
 
 
295
 
 
296
string replaceString(const string &original,
 
297
                     const char *findthis,
 
298
                     const char *replace) {
 
299
    size_t i = 0;
 
300
    const int size_of_replace = strlen(replace);
 
301
    const int size_of_find = strlen(findthis);
 
302
    string ret_str(original);
 
303
    while (i < ret_str.size()) {
 
304
        i = ret_str.find(findthis, i);
 
305
        if (i == string::npos)
 
306
            break;
 
307
        // erase old string and insert replacement
 
308
        ret_str.erase(i, size_of_find);
 
309
        ret_str.insert(i, replace);
 
310
        // jump to next position after insert
 
311
        i += size_of_replace;
 
312
    }
 
313
 
 
314
    return ret_str;
 
315
}
 
316
 
 
317
/**
 
318
   Parses a string between "first" and "last" characters
 
319
   and ignoring ok_chars as whitespaces. The value is
 
320
   returned in "out".
 
321
   Returns negative value on error and this value is the position
 
322
   in the in-string where the error occured.
 
323
   Returns positive value on success and this value is
 
324
   for the position + 1 in the in-string where the "last"-char value
 
325
   was found.
 
326
*/
 
327
int getStringBetween(string& out, const char *instr, char first, char last,
 
328
                     const char *ok_chars, bool allow_nesting) {
 
329
    assert(first);
 
330
    assert(last);
 
331
    assert(instr);
 
332
 
 
333
    string::size_type i = 0;
 
334
    string::size_type total_add=0; //used to add extra if there is a \last to skip
 
335
    string in(instr);
 
336
 
 
337
    // eat leading whitespace
 
338
    i = in.find_first_not_of(ok_chars);
 
339
    if (i == string::npos)
 
340
        return -in.size();   // nothing left but whitespace
 
341
 
 
342
    if (in[i]!=first)
 
343
        return -i; //return position to error
 
344
 
 
345
    // find the end of the token
 
346
    string::size_type j = i, k;
 
347
    int nesting = 0;
 
348
    while (1) {
 
349
        k = in.find_first_of(first, j+1);
 
350
        j = in.find_first_of(last, j+1);
 
351
        if (j==string::npos)
 
352
            return -in.size(); //send negative size
 
353
 
 
354
        if (allow_nesting && k < j && in[k-1] != '\\') {
 
355
            nesting++;
 
356
            j = k;
 
357
            continue;
 
358
        }
 
359
        //we found the last char, check so it doesn't have a '\' before
 
360
        if (j>1 && in[j-1] != '\\') {
 
361
            if (allow_nesting && nesting > 0) nesting--;
 
362
            else
 
363
                break;
 
364
        } else if (j>1 && !allow_nesting) { // we leave escapes if we're allowing nesting
 
365
            in.erase(j-1, 1); //remove the '\'
 
366
            j--;
 
367
            total_add++; //save numchars removed so we can calculate totalpos
 
368
        }
 
369
    }
 
370
 
 
371
    out = in.substr(i+1, j-i-1); //copy the string between first and last
 
372
    //return value to last character
 
373
    return (j+1+total_add);
 
374
}
 
375
 
 
376
string toLower(const string &conv) {
 
377
    string ret = conv;
 
378
    transform(ret.begin(), ret.end(), ret.begin(), tolower);
 
379
    return ret;
 
380
}
 
381
 
 
382
string toUpper(const string &conv) {
 
383
    string ret = conv;
 
384
    transform(ret.begin(), ret.end(), ret.begin(), toupper);
 
385
    return ret;
 
386
}
 
387
 
 
388
string basename(const string &filename) {
 
389
    string::size_type first_pos = filename.find_last_of("/");
 
390
    if (first_pos != string::npos)
 
391
        return filename.substr(first_pos + 1);
 
392
    return filename;
 
393
}
 
394
 
 
395
string::size_type removeFirstWhitespace(string &str) {
 
396
    string::size_type first_pos = str.find_first_not_of(" \t");
 
397
    str.erase(0, first_pos);
 
398
    return first_pos;
 
399
}
 
400
 
 
401
 
 
402
string::size_type removeTrailingWhitespace(string &str) {
 
403
    // strip trailing whitespace
 
404
    string::size_type first_pos = str.find_last_not_of(" \t");
 
405
    string::size_type last_pos = str.find_first_of(" \t", first_pos);
 
406
    if (last_pos != string::npos)
 
407
        str.erase(last_pos);
 
408
    return first_pos;
 
409
}
 
410
 
 
411
void getFirstWord(const std::string &in, std::string &word, std::string &rest) {
 
412
    word = in;
 
413
    string::size_type first_pos = StringUtil::removeFirstWhitespace(word);
 
414
    string::size_type second_pos = word.find_first_of(" \t", first_pos);
 
415
    if (second_pos != string::npos) {
 
416
        rest = word.substr(second_pos);
 
417
        word.erase(second_pos);
 
418
    }
 
419
}
 
420
 
 
421
} // end namespace StringUtil
 
422
 
 
423
} // end namespace FbTk