nvidia-texture-tools/src/nvcore/StrLib.h

356 lines
7.7 KiB
C
Raw Normal View History

2007-04-17 08:49:19 +00:00
// This code is in the public domain -- castanyo@yahoo.es
#ifndef NV_CORE_STRING_H
#define NV_CORE_STRING_H
#include <nvcore/nvcore.h>
#include <nvcore/Containers.h> // swap
#include <string.h> // strlen, strcmp, etc.
namespace nv
{
uint strHash(const char * str, uint h) NV_PURE;
2008-10-22 05:31:28 +00:00
/// String hash based on Bernstein's hash.
2007-04-17 08:49:19 +00:00
inline uint strHash(const char * data, uint h = 5381)
{
2010-03-02 01:29:48 +00:00
uint i = 0;
2007-04-17 08:49:19 +00:00
while(data[i] != 0) {
h = (33 * h) ^ uint(data[i]);
i++;
}
return h;
}
template <> struct hash<const char *> {
uint operator()(const char * str) const { return strHash(str); }
};
NVCORE_API int strCaseCmp(const char * s1, const char * s2) NV_PURE;
NVCORE_API int strCmp(const char * s1, const char * s2) NV_PURE;
NVCORE_API void strCpy(char * dst, int size, const char * src);
NVCORE_API void strCpy(char * dst, int size, const char * src, int len);
2007-04-17 08:49:19 +00:00
NVCORE_API void strCat(char * dst, int size, const char * src);
NVCORE_API bool strMatch(const char * str, const char * pat) NV_PURE;
/// String builder.
class NVCORE_CLASS StringBuilder
2007-04-17 08:49:19 +00:00
{
public:
StringBuilder();
explicit StringBuilder( int size_hint );
StringBuilder( const char * str );
StringBuilder( const StringBuilder & );
2007-04-17 08:49:19 +00:00
~StringBuilder();
2007-04-17 08:49:19 +00:00
StringBuilder & format( const char * format, ... ) __attribute__((format (printf, 2, 3)));
StringBuilder & format( const char * format, va_list arg );
2007-04-17 08:49:19 +00:00
StringBuilder & append( const char * str );
StringBuilder & appendFormat( const char * format, ... ) __attribute__((format (printf, 2, 3)));
StringBuilder & appendFormat( const char * format, va_list arg );
2007-04-17 08:49:19 +00:00
StringBuilder & number( int i, int base = 10 );
StringBuilder & number( uint i, int base = 10 );
2007-04-17 08:49:19 +00:00
StringBuilder & reserve( uint size_hint );
StringBuilder & copy( const char * str );
StringBuilder & copy( const StringBuilder & str );
2007-04-17 08:49:19 +00:00
StringBuilder & toLower();
StringBuilder & toUpper();
2007-04-17 08:49:19 +00:00
void reset();
bool isNull() const { return m_size == 0; }
2007-04-17 08:49:19 +00:00
// const char * accessors
operator const char * () const { return m_str; }
operator char * () { return m_str; }
const char * str() const { return m_str; }
char * str() { return m_str; }
/// Implement value semantics.
StringBuilder & operator=( const StringBuilder & s ) {
return copy(s);
}
2007-07-01 08:52:38 +00:00
/// Implement value semantics.
StringBuilder & operator=( const char * s ) {
return copy(s);
}
2007-04-17 08:49:19 +00:00
/// Equal operator.
bool operator==( const StringBuilder & s ) const {
2007-07-01 08:52:38 +00:00
if (s.isNull()) return isNull();
else if (isNull()) return false;
else return strcmp(s.m_str, m_str) != 0;
2007-04-17 08:49:19 +00:00
}
/// Return the exact length.
2007-07-01 08:52:38 +00:00
uint length() const { return isNull() ? 0 : uint(strlen(m_str)); }
2007-04-17 08:49:19 +00:00
/// Return the size of the string container.
2007-07-01 08:52:38 +00:00
uint capacity() const { return m_size; }
2007-04-17 08:49:19 +00:00
/// Return the hash of the string.
2007-07-01 08:52:38 +00:00
uint hash() const { return isNull() ? 0 : strHash(m_str); }
2007-04-17 08:49:19 +00:00
/// Swap strings.
friend void swap(StringBuilder & a, StringBuilder & b) {
nv::swap(a.m_size, b.m_size);
nv::swap(a.m_str, b.m_str);
}
protected:
/// Size of the string container.
uint m_size;
/// String.
char * m_str;
};
/// Path string. @@ This should be called PathBuilder.
class NVCORE_CLASS Path : public StringBuilder
2007-04-17 08:49:19 +00:00
{
public:
Path() : StringBuilder() {}
explicit Path(int size_hint) : StringBuilder(size_hint) {}
Path(const char * str) : StringBuilder(str) {}
Path(const Path & path) : StringBuilder(path) {}
2007-04-17 08:49:19 +00:00
const char * fileName() const;
const char * extension() const;
2007-04-17 08:49:19 +00:00
void translatePath();
2007-04-17 08:49:19 +00:00
void stripFileName();
void stripExtension();
2007-04-17 08:49:19 +00:00
// statics
2009-03-18 04:04:09 +00:00
NVCORE_API static char separator();
NVCORE_API static const char * fileName(const char *);
NVCORE_API static const char * extension(const char *);
2007-04-17 08:49:19 +00:00
};
/// String class.
class NVCORE_CLASS String
2007-04-17 08:49:19 +00:00
{
public:
/// Constructs a null string. @sa isNull()
String()
{
2009-06-13 13:54:04 +00:00
data = NULL;
2007-04-17 08:49:19 +00:00
}
/// Constructs a shared copy of str.
String(const String & str)
{
data = str.data;
2009-06-13 13:54:04 +00:00
if (data != NULL) addRef();
2007-04-17 08:49:19 +00:00
}
/// Constructs a shared string from a standard string.
String(const char * str)
{
setString(str);
}
/// Constructs a shared string from a standard string.
String(const char * str, int length)
{
setString(str, length);
}
/// Constructs a shared string from a StringBuilder.
String(const StringBuilder & str)
{
setString(str);
}
/// Dtor.
~String()
{
release();
}
String clone() const;
2007-04-17 08:49:19 +00:00
/// Release the current string and allocate a new one.
const String & operator=( const char * str )
{
release();
setString( str );
return *this;
}
/// Release the current string and allocate a new one.
const String & operator=( const StringBuilder & str )
{
release();
setString( str );
return *this;
}
/// Implement value semantics.
String & operator=( const String & str )
{
2008-10-22 05:31:28 +00:00
if (str.data != data)
{
release();
data = str.data;
addRef();
}
2007-04-17 08:49:19 +00:00
return *this;
}
/// Equal operator.
bool operator==( const String & str ) const
{
if( str.data == data ) {
return true;
}
2009-07-03 00:07:10 +00:00
if ((data == NULL) != (str.data == NULL)) {
return false;
}
2007-04-17 08:49:19 +00:00
return strcmp(data, str.data) == 0;
}
/// Equal operator.
bool operator==( const char * str ) const
{
nvCheck(str != NULL); // Use isNull!
2009-07-03 00:07:10 +00:00
if (data == NULL) {
return false;
}
2007-04-17 08:49:19 +00:00
return strcmp(data, str) == 0;
}
/// Not equal operator.
bool operator!=( const String & str ) const
{
if( str.data == data ) {
return false;
}
2009-07-03 00:07:10 +00:00
if ((data == NULL) != (str.data == NULL)) {
return true;
}
2007-04-17 08:49:19 +00:00
return strcmp(data, str.data) != 0;
}
/// Not equal operator.
bool operator!=( const char * str ) const
{
nvCheck(str != NULL); // Use isNull!
2009-07-03 00:07:10 +00:00
if (data == NULL) {
return false;
}
2007-04-17 08:49:19 +00:00
return strcmp(data, str) != 0;
}
/// Returns true if this string is the null string.
2009-06-13 13:54:04 +00:00
bool isNull() const { return data == NULL; }
2007-04-17 08:49:19 +00:00
/// Return the exact length.
uint length() const { nvDebugCheck(data != NULL); return uint(strlen(data)); }
/// Return the hash of the string.
uint hash() const { nvDebugCheck(data != NULL); return strHash(data); }
/// const char * cast operator.
2009-06-13 13:54:04 +00:00
operator const char * () const { return data; }
2007-04-17 08:49:19 +00:00
/// Get string pointer.
2009-06-13 13:54:04 +00:00
const char * str() const { return data; }
2007-04-17 08:49:19 +00:00
private:
// Add reference count.
2009-06-13 13:54:04 +00:00
void addRef()
{
if (data != NULL)
{
setRefCount(getRefCount() + 1);
}
2007-04-17 08:49:19 +00:00
}
// Decrease reference count.
2009-06-13 13:54:04 +00:00
void release()
{
if (data != NULL)
{
const uint16 count = getRefCount();
setRefCount(count - 1);
if (count - 1 == 0) {
free(data - 2);
2009-06-13 13:54:04 +00:00
data = NULL;
}
2007-04-17 08:49:19 +00:00
}
}
2009-06-13 13:54:04 +00:00
uint16 getRefCount() const
{
nvDebugCheck(data != NULL);
2007-04-17 08:49:19 +00:00
return *reinterpret_cast<const uint16 *>(data - 2);
}
void setRefCount(uint16 count) {
2009-06-13 13:54:04 +00:00
nvDebugCheck(data != NULL);
2007-04-17 08:49:19 +00:00
nvCheck(count < 0xFFFF);
*reinterpret_cast<uint16 *>(const_cast<char *>(data - 2)) = uint16(count);
}
void setData(const char * str) {
data = str + 2;
}
void allocString(const char * str)
{
allocString(str, (int)strlen(str));
}
void allocString(const char * str, int len)
{
const char * ptr = static_cast<const char *>(::malloc(2 + len + 1));
2007-04-17 08:49:19 +00:00
setData( ptr );
setRefCount( 0 );
// Copy string.
strCpy(const_cast<char *>(data), len+1, str, len);
// Add terminating character.
const_cast<char *>(data)[len] = '\0';
2007-04-17 08:49:19 +00:00
}
void setString(const char * str);
void setString(const char * str, int length);
void setString(const StringBuilder & str);
2007-04-17 08:49:19 +00:00
/// Swap strings.
friend void swap(String & a, String & b) {
swap(a.data, b.data);
}
private:
const char * data;
};
} // nv namespace
#endif // NV_CORE_STRING_H