Command.cpp 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087
  1. /*
  2. * Copyright (c) 2020 Project CHIP Authors
  3. * All rights reserved.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. #include "Command.h"
  19. #include "CustomStringPrefix.h"
  20. #include "HexConversion.h"
  21. #include "platform/PlatformManager.h"
  22. #include <functional>
  23. #include <netdb.h>
  24. #include <sstream>
  25. #include <sys/socket.h>
  26. #include <sys/types.h>
  27. #include <math.h> // For INFINITY
  28. #include <lib/core/CHIPSafeCasts.h>
  29. #include <lib/support/BytesToHex.h>
  30. #include <lib/support/CHIPMem.h>
  31. #include <lib/support/CodeUtils.h>
  32. #include <lib/support/SafeInt.h>
  33. #include <lib/support/ScopedBuffer.h>
  34. #include <lib/support/StringSplitter.h>
  35. #include <lib/support/logging/CHIPLogging.h>
  36. constexpr const char * kOptionalArgumentPrefix = "--";
  37. constexpr size_t kOptionalArgumentPrefixLength = 2;
  38. bool Command::InitArguments(int argc, char ** argv)
  39. {
  40. bool isValidCommand = false;
  41. size_t argvExtraArgsCount = (size_t) argc;
  42. size_t mandatoryArgsCount = 0;
  43. size_t optionalArgsCount = 0;
  44. for (auto & arg : mArgs)
  45. {
  46. if (arg.isOptional())
  47. {
  48. optionalArgsCount++;
  49. }
  50. else
  51. {
  52. mandatoryArgsCount++;
  53. argvExtraArgsCount--;
  54. }
  55. }
  56. VerifyOrExit((size_t)(argc) >= mandatoryArgsCount && (argvExtraArgsCount == 0 || (argvExtraArgsCount && optionalArgsCount)),
  57. ChipLogError(chipTool, "InitArgs: Wrong arguments number: %d instead of %u", argc,
  58. static_cast<unsigned int>(mandatoryArgsCount)));
  59. // Initialize mandatory arguments
  60. for (size_t i = 0; i < mandatoryArgsCount; i++)
  61. {
  62. char * arg = argv[i];
  63. if (!InitArgument(i, arg))
  64. {
  65. ExitNow();
  66. }
  67. }
  68. // Initialize optional arguments
  69. // Optional arguments expect a name and a value, so i is increased by 2 on every step.
  70. for (size_t i = mandatoryArgsCount; i < (size_t) argc; i += 2)
  71. {
  72. bool found = false;
  73. for (size_t j = mandatoryArgsCount; j < mandatoryArgsCount + optionalArgsCount; j++)
  74. {
  75. // optional arguments starts with kOptionalArgumentPrefix
  76. if (strlen(argv[i]) <= kOptionalArgumentPrefixLength &&
  77. strncmp(argv[i], kOptionalArgumentPrefix, kOptionalArgumentPrefixLength) != 0)
  78. {
  79. continue;
  80. }
  81. if (strcmp(argv[i] + strlen(kOptionalArgumentPrefix), mArgs[j].name) == 0)
  82. {
  83. found = true;
  84. VerifyOrExit((size_t) argc > (i + 1),
  85. ChipLogError(chipTool, "InitArgs: Optional argument %s missing value.", argv[i]));
  86. if (!InitArgument(j, argv[i + 1]))
  87. {
  88. ExitNow();
  89. }
  90. }
  91. }
  92. VerifyOrExit(found, ChipLogError(chipTool, "InitArgs: Optional argument %s does not exist.", argv[i]));
  93. }
  94. isValidCommand = true;
  95. exit:
  96. return isValidCommand;
  97. }
  98. static bool ParseAddressWithInterface(const char * addressString, Command::AddressWithInterface * address)
  99. {
  100. struct addrinfo hints;
  101. struct addrinfo * result;
  102. int ret;
  103. memset(&hints, 0, sizeof(hints));
  104. hints.ai_family = AF_UNSPEC;
  105. hints.ai_socktype = SOCK_DGRAM;
  106. ret = getaddrinfo(addressString, nullptr, &hints, &result);
  107. if (ret < 0)
  108. {
  109. ChipLogError(chipTool, "Invalid address: %s", addressString);
  110. return false;
  111. }
  112. if (result->ai_family == AF_INET6)
  113. {
  114. struct sockaddr_in6 * addr = reinterpret_cast<struct sockaddr_in6 *>(result->ai_addr);
  115. address->address = ::chip::Inet::IPAddress::FromSockAddr(*addr);
  116. address->interfaceId = ::chip::Inet::InterfaceId(addr->sin6_scope_id);
  117. }
  118. #if INET_CONFIG_ENABLE_IPV4
  119. else if (result->ai_family == AF_INET)
  120. {
  121. address->address = ::chip::Inet::IPAddress::FromSockAddr(*reinterpret_cast<struct sockaddr_in *>(result->ai_addr));
  122. address->interfaceId = chip::Inet::InterfaceId::Null();
  123. }
  124. #endif // INET_CONFIG_ENABLE_IPV4
  125. else
  126. {
  127. ChipLogError(chipTool, "Unsupported address: %s", addressString);
  128. return false;
  129. }
  130. return true;
  131. }
  132. // The callback should return whether the argument is valid, for the non-null
  133. // case. It can't directly write to isValidArgument (by closing over it)
  134. // because in the nullable-and-null case we need to do that from this function,
  135. // via the return value.
  136. template <typename T>
  137. bool HandleNullableOptional(Argument & arg, char * argValue, std::function<bool(T * value)> callback)
  138. {
  139. if (arg.isOptional())
  140. {
  141. if (arg.isNullable())
  142. {
  143. arg.value = &(reinterpret_cast<chip::Optional<chip::app::DataModel::Nullable<T>> *>(arg.value)->Emplace());
  144. }
  145. else
  146. {
  147. arg.value = &(reinterpret_cast<chip::Optional<T> *>(arg.value)->Emplace());
  148. }
  149. }
  150. if (arg.isNullable())
  151. {
  152. auto * nullable = reinterpret_cast<chip::app::DataModel::Nullable<T> *>(arg.value);
  153. if (strcmp(argValue, "null") == 0)
  154. {
  155. nullable->SetNull();
  156. return true;
  157. }
  158. arg.value = &(nullable->SetNonNull());
  159. }
  160. return callback(reinterpret_cast<T *>(arg.value));
  161. }
  162. bool Command::InitArgument(size_t argIndex, char * argValue)
  163. {
  164. bool isValidArgument = false;
  165. bool isHexNotation = strncmp(argValue, "0x", 2) == 0 || strncmp(argValue, "0X", 2) == 0;
  166. Argument arg = mArgs.at(argIndex);
  167. // We have two places where we handle uint8_t-typed args (actual int8u and
  168. // bool args), so declare the handler function here so it can be reused.
  169. auto uint8Handler = [&](uint8_t * value) {
  170. // stringstream treats uint8_t as char, which is not what we want here.
  171. uint16_t tmpValue;
  172. std::stringstream ss;
  173. isHexNotation ? (ss << std::hex << argValue) : (ss << argValue);
  174. ss >> tmpValue;
  175. if (chip::CanCastTo<uint8_t>(tmpValue))
  176. {
  177. *value = static_cast<uint8_t>(tmpValue);
  178. uint64_t min = chip::CanCastTo<uint64_t>(arg.min) ? static_cast<uint64_t>(arg.min) : 0;
  179. uint64_t max = arg.max;
  180. return (!ss.fail() && ss.eof() && *value >= min && *value <= max);
  181. }
  182. return false;
  183. };
  184. switch (arg.type)
  185. {
  186. case ArgumentType::Complex: {
  187. // Complex arguments may be optional, but they are not currently supported via the <chip::Optional> class.
  188. // Instead, they must be explicitly specified as optional using the kOptional flag,
  189. // and the base TypedComplexArgument<T> class is still referenced.
  190. auto complexArgument = static_cast<ComplexArgument *>(arg.value);
  191. return CHIP_NO_ERROR == complexArgument->Parse(arg.name, argValue);
  192. }
  193. case ArgumentType::Custom: {
  194. auto customArgument = static_cast<CustomArgument *>(arg.value);
  195. return CHIP_NO_ERROR == customArgument->Parse(arg.name, argValue);
  196. }
  197. case ArgumentType::VectorString: {
  198. std::vector<std::string> vectorArgument;
  199. chip::StringSplitter splitter(argValue, ',');
  200. chip::CharSpan value;
  201. while (splitter.Next(value))
  202. {
  203. vectorArgument.push_back(std::string(value.data(), value.size()));
  204. }
  205. if (arg.flags == Argument::kOptional)
  206. {
  207. auto argument = static_cast<chip::Optional<std::vector<std::string>> *>(arg.value);
  208. argument->SetValue(vectorArgument);
  209. }
  210. else
  211. {
  212. auto argument = static_cast<std::vector<std::string> *>(arg.value);
  213. *argument = vectorArgument;
  214. }
  215. return true;
  216. }
  217. case ArgumentType::VectorBool: {
  218. // Currently only chip::Optional<std::vector<bool>> is supported.
  219. if (arg.flags != Argument::kOptional)
  220. {
  221. return false;
  222. }
  223. std::vector<bool> vectorArgument;
  224. std::stringstream ss(argValue);
  225. while (ss.good())
  226. {
  227. std::string valueAsString;
  228. getline(ss, valueAsString, ',');
  229. if (strcasecmp(valueAsString.c_str(), "true") == 0)
  230. {
  231. vectorArgument.push_back(true);
  232. }
  233. else if (strcasecmp(valueAsString.c_str(), "false") == 0)
  234. {
  235. vectorArgument.push_back(false);
  236. }
  237. else
  238. {
  239. return false;
  240. }
  241. }
  242. auto optionalArgument = static_cast<chip::Optional<std::vector<bool>> *>(arg.value);
  243. optionalArgument->SetValue(vectorArgument);
  244. return true;
  245. }
  246. case ArgumentType::Vector16:
  247. case ArgumentType::Vector32: {
  248. std::vector<uint64_t> values;
  249. uint64_t min = chip::CanCastTo<uint64_t>(arg.min) ? static_cast<uint64_t>(arg.min) : 0;
  250. uint64_t max = arg.max;
  251. std::stringstream ss(argValue);
  252. while (ss.good())
  253. {
  254. std::string valueAsString;
  255. getline(ss, valueAsString, ',');
  256. isHexNotation = strncmp(valueAsString.c_str(), "0x", 2) == 0 || strncmp(valueAsString.c_str(), "0X", 2) == 0;
  257. std::stringstream subss;
  258. isHexNotation ? subss << std::hex << valueAsString : subss << valueAsString;
  259. uint64_t value;
  260. subss >> value;
  261. VerifyOrReturnError(!subss.fail() && subss.eof() && value >= min && value <= max, false);
  262. values.push_back(value);
  263. }
  264. if (arg.type == ArgumentType::Vector16)
  265. {
  266. auto vectorArgument = static_cast<std::vector<uint16_t> *>(arg.value);
  267. for (uint64_t v : values)
  268. {
  269. vectorArgument->push_back(static_cast<uint16_t>(v));
  270. }
  271. }
  272. else if (arg.type == ArgumentType::Vector32 && arg.flags != Argument::kOptional)
  273. {
  274. auto vectorArgument = static_cast<std::vector<uint32_t> *>(arg.value);
  275. for (uint64_t v : values)
  276. {
  277. vectorArgument->push_back(static_cast<uint32_t>(v));
  278. }
  279. }
  280. else if (arg.type == ArgumentType::Vector32 && arg.flags == Argument::kOptional)
  281. {
  282. std::vector<uint32_t> vectorArgument;
  283. for (uint64_t v : values)
  284. {
  285. vectorArgument.push_back(static_cast<uint32_t>(v));
  286. }
  287. auto optionalArgument = static_cast<chip::Optional<std::vector<uint32_t>> *>(arg.value);
  288. optionalArgument->SetValue(vectorArgument);
  289. }
  290. else
  291. {
  292. return false;
  293. }
  294. return true;
  295. }
  296. case ArgumentType::VectorCustom: {
  297. auto vectorArgument = static_cast<std::vector<CustomArgument *> *>(arg.value);
  298. std::stringstream ss(argValue);
  299. while (ss.good())
  300. {
  301. std::string valueAsString;
  302. // By default the parameter separator is ";" in order to not collapse with the argument itself if it contains commas
  303. // (e.g a struct argument with multiple fields). In case one needs to use ";" it can be overriden with the following
  304. // environment variable.
  305. constexpr const char * kSeparatorVariable = "CHIPTOOL_CUSTOM_ARGUMENTS_SEPARATOR";
  306. char * getenvSeparatorVariableResult = getenv(kSeparatorVariable);
  307. getline(ss, valueAsString, getenvSeparatorVariableResult ? getenvSeparatorVariableResult[0] : ';');
  308. CustomArgument * customArgument = new CustomArgument();
  309. vectorArgument->push_back(customArgument);
  310. VerifyOrReturnError(CHIP_NO_ERROR == vectorArgument->back()->Parse(arg.name, valueAsString.c_str()), false);
  311. }
  312. return true;
  313. }
  314. case ArgumentType::String: {
  315. isValidArgument = HandleNullableOptional<char *>(arg, argValue, [&](auto * value) {
  316. *value = argValue;
  317. return true;
  318. });
  319. break;
  320. }
  321. case ArgumentType::CharString: {
  322. isValidArgument = HandleNullableOptional<chip::CharSpan>(arg, argValue, [&](auto * value) {
  323. *value = chip::Span<const char>(argValue, strlen(argValue));
  324. return true;
  325. });
  326. break;
  327. }
  328. case ArgumentType::OctetString: {
  329. isValidArgument = HandleNullableOptional<chip::ByteSpan>(arg, argValue, [&](auto * value) {
  330. // We support two ways to pass an octet string argument. If it happens
  331. // to be all-ASCII, you can just pass it in. Otherwise you can pass in
  332. // "hex:" followed by the hex-encoded bytes.
  333. size_t argLen = strlen(argValue);
  334. if (IsHexString(argValue))
  335. {
  336. // Hex-encoded. Decode it into a temporary buffer first, so if we
  337. // run into errors we can do correct "argument is not valid" logging
  338. // that actually shows the value that was passed in. After we
  339. // determine it's valid, modify the passed-in value to hold the
  340. // right bytes, so we don't need to worry about allocating storage
  341. // for this somewhere else. This works because the hex
  342. // representation is always longer than the octet string it encodes,
  343. // so we have enough space in argValue for the decoded version.
  344. chip::Platform::ScopedMemoryBuffer<uint8_t> buffer;
  345. size_t octetCount;
  346. CHIP_ERROR err = HexToBytes(
  347. chip::CharSpan(argValue + kHexStringPrefixLen, argLen - kHexStringPrefixLen),
  348. [&buffer](size_t allocSize) {
  349. buffer.Calloc(allocSize);
  350. return buffer.Get();
  351. },
  352. &octetCount);
  353. if (err != CHIP_NO_ERROR)
  354. {
  355. return false;
  356. }
  357. memcpy(argValue, buffer.Get(), octetCount);
  358. *value = chip::ByteSpan(chip::Uint8::from_char(argValue), octetCount);
  359. return true;
  360. }
  361. // Just ASCII. Check for the "str:" prefix.
  362. if (IsStrString(argValue))
  363. {
  364. // Skip the prefix
  365. argValue += kStrStringPrefixLen;
  366. argLen -= kStrStringPrefixLen;
  367. }
  368. *value = chip::ByteSpan(chip::Uint8::from_char(argValue), argLen);
  369. return true;
  370. });
  371. break;
  372. }
  373. case ArgumentType::Bool: {
  374. isValidArgument = HandleNullableOptional<bool>(arg, argValue, [&](auto * value) {
  375. // Start with checking for actual boolean values.
  376. if (strcasecmp(argValue, "true") == 0)
  377. {
  378. *value = true;
  379. return true;
  380. }
  381. if (strcasecmp(argValue, "false") == 0)
  382. {
  383. *value = false;
  384. return true;
  385. }
  386. // For backwards compat, keep accepting 0 and 1 for now as synonyms
  387. // for false and true. Since we set our min to 0 and max to 1 for
  388. // booleans, calling uint8Handler does the right thing in terms of
  389. // only allowing those two values.
  390. uint8_t temp = 0;
  391. if (!uint8Handler(&temp))
  392. {
  393. return false;
  394. }
  395. *value = (temp == 1);
  396. return true;
  397. });
  398. break;
  399. }
  400. case ArgumentType::Number_uint8: {
  401. isValidArgument = HandleNullableOptional<uint8_t>(arg, argValue, uint8Handler);
  402. break;
  403. }
  404. case ArgumentType::Number_uint16: {
  405. isValidArgument = HandleNullableOptional<uint16_t>(arg, argValue, [&](auto * value) {
  406. std::stringstream ss;
  407. isHexNotation ? ss << std::hex << argValue : ss << argValue;
  408. ss >> *value;
  409. uint64_t min = chip::CanCastTo<uint64_t>(arg.min) ? static_cast<uint64_t>(arg.min) : 0;
  410. uint64_t max = arg.max;
  411. return (!ss.fail() && ss.eof() && *value >= min && *value <= max);
  412. });
  413. break;
  414. }
  415. case ArgumentType::Number_uint32: {
  416. isValidArgument = HandleNullableOptional<uint32_t>(arg, argValue, [&](auto * value) {
  417. std::stringstream ss;
  418. isHexNotation ? ss << std::hex << argValue : ss << argValue;
  419. ss >> *value;
  420. uint64_t min = chip::CanCastTo<uint64_t>(arg.min) ? static_cast<uint64_t>(arg.min) : 0;
  421. uint64_t max = arg.max;
  422. return (!ss.fail() && ss.eof() && *value >= min && *value <= max);
  423. });
  424. break;
  425. }
  426. case ArgumentType::Number_uint64: {
  427. isValidArgument = HandleNullableOptional<uint64_t>(arg, argValue, [&](auto * value) {
  428. std::stringstream ss;
  429. isHexNotation ? ss << std::hex << argValue : ss << argValue;
  430. ss >> *value;
  431. uint64_t min = chip::CanCastTo<uint64_t>(arg.min) ? static_cast<uint64_t>(arg.min) : 0;
  432. uint64_t max = arg.max;
  433. return (!ss.fail() && ss.eof() && *value >= min && *value <= max);
  434. });
  435. break;
  436. }
  437. case ArgumentType::Number_int8: {
  438. isValidArgument = HandleNullableOptional<int8_t>(arg, argValue, [&](auto * value) {
  439. // stringstream treats int8_t as char, which is not what we want here.
  440. int16_t tmpValue;
  441. std::stringstream ss;
  442. isHexNotation ? ss << std::hex << argValue : ss << argValue;
  443. ss >> tmpValue;
  444. if (chip::CanCastTo<int8_t>(tmpValue))
  445. {
  446. *value = static_cast<int8_t>(tmpValue);
  447. int64_t min = arg.min;
  448. int64_t max = chip::CanCastTo<int64_t>(arg.max) ? static_cast<int64_t>(arg.max) : INT64_MAX;
  449. return (!ss.fail() && ss.eof() && *value >= min && *value <= max);
  450. }
  451. return false;
  452. });
  453. break;
  454. }
  455. case ArgumentType::Number_int16: {
  456. isValidArgument = HandleNullableOptional<int16_t>(arg, argValue, [&](auto * value) {
  457. std::stringstream ss;
  458. isHexNotation ? ss << std::hex << argValue : ss << argValue;
  459. ss >> *value;
  460. int64_t min = arg.min;
  461. int64_t max = chip::CanCastTo<int64_t>(arg.max) ? static_cast<int64_t>(arg.max) : INT64_MAX;
  462. return (!ss.fail() && ss.eof() && *value >= min && *value <= max);
  463. });
  464. break;
  465. }
  466. case ArgumentType::Number_int32: {
  467. isValidArgument = HandleNullableOptional<int32_t>(arg, argValue, [&](auto * value) {
  468. std::stringstream ss;
  469. isHexNotation ? ss << std::hex << argValue : ss << argValue;
  470. ss >> *value;
  471. int64_t min = arg.min;
  472. int64_t max = chip::CanCastTo<int64_t>(arg.max) ? static_cast<int64_t>(arg.max) : INT64_MAX;
  473. return (!ss.fail() && ss.eof() && *value >= min && *value <= max);
  474. });
  475. break;
  476. }
  477. case ArgumentType::Number_int64: {
  478. isValidArgument = HandleNullableOptional<int64_t>(arg, argValue, [&](auto * value) {
  479. std::stringstream ss;
  480. isHexNotation ? ss << std::hex << argValue : ss << argValue;
  481. ss >> *value;
  482. int64_t min = arg.min;
  483. int64_t max = chip::CanCastTo<int64_t>(arg.max) ? static_cast<int64_t>(arg.max) : INT64_MAX;
  484. return (!ss.fail() && ss.eof() && *value >= min && *value <= max);
  485. });
  486. break;
  487. }
  488. case ArgumentType::Float: {
  489. isValidArgument = HandleNullableOptional<float>(arg, argValue, [&](auto * value) {
  490. if (strcmp(argValue, "Infinity") == 0)
  491. {
  492. *value = INFINITY;
  493. return true;
  494. }
  495. if (strcmp(argValue, "-Infinity") == 0)
  496. {
  497. *value = -INFINITY;
  498. return true;
  499. }
  500. std::stringstream ss;
  501. ss << argValue;
  502. ss >> *value;
  503. return (!ss.fail() && ss.eof());
  504. });
  505. break;
  506. }
  507. case ArgumentType::Double: {
  508. isValidArgument = HandleNullableOptional<double>(arg, argValue, [&](auto * value) {
  509. if (strcmp(argValue, "Infinity") == 0)
  510. {
  511. *value = INFINITY;
  512. return true;
  513. }
  514. if (strcmp(argValue, "-Infinity") == 0)
  515. {
  516. *value = -INFINITY;
  517. return true;
  518. }
  519. std::stringstream ss;
  520. ss << argValue;
  521. ss >> *value;
  522. return (!ss.fail() && ss.eof());
  523. });
  524. break;
  525. }
  526. case ArgumentType::Address: {
  527. isValidArgument = HandleNullableOptional<AddressWithInterface>(
  528. arg, argValue, [&](auto * value) { return ParseAddressWithInterface(argValue, value); });
  529. break;
  530. }
  531. }
  532. if (!isValidArgument)
  533. {
  534. ChipLogError(chipTool, "InitArgs: Invalid argument %s: %s", arg.name, argValue);
  535. }
  536. return isValidArgument;
  537. }
  538. void Command::AddArgument(const char * name, const char * value, const char * desc)
  539. {
  540. ReadOnlyGlobalCommandArgument arg;
  541. arg.name = name;
  542. arg.value = value;
  543. arg.desc = desc;
  544. mReadOnlyGlobalCommandArgument.SetValue(arg);
  545. }
  546. size_t Command::AddArgument(const char * name, char ** value, const char * desc, uint8_t flags)
  547. {
  548. Argument arg;
  549. arg.type = ArgumentType::String;
  550. arg.name = name;
  551. arg.value = reinterpret_cast<void *>(value);
  552. arg.flags = flags;
  553. arg.desc = desc;
  554. return AddArgumentToList(std::move(arg));
  555. }
  556. size_t Command::AddArgument(const char * name, chip::CharSpan * value, const char * desc, uint8_t flags)
  557. {
  558. Argument arg;
  559. arg.type = ArgumentType::CharString;
  560. arg.name = name;
  561. arg.value = reinterpret_cast<void *>(value);
  562. arg.flags = flags;
  563. arg.desc = desc;
  564. return AddArgumentToList(std::move(arg));
  565. }
  566. size_t Command::AddArgument(const char * name, chip::ByteSpan * value, const char * desc, uint8_t flags)
  567. {
  568. Argument arg;
  569. arg.type = ArgumentType::OctetString;
  570. arg.name = name;
  571. arg.value = reinterpret_cast<void *>(value);
  572. arg.flags = flags;
  573. arg.desc = desc;
  574. return AddArgumentToList(std::move(arg));
  575. }
  576. size_t Command::AddArgument(const char * name, AddressWithInterface * out, const char * desc, uint8_t flags)
  577. {
  578. Argument arg;
  579. arg.type = ArgumentType::Address;
  580. arg.name = name;
  581. arg.value = reinterpret_cast<void *>(out);
  582. arg.flags = flags;
  583. arg.desc = desc;
  584. return AddArgumentToList(std::move(arg));
  585. }
  586. size_t Command::AddArgument(const char * name, int64_t min, uint64_t max, std::vector<uint16_t> * value, const char * desc)
  587. {
  588. Argument arg;
  589. arg.type = ArgumentType::Vector16;
  590. arg.name = name;
  591. arg.value = static_cast<void *>(value);
  592. arg.min = min;
  593. arg.max = max;
  594. arg.flags = 0;
  595. arg.desc = desc;
  596. return AddArgumentToList(std::move(arg));
  597. }
  598. size_t Command::AddArgument(const char * name, int64_t min, uint64_t max, std::vector<uint32_t> * value, const char * desc)
  599. {
  600. Argument arg;
  601. arg.type = ArgumentType::Vector32;
  602. arg.name = name;
  603. arg.value = static_cast<void *>(value);
  604. arg.min = min;
  605. arg.max = max;
  606. arg.flags = 0;
  607. arg.desc = desc;
  608. return AddArgumentToList(std::move(arg));
  609. }
  610. size_t Command::AddArgument(const char * name, int64_t min, uint64_t max, chip::Optional<std::vector<uint32_t>> * value,
  611. const char * desc)
  612. {
  613. Argument arg;
  614. arg.type = ArgumentType::Vector32;
  615. arg.name = name;
  616. arg.value = static_cast<void *>(value);
  617. arg.min = min;
  618. arg.max = max;
  619. arg.flags = Argument::kOptional;
  620. arg.desc = desc;
  621. return AddArgumentToList(std::move(arg));
  622. }
  623. size_t Command::AddArgument(const char * name, int64_t min, uint64_t max, chip::Optional<std::vector<bool>> * value,
  624. const char * desc)
  625. {
  626. Argument arg;
  627. arg.type = ArgumentType::VectorBool;
  628. arg.name = name;
  629. arg.value = static_cast<void *>(value);
  630. arg.min = min;
  631. arg.max = max;
  632. arg.flags = Argument::kOptional;
  633. arg.desc = desc;
  634. return AddArgumentToList(std::move(arg));
  635. }
  636. size_t Command::AddArgument(const char * name, ComplexArgument * value, const char * desc, uint8_t flags)
  637. {
  638. Argument arg;
  639. arg.type = ArgumentType::Complex;
  640. arg.name = name;
  641. arg.value = static_cast<void *>(value);
  642. arg.flags = flags;
  643. arg.desc = desc;
  644. return AddArgumentToList(std::move(arg));
  645. }
  646. size_t Command::AddArgument(const char * name, CustomArgument * value, const char * desc)
  647. {
  648. Argument arg;
  649. arg.type = ArgumentType::Custom;
  650. arg.name = name;
  651. arg.value = const_cast<void *>(reinterpret_cast<const void *>(value));
  652. arg.flags = 0;
  653. arg.desc = desc;
  654. return AddArgumentToList(std::move(arg));
  655. }
  656. size_t Command::AddArgument(const char * name, std::vector<CustomArgument *> * value, const char * desc)
  657. {
  658. Argument arg;
  659. arg.type = ArgumentType::VectorCustom;
  660. arg.name = name;
  661. arg.value = static_cast<void *>(value);
  662. arg.flags = 0;
  663. arg.desc = desc;
  664. return AddArgumentToList(std::move(arg));
  665. }
  666. size_t Command::AddArgument(const char * name, float min, float max, float * out, const char * desc, uint8_t flags)
  667. {
  668. Argument arg;
  669. arg.type = ArgumentType::Float;
  670. arg.name = name;
  671. arg.value = reinterpret_cast<void *>(out);
  672. arg.flags = flags;
  673. arg.desc = desc;
  674. // Ignore min/max for now; they're always +-Infinity anyway.
  675. return AddArgumentToList(std::move(arg));
  676. }
  677. size_t Command::AddArgument(const char * name, double min, double max, double * out, const char * desc, uint8_t flags)
  678. {
  679. Argument arg;
  680. arg.type = ArgumentType::Double;
  681. arg.name = name;
  682. arg.value = reinterpret_cast<void *>(out);
  683. arg.flags = flags;
  684. arg.desc = desc;
  685. // Ignore min/max for now; they're always +-Infinity anyway.
  686. return AddArgumentToList(std::move(arg));
  687. }
  688. size_t Command::AddArgument(const char * name, int64_t min, uint64_t max, void * out, ArgumentType type, const char * desc,
  689. uint8_t flags)
  690. {
  691. Argument arg;
  692. arg.type = type;
  693. arg.name = name;
  694. arg.value = out;
  695. arg.min = min;
  696. arg.max = max;
  697. arg.flags = flags;
  698. arg.desc = desc;
  699. return AddArgumentToList(std::move(arg));
  700. }
  701. size_t Command::AddArgument(const char * name, int64_t min, uint64_t max, void * out, const char * desc, uint8_t flags)
  702. {
  703. Argument arg;
  704. arg.type = ArgumentType::Number_uint8;
  705. arg.name = name;
  706. arg.value = out;
  707. arg.min = min;
  708. arg.max = max;
  709. arg.flags = flags;
  710. arg.desc = desc;
  711. return AddArgumentToList(std::move(arg));
  712. }
  713. size_t Command::AddArgument(const char * name, std::vector<std::string> * value, const char * desc)
  714. {
  715. Argument arg;
  716. arg.type = ArgumentType::VectorString;
  717. arg.name = name;
  718. arg.value = static_cast<void *>(value);
  719. arg.flags = 0;
  720. arg.desc = desc;
  721. return AddArgumentToList(std::move(arg));
  722. }
  723. size_t Command::AddArgument(const char * name, chip::Optional<std::vector<std::string>> * value, const char * desc)
  724. {
  725. Argument arg;
  726. arg.type = ArgumentType::VectorString;
  727. arg.name = name;
  728. arg.value = static_cast<void *>(value);
  729. arg.flags = Argument::kOptional;
  730. arg.desc = desc;
  731. return AddArgumentToList(std::move(arg));
  732. }
  733. const char * Command::GetArgumentName(size_t index) const
  734. {
  735. if (index < mArgs.size())
  736. {
  737. return mArgs.at(index).name;
  738. }
  739. return nullptr;
  740. }
  741. const char * Command::GetArgumentDescription(size_t index) const
  742. {
  743. if (index < mArgs.size())
  744. {
  745. return mArgs.at(index).desc;
  746. }
  747. return nullptr;
  748. }
  749. const char * Command::GetReadOnlyGlobalCommandArgument() const
  750. {
  751. if (GetAttribute())
  752. {
  753. return GetAttribute();
  754. }
  755. if (GetEvent())
  756. {
  757. return GetEvent();
  758. }
  759. return nullptr;
  760. }
  761. const char * Command::GetAttribute() const
  762. {
  763. if (mReadOnlyGlobalCommandArgument.HasValue())
  764. {
  765. return mReadOnlyGlobalCommandArgument.Value().value;
  766. }
  767. return nullptr;
  768. }
  769. const char * Command::GetEvent() const
  770. {
  771. if (mReadOnlyGlobalCommandArgument.HasValue())
  772. {
  773. return mReadOnlyGlobalCommandArgument.Value().value;
  774. }
  775. return nullptr;
  776. }
  777. size_t Command::AddArgumentToList(Argument && argument)
  778. {
  779. if (argument.isOptional() || mArgs.empty() || !mArgs.back().isOptional())
  780. {
  781. // Safe to just append.
  782. mArgs.emplace_back(std::move(argument));
  783. return mArgs.size();
  784. }
  785. // We're inserting a non-optional arg but we already have something optional
  786. // in the list. Insert before the first optional arg.
  787. for (auto cur = mArgs.cbegin(), end = mArgs.cend(); cur != end; ++cur)
  788. {
  789. if ((*cur).isOptional())
  790. {
  791. mArgs.emplace(cur, std::move(argument));
  792. return mArgs.size();
  793. }
  794. }
  795. // Never reached.
  796. VerifyOrDie(false);
  797. return 0;
  798. }
  799. namespace {
  800. template <typename T>
  801. void ResetOptionalArg(const Argument & arg)
  802. {
  803. VerifyOrDie(arg.isOptional());
  804. if (arg.isNullable())
  805. {
  806. reinterpret_cast<chip::Optional<chip::app::DataModel::Nullable<T>> *>(arg.value)->ClearValue();
  807. }
  808. else
  809. {
  810. reinterpret_cast<chip::Optional<T> *>(arg.value)->ClearValue();
  811. }
  812. }
  813. } // anonymous namespace
  814. void Command::ResetArguments()
  815. {
  816. for (const auto & arg : mArgs)
  817. {
  818. const ArgumentType type = arg.type;
  819. if (arg.isOptional())
  820. {
  821. // Must always clean these up so they don't carry over to the next
  822. // command invocation in interactive mode.
  823. switch (type)
  824. {
  825. case ArgumentType::Complex: {
  826. // Optional Complex arguments are not currently supported via the <chip::Optional> class.
  827. // Instead, they must be explicitly specified as optional using the kOptional flag,
  828. // and the base TypedComplexArgument<T> class is referenced.
  829. auto argument = static_cast<ComplexArgument *>(arg.value);
  830. argument->Reset();
  831. break;
  832. }
  833. case ArgumentType::Custom: {
  834. // No optional custom arguments so far.
  835. VerifyOrDie(false);
  836. break;
  837. }
  838. case ArgumentType::VectorString: {
  839. ResetOptionalArg<std::vector<std::string>>(arg);
  840. break;
  841. }
  842. case ArgumentType::VectorBool: {
  843. ResetOptionalArg<std::vector<bool>>(arg);
  844. break;
  845. }
  846. case ArgumentType::Vector16: {
  847. // No optional Vector16 arguments so far.
  848. VerifyOrDie(false);
  849. break;
  850. }
  851. case ArgumentType::Vector32: {
  852. ResetOptionalArg<std::vector<uint32_t>>(arg);
  853. break;
  854. }
  855. case ArgumentType::VectorCustom: {
  856. // No optional VectorCustom arguments so far.
  857. VerifyOrDie(false);
  858. break;
  859. }
  860. case ArgumentType::String: {
  861. ResetOptionalArg<char *>(arg);
  862. break;
  863. }
  864. case ArgumentType::CharString: {
  865. ResetOptionalArg<chip::CharSpan>(arg);
  866. break;
  867. }
  868. case ArgumentType::OctetString: {
  869. ResetOptionalArg<chip::ByteSpan>(arg);
  870. break;
  871. }
  872. case ArgumentType::Bool: {
  873. ResetOptionalArg<bool>(arg);
  874. break;
  875. }
  876. case ArgumentType::Number_uint8: {
  877. ResetOptionalArg<uint8_t>(arg);
  878. break;
  879. }
  880. case ArgumentType::Number_uint16: {
  881. ResetOptionalArg<uint16_t>(arg);
  882. break;
  883. }
  884. case ArgumentType::Number_uint32: {
  885. ResetOptionalArg<uint32_t>(arg);
  886. break;
  887. }
  888. case ArgumentType::Number_uint64: {
  889. ResetOptionalArg<uint64_t>(arg);
  890. break;
  891. }
  892. case ArgumentType::Number_int8: {
  893. ResetOptionalArg<int8_t>(arg);
  894. break;
  895. }
  896. case ArgumentType::Number_int16: {
  897. ResetOptionalArg<int16_t>(arg);
  898. break;
  899. }
  900. case ArgumentType::Number_int32: {
  901. ResetOptionalArg<int32_t>(arg);
  902. break;
  903. }
  904. case ArgumentType::Number_int64: {
  905. ResetOptionalArg<int64_t>(arg);
  906. break;
  907. }
  908. case ArgumentType::Float: {
  909. ResetOptionalArg<float>(arg);
  910. break;
  911. }
  912. case ArgumentType::Double: {
  913. ResetOptionalArg<double>(arg);
  914. break;
  915. }
  916. case ArgumentType::Address: {
  917. ResetOptionalArg<AddressWithInterface>(arg);
  918. break;
  919. }
  920. }
  921. }
  922. else
  923. {
  924. // Some non-optional arguments have state that needs to be cleaned
  925. // up too.
  926. if (type == ArgumentType::Vector16)
  927. {
  928. auto vectorArgument = static_cast<std::vector<uint16_t> *>(arg.value);
  929. vectorArgument->clear();
  930. }
  931. else if (type == ArgumentType::Vector32)
  932. {
  933. auto vectorArgument = static_cast<std::vector<uint32_t> *>(arg.value);
  934. vectorArgument->clear();
  935. }
  936. else if (type == ArgumentType::VectorCustom)
  937. {
  938. auto vectorArgument = static_cast<std::vector<CustomArgument *> *>(arg.value);
  939. for (auto & customArgument : *vectorArgument)
  940. {
  941. delete customArgument;
  942. }
  943. vectorArgument->clear();
  944. }
  945. else if (type == ArgumentType::Complex)
  946. {
  947. auto argument = static_cast<ComplexArgument *>(arg.value);
  948. argument->Reset();
  949. }
  950. }
  951. }
  952. }