util.cpp
/*
Copyright (c) 2006-2023 by Jakob Schröter <js@camaya.net>
This file is part of the gloox library. http://camaya.net/gloox
This software is distributed under a license. The full license
agreement can be found in the file LICENSE in this distribution.
This software may not be copied, modified, sold or distributed
other than expressed in the named license agreement.
This software is distributed without any warranty.
*/
#include "util.h"
#include "gloox.h"
#include <cstdio>
namespace gloox
{
namespace util
{
int internalLog2( unsigned int n )
{
int pos = 0;
if ( n >= 1<<16 ) { n >>= 16; pos += 16; }
if ( n >= 1<< 8 ) { n >>= 8; pos += 8; }
if ( n >= 1<< 4 ) { n >>= 4; pos += 4; }
if ( n >= 1<< 2 ) { n >>= 2; pos += 2; }
if ( n >= 1<< 1 ) { pos += 1; }
return ( (n == 0) ? (-1) : pos );
}
unsigned _lookup( const std::string& str, const char* values[], unsigned size, int def )
{
unsigned i = 0;
for( ; i < size && str != values[i]; ++i )
;
return ( i == size && def >= 0 ) ? static_cast<unsigned int>( def ) : i;
}
const std::string _lookup( unsigned code, const char* values[], unsigned size, const std::string& def )
{
return code < size ? std::string( values[code] ) : def;
}
unsigned _lookup2( const std::string& str, const char* values[],
unsigned size, int def )
{
return 1 << _lookup( str, values, size, def <= 0 ? def : static_cast<int>( internalLog2( def ) ) );
}
const std::string _lookup2( unsigned code, const char* values[], unsigned size, const std::string& def )
{
const unsigned i = static_cast<unsigned int>( internalLog2( code ) );
return i < size ? std::string( values[i] ) : def;
}
std::string hex( const std::string& input )
{
const char* H = input.c_str();
char* buf = new char[input.length() * 2 + 1];
for( unsigned int i = 0; i < input.length(); ++i )
sprintf( buf + i * 2, "%02x", static_cast<unsigned char>( H[i] ) );
return std::string( buf, 40 );
}
static const char escape_chars[] = { '&', '<', '>', '\'', '"' };
static const std::string escape_seqs[] = { "amp;", "lt;", "gt;", "apos;", "quot;" };
static const std::string escape_seqs_full[] = { "&amp;", "&lt;", "&gt;", "&apos;", "&quot;" };
static const unsigned escape_size = 5;
const std::string escape( std::string what )
{
for( size_t val, i = 0; i < what.length(); ++i )
{
for( val = 0; val < escape_size; ++val )
{
if( what[i] == escape_chars[val] )
{
what[i] = '&';
what.insert( i+1, escape_seqs[val] );
i += escape_seqs[val].length();
break;
}
}
}
return what;
}
void appendEscaped( std::string& target, const std::string& data )
{
size_t rangeStart = 0, rangeCount = 0;
size_t length = data.length();
const char* dataPtr = data.data();
for( size_t val, i = 0; i < length; ++i )
{
const char current = dataPtr[i];
for( val = 0; val < escape_size; ++val )
{
if( current == escape_chars[val] )
{
// We have a character that needs to be escaped.
if( rangeCount > 0 )
{
// We have a range of the data that needs to be appended
// before we escape the current character.
// NOTE: Use "data" (std::string) here not dataPtr (const char*).
// Both have the same content, but there isn't
// an append override that takes const char*, pos, n
// (so a temporary std::string would be created)
target.append( data, rangeStart, rangeCount );
}
target.append( escape_seqs_full[val] );
rangeStart = i + 1;
rangeCount = 0;
break;
}
}
if( rangeStart <= i )
{
// current did not need to be escaped
++rangeCount;
}
}
if( rangeCount > 0 )
{
// Append the remaining pending range of data that does
// not need to be escaped.
// NOTE: See previous comment on using data not dataPtr for append.
target.append( data, rangeStart, rangeCount );
}
}
bool checkValidXMLChars( const std::string& data )
{
if( data.empty() )
return true;
const char* dataPtr = data.data();
const char* end = dataPtr + data.length();
for( ; dataPtr != end; ++dataPtr )
{
unsigned char current = static_cast<unsigned char>( *dataPtr );
if( current < 0x20 )
{
if( current == 0x09
|| current == 0x0a
|| current == 0x0d )
// Valid character
continue;
else
// Invalid character
break;
}
else if( current >= 0xf5 )
// Invalid character
break;
else if( current == 0xc0
|| current == 0xc1 )
// Invalid character
break;
else
// Valid character
continue;
}
return ( dataPtr == end );
}
void replaceAll( std::string& target, const std::string& find, const std::string& replace )
{
std::string::size_type findSize = find.size();
std::string::size_type replaceSize = replace.size();
if( findSize == 0 )
return;
std::string::size_type index = target.find( find, 0 );
while( index != std::string::npos )
{
target.replace( index, findSize, replace );
index = target.find( find, index+replaceSize );
}
}
}
}
gloox::util
A namespace holding a couple utility functions.
Definition atomicrefcount.cpp:36
gloox::util::internalLog2
int internalLog2(unsigned int n)
Definition util.cpp:24
gloox::util::_lookup
unsigned _lookup(const std::string &str, const char *values[], unsigned size, int def)
Definition util.cpp:35
gloox::util::_lookup2
unsigned _lookup2(const std::string &str, const char *values[], unsigned size, int def)
Definition util.cpp:48
gloox::util::appendEscaped
void appendEscaped(std::string &target, const std::string &data)
Definition util.cpp:95
gloox::util::replaceAll
void replaceAll(std::string &target, const std::string &find, const std::string &replace)
Definition util.cpp:177
gloox::util::checkValidXMLChars
bool checkValidXMLChars(const std::string &data)
Definition util.cpp:141
gloox::util::hex
std::string hex(const std::string &input)
Definition util.cpp:60
gloox::util::escape
const std::string escape(std::string what)
Definition util.cpp:77
gloox
The namespace for the gloox library.
Definition adhoc.cpp:28