~ubuntu-branches/debian/experimental/kopete/experimental

« back to all changes in this revision

Viewing changes to protocols/jabber/libjingle/talk/base/flags.cc

  • Committer: Package Import Robot
  • Author(s): Maximiliano Curia
  • Date: 2015-02-24 11:32:57 UTC
  • mfrom: (1.1.41 vivid)
  • Revision ID: package-import@ubuntu.com-20150224113257-gnupg4v7lzz18ij0
Tags: 4:14.12.2-1
* New upstream release (14.12.2).
* Bump Standards-Version to 3.9.6, no changes needed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * libjingle
 
3
 * Copyright 2006, Google Inc.
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions are met:
 
7
 *
 
8
 *  1. Redistributions of source code must retain the above copyright notice,
 
9
 *     this list of conditions and the following disclaimer.
 
10
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 
11
 *     this list of conditions and the following disclaimer in the documentation
 
12
 *     and/or other materials provided with the distribution.
 
13
 *  3. The name of the author may not be used to endorse or promote products
 
14
 *     derived from this software without specific prior written permission.
 
15
 *
 
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 
17
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 
18
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 
19
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
20
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 
21
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 
22
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 
23
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 
24
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 
25
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
26
 */
 
27
 
 
28
#include <stdio.h>
 
29
#include <stdlib.h>
 
30
#include <string.h>
 
31
 
 
32
 
 
33
#ifdef WIN32
 
34
#include "talk/base/win32.h"
 
35
#include <shellapi.h>
 
36
#endif
 
37
 
 
38
#include "talk/base/flags.h"
 
39
 
 
40
 
 
41
// -----------------------------------------------------------------------------
 
42
// Implementation of Flag
 
43
 
 
44
Flag::Flag(const char* file, const char* name, const char* comment,
 
45
           Type type, void* variable, FlagValue default__)
 
46
    : file_(file),
 
47
      name_(name),
 
48
      comment_(comment),
 
49
      type_(type),
 
50
      variable_(reinterpret_cast<FlagValue*>(variable)),
 
51
      default_(default__) {
 
52
  FlagList::Register(this);
 
53
}
 
54
 
 
55
 
 
56
void Flag::SetToDefault() {
 
57
  // Note that we cannot simply do '*variable_ = default_;' since
 
58
  // flag variables are not really of type FlagValue and thus may
 
59
  // be smaller! The FlagValue union is simply 'overlayed' on top
 
60
  // of a flag variable for convenient access. Since union members
 
61
  // are guarantee to be aligned at the beginning, this works.
 
62
  switch (type_) {
 
63
    case Flag::BOOL:
 
64
      variable_->b = default_.b;
 
65
      return;
 
66
    case Flag::INT:
 
67
      variable_->i = default_.i;
 
68
      return;
 
69
    case Flag::FLOAT:
 
70
      variable_->f = default_.f;
 
71
      return;
 
72
    case Flag::STRING:
 
73
      variable_->s = default_.s;
 
74
      return;
 
75
  }
 
76
  UNREACHABLE();
 
77
}
 
78
 
 
79
 
 
80
static const char* Type2String(Flag::Type type) {
 
81
  switch (type) {
 
82
    case Flag::BOOL: return "bool";
 
83
    case Flag::INT: return "int";
 
84
    case Flag::FLOAT: return "float";
 
85
    case Flag::STRING: return "string";
 
86
  }
 
87
  UNREACHABLE();
 
88
  return NULL;
 
89
}
 
90
 
 
91
 
 
92
static void PrintFlagValue(Flag::Type type, FlagValue* p) {
 
93
  switch (type) {
 
94
    case Flag::BOOL:
 
95
      printf("%s", (p->b ? "true" : "false"));
 
96
      return;
 
97
    case Flag::INT:
 
98
      printf("%d", p->i);
 
99
      return;
 
100
    case Flag::FLOAT:
 
101
      printf("%f", p->f);
 
102
      return;
 
103
    case Flag::STRING:
 
104
      printf("%s", p->s);
 
105
      return;
 
106
  }
 
107
  UNREACHABLE();
 
108
}
 
109
 
 
110
 
 
111
void Flag::Print(bool print_current_value) {
 
112
  printf("  --%s (%s)  type: %s  default: ", name_, comment_,
 
113
          Type2String(type_));
 
114
  PrintFlagValue(type_, &default_);
 
115
  if (print_current_value) {
 
116
    printf("  current value: ");
 
117
    PrintFlagValue(type_, variable_);
 
118
  }
 
119
  printf("\n");
 
120
}
 
121
 
 
122
 
 
123
// -----------------------------------------------------------------------------
 
124
// Implementation of FlagList
 
125
 
 
126
Flag* FlagList::list_ = NULL;
 
127
 
 
128
 
 
129
FlagList::FlagList() {
 
130
  list_ = NULL;
 
131
}
 
132
 
 
133
void FlagList::Print(const char* file, bool print_current_value) {
 
134
  // Since flag registration is likely by file (= C++ file),
 
135
  // we don't need to sort by file and still get grouped output.
 
136
  const char* current = NULL;
 
137
  for (Flag* f = list_; f != NULL; f = f->next()) {
 
138
    if (file == NULL || file == f->file()) {
 
139
      if (current != f->file()) {
 
140
        printf("Flags from %s:\n", f->file());
 
141
        current = f->file();
 
142
      }
 
143
      f->Print(print_current_value);
 
144
    }
 
145
  }
 
146
}
 
147
 
 
148
 
 
149
Flag* FlagList::Lookup(const char* name) {
 
150
  Flag* f = list_;
 
151
  while (f != NULL && strcmp(name, f->name()) != 0)
 
152
    f = f->next();
 
153
  return f;
 
154
}
 
155
 
 
156
 
 
157
void FlagList::SplitArgument(const char* arg,
 
158
                             char* buffer, int buffer_size,
 
159
                             const char** name, const char** value,
 
160
                             bool* is_bool) {
 
161
  *name = NULL;
 
162
  *value = NULL;
 
163
  *is_bool = false;
 
164
 
 
165
  if (*arg == '-') {
 
166
    // find the begin of the flag name
 
167
    arg++;  // remove 1st '-'
 
168
    if (*arg == '-')
 
169
      arg++;  // remove 2nd '-'
 
170
    if (arg[0] == 'n' && arg[1] == 'o') {
 
171
      arg += 2;  // remove "no"
 
172
      *is_bool = true;
 
173
    }
 
174
    *name = arg;
 
175
 
 
176
    // find the end of the flag name
 
177
    while (*arg != '\0' && *arg != '=')
 
178
      arg++;
 
179
 
 
180
    // get the value if any
 
181
    if (*arg == '=') {
 
182
      // make a copy so we can NUL-terminate flag name
 
183
      int n = static_cast<int>(arg - *name);
 
184
      if (n >= buffer_size)
 
185
        Fatal(__FILE__, __LINE__, "CHECK(%s) failed", "n < buffer_size");
 
186
      memcpy(buffer, *name, n * sizeof(char));
 
187
      buffer[n] = '\0';
 
188
      *name = buffer;
 
189
      // get the value
 
190
      *value = arg + 1;
 
191
    }
 
192
  }
 
193
}
 
194
 
 
195
 
 
196
int FlagList::SetFlagsFromCommandLine(int* argc, const char** argv,
 
197
                                      bool remove_flags) {
 
198
  // parse arguments
 
199
  for (int i = 1; i < *argc; /* see below */) {
 
200
    int j = i;  // j > 0
 
201
    const char* arg = argv[i++];
 
202
 
 
203
    // split arg into flag components
 
204
    char buffer[1024];
 
205
    const char* name;
 
206
    const char* value;
 
207
    bool is_bool;
 
208
    SplitArgument(arg, buffer, sizeof buffer, &name, &value, &is_bool);
 
209
 
 
210
    if (name != NULL) {
 
211
      // lookup the flag
 
212
      Flag* flag = Lookup(name);
 
213
      if (flag == NULL) {
 
214
        fprintf(stderr, "Error: unrecognized flag %s\n", arg);
 
215
        return j;
 
216
      }
 
217
 
 
218
      // if we still need a flag value, use the next argument if available
 
219
      if (flag->type() != Flag::BOOL && value == NULL) {
 
220
        if (i < *argc) {
 
221
          value = argv[i++];
 
222
        } else {
 
223
          fprintf(stderr, "Error: missing value for flag %s of type %s\n",
 
224
            arg, Type2String(flag->type()));
 
225
          return j;
 
226
        }
 
227
      }
 
228
 
 
229
      // set the flag
 
230
      char empty[] = { '\0' };
 
231
      char* endp = empty;
 
232
      switch (flag->type()) {
 
233
        case Flag::BOOL:
 
234
          *flag->bool_variable() = !is_bool;
 
235
          break;
 
236
        case Flag::INT:
 
237
          *flag->int_variable() = strtol(value, &endp, 10);
 
238
          break;
 
239
        case Flag::FLOAT:
 
240
          *flag->float_variable() = strtod(value, &endp);
 
241
          break;
 
242
        case Flag::STRING:
 
243
          *flag->string_variable() = value;
 
244
          break;
 
245
      }
 
246
 
 
247
      // handle errors
 
248
      if ((flag->type() == Flag::BOOL && value != NULL) ||
 
249
          (flag->type() != Flag::BOOL && is_bool) ||
 
250
          *endp != '\0') {
 
251
        fprintf(stderr, "Error: illegal value for flag %s of type %s\n",
 
252
          arg, Type2String(flag->type()));
 
253
        return j;
 
254
      }
 
255
 
 
256
      // remove the flag & value from the command
 
257
      if (remove_flags)
 
258
        while (j < i)
 
259
          argv[j++] = NULL;
 
260
    }
 
261
  }
 
262
 
 
263
  // shrink the argument list
 
264
  if (remove_flags) {
 
265
    int j = 1;
 
266
    for (int i = 1; i < *argc; i++) {
 
267
      if (argv[i] != NULL)
 
268
        argv[j++] = argv[i];
 
269
    }
 
270
    *argc = j;
 
271
  }
 
272
 
 
273
  // parsed all flags successfully
 
274
  return 0;
 
275
}
 
276
 
 
277
void FlagList::Register(Flag* flag) {
 
278
  assert(flag != NULL && strlen(flag->name()) > 0);
 
279
  if (Lookup(flag->name()) != NULL)
 
280
    Fatal(flag->file(), 0, "flag %s declared twice", flag->name());
 
281
  flag->next_ = list_;
 
282
  list_ = flag;
 
283
}
 
284
 
 
285
#ifdef WIN32
 
286
WindowsCommandLineArguments::WindowsCommandLineArguments() {
 
287
  // start by getting the command line.
 
288
  LPTSTR command_line = ::GetCommandLine();
 
289
   // now, convert it to a list of wide char strings.
 
290
  LPWSTR *wide_argv = ::CommandLineToArgvW(command_line, &argc_);
 
291
  // now allocate an array big enough to hold that many string pointers.
 
292
  argv_ = new char*[argc_];
 
293
 
 
294
  // iterate over the returned wide strings;
 
295
  for(int i = 0; i < argc_; ++i) {
 
296
    std::string s = talk_base::ToUtf8(wide_argv[i], wcslen(wide_argv[i]));
 
297
    char *buffer = new char[s.length() + 1];
 
298
    talk_base::strcpyn(buffer, s.length() + 1, s.c_str());
 
299
 
 
300
    // make sure the argv array has the right string at this point.
 
301
    argv_[i] = buffer;
 
302
  }
 
303
  LocalFree(wide_argv);
 
304
}
 
305
 
 
306
WindowsCommandLineArguments::~WindowsCommandLineArguments() {
 
307
  // need to free each string in the array, and then the array.
 
308
  for(int i = 0; i < argc_; i++) {
 
309
    delete[] argv_[i];
 
310
  }
 
311
 
 
312
  delete[] argv_;
 
313
}
 
314
#endif  // WIN32
 
315