mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2024-12-30 10:26:58 +01:00
merge android_branch->
This commit is contained in:
commit
f954b09391
7 changed files with 278 additions and 131 deletions
|
@ -38,6 +38,7 @@ SRC = \
|
|||
udpager.cpp \
|
||||
udpqueue.cpp \
|
||||
xwrelay.cpp \
|
||||
querybld.cpp \
|
||||
|
||||
# STATIC ?= -static
|
||||
GITINFO = gitversion.txt
|
||||
|
|
|
@ -43,11 +43,8 @@
|
|||
|
||||
static DBMgr* s_instance = NULL;
|
||||
|
||||
#define DELIM "\1"
|
||||
#define MAX_NUM_PLAYERS 4
|
||||
|
||||
static void formatParams( char* paramValues[], int nParams, const char* fmt,
|
||||
char* buf, int bufLen, ... );
|
||||
static int here_less_seed( const char* seeds, int perDeviceSum,
|
||||
unsigned short seed );
|
||||
static void destr_function( void* conn );
|
||||
|
@ -105,20 +102,21 @@ DBMgr::AddNew( const char* cookie, const char* connName, CookieID cid,
|
|||
if ( !cookie ) cookie = "";
|
||||
if ( !connName ) connName = "";
|
||||
|
||||
const char* command = "INSERT INTO " GAMES_TABLE
|
||||
" (cid, room, connName, nTotal, lang, pub)"
|
||||
" VALUES( $1, $2, $3, $4, $5, $6 )";
|
||||
int nParams = 6;
|
||||
char* paramValues[nParams];
|
||||
char buf[512];
|
||||
formatParams( paramValues, nParams,
|
||||
"%d"DELIM"%s"DELIM"%s"DELIM"%d"DELIM"%d"DELIM"%s",
|
||||
buf, sizeof(buf), cid, cookie, connName, nPlayersT,
|
||||
langCode, isPublic?"TRUE":"FALSE" );
|
||||
QueryBuilder qb;
|
||||
qb.appendQueryf( "INSERT INTO " GAMES_TABLE
|
||||
" (cid, room, connName, nTotal, lang, pub)"
|
||||
" VALUES( $$, $$, $$, $$, $$, $$ )" )
|
||||
.appendParam(cid)
|
||||
.appendParam(cookie)
|
||||
.appendParam(connName)
|
||||
.appendParam(nPlayersT)
|
||||
.appendParam(langCode)
|
||||
.appendParam(isPublic?"TRUE":"FALSE" )
|
||||
.finish();
|
||||
|
||||
PGresult* result = PQexecParams( getThreadConn(), command,
|
||||
nParams, NULL,
|
||||
paramValues,
|
||||
PGresult* result = PQexecParams( getThreadConn(), qb.c_str(),
|
||||
qb.paramCount(), NULL,
|
||||
qb.paramValues(),
|
||||
NULL, NULL, 0 );
|
||||
if ( PGRES_COMMAND_OK != PQresultStatus(result) ) {
|
||||
logf( XW_LOGERROR, "PQexec=>%s;%s", PQresStatus(PQresultStatus(result)),
|
||||
|
@ -271,28 +269,27 @@ DBMgr::SeenSeed( const char* cookie, unsigned short seed,
|
|||
char* connNameBuf, int bufLen, int* nPlayersHP,
|
||||
CookieID* cid )
|
||||
{
|
||||
int nParams = 5;
|
||||
char* paramValues[nParams];
|
||||
char buf[512];
|
||||
formatParams( paramValues, nParams,
|
||||
"%s"DELIM"%d"DELIM"%d"DELIM"%d"DELIM"%s", buf, sizeof(buf),
|
||||
cookie, langCode, nPlayersT, seed,
|
||||
wantsPublic?"TRUE":"FALSE" );
|
||||
QueryBuilder qb;
|
||||
qb.appendQueryf( "SELECT cid, connName, seeds, sum_array(nPerDevice) FROM "
|
||||
GAMES_TABLE
|
||||
" WHERE NOT dead"
|
||||
" AND room ILIKE $$"
|
||||
" AND lang = $$"
|
||||
" AND nTotal = $$"
|
||||
" AND $$ = ANY(seeds)"
|
||||
" AND $$ = pub"
|
||||
" ORDER BY ctime DESC"
|
||||
" LIMIT 1")
|
||||
.appendParam(cookie)
|
||||
.appendParam(langCode)
|
||||
.appendParam(nPlayersT)
|
||||
.appendParam(seed)
|
||||
.appendParam(wantsPublic?"TRUE":"FALSE" )
|
||||
.finish();
|
||||
|
||||
const char* cmd = "SELECT cid, connName, seeds, sum_array(nPerDevice) FROM "
|
||||
GAMES_TABLE
|
||||
" WHERE NOT dead"
|
||||
" AND room ILIKE $1"
|
||||
" AND lang = $2"
|
||||
" AND nTotal = $3"
|
||||
" AND $4 = ANY(seeds)"
|
||||
" AND $5 = pub"
|
||||
" ORDER BY ctime DESC"
|
||||
" LIMIT 1";
|
||||
|
||||
PGresult* result = PQexecParams( getThreadConn(), cmd,
|
||||
nParams, NULL,
|
||||
paramValues,
|
||||
PGresult* result = PQexecParams( getThreadConn(), qb.c_str(),
|
||||
qb.paramCount(), NULL,
|
||||
qb.paramValues(),
|
||||
NULL, NULL, 0 );
|
||||
bool found = 1 == PQntuples( result );
|
||||
if ( found ) {
|
||||
|
@ -312,31 +309,28 @@ DBMgr::FindOpen( const char* cookie, int lang, int nPlayersT, int nPlayersH,
|
|||
bool wantsPublic, char* connNameBuf, int bufLen,
|
||||
int* nPlayersHP )
|
||||
{
|
||||
CookieID cid = 0;
|
||||
QueryBuilder qb;
|
||||
qb.appendQueryf("SELECT cid, connName, sum_array(nPerDevice) FROM "
|
||||
GAMES_TABLE
|
||||
" WHERE NOT dead"
|
||||
" AND room ILIKE $$"
|
||||
" AND lang = $$"
|
||||
" AND nTotal = $$"
|
||||
" AND $$ <= nTotal-sum_array(nPerDevice)"
|
||||
" AND $$ = pub"
|
||||
" LIMIT 1")
|
||||
.appendParam(cookie)
|
||||
.appendParam(lang)
|
||||
.appendParam(nPlayersT)
|
||||
.appendParam(nPlayersH)
|
||||
.appendParam(wantsPublic?"TRUE":"FALSE" )
|
||||
.finish();
|
||||
|
||||
int nParams = 5;
|
||||
char* paramValues[nParams];
|
||||
char buf[512];
|
||||
formatParams( paramValues, nParams,
|
||||
"%s"DELIM"%d"DELIM"%d"DELIM"%d"DELIM"%s", buf, sizeof(buf),
|
||||
cookie, lang, nPlayersT, nPlayersH, wantsPublic?"TRUE":"FALSE" );
|
||||
|
||||
/* NOTE: ILIKE, for case-insensitive comparison, is a postgres extension
|
||||
to SQL. */
|
||||
const char* cmd = "SELECT cid, connName, sum_array(nPerDevice) FROM "
|
||||
GAMES_TABLE
|
||||
" WHERE NOT dead"
|
||||
" AND room ILIKE $1"
|
||||
" AND lang = $2"
|
||||
" AND nTotal = $3"
|
||||
" AND $4 <= nTotal-sum_array(nPerDevice)"
|
||||
" AND $5 = pub"
|
||||
" LIMIT 1";
|
||||
|
||||
PGresult* result = PQexecParams( getThreadConn(), cmd,
|
||||
nParams, NULL,
|
||||
paramValues,
|
||||
PGresult* result = PQexecParams( getThreadConn(), qb.c_str(),
|
||||
qb.paramCount(), NULL,
|
||||
qb.paramValues(),
|
||||
NULL, NULL, 0 );
|
||||
CookieID cid = 0;
|
||||
if ( 1 == PQntuples( result ) ) {
|
||||
cid = atoi( PQgetvalue( result, 0, 0 ) );
|
||||
snprintf( connNameBuf, bufLen, "%s", PQgetvalue( result, 0, 1 ) );
|
||||
|
@ -396,14 +390,21 @@ DBMgr::RegisterDevice( const DevID* host, int clientVersion,
|
|||
devID = (DevIDRelay)random();
|
||||
} while ( DEVID_NONE == devID );
|
||||
|
||||
StrWPF query;
|
||||
query.catf( "INSERT INTO " DEVICES_TABLE " (id, devTypes[1],"
|
||||
" devids[1], clntVers, versdesc, model, osvers)"
|
||||
" VALUES( %d, %d, '%s', %d, '%s', '%s', '%s' )",
|
||||
devID, host->m_devIDType, devidStr, clientVersion,
|
||||
desc, model, osVers );
|
||||
logf( XW_LOGINFO, "%s: %s", __func__, query.c_str() );
|
||||
success = execSql( query );
|
||||
QueryBuilder qb;
|
||||
qb.appendQueryf( "INSERT INTO " DEVICES_TABLE " (id, devTypes[1],"
|
||||
" devids[1], clntVers, versdesc, model, osvers)"
|
||||
" VALUES($$, $$, $$, $$, $$, $$, $$)" );
|
||||
|
||||
qb.appendParam( devID )
|
||||
.appendParam( host->m_devIDType )
|
||||
.appendParam( devidStr )
|
||||
.appendParam( clientVersion )
|
||||
.appendParam( desc )
|
||||
.appendParam( model )
|
||||
.appendParam( osVers )
|
||||
.finish();
|
||||
|
||||
success = execParams( qb );
|
||||
}
|
||||
}
|
||||
return devID;
|
||||
|
@ -420,15 +421,17 @@ DBMgr::ReregisterDevice( DevIDRelay relayID, const DevID* host,
|
|||
const char* const desc, int clientVersion,
|
||||
const char* const model, const char* const osVers )
|
||||
{
|
||||
// First update the existing
|
||||
StrWPF query;
|
||||
query.catf( "UPDATE " DEVICES_TABLE " SET "
|
||||
"devTypes = array_prepend( %d, devTypes), "
|
||||
"devids = array_prepend('%s', devids), ",
|
||||
host->m_devIDType, host->m_devIDString.c_str() );
|
||||
QueryBuilder qb;
|
||||
qb.appendQueryf( "UPDATE " DEVICES_TABLE " SET "
|
||||
"devTypes = array_prepend($$, devTypes), "
|
||||
"devids = array_prepend($$, devids), " )
|
||||
|
||||
formatUpdate( query, true, desc, clientVersion, model, osVers, relayID );
|
||||
execSql( query );
|
||||
.appendParam( host->m_devIDType )
|
||||
.appendParam( host->m_devIDString.c_str() );
|
||||
|
||||
formatUpdate( qb, true, desc, clientVersion, model, osVers, relayID );
|
||||
qb.finish();
|
||||
execParams( qb );
|
||||
}
|
||||
|
||||
// Return true if the relayID exists in the DB already
|
||||
|
@ -445,10 +448,11 @@ DBMgr::UpdateDevice( DevIDRelay relayID, const char* const desc,
|
|||
}
|
||||
|
||||
if ( exists ) {
|
||||
StrWPF query;
|
||||
query.catf( "UPDATE " DEVICES_TABLE " SET " );
|
||||
formatUpdate( query, false, desc, clientVersion, model, osVers, relayID );
|
||||
execSql( query );
|
||||
QueryBuilder qb;
|
||||
qb.appendQueryf( "UPDATE " DEVICES_TABLE " SET " );
|
||||
formatUpdate( qb, false, desc, clientVersion, model, osVers, relayID );
|
||||
qb.finish();
|
||||
execParams( qb );
|
||||
}
|
||||
return exists;
|
||||
}
|
||||
|
@ -460,26 +464,33 @@ DBMgr::UpdateDevice( DevIDRelay relayID )
|
|||
}
|
||||
|
||||
void
|
||||
DBMgr::formatUpdate( StrWPF& query, bool append, const char* const desc,
|
||||
DBMgr::formatUpdate( QueryBuilder& qb,
|
||||
bool append, const char* const desc,
|
||||
int clientVersion, const char* const model,
|
||||
const char* const osVers, DevIDRelay relayID )
|
||||
{
|
||||
if ( append ) {
|
||||
query.catf( "mtimes=array_prepend('now', mtimes)" ); // FIXME: too many
|
||||
qb.appendQueryf( "mtimes=array_prepend('now', mtimes)" ); // FIXME: too many
|
||||
} else {
|
||||
query.catf( "mtimes[1]='now'" );
|
||||
qb.appendQueryf( "mtimes[1]='now'" );
|
||||
}
|
||||
|
||||
if ( NULL != desc && '\0' != desc[0] ) {
|
||||
query.catf( ", clntVers=%d, versDesc='%s'", clientVersion, desc );
|
||||
qb.appendQueryf( ", clntVers=$$" )
|
||||
.appendParam( clientVersion )
|
||||
.appendQueryf( ", versDesc=$$" )
|
||||
.appendParam( desc );
|
||||
}
|
||||
if ( NULL != model && '\0' != model[0] ) {
|
||||
query.catf( ", model='%s'", model );
|
||||
qb.appendQueryf( ", model=$$" )
|
||||
.appendParam( model );
|
||||
}
|
||||
if ( NULL != osVers && '\0' != osVers[0] ) {
|
||||
query.catf( ", osvers='%s'", osVers );
|
||||
qb.appendQueryf( ", osvers=$$" )
|
||||
.appendParam( osVers );
|
||||
}
|
||||
query.catf( " WHERE id = %d", relayID );
|
||||
qb.appendQueryf( " WHERE id = $$" )
|
||||
.appendParam( relayID );
|
||||
}
|
||||
|
||||
HostID
|
||||
|
@ -831,6 +842,22 @@ DBMgr::execSql( const char* const query )
|
|||
return ok;
|
||||
}
|
||||
|
||||
bool
|
||||
DBMgr::execParams( QueryBuilder& qb )
|
||||
{
|
||||
PGresult* result = PQexecParams( getThreadConn(), qb.c_str(),
|
||||
qb.paramCount(), NULL,
|
||||
qb.paramValues(),
|
||||
NULL, NULL, 0 );
|
||||
bool success = PGRES_COMMAND_OK == PQresultStatus( result );
|
||||
if ( !success ) {
|
||||
logf( XW_LOGERROR, "PQexecParams(%s)=>%s;%s", qb.c_str(),
|
||||
PQresStatus(PQresultStatus(result)),
|
||||
PQresultErrorMessage(result) );
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void
|
||||
DBMgr::readArray( const char* const connName, const char* column, int arr[] ) /* len 4 */
|
||||
{
|
||||
|
@ -1255,31 +1282,6 @@ void DBMgr::clearHasNoMessages( DevIDRelay devid )
|
|||
assert( !hasNoMessages( devid ) );
|
||||
}
|
||||
|
||||
static void
|
||||
formatParams( char* paramValues[], int nParams, const char* fmt, char* buf,
|
||||
int bufLen, ... )
|
||||
{
|
||||
va_list ap;
|
||||
va_start( ap, bufLen );
|
||||
|
||||
int len = vsnprintf( buf, bufLen, fmt, ap );
|
||||
assert( buf[len] == '\0' );
|
||||
|
||||
int pnum;
|
||||
char* ptr = buf;
|
||||
for ( pnum = 0; pnum < nParams; ++pnum ) {
|
||||
paramValues[pnum] = ptr;
|
||||
for ( ; *ptr != '\0' && *ptr != DELIM[0]; ++ptr ) {
|
||||
// do nothing
|
||||
assert( ptr < &buf[bufLen] );
|
||||
}
|
||||
// we've found an end
|
||||
*ptr = '\0';
|
||||
++ptr;
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static int
|
||||
here_less_seed( const char* seeds, int sumPerDevice, unsigned short seed )
|
||||
{
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "xwrelay_priv.h"
|
||||
#include "devid.h"
|
||||
#include "strwpf.h"
|
||||
#include "querybld.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -149,6 +150,7 @@ class DBMgr {
|
|||
DBMgr();
|
||||
bool execSql( const string& query );
|
||||
bool execSql( const char* const query ); /* no-results query */
|
||||
bool execParams( QueryBuilder& qb );
|
||||
void readArray( const char* const connName, const char* column, int arr[] );
|
||||
DevIDRelay getDevID( const char* connName, int hid );
|
||||
DevIDRelay getDevID( const DevID* devID );
|
||||
|
@ -160,7 +162,7 @@ class DBMgr {
|
|||
bool nullConnnameOK );
|
||||
int CountStoredMessages( const char* const connName, int hid );
|
||||
bool UpdateDevice( DevIDRelay relayID );
|
||||
void formatUpdate( StrWPF& query, bool append, const char* const desc,
|
||||
void formatUpdate( QueryBuilder& qb, bool append, const char* const desc,
|
||||
int clientVersion, const char* const model,
|
||||
const char* const osVers, DevIDRelay relayID );
|
||||
|
||||
|
|
78
xwords4/relay/querybld.cpp
Normal file
78
xwords4/relay/querybld.cpp
Normal file
|
@ -0,0 +1,78 @@
|
|||
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
|
||||
/*
|
||||
* Copyright 2014 by Eric House (xwords@eehouse.org). All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "querybld.h"
|
||||
#include "xwrelay_priv.h"
|
||||
|
||||
QueryBuilder&
|
||||
QueryBuilder::appendQueryf( const char* fmt, ... )
|
||||
{
|
||||
bool done;
|
||||
do {
|
||||
va_list ap;
|
||||
va_start( ap, fmt );
|
||||
done = m_query.catf( fmt, ap );
|
||||
va_end( ap );
|
||||
} while ( !done );
|
||||
return *this;
|
||||
}
|
||||
|
||||
QueryBuilder&
|
||||
QueryBuilder::appendParam( const char* value )
|
||||
{
|
||||
m_paramIndices.push_back( m_paramBuf.size() );
|
||||
m_paramBuf.catf( "%s%c", value, '\0' );
|
||||
return *this;
|
||||
}
|
||||
|
||||
QueryBuilder&
|
||||
QueryBuilder::appendParam( int value )
|
||||
{
|
||||
m_paramIndices.push_back( m_paramBuf.size() );
|
||||
m_paramBuf.catf( "%d%c", value, '\0' );
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* When done adding params, some of which contain $$, turn these into an order
|
||||
* progression of $1, $2 .. $9. Note assumption that we don't go above 9 since
|
||||
*/
|
||||
void
|
||||
QueryBuilder::finish()
|
||||
{
|
||||
assert( 0 == m_paramValues.size() );
|
||||
|
||||
size_t ii;
|
||||
const char* base = m_paramBuf.c_str();
|
||||
for ( ii = 0; ii < m_paramIndices.size(); ++ii ) {
|
||||
const char* ptr = m_paramIndices[ii] + base;
|
||||
m_paramValues.push_back( ptr );
|
||||
}
|
||||
|
||||
for ( size_t count = 0; ; ++count ) {
|
||||
const char* str = m_query.c_str();
|
||||
const char* ptr = strstr( str, "$$" );
|
||||
if ( !ptr ) {
|
||||
assert( count == m_paramIndices.size() );
|
||||
break;
|
||||
}
|
||||
assert( count < 9 );
|
||||
m_query[1 + ptr - str] = '1' + count;
|
||||
}
|
||||
}
|
47
xwords4/relay/querybld.h
Normal file
47
xwords4/relay/querybld.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
|
||||
/*
|
||||
* Copyright 2014 by Eric House (xwords@eehouse.org). All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef _QUERYBLD_H_
|
||||
#define _QUERYBLD_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "strwpf.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class QueryBuilder {
|
||||
|
||||
public:
|
||||
QueryBuilder& appendQueryf( const char* fmt, ... );
|
||||
QueryBuilder& appendParam( const char* value );
|
||||
QueryBuilder& appendParam( int value );
|
||||
void finish();
|
||||
int paramCount() const { return m_paramValues.size(); }
|
||||
const char* const* paramValues() const { return &m_paramValues[0]; }
|
||||
const char* const c_str() const { return m_query.c_str(); }
|
||||
|
||||
private:
|
||||
StrWPF m_query;
|
||||
StrWPF m_paramBuf;
|
||||
vector<size_t> m_paramIndices;
|
||||
vector<const char*> m_paramValues;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -27,26 +27,37 @@
|
|||
/* From stack overflow: snprintf with an expanding buffer.
|
||||
*/
|
||||
|
||||
bool
|
||||
StrWPF::catf( const char* fmt, va_list ap )
|
||||
{
|
||||
bool success = false;
|
||||
const int origsiz = size();
|
||||
resize( origsiz + m_addsiz );
|
||||
|
||||
int len = vsnprintf( (char*)c_str() + origsiz, m_addsiz, fmt, ap );
|
||||
|
||||
if ( len >= m_addsiz ) { // needs more space
|
||||
m_addsiz = len + 1;
|
||||
resize( origsiz );
|
||||
} else if ( -1 == len ) {
|
||||
assert(0); // should be impossible
|
||||
} else {
|
||||
resize( origsiz + len );
|
||||
m_addsiz = 100;
|
||||
success = true;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
void
|
||||
StrWPF::catf( const char* fmt, ... )
|
||||
{
|
||||
const int origsiz = size();
|
||||
int addsiz = 100;
|
||||
va_list ap;
|
||||
for ( ; ; ) {
|
||||
resize( origsiz + addsiz );
|
||||
|
||||
bool done;
|
||||
do {
|
||||
va_list ap;
|
||||
va_start( ap, fmt );
|
||||
int len = vsnprintf( (char *)c_str() + origsiz, addsiz, fmt, ap );
|
||||
done = catf( fmt, ap );
|
||||
va_end( ap );
|
||||
|
||||
if ( len >= addsiz ) { // needs more space
|
||||
addsiz = len + 1;
|
||||
} else if ( -1 == len ) {
|
||||
assert(0); // should be impossible
|
||||
} else {
|
||||
resize( origsiz + len );
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while ( !done );
|
||||
}
|
||||
|
|
|
@ -21,10 +21,16 @@
|
|||
#define _STRWPF_H_
|
||||
|
||||
#include <string>
|
||||
#include <stdarg.h>
|
||||
|
||||
class StrWPF : public std::string {
|
||||
class StrWPF : public std::string {
|
||||
public:
|
||||
StrWPF() : m_addsiz(100){}
|
||||
|
||||
void catf( const char* fmt, ... );
|
||||
bool catf( const char* fmt, va_list ap );
|
||||
private:
|
||||
int m_addsiz;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue