Here is the simpliest (I think) boost-preprocessor library based approach (from stackoverflow) for converting enum values to string:
#include <boost/preprocessor.hpp>
#define X_ENUM_STRING_TOSTRING_CASE(r, data, elem) \
case elem : return BOOST_PP_STRINGIZE(elem);
#define ENUM_STRING(name, enumerators) \
enum name \
{ \
BOOST_PP_SEQ_ENUM(enumerators) \
}; \
\
inline const char* toString(name val) \
{ \
switch (val) \
{ \
BOOST_PP_SEQ_FOR_EACH( \
X_ENUM_STRING_TOSTRING_CASE, \
name, \
enumerators \
) \
default: \
assert(false); return "[Unknown " BOOST_PP_STRINGIZE(name) "]"; \
} \
}
// Usage sample:
ENUM_STRING(Button, (Ok)(Close)(Retry)(Yes)(No)(Abort)(Help)(Cancel))
void foo()
{
std::string btnHelpName = toString(Button::Help); // btnHelpName == "Help"
std::string btnCloseName = toString(Button::Close); // btnCloseName == "Close"
}
Smalti
Monday, June 29, 2015
Tuesday, November 25, 2014
How to revert a singly linked list
struct Node
{
Node* next;
int value;
};
Node* revert_iteratively(Node* node)
{
Node* new_node = nullptr;
while (node)
{
auto next = node->next;
node->next = new_node;
new_node = node;
node = next;
}
return new_node;
}
Node* revert_iteratively_simple(Node* node)
{
using std::swap;
for (Node* tmp = nullptr; swap(node, tmp), tmp; swap(node, tmp->next));
return node;
}
Node* revert_recursively(Node* node)
{
if (!node || !node->next)
return node;
auto new_node = revert_recursively(node->next);
node->next->next = node;
node->next = nullptr;
return new_node;
}
{
Node* next;
int value;
};
Node* revert_iteratively(Node* node)
{
Node* new_node = nullptr;
while (node)
{
auto next = node->next;
node->next = new_node;
new_node = node;
node = next;
}
return new_node;
}
Node* revert_iteratively_simple(Node* node)
{
using std::swap;
for (Node* tmp = nullptr; swap(node, tmp), tmp; swap(node, tmp->next));
return node;
}
Node* revert_recursively(Node* node)
{
if (!node || !node->next)
return node;
auto new_node = revert_recursively(node->next);
node->next->next = node;
node->next = nullptr;
return new_node;
}
Sunday, December 29, 2013
Three ways to get UTC time in C++
1. C++ way:
#include <ctime>std::string currentDateTimeUTC( )
{
struct tm tm;
std::time_t time = std::time(nullptr);
if (gmtime_s(&tm, &time))
return ("");
char utc[_countof("1970-01-01T00:00:00")];
strftime(utc, _countof(utc), "%Y-%m-%dT%H:%M:%S", &tm);
return (utc);
}
auto result = currentDateTimeUTC( );
2. boost way:
#include <boost/date_time/posix_time/posix_time.hpp>
using namespace boost::posix_time;
auto result = to_iso_extended_string(second_clock::universal_time());
3. Qt way:
#include <QDateTime>
auto result = QDateTime::currentDateTimeUtc().toString(Qt::ISODate).toStdString();
Friday, August 2, 2013
How to fast initialize a really big array with 16, 32, 64 bit asf values
Sometimes we need a version of memset which sets a value that is larger than one byte. memset only uses one byte of the value passed in and does byte-wise initialization. If you want to initialize an array with a particular value larger than one byte, just use these approaches:
1. Just use a simple for ( ; ; ) In most cases this is a simple and good way.
2. std::fill, std::fill_n
#define BUFF_SIZE 1024 * 1024 * 1536
...
uint16_t val16 = 10000;
uint32_t val32 = 10000 * 10000L;
uint64_t val64 = 10000 * 10000 * 10000LL;
void* buff = new uint8_t[BUFF_SIZE];
...
std::fill_n((uint16_t*)buff, BUFF_SIZE / sizeof(val16), val16);
std::fill_n((uint32_t*)buff, BUFF_SIZE / sizeof(val32), val32);
std::fill_n((uint64_t*)buff, BUFF_SIZE / sizeof(val64), val64);
3. The memset function is very optimized in the compilers. Some implementations offer a 16-bit version memsetw, but that's not everywhere. The memcpy implementations are often written with SIMD instructions which makes it possible to shuffle 128 bits at a time. SIMD instructions are assembly instructions that can perform the same operation on each element in a vector up to 16 bytes long. That includes load and store instructions. So, here is a memsetx function which is implemented via memcpy:
template <typename T>
void memsetx(void* dst, T& val, unsigned int size)
{
uint32_t i = 0;
for ( ; i < (size & (~(sizeof(T) - 1))); i += sizeof(T))
memcpy((uint8_t*)dst + i, &val, sizeof(T));
for ( ; i < size; ++i)
((uint8_t*)dst)[i] = ((uint8_t*)&val)[i & (sizeof(T) - 1)];
}
...
memsetx(buff, val16, BUFF_SIZE);
memsetx(buff, val32, BUFF_SIZE);
memsetx(buff, val64, BUFF_SIZE);
...
memsetx(buff, val1024, BUFF_SIZE);
...
1. Just use a simple for ( ; ; ) In most cases this is a simple and good way.
2. std::fill, std::fill_n
#define BUFF_SIZE 1024 * 1024 * 1536
...
uint16_t val16 = 10000;
uint32_t val32 = 10000 * 10000L;
uint64_t val64 = 10000 * 10000 * 10000LL;
void* buff = new uint8_t[BUFF_SIZE];
...
std::fill_n((uint16_t*)buff, BUFF_SIZE / sizeof(val16), val16);
std::fill_n((uint32_t*)buff, BUFF_SIZE / sizeof(val32), val32);
std::fill_n((uint64_t*)buff, BUFF_SIZE / sizeof(val64), val64);
3. The memset function is very optimized in the compilers. Some implementations offer a 16-bit version memsetw, but that's not everywhere. The memcpy implementations are often written with SIMD instructions which makes it possible to shuffle 128 bits at a time. SIMD instructions are assembly instructions that can perform the same operation on each element in a vector up to 16 bytes long. That includes load and store instructions. So, here is a memsetx function which is implemented via memcpy:
template <typename T>
void memsetx(void* dst, T& val, unsigned int size)
{
uint32_t i = 0;
for ( ; i < (size & (~(sizeof(T) - 1))); i += sizeof(T))
memcpy((uint8_t*)dst + i, &val, sizeof(T));
for ( ; i < size; ++i)
((uint8_t*)dst)[i] = ((uint8_t*)&val)[i & (sizeof(T) - 1)];
}
...
memsetx(buff, val16, BUFF_SIZE);
memsetx(buff, val32, BUFF_SIZE);
memsetx(buff, val64, BUFF_SIZE);
...
memsetx(buff, val1024, BUFF_SIZE);
...
Subscribe to:
Posts (Atom)