8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-31 13:23:02 +01:00
firebird-mirror/src/common/classes/SafeArg.h

220 lines
6.5 KiB
C
Raw Normal View History

/*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
*
* Software distributed under the License is distributed AS IS,
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the License for the specific language governing rights
* and limitations under the License.
*
* The Original Code was created by Claudio Valderrama on 3-Mar-2007
* for the Firebird Open Source RDBMS project.
*
* Copyright (c) 2007 Claudio Valderrama
* and all contributors signed below.
*
* The author thanks specially Fred Polizo Jr and Adriano dos Santos Fernandes
* for comments and corrections.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*
*/
// Localized messages type-safe printing facility.
#ifndef FB_SAFEARG_H
#define FB_SAFEARG_H
// Definitions to generate fixed-length integral data types.
#ifdef _MSC_VER
typedef _int64 int64_t;
typedef unsigned _int64 uint64_t;
typedef _int32 int32_t;
typedef unsigned _int32 uint32_t;
typedef _int16 int16_t;
typedef unsigned _int16 uint16_t;
/* These macros were used to generate constants for testing.
#define c64(n) (n)
#define uc64(n) (n)
#else
#define c64(n) (n##LL)
#define uc64(n) (n##ULL)
*/
#endif
// Just an emulation of 128-bit numbers for now.
struct DoubleQuad
{
int64_t high;
uint64_t low;
};
typedef DoubleQuad SINT128;
namespace MsgFormat
{
// For now we allow 7 parameters; @1..@7 in MsgPrint.
const size_t SAFEARG_MAX_ARG = 7;
// This is the unit that represents one parameter in the format routines.
// The user of the routines rarely needs to be concerned with it.
// For now it contains only the data type and the value.
struct safe_cell
{
enum arg_type
{
at_none,
at_char,
at_uchar,
//at_int16,
//at_int32,
at_int64,
at_uint64,
at_int128,
at_double,
at_str,
at_counted_str,
at_ptr
};
struct safe_str
{
const char* s_string;
size_t s_len; // Optional, meaningful if type == at_counted_str.
};
arg_type type;
union
{
unsigned char c_value;
int64_t i_value;
SINT128 i128_value;
double d_value;
safe_str st_value;
void* p_value;
};
};
// Used to invoke the operator<< or we can't distinguish from null terminated string.
// Construct a counted_string on the fly (anonymous object) and pass it your
// unterminated string and its length.
struct counted_string
{
counted_string(const char* s, size_t len);
counted_string(const unsigned char* s, size_t len);
const char* const cs_string;
const size_t cs_len;
};
inline counted_string::counted_string(const char* s, size_t len)
: cs_string(s), cs_len(len)
{
}
inline counted_string::counted_string(const unsigned char* s, size_t len)
: cs_string(reinterpret_cast<const char*>(s)), cs_len(len)
{
}
class BaseStream;
// This is the main class that does the magic of receiving a chain of type-safe
// parameters. All parameters should be appended to it using the << operator.
// Only basic data types are supported, with the exception of length counted strings.
// The allowed types are char, UCHAR, all lengths of signed/unsigned integral values,
// the SINT128 fake type (a struct, really), double, strings, UCHAR strings,
// counted string and the (non-const) void pointer. Care should be taken to not
// pass something by address (except char* and UCHAR* types) because the compiler
// may route it to the overload for the void pointer and it will be printed as an
// address in hex.
// An object of this class can be created, filled and passed later to the printing
// routines, cleaned with clear(), refilled and passed again to the printing routines
// or simply constructed as an anonymous object and being filled at the same time
// that it serves as input to the printing routines (the MsgPrint family).
// Using << to pass more than 7 parameters will ignore the rest of the parameters
// silently instead of throwing exceptions or crashing.
// Only the full MsgPrint is declared a friend below, so the other routines should
// work through it.
// Typically the construction doesn't have parameters, but there's an overload
// that takes an array of integers. If the array has more than 7 elements, the
// rest are ignored. Then probably no more parameters will be pushed using <<.
// A dump() method is provided to dump all the parameters to a TEXT array or up
// to the number of elements in the target array if it's smallers than the number
// of parameters in SafeArg. In case it's bigger, the elements are set to NULL.
// Finally getCount() and getCell() are provided for the rare need to loop
// retrieving individual parameters as safe_cell structures. No provision is
// made to modify parameters once pushed into a SafeArg object.
// The parameter formatting is just an indication for the future, thus the
// m_extras pointer is not used for now. No need for parameter formatting (like
// alignment, width, precision, padding, numeric base) was evident as the msg.fdb
// contains rather simple format strings.
// Usage examples appear in the MsgPrint.h file.
class SafeArg
{
public:
SafeArg();
SafeArg(const int val[], size_t v_size);
SafeArg& clear();
SafeArg& operator<<(char c);
SafeArg& operator<<(unsigned char c);
//SafeArg& operator<<(int16_t c);
SafeArg& operator<<(short c);
SafeArg& operator<<(unsigned short c);
//SafeArg& operator<<(int32_t c);
SafeArg& operator<<(int c);
SafeArg& operator<<(unsigned int c);
SafeArg& operator<<(long int c);
SafeArg& operator<<(unsigned long int c);
SafeArg& operator<<(SINT64 c);
SafeArg& operator<<(UINT64 c);
//SafeArg& operator<<(long c);
SafeArg& operator<<(SINT128 c);
SafeArg& operator<<(double c);
SafeArg& operator<<(const char* c);
SafeArg& operator<<(const unsigned char* c);
SafeArg& operator<<(const counted_string& c);
SafeArg& operator<<(void* c);
void dump(const TEXT* target[], size_t v_size) const;
const safe_cell& getCell(size_t index) const;
size_t getCount() const;
private:
size_t m_count;
safe_cell m_arguments[SAFEARG_MAX_ARG];
const void* m_extras; // Formatting, etc.
friend int MsgPrint(BaseStream& out_stream, const char* format, const SafeArg& arg);
};
inline SafeArg::SafeArg()
: m_count(0), m_extras(0)
{
}
inline SafeArg& SafeArg::clear()
{
m_count = 0;
m_extras = 0;
return *this;
}
inline size_t SafeArg::getCount() const
{
return m_count;
}
} // namespace
#endif // FB_SAFEARG_H