mirror of https://github.com/Icinga/icinga2.git
Merge pull request #8693 from Icinga/bugfix/stringbuilder-malloc
PackObject(): avoid one malloc()
This commit is contained in:
commit
8813b74c9f
|
@ -70,7 +70,6 @@ set(base_SOURCES
|
||||||
stream.cpp stream.hpp
|
stream.cpp stream.hpp
|
||||||
streamlogger.cpp streamlogger.hpp streamlogger-ti.hpp
|
streamlogger.cpp streamlogger.hpp streamlogger-ti.hpp
|
||||||
string.cpp string.hpp string-script.cpp
|
string.cpp string.hpp string-script.cpp
|
||||||
stringbuilder.cpp stringbuilder.hpp
|
|
||||||
sysloglogger.cpp sysloglogger.hpp sysloglogger-ti.hpp
|
sysloglogger.cpp sysloglogger.hpp sysloglogger-ti.hpp
|
||||||
tcpsocket.cpp tcpsocket.hpp
|
tcpsocket.cpp tcpsocket.hpp
|
||||||
threadpool.cpp threadpool.hpp
|
threadpool.cpp threadpool.hpp
|
||||||
|
|
|
@ -5,12 +5,11 @@
|
||||||
#include "base/dictionary.hpp"
|
#include "base/dictionary.hpp"
|
||||||
#include "base/array.hpp"
|
#include "base/array.hpp"
|
||||||
#include "base/objectlock.hpp"
|
#include "base/objectlock.hpp"
|
||||||
#include "base/stringbuilder.hpp"
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
using namespace icinga;
|
using namespace icinga;
|
||||||
|
|
||||||
|
@ -30,7 +29,7 @@ static const EndiannessDetector l_EndiannessDetector;
|
||||||
// Assumption: The compiler will optimize (away) if/else statements using this.
|
// Assumption: The compiler will optimize (away) if/else statements using this.
|
||||||
#define MACHINE_LITTLE_ENDIAN (l_EndiannessDetector.buf[0])
|
#define MACHINE_LITTLE_ENDIAN (l_EndiannessDetector.buf[0])
|
||||||
|
|
||||||
static void PackAny(const Value& value, StringBuilder& builder);
|
static void PackAny(const Value& value, std::string& builder);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* std::swap() seems not to work
|
* std::swap() seems not to work
|
||||||
|
@ -73,7 +72,7 @@ static inline char UIntToByte(unsigned i)
|
||||||
/**
|
/**
|
||||||
* Append the given int as big-endian 64-bit unsigned int
|
* Append the given int as big-endian 64-bit unsigned int
|
||||||
*/
|
*/
|
||||||
static inline void PackUInt64BE(uint_least64_t i, StringBuilder& builder)
|
static inline void PackUInt64BE(uint_least64_t i, std::string& builder)
|
||||||
{
|
{
|
||||||
char buf[8] = {
|
char buf[8] = {
|
||||||
UIntToByte(i >> 56u),
|
UIntToByte(i >> 56u),
|
||||||
|
@ -86,7 +85,7 @@ static inline void PackUInt64BE(uint_least64_t i, StringBuilder& builder)
|
||||||
UIntToByte(i & 255u)
|
UIntToByte(i & 255u)
|
||||||
};
|
};
|
||||||
|
|
||||||
builder.Append((char*)buf, (char*)buf + 8);
|
builder.append((char*)buf, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
union Double2BytesConverter
|
union Double2BytesConverter
|
||||||
|
@ -110,7 +109,7 @@ union Double2BytesConverter
|
||||||
/**
|
/**
|
||||||
* Append the given double as big-endian IEEE 754 binary64
|
* Append the given double as big-endian IEEE 754 binary64
|
||||||
*/
|
*/
|
||||||
static inline void PackFloat64BE(double f, StringBuilder& builder)
|
static inline void PackFloat64BE(double f, std::string& builder)
|
||||||
{
|
{
|
||||||
Double2BytesConverter converter;
|
Double2BytesConverter converter;
|
||||||
|
|
||||||
|
@ -123,26 +122,26 @@ static inline void PackFloat64BE(double f, StringBuilder& builder)
|
||||||
SwapBytes(converter.buf[3], converter.buf[4]);
|
SwapBytes(converter.buf[3], converter.buf[4]);
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.Append((char*)converter.buf, (char*)converter.buf + 8);
|
builder.append((char*)converter.buf, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append the given string's length (BE uint64) and the string itself
|
* Append the given string's length (BE uint64) and the string itself
|
||||||
*/
|
*/
|
||||||
static inline void PackString(const String& string, StringBuilder& builder)
|
static inline void PackString(const String& string, std::string& builder)
|
||||||
{
|
{
|
||||||
PackUInt64BE(string.GetLength(), builder);
|
PackUInt64BE(string.GetLength(), builder);
|
||||||
builder.Append(string);
|
builder += string.GetData();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append the given array
|
* Append the given array
|
||||||
*/
|
*/
|
||||||
static inline void PackArray(const Array::Ptr& arr, StringBuilder& builder)
|
static inline void PackArray(const Array::Ptr& arr, std::string& builder)
|
||||||
{
|
{
|
||||||
ObjectLock olock(arr);
|
ObjectLock olock(arr);
|
||||||
|
|
||||||
builder.Append('\5');
|
builder += '\5';
|
||||||
PackUInt64BE(arr->GetLength(), builder);
|
PackUInt64BE(arr->GetLength(), builder);
|
||||||
|
|
||||||
for (const Value& value : arr) {
|
for (const Value& value : arr) {
|
||||||
|
@ -153,11 +152,11 @@ static inline void PackArray(const Array::Ptr& arr, StringBuilder& builder)
|
||||||
/**
|
/**
|
||||||
* Append the given dictionary
|
* Append the given dictionary
|
||||||
*/
|
*/
|
||||||
static inline void PackDictionary(const Dictionary::Ptr& dict, StringBuilder& builder)
|
static inline void PackDictionary(const Dictionary::Ptr& dict, std::string& builder)
|
||||||
{
|
{
|
||||||
ObjectLock olock(dict);
|
ObjectLock olock(dict);
|
||||||
|
|
||||||
builder.Append('\6');
|
builder += '\6';
|
||||||
PackUInt64BE(dict->GetLength(), builder);
|
PackUInt64BE(dict->GetLength(), builder);
|
||||||
|
|
||||||
for (const Dictionary::Pair& kv : dict) {
|
for (const Dictionary::Pair& kv : dict) {
|
||||||
|
@ -169,25 +168,25 @@ static inline void PackDictionary(const Dictionary::Ptr& dict, StringBuilder& bu
|
||||||
/**
|
/**
|
||||||
* Append any JSON-encodable value
|
* Append any JSON-encodable value
|
||||||
*/
|
*/
|
||||||
static void PackAny(const Value& value, StringBuilder& builder)
|
static void PackAny(const Value& value, std::string& builder)
|
||||||
{
|
{
|
||||||
switch (value.GetType()) {
|
switch (value.GetType()) {
|
||||||
case ValueString:
|
case ValueString:
|
||||||
builder.Append('\4');
|
builder += '\4';
|
||||||
PackString(value.Get<String>(), builder);
|
PackString(value.Get<String>(), builder);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ValueNumber:
|
case ValueNumber:
|
||||||
builder.Append('\3');
|
builder += '\3';
|
||||||
PackFloat64BE(value.Get<double>(), builder);
|
PackFloat64BE(value.Get<double>(), builder);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ValueBoolean:
|
case ValueBoolean:
|
||||||
builder.Append(value.ToBool() ? '\2' : '\1');
|
builder += (value.ToBool() ? '\2' : '\1');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ValueEmpty:
|
case ValueEmpty:
|
||||||
builder.Append('\0');
|
builder += '\0';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ValueObject:
|
case ValueObject:
|
||||||
|
@ -207,7 +206,7 @@ static void PackAny(const Value& value, StringBuilder& builder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.Append('\0');
|
builder += '\0';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -240,8 +239,8 @@ static void PackAny(const Value& value, StringBuilder& builder)
|
||||||
*/
|
*/
|
||||||
String icinga::PackObject(const Value& value)
|
String icinga::PackObject(const Value& value)
|
||||||
{
|
{
|
||||||
StringBuilder builder;
|
std::string builder;
|
||||||
PackAny(value, builder);
|
PackAny(value, builder);
|
||||||
|
|
||||||
return builder.ToString();
|
return std::move(builder);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
|
|
||||||
|
|
||||||
#include "base/stringbuilder.hpp"
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
using namespace icinga;
|
|
||||||
|
|
||||||
void StringBuilder::Append(const String& str)
|
|
||||||
{
|
|
||||||
m_Buffer.insert(m_Buffer.end(), str.Begin(), str.End());
|
|
||||||
}
|
|
||||||
|
|
||||||
void StringBuilder::Append(const std::string& str)
|
|
||||||
{
|
|
||||||
m_Buffer.insert(m_Buffer.end(), str.begin(), str.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
void StringBuilder::Append(const char *begin, const char *end)
|
|
||||||
{
|
|
||||||
m_Buffer.insert(m_Buffer.end(), begin, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StringBuilder::Append(const char *cstr)
|
|
||||||
{
|
|
||||||
m_Buffer.insert(m_Buffer.end(), cstr, cstr + std::strlen(cstr));
|
|
||||||
}
|
|
||||||
|
|
||||||
void StringBuilder::Append(char chr)
|
|
||||||
{
|
|
||||||
m_Buffer.emplace_back(chr);
|
|
||||||
}
|
|
||||||
|
|
||||||
String StringBuilder::ToString() const
|
|
||||||
{
|
|
||||||
return String(m_Buffer.data(), m_Buffer.data() + m_Buffer.size());
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
|
|
||||||
|
|
||||||
#ifndef STRINGBUILDER_H
|
|
||||||
#define STRINGBUILDER_H
|
|
||||||
|
|
||||||
#include "base/i2-base.hpp"
|
|
||||||
#include "base/string.hpp"
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace icinga
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A string builder.
|
|
||||||
*
|
|
||||||
* @ingroup base
|
|
||||||
*/
|
|
||||||
class StringBuilder final
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void Append(const String&);
|
|
||||||
void Append(const std::string&);
|
|
||||||
void Append(const char *, const char *);
|
|
||||||
void Append(const char *);
|
|
||||||
void Append(char);
|
|
||||||
|
|
||||||
String ToString() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<char> m_Buffer;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* STRINGBUILDER_H */
|
|
Loading…
Reference in New Issue