blob: ebf4f913aa799af3efb797cf891c4f414f720bd9 [file] [log] [blame]
#ifndef _GEMFIRE_CACHEABLESTRING_HPP_
#define _GEMFIRE_CACHEABLESTRING_HPP_
/*=========================================================================
* Copyright (c) 2002-2014 Pivotal Software, Inc. All Rights Reserved.
* This product is protected by U.S. and international copyright
* and intellectual property laws. Pivotal products are covered by
* more patents listed at http://www.pivotal.io/patents.
*=========================================================================
*/
#include "gfcpp_globals.hpp"
#include "gf_types.hpp"
#include "CacheableKey.hpp"
#include "GemfireTypeIds.hpp"
#include "ExceptionTypes.hpp"
/** @file
*/
namespace gemfire
{
#define GF_STRING (int8_t)GemfireTypeIds::CacheableASCIIString
#define GF_STRING_HUGE (int8_t)GemfireTypeIds::CacheableASCIIStringHuge
#define GF_WIDESTRING (int8_t)GemfireTypeIds::CacheableString
#define GF_WIDESTRING_HUGE (int8_t)GemfireTypeIds::CacheableStringHuge
/**
* Implement a immutable C string wrapper that can serve as a distributable
* key object for caching as well as being a string value.
*/
class CPPCACHE_EXPORT CacheableString: public CacheableKey
{
protected:
void* m_str;
int8_t m_type;
uint32_t m_len;
mutable int m_hashcode;
public:
/**
*@brief serialize this object
**/
virtual void toData(DataOutput& output) const;
/**
*@brief deserialize this object
* Throw IllegalArgumentException if the packed CacheableString is not less
* than 64K bytes.
**/
virtual Serializable* fromData(DataInput& input);
/** creation function for strings */
static Serializable* createDeserializable();
/** creation function for strings > 64K length */
static Serializable* createDeserializableHuge();
/** creation function for wide strings */
static Serializable* createUTFDeserializable();
/** creation function for wide strings > 64K length in UTF8 encoding */
static Serializable* createUTFDeserializableHuge();
/**
*@brief Return the classId of the instance being serialized.
* This is used by deserialization to determine what instance
* type to create and deserialize into.
*/
virtual int32_t classId() const;
/**
* Return the typeId byte of the instance being serialized.
* This is used by deserialization to determine what instance
* type to create and deserialize into.
*
* For a <code>CacheableString</code> this shall return
* <code>GemfireTypeIds::CacheableNullString</code> if the underlying
* string is null, <code>GemfireTypeIds::CacheableASCIIString</code>
* if the underlying string is a char*, and
* <code>GemfireTypeIds::CacheableString</code> if it is a wchar_t*.
* For strings larger than 64K it will return
* <code>GemfireTypeIds::CacheableASCIIStringHuge</code> and
* <code>GemfireTypeIds::CacheableStringHuge</code> for char* and wchar_t*
* respectively.
*/
virtual int8_t typeId() const;
/** return true if this key matches other. */
virtual bool operator==(const CacheableKey& other) const;
/** return the hashcode for this key. */
virtual uint32_t hashcode() const;
/**
* Factory method for creating an instance of CacheableString from
* a null terminated C string optionally giving the length.
*
* This should be used only for ASCII strings.
*/
static CacheableStringPtr create(const char* value, int32_t len = 0)
{
CacheableStringPtr str = NULLPTR;
if (value != NULL) {
str = new CacheableString();
str->initString(value, len);
}
return str;
}
/**
* Factory method for creating an instance of CacheableString from
* a C string of given length by taking ownership of the string without
* making a copy. The string should have been allocated using
* the standard C++ new operator.
*
* This should be used only for ASCII strings.
*
* CAUTION: use this only when you really know what you are doing.
*/
static CacheableStringPtr createNoCopy(char* value, int32_t len = 0)
{
CacheableStringPtr str = NULLPTR;
if (value != NULL) {
str = new CacheableString();
str->initStringNoCopy(value, len);
}
return str;
}
/**
* Factory method for creating an instance of CacheableString from a
* wide-character null terminated C string optionally giving the length.
*
* This should be used for non-ASCII strings.
*/
static CacheableStringPtr create(const wchar_t* value, int32_t len = 0)
{
CacheableStringPtr str = NULLPTR;
if (value != NULL) {
str = new CacheableString();
str->initString(value, len);
}
return str;
}
/**
* Factory method for creating an instance of CacheableString from a
* wide-character C string of given length by taking ownership of the
* string without making a copy. The string should have been allocated
* using the standard C++ new operator.
*
* This should be used for non-ASCII strings.
*
* CAUTION: use this only when you really know what you are doing.
*/
static CacheableStringPtr createNoCopy(wchar_t* value, int32_t len = 0)
{
CacheableStringPtr str = NULLPTR;
if (value != NULL) {
str = new CacheableString();
str->initStringNoCopy(value, len);
}
return str;
}
/** Returns true if the underlying string is a normal C string. */
inline bool isCString() const
{
return (m_type == GF_STRING || m_type == GF_STRING_HUGE);
}
/** Returns true if the underlying string is a wide-character string. */
inline bool isWideString() const
{
return (m_type == GF_WIDESTRING || m_type == GF_WIDESTRING_HUGE);
}
/**
* Return the string that backs this CacheableString as a char *. This
* shall throw an exception if the underlying string is a wchar_t* --
* the caller should use <code>typeId</code> to determine the actual type,
* or <code>isWideString</code> to find whether this is a wide-character
* string.
*
* @throws IllegalStateException if the underlying string is a wchar_t *
*/
const char* asChar() const
{
if (isWideString()) {
throw IllegalStateException("CacheableString::asChar: the string is a "
"wide character string; use asWChar() to obtain it.");
}
return (const char*) m_str;
}
/**
* Return the string that backs this CacheableString as a wchar_t *. This
* shall throw an exception if the underlying string is a char* --
* the caller should use <code>typeId</code> to determine the actual type,
* or <code>isWideString</code> to find whether this is indeed a
* wide-character string.
*
* @throws IllegalStateException if the underlying string is a char *
*/
const wchar_t* asWChar() const
{
if (isCString()) {
throw IllegalStateException("CacheableString::asWChar: the string is "
"not a wide character string; use asChar() to obtain it.");
}
return (const wchar_t*) m_str;
}
/** Return the length of the contained string. */
inline uint32_t length() const
{
return m_len;
}
/**
* Display this object as c string. In this case, it returns the same
* value as asChar() when underlying type is a char* and returns the same
* value as asWChar() cast to char* when the underlying type is a wchar_t*.
* To handle this correctly the user should find the actual type by calling
* typeId() or isWideString() and cast to the correct type accordingly.
* Note: this is a debugging API, not intended for getting the exact value
* of the CacheableString. In a future release this may return a more
* summary representation. This is historical. It is preferred that the
* user call logString or asChar/asWChar, depending on the need.
*/
const char* toString()
{
return (const char*) m_str;
}
virtual CacheableStringPtr toString() const
{
return CacheableStringPtr(this);
}
/** get the name of the class of this object for logging purpose */
virtual const char* className() const
{
return "CacheableString";
}
/** Destructor */
virtual ~CacheableString();
/** used to render as a string for logging. */
virtual int32_t logString(char* buffer, int32_t maxLength) const;
virtual uint32_t objectSize() const;
protected:
/** Private method to populate the <code>CacheableString</code>. */
void copyString(const char* value, int32_t len);
/** Private method to populate the <code>CacheableString</code>. */
void copyString(const wchar_t* value, int32_t len);
/** initialize the string, given a value and length. */
void initString(const char* value, int32_t len);
/**
* Initialize the string without making a copy, given a C string
* and length.
*/
void initStringNoCopy(char* value, int32_t len);
/** initialize the string, given a wide-char string and length. */
void initString(const wchar_t* value, int32_t len);
/**
* Initialize the string without making a copy, given a wide-char string
* and length.
*/
void initStringNoCopy(wchar_t* value, int32_t len);
/** Private method to get ASCII string for wide-string if possible. */
char* getASCIIString(const wchar_t* value, int32_t& len,
int32_t& encodedLen);
/** Default constructor. */
inline CacheableString(int8_t type = GF_STRING) :
m_str(NULL), m_type(type), m_len(0), m_hashcode(0)
{
}
private:
// never implemented.
void operator=(const CacheableString& other);
CacheableString(const CacheableString& other);
};
/** overload of gemfire::createKeyArr to pass char* */
inline CacheableKeyPtr createKeyArr(const char* value)
{
return (value != NULL ? CacheableKeyPtr(CacheableString::create(
value).ptr()) : NULLPTR);
}
/** overload of gemfire::createKeyArr to pass wchar_t* */
inline CacheableKeyPtr createKeyArr(const wchar_t* value)
{
return (value != NULL ? CacheableKeyPtr(CacheableString::create(
value).ptr()) : NULLPTR);
}
/** overload of gemfire::createValueArr to pass char* */
inline CacheablePtr createValueArr(const char* value)
{
return (value != NULL ? CacheablePtr(CacheableString::create(
value).ptr()) : NULLPTR);
}
/** overload of gemfire::createValueArr to pass wchar_t* */
inline CacheablePtr createValueArr(const wchar_t* value)
{
return (value != NULL ? CacheablePtr(CacheableString::create(
value).ptr()) : NULLPTR);
}
}
#endif