File: flags_use_no_gflags.cpp

package info (click to toggle)
pytorch 1.13.1%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 139,252 kB
  • sloc: cpp: 1,100,274; python: 706,454; ansic: 83,052; asm: 7,618; java: 3,273; sh: 2,841; javascript: 612; makefile: 323; xml: 269; ruby: 185; yacc: 144; objc: 68; lex: 44
file content (206 lines) | stat: -rw-r--r-- 6,067 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#include <c10/macros/Macros.h>
#include <c10/util/Flags.h>

#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>

#ifndef C10_USE_GFLAGS

namespace c10 {

using std::string;

C10_DEFINE_REGISTRY(C10FlagsRegistry, C10FlagParser, const string&);

namespace {
static bool gCommandLineFlagsParsed = false;
// Since flags is going to be loaded before logging, we would
// need to have a stringstream to hold the messages instead of directly
// using caffe logging.
std::stringstream& GlobalInitStream() {
  static std::stringstream ss;
  return ss;
}
static const char* gUsageMessage = "(Usage message not set.)";
} // namespace

C10_EXPORT void SetUsageMessage(const string& str) {
  static string usage_message_safe_copy = str;
  gUsageMessage = usage_message_safe_copy.c_str();
}

C10_EXPORT const char* UsageMessage() {
  return gUsageMessage;
}

C10_EXPORT bool ParseCommandLineFlags(int* pargc, char*** pargv) {
  if (*pargc == 0)
    return true;
  char** argv = *pargv;
  bool success = true;
  GlobalInitStream() << "Parsing commandline arguments for c10." << std::endl;
  // write_head is the location we write the unused arguments to.
  int write_head = 1;
  for (int i = 1; i < *pargc; ++i) {
    string arg(argv[i]);

    if (arg.find("--help") != string::npos) {
      // Print the help message, and quit.
      std::cout << UsageMessage() << std::endl;
      std::cout << "Arguments: " << std::endl;
      for (const auto& help_msg : C10FlagsRegistry()->HelpMessage()) {
        std::cout << "    " << help_msg.first << ": " << help_msg.second
                  << std::endl;
      }
      exit(0);
    }
    // If the arg does not start with "--", we will ignore it.
    if (arg[0] != '-' || arg[1] != '-') {
      GlobalInitStream()
          << "C10 flag: commandline argument does not match --name=var "
             "or --name format: "
          << arg << ". Ignoring this argument." << std::endl;
      argv[write_head++] = argv[i];
      continue;
    }

    string key;
    string value;
    size_t prefix_idx = arg.find('=');
    if (prefix_idx == string::npos) {
      // If there is no equality char in the arg, it means that the
      // arg is specified in the next argument.
      key = arg.substr(2, arg.size() - 2);
      ++i;
      if (i == *pargc) {
        GlobalInitStream()
            << "C10 flag: reached the last commandline argument, but "
               "I am expecting a value for "
            << arg;
        success = false;
        break;
      }
      value = string(argv[i]);
    } else {
      // If there is an equality character, we will basically use the value
      // after the "=".
      key = arg.substr(2, prefix_idx - 2);
      value = arg.substr(prefix_idx + 1, string::npos);
    }
    // If the flag is not registered, we will ignore it.
    if (!C10FlagsRegistry()->Has(key)) {
      GlobalInitStream() << "C10 flag: unrecognized commandline argument: "
                         << arg << std::endl;
      success = false;
      break;
    }
    std::unique_ptr<C10FlagParser> parser(
        C10FlagsRegistry()->Create(key, value));
    if (!parser->success()) {
      GlobalInitStream() << "C10 flag: illegal argument: " << arg << std::endl;
      success = false;
      break;
    }
  }
  *pargc = write_head;
  gCommandLineFlagsParsed = true;
  // TODO: when we fail commandline flag parsing, shall we continue, or
  // shall we just quit loudly? Right now we carry on the computation, but
  // since there are failures in parsing, it is very likely that some
  // downstream things will break, in which case it makes sense to quit loud
  // and early.
  if (!success) {
    std::cerr << GlobalInitStream().str();
  }
  // Clear the global init stream.
  GlobalInitStream().str(std::string());
  return success;
}

C10_EXPORT bool CommandLineFlagsHasBeenParsed() {
  return gCommandLineFlagsParsed;
}

template <>
C10_EXPORT bool C10FlagParser::Parse<string>(
    const string& content,
    string* value) {
  *value = content;
  return true;
}

template <>
C10_EXPORT bool C10FlagParser::Parse<int>(const string& content, int* value) {
  try {
    *value = std::atoi(content.c_str());
    return true;
  } catch (...) {
    GlobalInitStream() << "C10 flag error: Cannot convert argument to int: "
                       << content << std::endl;
    return false;
  }
}

template <>
C10_EXPORT bool C10FlagParser::Parse<int64_t>(
    const string& content,
    int64_t* value) {
  try {
    static_assert(sizeof(long long) == sizeof(int64_t), "");
#ifdef __ANDROID__
    // Android does not have std::atoll.
    *value = atoll(content.c_str());
#else
    *value = std::atoll(content.c_str());
#endif
    return true;
  } catch (...) {
    GlobalInitStream() << "C10 flag error: Cannot convert argument to int: "
                       << content << std::endl;
    return false;
  }
}

template <>
C10_EXPORT bool C10FlagParser::Parse<double>(
    const string& content,
    double* value) {
  try {
    *value = std::atof(content.c_str());
    return true;
  } catch (...) {
    GlobalInitStream() << "C10 flag error: Cannot convert argument to double: "
                       << content << std::endl;
    return false;
  }
}

template <>
C10_EXPORT bool C10FlagParser::Parse<bool>(const string& content, bool* value) {
  if (content == "false" || content == "False" || content == "FALSE" ||
      content == "0") {
    *value = false;
    return true;
  } else if (
      content == "true" || content == "True" || content == "TRUE" ||
      content == "1") {
    *value = true;
    return true;
  } else {
    GlobalInitStream()
        << "C10 flag error: Cannot convert argument to bool: " << content
        << std::endl
        << "Note that if you are passing in a bool flag, you need to "
           "explicitly specify it, like --arg=True or --arg True. Otherwise, "
           "the next argument may be inadvertently used as the argument, "
           "causing the above error."
        << std::endl;
    return false;
  }
}

} // namespace c10

#endif // C10_USE_GFLAGS