-
Notifications
You must be signed in to change notification settings - Fork 273
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add utility for string and redis #434
Add utility for string and redis #434
Conversation
Signed-off-by: Ze Gan <[email protected]>
5189e4e
to
8f4f88d
Compare
common/stringutility.h
Outdated
@@ -0,0 +1,75 @@ | |||
#ifndef __STRINGUTILITY__ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
STRINGUTILITY [](start = 8, length = 17)
The use of two underscores (__) in identifiers is reserved for the compiler's internal use according to the ANSI-C standard.
Suggest use #pragma once
#Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
common/stringutility.h
Outdated
{ | ||
return false; | ||
} | ||
std::istringstream istream(input); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
istream [](start = 23, length = 7)
How is delimiter used in the input stream? #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function is as a terminator to bool split(const std::string &input, char delimiter, T &output, Args &... args)
, so I assume the last part of input string should not include any delimiter.
common/stringutility.h
Outdated
} | ||
|
||
template <typename T> | ||
std::string join(char delimiter, const T &input) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
delimiter [](start = 22, length = 9)
Not used? #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it isn't used. It's a terminator of std::string join(char delimiter, const T &input, const Args &... args)
. So this parameters is to adapt the recursive style.
I will add qualifier, __attribute__((unused))
, before this parameter delimiter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it. Then better to remove the variable name and just use char
. No need to add attribute.
In reply to: 547451799 [](ancestors = 547451799)
common/stringutility.h
Outdated
namespace swss { | ||
|
||
template <typename T> | ||
bool split(const std::string &input, char delimiter, T &output) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
split [](start = 5, length = 5)
Did you try boost split and join functions? #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want to directly get some variables with expected type from the input string. I think boost split can just help us to split string into vector.Meanwhile I know we have had a helper tokenize
can split string like boost split.
So what's your suggestion about replacing my code to boost split or tokenize and then convert vector to expected type? or just keep it as it is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggest you reuse existing function or common libraries (stl/boost/etc) first. If you find anything missing, try improve it based on existing ones by wrapping or preprocessing.
The last resort is to implement yourself.
In reply to: 547464854 [](ancestors = 547464854)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for misleading. I mean the caller could just use tokenize
or any common library function instead of your split
.
They are roughly the same, I don't see significant benefit added in the split
.
In reply to: 547616749 [](ancestors = 547616749,547464854)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want a helper function that I can directly get the variable with the expected type. If the caller use tokenize or split in boost, I have to explicitly convert the string to target type at many positions.
common/stringutility.cpp
Outdated
std::istringstream &istream, | ||
bool &b) | ||
{ | ||
std::string buffer = istream.str(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
str [](start = 33, length = 3)
Assume istream is extremely long, calling str()
is not efficient. #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
common/stringutility.cpp
Outdated
buffer.end(), | ||
buffer.begin(), | ||
::tolower); | ||
if (buffer == "true" || buffer == "1") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
buffer [](start = 8, length = 6)
You did not consume the string in istream #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
common/stringutility.cpp
Outdated
return istream; | ||
} | ||
|
||
bool swss::hex_to_binary( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hex_to_binary [](start = 11, length = 13)
It would be easier if you use boost unhex
or stringstream
+ std::hex
#Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As comments
Signed-off-by: Ze Gan <[email protected]>
Signed-off-by: Ze Gan <[email protected]>
Signed-off-by: Ze Gan <[email protected]>
Signed-off-by: Ze Gan <[email protected]>
Signed-off-by: Ze Gan <[email protected]>
common/stringutility.h
Outdated
} | ||
|
||
template <typename T, typename... Args> | ||
void cast( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cast [](start = 5, length = 4)
These functions are not expected to be used by applications directly. So suggest move them into another namespace swss::xxxx_details::
#Closed
common/stringutility.h
Outdated
} | ||
|
||
template <typename T, typename... Args> | ||
void cast(const std::vector<std::string> &strs, T &t, Args &... args) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cast [](start = 5, length = 4)
After 2nd thought, I see cast
is too ambiguous. I propose the name swss::lexical_convert
. #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree, How about to follow the boost and C++ convention? use swss::lexical_cast
?
common/stringutility.h
Outdated
} | ||
|
||
template <typename T> | ||
void join(std::ostringstream &ostream, char, const T &t) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
join [](start = 5, length = 4)
These functions are not expected to be used by applications directly. So suggest move them into another namespace swss::xxxx_details:: #Closed
common/stringutility.h
Outdated
template<typename T> | ||
void hex_to_binary( | ||
const std::string &s, | ||
T &value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't break lines for short parameter list. #Closed
common/redisutility.h
Outdated
CASE_INSENSITIVE, | ||
}; | ||
|
||
static inline boost::optional<std::string> fvtGetValue( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
inline [](start = 7, length = 6)
Don't inline non-trivial functions. Separate into cpp will make dependent project easy to build. #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then make the include headers as minimal as possible. Only for function declaration purpose, not for function implementation.
In reply to: 548762018 [](ancestors = 548762018)
common/stringutility.h
Outdated
t = boost::lexical_cast<T>(str); | ||
} | ||
|
||
static inline void cast(const std::string &str, bool &b) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cast [](start = 19, length = 4)
If it is ambiguous in schema, maybe we can improve schema to use only 0/1.
Then we don't need this flexible bool casting. #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think to support "true"/"false" in schema is useful because it can be consistent with SONiC doc, like https://github.com/Azure/SONiC/blob/b16791f3ca16398153556f40b11831cfbb6aba79/thermal-control-design.md.
Only if we will revise all existed bool to 0/1, otherwise, I think, it will be a little bit confused to a new developer about how to declare a bool.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Discussed offline. I anticipate a general solution will be:
- support any customized pair, even like down/up -> 0/1
- never mix pair, like down/enable
We could achieve this by new classes, which could be implicitly convert to bool. They are different only when serialize/deserialize.
In reply to: 548762444 [](ancestors = 548762444)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Signed-off-by: Ze Gan <[email protected]>
3baa179
to
7a0a672
Compare
Signed-off-by: Ze Gan <[email protected]>
Signed-off-by: Ze Gan <[email protected]>
common/stringutility.h
Outdated
// throw e; | ||
// } | ||
// } | ||
// } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove unused code #Closed
common/boolean.h
Outdated
class AlphaBoolean : public Boolean | ||
{ | ||
public: | ||
static const std::string ALPHA_TRUE; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ALPHA_TRUE [](start = 29, length = 10)
TRUE_STRING #Closed
common/boolean.h
Outdated
{ | ||
public: | ||
static const std::string ALPHA_TRUE; | ||
static const std::string ALPHA_FALSE; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ALPHA_FALSE [](start = 29, length = 11)
FALSE_STRING #Closed
common/boolean.cpp
Outdated
} | ||
|
||
const std::string swss::AlphaBoolean::ALPHA_TRUE = "true"; | ||
const std::string swss::AlphaBoolean::ALPHA_FALSE = "false"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You may inline the super short functions and member constants, to it will be optimized out. #Closed
common/boolean.cpp
Outdated
|
||
std::ostream &swss::operator<<(std::ostream &out, const swss::AlphaBoolean &b) | ||
{ | ||
out << (b ? swss::AlphaBoolean::ALPHA_TRUE : swss::AlphaBoolean::ALPHA_FALSE); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
swss::AlphaBoolean::ALPHA_TRUE [](start = 16, length = 30)
b.TRUE_STRING
If you improve the classes, you may write a generic <<
for all Boolean
and its subclasses. #Closed
common/stringutility.h
Outdated
t = boost::lexical_cast<T>(str); | ||
} | ||
|
||
// static inline void lexical_convert(const std::string &str, bool &b) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lexical_convert [](start = 22, length = 15)
Do you need to implement lexical_convert for AlphaBoolean?
If there is a default one, is it implemented by stringstream? If yes, I think you can provide a simpler one by overload here. #WontFix
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it will call the default one. But I cannot understand why we need a special overload lexical_convert for AlphaBoolean?
common/boolean.cpp
Outdated
return out; | ||
} | ||
|
||
std::istream &swss::operator>>(std::istream &in, swss::AlphaBoolean &b) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[](start = 28, length = 2)
For this special class, you can use in >> boolalpha >> b
#Closed
Signed-off-by: Ze Gan <[email protected]>
Signed-off-by: Ze Gan <[email protected]>
Boolean(bool boolean) : m_boolean(boolean) | ||
{ | ||
} | ||
operator bool() const |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
operator bool() [](start = 4, length = 15)
You need another cast operator
operator bool&()
{
return m_boolean;
}
``` #Closed
Signed-off-by: Ze Gan <[email protected]>
4e62624
to
c452b86
Compare
This PR provides the following utilities
AlphaBool
This is a class to provide a unified bool string
lexical_convert
This function can be used to convert the key in redis to variables with expected type
join
This function can be used to generate key for redis by some different material
hex_to_binary
Generate a segment binary according to a hex string
binary_to_hex
Serialize a segment binary to a hex string
fvtGetValue
This function provides a method to easily get the value from
std::vector<FieldValueTuple>
which is typical exchange format of redis in SONiCDepends on: #435
Signed-off-by: Ze Gan [email protected]