diff --git a/examples/chip-tool/commands/common/Command.cpp b/examples/chip-tool/commands/common/Command.cpp index 00658fc9cf9168..01559c5376599f 100644 --- a/examples/chip-tool/commands/common/Command.cpp +++ b/examples/chip-tool/commands/common/Command.cpp @@ -44,7 +44,7 @@ bool Command::InitArguments(int argc, char ** argv) size_t optionalArgsCount = 0; for (size_t i = 0; i < mArgs.size(); i++) { - if (mArgs[i].optional) + if (mArgs[i].isOptional()) { optionalArgsCount++; } @@ -133,6 +133,40 @@ static bool ParseAddressWithInterface(const char * addressString, Command::Addre return true; } +// The callback should return whether the argument is valid, for the non-null +// case. It can't directly write to isValidArgument (by closing over it) +// because in the nullable-and-null case we need to do that from this function, +// via the return value. +template +bool HandleNullableOptional(Argument & arg, char * argValue, std::function callback) +{ + if (arg.isOptional()) + { + if (arg.isNullable()) + { + arg.value = &(reinterpret_cast> *>(arg.value)->Emplace()); + } + else + { + arg.value = &(reinterpret_cast *>(arg.value)->Emplace()); + } + } + + if (arg.isNullable()) + { + auto * nullable = reinterpret_cast *>(arg.value); + if (strcmp(argValue, "null") == 0) + { + nullable->SetNull(); + return true; + } + + arg.value = &(nullable->SetNonNull()); + } + + return callback(reinterpret_cast(arg.value)); +} + bool Command::InitArgument(size_t argIndex, char * argValue) { bool isValidArgument = false; @@ -142,248 +176,234 @@ bool Command::InitArgument(size_t argIndex, char * argValue) switch (arg.type) { case ArgumentType::Attribute: { - if (arg.optional) - arg.value = &(reinterpret_cast *>(arg.value))->Emplace(); - char * value = reinterpret_cast(arg.value); - isValidArgument = (strcmp(argValue, value) == 0); + if (arg.isOptional() || arg.isNullable()) + { + isValidArgument = false; + } + else + { + char * value = reinterpret_cast(arg.value); + isValidArgument = (strcmp(argValue, value) == 0); + } break; } case ArgumentType::String: { - if (arg.optional) - arg.value = &(reinterpret_cast *>(arg.value))->Emplace(); - const char ** value = reinterpret_cast(arg.value); - *value = argValue; - isValidArgument = true; + isValidArgument = HandleNullableOptional(arg, argValue, [&](auto * value) { + *value = argValue; + return true; + }); break; } case ArgumentType::CharString: { - if (arg.optional) - arg.value = &(reinterpret_cast> *>(arg.value))->Emplace(); - auto * value = static_cast *>(arg.value); - *value = chip::Span(argValue, strlen(argValue)); - isValidArgument = true; + isValidArgument = HandleNullableOptional(arg, argValue, [&](auto * value) { + *value = chip::Span(argValue, strlen(argValue)); + return true; + }); break; } case ArgumentType::OctetString: { - if (arg.optional) - arg.value = &(reinterpret_cast *>(arg.value))->Emplace(); - auto * value = static_cast(arg.value); - // We support two ways to pass an octet string argument. If it happens - // to be all-ASCII, you can just pass it in. Otherwise you can pass in - // 0x followed by the hex-encoded bytes. - size_t argLen = strlen(argValue); - static constexpr char hexPrefix[] = "hex:"; - constexpr size_t prefixLen = ArraySize(hexPrefix) - 1; // Don't count the null - if (strncmp(argValue, hexPrefix, prefixLen) == 0) - { - // Hex-encoded. Decode it into a temporary buffer first, so if we - // run into errors we can do correct "argument is not valid" logging - // that actually shows the value that was passed in. After we - // determine it's valid, modify the passed-in value to hold the - // right bytes, so we don't need to worry about allocating storage - // for this somewhere else. This works because the hex - // representation is always longer than the octet string it encodes, - // so we have enough space in argValue for the decoded version. - chip::Platform::ScopedMemoryBuffer buffer; - if (!buffer.Calloc(argLen)) // Bigger than needed, but it's fine. + isValidArgument = HandleNullableOptional(arg, argValue, [&](auto * value) { + // We support two ways to pass an octet string argument. If it happens + // to be all-ASCII, you can just pass it in. Otherwise you can pass in + // 0x followed by the hex-encoded bytes. + size_t argLen = strlen(argValue); + static constexpr char hexPrefix[] = "hex:"; + constexpr size_t prefixLen = ArraySize(hexPrefix) - 1; // Don't count the null + if (strncmp(argValue, hexPrefix, prefixLen) == 0) { - isValidArgument = false; - break; - } + // Hex-encoded. Decode it into a temporary buffer first, so if we + // run into errors we can do correct "argument is not valid" logging + // that actually shows the value that was passed in. After we + // determine it's valid, modify the passed-in value to hold the + // right bytes, so we don't need to worry about allocating storage + // for this somewhere else. This works because the hex + // representation is always longer than the octet string it encodes, + // so we have enough space in argValue for the decoded version. + chip::Platform::ScopedMemoryBuffer buffer; + if (!buffer.Calloc(argLen)) // Bigger than needed, but it's fine. + { + return false; + } - size_t octetCount = chip::Encoding::HexToBytes(argValue + prefixLen, argLen - prefixLen, buffer.Get(), argLen); - if (octetCount == 0) - { - isValidArgument = false; - break; - } + size_t octetCount = chip::Encoding::HexToBytes(argValue + prefixLen, argLen - prefixLen, buffer.Get(), argLen); + if (octetCount == 0) + { + return false; + } - memcpy(argValue, buffer.Get(), octetCount); - *value = chip::ByteSpan(chip::Uint8::from_char(argValue), octetCount); - isValidArgument = true; - } - else - { - // Just ASCII. Check for the "str:" prefix. - static constexpr char strPrefix[] = "str:"; - constexpr size_t strPrefixLen = ArraySize(strPrefix) - 1; // Don't count the null - if (strncmp(argValue, strPrefix, strPrefixLen) == 0) + memcpy(argValue, buffer.Get(), octetCount); + *value = chip::ByteSpan(chip::Uint8::from_char(argValue), octetCount); + return true; + } + else { - // Skip the prefix - argValue += strPrefixLen; - argLen -= strPrefixLen; + // Just ASCII. Check for the "str:" prefix. + static constexpr char strPrefix[] = "str:"; + constexpr size_t strPrefixLen = ArraySize(strPrefix) - 1; // Don't count the null + if (strncmp(argValue, strPrefix, strPrefixLen) == 0) + { + // Skip the prefix + argValue += strPrefixLen; + argLen -= strPrefixLen; + } + *value = chip::ByteSpan(chip::Uint8::from_char(argValue), argLen); + return true; } - *value = chip::ByteSpan(chip::Uint8::from_char(argValue), argLen); - isValidArgument = true; - } + }); break; } case ArgumentType::Boolean: case ArgumentType::Number_uint8: { - if (arg.optional) - arg.value = &(reinterpret_cast *>(arg.value))->Emplace(); - uint8_t * value = reinterpret_cast(arg.value); - - // stringstream treats uint8_t as char, which is not what we want here. - uint16_t tmpValue; - std::stringstream ss; - isHexNotation ? ss << std::hex << argValue : ss << argValue; - ss >> tmpValue; - if (chip::CanCastTo(tmpValue)) - { - *value = static_cast(tmpValue); + isValidArgument = HandleNullableOptional(arg, argValue, [&](auto * value) { + // stringstream treats uint8_t as char, which is not what we want here. + uint16_t tmpValue; + std::stringstream ss; + isHexNotation ? ss << std::hex << argValue : ss << argValue; + ss >> tmpValue; + if (chip::CanCastTo(tmpValue)) + { + *value = static_cast(tmpValue); - uint64_t min = chip::CanCastTo(arg.min) ? static_cast(arg.min) : 0; - uint64_t max = arg.max; - isValidArgument = (!ss.fail() && ss.eof() && *value >= min && *value <= max); - } - else - { - isValidArgument = false; - } + uint64_t min = chip::CanCastTo(arg.min) ? static_cast(arg.min) : 0; + uint64_t max = arg.max; + return (!ss.fail() && ss.eof() && *value >= min && *value <= max); + } + else + { + return false; + } + }); break; } case ArgumentType::Number_uint16: { - if (arg.optional) - arg.value = &(reinterpret_cast *>(arg.value))->Emplace(); - uint16_t * value = reinterpret_cast(arg.value); - std::stringstream ss; - isHexNotation ? ss << std::hex << argValue : ss << argValue; - ss >> *value; - - uint64_t min = chip::CanCastTo(arg.min) ? static_cast(arg.min) : 0; - uint64_t max = arg.max; - isValidArgument = (!ss.fail() && ss.eof() && *value >= min && *value <= max); + isValidArgument = HandleNullableOptional(arg, argValue, [&](auto * value) { + std::stringstream ss; + isHexNotation ? ss << std::hex << argValue : ss << argValue; + ss >> *value; + + uint64_t min = chip::CanCastTo(arg.min) ? static_cast(arg.min) : 0; + uint64_t max = arg.max; + return (!ss.fail() && ss.eof() && *value >= min && *value <= max); + }); break; } case ArgumentType::Number_uint32: { - if (arg.optional) - arg.value = &(reinterpret_cast *>(arg.value))->Emplace(); - uint32_t * value = reinterpret_cast(arg.value); - std::stringstream ss; - isHexNotation ? ss << std::hex << argValue : ss << argValue; - ss >> *value; - - uint64_t min = chip::CanCastTo(arg.min) ? static_cast(arg.min) : 0; - uint64_t max = arg.max; - isValidArgument = (!ss.fail() && ss.eof() && *value >= min && *value <= max); + isValidArgument = HandleNullableOptional(arg, argValue, [&](auto * value) { + std::stringstream ss; + isHexNotation ? ss << std::hex << argValue : ss << argValue; + ss >> *value; + + uint64_t min = chip::CanCastTo(arg.min) ? static_cast(arg.min) : 0; + uint64_t max = arg.max; + return (!ss.fail() && ss.eof() && *value >= min && *value <= max); + }); break; } case ArgumentType::Number_uint64: { - if (arg.optional) - arg.value = &(reinterpret_cast *>(arg.value))->Emplace(); - uint64_t * value = reinterpret_cast(arg.value); - std::stringstream ss; - isHexNotation ? ss << std::hex << argValue : ss << argValue; - ss >> *value; - - uint64_t min = chip::CanCastTo(arg.min) ? static_cast(arg.min) : 0; - uint64_t max = arg.max; - isValidArgument = (!ss.fail() && ss.eof() && *value >= min && *value <= max); + isValidArgument = HandleNullableOptional(arg, argValue, [&](auto * value) { + std::stringstream ss; + isHexNotation ? ss << std::hex << argValue : ss << argValue; + ss >> *value; + + uint64_t min = chip::CanCastTo(arg.min) ? static_cast(arg.min) : 0; + uint64_t max = arg.max; + return (!ss.fail() && ss.eof() && *value >= min && *value <= max); + }); break; } case ArgumentType::Number_int8: { - if (arg.optional) - arg.value = &(reinterpret_cast *>(arg.value))->Emplace(); - int8_t * value = reinterpret_cast(arg.value); - - // stringstream treats int8_t as char, which is not what we want here. - int16_t tmpValue; - std::stringstream ss; - isHexNotation ? ss << std::hex << argValue : ss << argValue; - ss >> tmpValue; - if (chip::CanCastTo(tmpValue)) - { - *value = static_cast(tmpValue); + isValidArgument = HandleNullableOptional(arg, argValue, [&](auto * value) { + // stringstream treats int8_t as char, which is not what we want here. + int16_t tmpValue; + std::stringstream ss; + isHexNotation ? ss << std::hex << argValue : ss << argValue; + ss >> tmpValue; + if (chip::CanCastTo(tmpValue)) + { + *value = static_cast(tmpValue); - int64_t min = arg.min; - int64_t max = chip::CanCastTo(arg.max) ? static_cast(arg.max) : INT64_MAX; - isValidArgument = (!ss.fail() && ss.eof() && *value >= min && *value <= max); - } - else - { - isValidArgument = false; - } + int64_t min = arg.min; + int64_t max = chip::CanCastTo(arg.max) ? static_cast(arg.max) : INT64_MAX; + return (!ss.fail() && ss.eof() && *value >= min && *value <= max); + } + else + { + return false; + } + }); break; } case ArgumentType::Number_int16: { - if (arg.optional) - arg.value = &(reinterpret_cast *>(arg.value))->Emplace(); - int16_t * value = reinterpret_cast(arg.value); - std::stringstream ss; - isHexNotation ? ss << std::hex << argValue : ss << argValue; - ss >> *value; - - int64_t min = arg.min; - int64_t max = chip::CanCastTo(arg.max) ? static_cast(arg.max) : INT64_MAX; - isValidArgument = (!ss.fail() && ss.eof() && *value >= min && *value <= max); + isValidArgument = HandleNullableOptional(arg, argValue, [&](auto * value) { + std::stringstream ss; + isHexNotation ? ss << std::hex << argValue : ss << argValue; + ss >> *value; + + int64_t min = arg.min; + int64_t max = chip::CanCastTo(arg.max) ? static_cast(arg.max) : INT64_MAX; + return (!ss.fail() && ss.eof() && *value >= min && *value <= max); + }); break; } case ArgumentType::Number_int32: { - if (arg.optional) - arg.value = &(reinterpret_cast *>(arg.value))->Emplace(); - int32_t * value = reinterpret_cast(arg.value); - std::stringstream ss; - isHexNotation ? ss << std::hex << argValue : ss << argValue; - ss >> *value; - - int64_t min = arg.min; - int64_t max = chip::CanCastTo(arg.max) ? static_cast(arg.max) : INT64_MAX; - isValidArgument = (!ss.fail() && ss.eof() && *value >= min && *value <= max); + isValidArgument = HandleNullableOptional(arg, argValue, [&](auto * value) { + std::stringstream ss; + isHexNotation ? ss << std::hex << argValue : ss << argValue; + ss >> *value; + + int64_t min = arg.min; + int64_t max = chip::CanCastTo(arg.max) ? static_cast(arg.max) : INT64_MAX; + return (!ss.fail() && ss.eof() && *value >= min && *value <= max); + }); break; } case ArgumentType::Number_int64: { - if (arg.optional) - arg.value = &(reinterpret_cast *>(arg.value))->Emplace(); - int64_t * value = reinterpret_cast(arg.value); - std::stringstream ss; - isHexNotation ? ss << std::hex << argValue : ss << argValue; - ss >> *value; - - int64_t min = arg.min; - int64_t max = chip::CanCastTo(arg.max) ? static_cast(arg.max) : INT64_MAX; - isValidArgument = (!ss.fail() && ss.eof() && *value >= min && *value <= max); + isValidArgument = HandleNullableOptional(arg, argValue, [&](auto * value) { + std::stringstream ss; + isHexNotation ? ss << std::hex << argValue : ss << argValue; + ss >> *value; + + int64_t min = arg.min; + int64_t max = chip::CanCastTo(arg.max) ? static_cast(arg.max) : INT64_MAX; + return (!ss.fail() && ss.eof() && *value >= min && *value <= max); + }); break; } case ArgumentType::Float: { - if (arg.optional) - arg.value = &(static_cast *>(arg.value))->Emplace(); - float * value = static_cast(arg.value); - std::stringstream ss; - ss << argValue; - ss >> *value; - isValidArgument = (!ss.fail() && ss.eof()); + isValidArgument = HandleNullableOptional(arg, argValue, [&](auto * value) { + std::stringstream ss; + ss << argValue; + ss >> *value; + return (!ss.fail() && ss.eof()); + }); break; } case ArgumentType::Double: { - if (arg.optional) - arg.value = &(static_cast *>(arg.value))->Emplace(); - double * value = static_cast(arg.value); - std::stringstream ss; - ss << argValue; - ss >> *value; - isValidArgument = (!ss.fail() && ss.eof()); + isValidArgument = HandleNullableOptional(arg, argValue, [&](auto * value) { + std::stringstream ss; + ss << argValue; + ss >> *value; + return (!ss.fail() && ss.eof()); + }); break; } case ArgumentType::Address: { - if (arg.optional) - arg.value = &(reinterpret_cast *>(arg.value))->Emplace(); - AddressWithInterface * value = reinterpret_cast(arg.value); - isValidArgument = ParseAddressWithInterface(argValue, value); + isValidArgument = HandleNullableOptional( + arg, argValue, [&](auto * value) { return ParseAddressWithInterface(argValue, value); }); break; } } @@ -396,107 +416,107 @@ bool Command::InitArgument(size_t argIndex, char * argValue) return isValidArgument; } -size_t Command::AddArgument(const char * name, const char * value, bool optional) +size_t Command::AddArgument(const char * name, const char * value, uint8_t flags) { Argument arg; - arg.type = ArgumentType::Attribute; - arg.name = name; - arg.value = const_cast(reinterpret_cast(value)); - arg.optional = optional; + arg.type = ArgumentType::Attribute; + arg.name = name; + arg.value = const_cast(reinterpret_cast(value)); + arg.flags = flags; return AddArgumentToList(std::move(arg)); } -size_t Command::AddArgument(const char * name, char ** value, bool optional) +size_t Command::AddArgument(const char * name, char ** value, uint8_t flags) { Argument arg; - arg.type = ArgumentType::String; - arg.name = name; - arg.value = reinterpret_cast(value); - arg.optional = optional; + arg.type = ArgumentType::String; + arg.name = name; + arg.value = reinterpret_cast(value); + arg.flags = flags; return AddArgumentToList(std::move(arg)); } -size_t Command::AddArgument(const char * name, chip::CharSpan * value, bool optional) +size_t Command::AddArgument(const char * name, chip::CharSpan * value, uint8_t flags) { Argument arg; - arg.type = ArgumentType::CharString; - arg.name = name; - arg.value = reinterpret_cast(value); - arg.optional = optional; + arg.type = ArgumentType::CharString; + arg.name = name; + arg.value = reinterpret_cast(value); + arg.flags = flags; return AddArgumentToList(std::move(arg)); } -size_t Command::AddArgument(const char * name, chip::ByteSpan * value, bool optional) +size_t Command::AddArgument(const char * name, chip::ByteSpan * value, uint8_t flags) { Argument arg; - arg.type = ArgumentType::OctetString; - arg.name = name; - arg.value = reinterpret_cast(value); - arg.optional = optional; + arg.type = ArgumentType::OctetString; + arg.name = name; + arg.value = reinterpret_cast(value); + arg.flags = flags; return AddArgumentToList(std::move(arg)); } -size_t Command::AddArgument(const char * name, AddressWithInterface * out, bool optional) +size_t Command::AddArgument(const char * name, AddressWithInterface * out, uint8_t flags) { Argument arg; - arg.type = ArgumentType::Address; - arg.name = name; - arg.value = reinterpret_cast(out); - arg.optional = optional; + arg.type = ArgumentType::Address; + arg.name = name; + arg.value = reinterpret_cast(out); + arg.flags = flags; return AddArgumentToList(std::move(arg)); } -size_t Command::AddArgument(const char * name, float min, float max, float * out, bool optional) +size_t Command::AddArgument(const char * name, float min, float max, float * out, uint8_t flags) { Argument arg; - arg.type = ArgumentType::Float; - arg.name = name; - arg.value = reinterpret_cast(out); - arg.optional = optional; + arg.type = ArgumentType::Float; + arg.name = name; + arg.value = reinterpret_cast(out); + arg.flags = flags; // Ignore min/max for now; they're always +-Infinity anyway. return AddArgumentToList(std::move(arg)); } -size_t Command::AddArgument(const char * name, double min, double max, double * out, bool optional) +size_t Command::AddArgument(const char * name, double min, double max, double * out, uint8_t flags) { Argument arg; - arg.type = ArgumentType::Double; - arg.name = name; - arg.value = reinterpret_cast(out); - arg.optional = optional; + arg.type = ArgumentType::Double; + arg.name = name; + arg.value = reinterpret_cast(out); + arg.flags = flags; // Ignore min/max for now; they're always +-Infinity anyway. return AddArgumentToList(std::move(arg)); } -size_t Command::AddArgument(const char * name, int64_t min, uint64_t max, void * out, ArgumentType type, bool optional) +size_t Command::AddArgument(const char * name, int64_t min, uint64_t max, void * out, ArgumentType type, uint8_t flags) { Argument arg; - arg.type = type; - arg.name = name; - arg.value = out; - arg.min = min; - arg.max = max; - arg.optional = optional; + arg.type = type; + arg.name = name; + arg.value = out; + arg.min = min; + arg.max = max; + arg.flags = flags; return AddArgumentToList(std::move(arg)); } -size_t Command::AddArgument(const char * name, int64_t min, uint64_t max, void * out, bool optional) +size_t Command::AddArgument(const char * name, int64_t min, uint64_t max, void * out, uint8_t flags) { Argument arg; - arg.type = ArgumentType::Number_uint8; - arg.name = name; - arg.value = out; - arg.min = min; - arg.max = max; - arg.optional = optional; + arg.type = ArgumentType::Number_uint8; + arg.name = name; + arg.value = out; + arg.min = min; + arg.max = max; + arg.flags = flags; return AddArgumentToList(std::move(arg)); } @@ -528,7 +548,7 @@ const char * Command::GetAttribute(void) const size_t Command::AddArgumentToList(Argument && argument) { - if (argument.optional || mArgs.empty() || !mArgs.back().optional) + if (argument.isOptional() || mArgs.empty() || !mArgs.back().isOptional()) { // Safe to just append. mArgs.emplace_back(std::move(argument)); @@ -539,7 +559,7 @@ size_t Command::AddArgumentToList(Argument && argument) // in the list. Insert before the first optional arg. for (auto cur = mArgs.cbegin(), end = mArgs.cend(); cur != end; ++cur) { - if ((*cur).optional) + if ((*cur).isOptional()) { mArgs.emplace(cur, std::move(argument)); return mArgs.size(); diff --git a/examples/chip-tool/commands/common/Command.h b/examples/chip-tool/commands/common/Command.h index 89ca64c5f2f47b..d1f5955eeb7266 100644 --- a/examples/chip-tool/commands/common/Command.h +++ b/examples/chip-tool/commands/common/Command.h @@ -79,7 +79,16 @@ struct Argument int64_t min; uint64_t max; void * value; - bool optional; + uint8_t flags; + + enum + { + kOptional = (1 << 0), + kNullable = (1 << 1), + }; + + bool isOptional() const { return flags & kOptional; } + bool isNullable() const { return flags & kNullable; } }; class Command @@ -97,11 +106,11 @@ class Command const char * GetName(void) const { return mName; } const char * GetAttribute(void) const; const char * GetArgumentName(size_t index) const; - bool GetArgumentIsOptional(size_t index) const { return mArgs[index].optional; } + bool GetArgumentIsOptional(size_t index) const { return mArgs[index].isOptional(); } size_t GetArgumentsCount(void) const { return mArgs.size(); } bool InitArguments(int argc, char ** argv); - size_t AddArgument(const char * name, const char * value, bool optional = false); + size_t AddArgument(const char * name, const char * value, uint8_t flags = 0); /** * @brief * Add a char string command argument @@ -110,106 +119,100 @@ class Command * @param value A pointer to a `char *` where the argv value will be stored * @returns The number of arguments currently added to the command */ - size_t AddArgument(const char * name, char ** value, bool optional = false); + size_t AddArgument(const char * name, char ** value, uint8_t flags = 0); + /** * Add an octet string command argument */ - size_t AddArgument(const char * name, chip::ByteSpan * value, bool optional = false); - size_t AddArgument(const char * name, chip::Span * value, bool optional = false); - size_t AddArgument(const char * name, AddressWithInterface * out, bool optional = false); - size_t AddArgument(const char * name, int64_t min, uint64_t max, bool * out, bool optional = false) + size_t AddArgument(const char * name, chip::ByteSpan * value, uint8_t flags = 0); + size_t AddArgument(const char * name, chip::Span * value, uint8_t flags = 0); + size_t AddArgument(const char * name, AddressWithInterface * out, uint8_t flags = 0); + size_t AddArgument(const char * name, int64_t min, uint64_t max, bool * out, uint8_t flags = 0) { - return AddArgument(name, min, max, reinterpret_cast(out), Boolean, optional); + return AddArgument(name, min, max, reinterpret_cast(out), Boolean, flags); } - size_t AddArgument(const char * name, int64_t min, uint64_t max, int8_t * out, bool optional = false) + size_t AddArgument(const char * name, int64_t min, uint64_t max, int8_t * out, uint8_t flags = 0) { - return AddArgument(name, min, max, reinterpret_cast(out), Number_int8, optional); + return AddArgument(name, min, max, reinterpret_cast(out), Number_int8, flags); } - size_t AddArgument(const char * name, int64_t min, uint64_t max, int16_t * out, bool optional = false) + size_t AddArgument(const char * name, int64_t min, uint64_t max, int16_t * out, uint8_t flags = 0) { - return AddArgument(name, min, max, reinterpret_cast(out), Number_int16, optional); + return AddArgument(name, min, max, reinterpret_cast(out), Number_int16, flags); } - size_t AddArgument(const char * name, int64_t min, uint64_t max, int32_t * out, bool optional = false) + size_t AddArgument(const char * name, int64_t min, uint64_t max, int32_t * out, uint8_t flags = 0) { - return AddArgument(name, min, max, reinterpret_cast(out), Number_int32, optional); + return AddArgument(name, min, max, reinterpret_cast(out), Number_int32, flags); } - size_t AddArgument(const char * name, int64_t min, uint64_t max, int64_t * out, bool optional = false) + size_t AddArgument(const char * name, int64_t min, uint64_t max, int64_t * out, uint8_t flags = 0) { - return AddArgument(name, min, max, reinterpret_cast(out), Number_int64, optional); + return AddArgument(name, min, max, reinterpret_cast(out), Number_int64, flags); } - size_t AddArgument(const char * name, int64_t min, uint64_t max, uint8_t * out, bool optional = false) + size_t AddArgument(const char * name, int64_t min, uint64_t max, uint8_t * out, uint8_t flags = 0) { - return AddArgument(name, min, max, reinterpret_cast(out), Number_uint8, optional); + return AddArgument(name, min, max, reinterpret_cast(out), Number_uint8, flags); } - size_t AddArgument(const char * name, int64_t min, uint64_t max, uint16_t * out, bool optional = false) + size_t AddArgument(const char * name, int64_t min, uint64_t max, uint16_t * out, uint8_t flags = 0) { - return AddArgument(name, min, max, reinterpret_cast(out), Number_uint16, optional); + return AddArgument(name, min, max, reinterpret_cast(out), Number_uint16, flags); } - size_t AddArgument(const char * name, int64_t min, uint64_t max, uint32_t * out, bool optional = false) + size_t AddArgument(const char * name, int64_t min, uint64_t max, uint32_t * out, uint8_t flags = 0) { - return AddArgument(name, min, max, reinterpret_cast(out), Number_uint32, optional); + return AddArgument(name, min, max, reinterpret_cast(out), Number_uint32, flags); } - size_t AddArgument(const char * name, int64_t min, uint64_t max, uint64_t * out, bool optional = false) + size_t AddArgument(const char * name, int64_t min, uint64_t max, uint64_t * out, uint8_t flags = 0) { - return AddArgument(name, min, max, reinterpret_cast(out), Number_uint64, optional); + return AddArgument(name, min, max, reinterpret_cast(out), Number_uint64, flags); } - size_t AddArgument(const char * name, float min, float max, float * out, bool optional = false); - size_t AddArgument(const char * name, double min, double max, double * out, bool optional = false); + size_t AddArgument(const char * name, float min, float max, float * out, uint8_t flags = 0); + size_t AddArgument(const char * name, double min, double max, double * out, uint8_t flags = 0); template ::value>> - size_t AddArgument(const char * name, int64_t min, uint64_t max, T * out, bool optional = false) + size_t AddArgument(const char * name, int64_t min, uint64_t max, T * out, uint8_t flags = 0) { - return AddArgument(name, min, max, reinterpret_cast *>(out), optional); + return AddArgument(name, min, max, reinterpret_cast *>(out), flags); } template size_t AddArgument(const char * name, chip::Optional * value) { - return AddArgument(name, reinterpret_cast(value), true); + return AddArgument(name, reinterpret_cast(value), Argument::kOptional); } template size_t AddArgument(const char * name, int64_t min, uint64_t max, chip::Optional * value) { - return AddArgument(name, min, max, reinterpret_cast(value), true); + return AddArgument(name, min, max, reinterpret_cast(value), Argument::kOptional); } template - size_t AddArgument(const char * name, chip::app::DataModel::Nullable * value, bool optional = false) + size_t AddArgument(const char * name, chip::app::DataModel::Nullable * value, uint8_t flags = 0) { - // We always require our args to be provided for the moment. - return AddArgument(name, &value->SetNonNull(), optional); + return AddArgument(name, reinterpret_cast(value), flags | Argument::kNullable); } template - size_t AddArgument(const char * name, int64_t min, uint64_t max, chip::app::DataModel::Nullable * value, - bool optional = false) + size_t AddArgument(const char * name, int64_t min, uint64_t max, chip::app::DataModel::Nullable * value, uint8_t flags = 0) { - // We always require our args to be provided for the moment. - return AddArgument(name, min, max, &value->SetNonNull(), optional); + return AddArgument(name, min, max, reinterpret_cast(value), flags | Argument::kNullable); } - size_t AddArgument(const char * name, float min, float max, chip::app::DataModel::Nullable * value, - bool optional = false) + size_t AddArgument(const char * name, float min, float max, chip::app::DataModel::Nullable * value, uint8_t flags = 0) { - // We always require our args to be provided for the moment. - return AddArgument(name, min, max, &value->SetNonNull(), optional); + return AddArgument(name, min, max, reinterpret_cast(value), flags | Argument::kNullable); } - size_t AddArgument(const char * name, double min, double max, chip::app::DataModel::Nullable * value, - bool optional = false) + size_t AddArgument(const char * name, double min, double max, chip::app::DataModel::Nullable * value, uint8_t flags = 0) { - // We always require our args to be provided for the moment. - return AddArgument(name, min, max, &value->SetNonNull(), optional); + return AddArgument(name, min, max, reinterpret_cast(value), flags | Argument::kNullable); } virtual CHIP_ERROR Run() = 0; private: bool InitArgument(size_t argIndex, char * argValue); - size_t AddArgument(const char * name, int64_t min, uint64_t max, void * out, ArgumentType type, bool optional); - size_t AddArgument(const char * name, int64_t min, uint64_t max, void * out, bool optional); + size_t AddArgument(const char * name, int64_t min, uint64_t max, void * out, ArgumentType type, uint8_t flags); + size_t AddArgument(const char * name, int64_t min, uint64_t max, void * out, uint8_t flags); /** * Add the Argument to our list. This preserves the property that all