Merge remote-tracking branch 'origin/master' into customnames
This commit is contained in:
commit
3373daca26
@ -80,3 +80,12 @@ This is useful if you want to compile MCServer to use on another 32-bit machine.
|
|||||||
-DFORCE_32=1
|
-DFORCE_32=1
|
||||||
|
|
||||||
to your cmake command and 32 bit will be forced.
|
to your cmake command and 32 bit will be forced.
|
||||||
|
|
||||||
|
Compiling for another computer
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
When compiling for another computer it is important to set cross compiling mode. This tells the compiler not to optimise for your machine. It can be used with debug or release mode. To enable simply add:
|
||||||
|
|
||||||
|
-DCROSSCOMPILE=1
|
||||||
|
|
||||||
|
to your cmake command.
|
||||||
|
@ -2087,6 +2087,7 @@ end
|
|||||||
QueueSetBlock = { Params = "BlockX, BlockY, BlockZ, BlockType, BlockMeta, TickDelay", Return = "", Notes = "Queues the block to be set to the specified blocktype and meta after the specified amount of game ticks. Uses SetBlock() for the actual setting, so simulators are woken up and block entities are handled correctly." },
|
QueueSetBlock = { Params = "BlockX, BlockY, BlockZ, BlockType, BlockMeta, TickDelay", Return = "", Notes = "Queues the block to be set to the specified blocktype and meta after the specified amount of game ticks. Uses SetBlock() for the actual setting, so simulators are woken up and block entities are handled correctly." },
|
||||||
QueueTask = { Params = "TaskFunction", Return = "", Notes = "Queues the specified function to be executed in the tick thread. This is the primary means of interaction with a cWorld from the WebAdmin page handlers (see {{WebWorldThreads}}). The function signature is <pre class=\"pretty-print lang-lua\">function()</pre>All return values from the function are ignored. Note that this function is actually called *after* the QueueTask() function returns." },
|
QueueTask = { Params = "TaskFunction", Return = "", Notes = "Queues the specified function to be executed in the tick thread. This is the primary means of interaction with a cWorld from the WebAdmin page handlers (see {{WebWorldThreads}}). The function signature is <pre class=\"pretty-print lang-lua\">function()</pre>All return values from the function are ignored. Note that this function is actually called *after* the QueueTask() function returns." },
|
||||||
RegenerateChunk = { Params = "ChunkX, ChunkZ", Return = "", Notes = "Queues the specified chunk to be re-generated, overwriting the current data. To queue a chunk for generating only if it doesn't exist, use the GenerateChunk() instead." },
|
RegenerateChunk = { Params = "ChunkX, ChunkZ", Return = "", Notes = "Queues the specified chunk to be re-generated, overwriting the current data. To queue a chunk for generating only if it doesn't exist, use the GenerateChunk() instead." },
|
||||||
|
ScheduleTask = { Params = "TaskFunction, Ticks", Return = "", Notes = "Queues the specified function to be executed in the tick thread after a number of ticks. This enables operations to be queued for execution in the future. The function signature is <pre class=\"pretty-print lang-lua\">function()</pre>All return values from the function are ignored." },
|
||||||
SendBlockTo = { Params = "BlockX, BlockY, BlockZ, {{cPlayer|Player}}", Return = "", Notes = "Sends the block at the specified coords to the specified player's client, as an UpdateBlock packet." },
|
SendBlockTo = { Params = "BlockX, BlockY, BlockZ, {{cPlayer|Player}}", Return = "", Notes = "Sends the block at the specified coords to the specified player's client, as an UpdateBlock packet." },
|
||||||
SetBlock = { Params = "BlockX, BlockY, BlockZ, BlockType, BlockMeta", Return = "", Notes = "Sets the block at the specified coords, replaces the block entities for the previous block type, creates a new block entity for the new block, if appropriate, and wakes up the simulators. This is the preferred way to set blocks, as opposed to FastSetBlock(), which is only to be used under special circumstances." },
|
SetBlock = { Params = "BlockX, BlockY, BlockZ, BlockType, BlockMeta", Return = "", Notes = "Sets the block at the specified coords, replaces the block entities for the previous block type, creates a new block entity for the new block, if appropriate, and wakes up the simulators. This is the preferred way to set blocks, as opposed to FastSetBlock(), which is only to be used under special circumstances." },
|
||||||
SetBlockMeta =
|
SetBlockMeta =
|
||||||
|
@ -446,12 +446,10 @@ bool cIniFile::SetValueF(const AString & a_KeyName, const AString & a_ValueName,
|
|||||||
|
|
||||||
bool cIniFile::SetValueV(const AString & a_KeyName, const AString & a_ValueName, const char * a_Format, ...)
|
bool cIniFile::SetValueV(const AString & a_KeyName, const AString & a_ValueName, const char * a_Format, ...)
|
||||||
{
|
{
|
||||||
va_list args, argsCopy;
|
va_list args;
|
||||||
va_start(args, a_Format);
|
va_start(args, a_Format);
|
||||||
va_start(argsCopy, a_Format);
|
|
||||||
AString Data;
|
AString Data;
|
||||||
AppendVPrintf(Data, a_Format, args, argsCopy);
|
AppendVPrintf(Data, a_Format, args);
|
||||||
va_end(argsCopy);
|
|
||||||
va_end(args);
|
va_end(args);
|
||||||
return SetValue(a_KeyName, a_ValueName, Data);
|
return SetValue(a_KeyName, a_ValueName, Data);
|
||||||
}
|
}
|
||||||
|
@ -22,11 +22,17 @@ endif()
|
|||||||
if (WIN32)
|
if (WIN32)
|
||||||
add_library(lua SHARED ${SOURCE})
|
add_library(lua SHARED ${SOURCE})
|
||||||
set(LIBRARY_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/MCServer)
|
set(LIBRARY_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/MCServer)
|
||||||
if (MSVC)
|
|
||||||
# MSVC generator adds a "Debug" or "Release" postfixes to the LIBRARY_OUTPUT_PATH, we need to cancel them:
|
|
||||||
SET_TARGET_PROPERTIES(lua PROPERTIES PREFIX "../")
|
|
||||||
SET_TARGET_PROPERTIES(lua PROPERTIES IMPORT_PREFIX "../")
|
|
||||||
|
|
||||||
|
# Output the executable into the $/MCServer folder, so that MCServer can find it:
|
||||||
|
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/MCServer)
|
||||||
|
SET_TARGET_PROPERTIES(${EXECUTABLE} PROPERTIES
|
||||||
|
RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_SOURCE_DIR}/MCServer
|
||||||
|
RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_SOURCE_DIR}/MCServer
|
||||||
|
RUNTIME_OUTPUT_DIRECTORY_DEBUGPROFILE ${CMAKE_SOURCE_DIR}/MCServer
|
||||||
|
RUNTIME_OUTPUT_DIRECTORY_RELEASEPROFILE ${CMAKE_SOURCE_DIR}/MCServer
|
||||||
|
)
|
||||||
|
|
||||||
|
if (MSVC)
|
||||||
# Remove SCL warnings, we expect this library to have been tested safe
|
# Remove SCL warnings, we expect this library to have been tested safe
|
||||||
SET_TARGET_PROPERTIES(
|
SET_TARGET_PROPERTIES(
|
||||||
lua PROPERTIES COMPILE_FLAGS "-D_CRT_SECURE_NO_WARNINGS"
|
lua PROPERTIES COMPILE_FLAGS "-D_CRT_SECURE_NO_WARNINGS"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
cmake_minimum_required (VERSION 2.6)
|
cmake_minimum_required (VERSION 2.8.2)
|
||||||
project (MCServer)
|
project (MCServer)
|
||||||
|
|
||||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||||
@ -88,13 +88,15 @@ set(EXECUTABLE MCServer)
|
|||||||
|
|
||||||
add_executable(${EXECUTABLE} ${SOURCE})
|
add_executable(${EXECUTABLE} ${SOURCE})
|
||||||
|
|
||||||
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/MCServer)
|
|
||||||
|
|
||||||
if (MSVC)
|
# Output the executable into the $/MCServer folder, so that it has access to external resources:
|
||||||
# MSVC generator adds a "Debug" or "Release" postfixes to the EXECUTABLE_OUTPUT_PATH, we need to cancel them:
|
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/MCServer)
|
||||||
SET_TARGET_PROPERTIES(${EXECUTABLE} PROPERTIES PREFIX "../")
|
SET_TARGET_PROPERTIES(${EXECUTABLE} PROPERTIES
|
||||||
SET_TARGET_PROPERTIES(${EXECUTABLE} PROPERTIES IMPORT_PREFIX "../")
|
RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_SOURCE_DIR}/MCServer
|
||||||
endif()
|
RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_SOURCE_DIR}/MCServer
|
||||||
|
RUNTIME_OUTPUT_DIRECTORY_DEBUGPROFILE ${CMAKE_SOURCE_DIR}/MCServer
|
||||||
|
RUNTIME_OUTPUT_DIRECTORY_RELEASEPROFILE ${CMAKE_SOURCE_DIR}/MCServer
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# Make the debug executable have a "_debug" suffix
|
# Make the debug executable have a "_debug" suffix
|
||||||
|
@ -16,11 +16,9 @@
|
|||||||
void cCommandOutputCallback::Out(const char * a_Fmt, ...)
|
void cCommandOutputCallback::Out(const char * a_Fmt, ...)
|
||||||
{
|
{
|
||||||
AString Output;
|
AString Output;
|
||||||
va_list args, argsCopy;
|
va_list args;
|
||||||
va_start(args, a_Fmt);
|
va_start(args, a_Fmt);
|
||||||
va_start(argsCopy, a_Fmt);
|
AppendVPrintf(Output, a_Fmt, args);
|
||||||
AppendVPrintf(Output, a_Fmt, args, argsCopy);
|
|
||||||
va_end(argsCopy);
|
|
||||||
va_end(args);
|
va_end(args);
|
||||||
Output.append("\n");
|
Output.append("\n");
|
||||||
Out(Output);
|
Out(Output);
|
||||||
|
10
src/Log.cpp
10
src/Log.cpp
@ -99,10 +99,10 @@ void cLog::ClearLog()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cLog::Log(const char * a_Format, va_list argList, va_list argListCopy)
|
void cLog::Log(const char * a_Format, va_list argList)
|
||||||
{
|
{
|
||||||
AString Message;
|
AString Message;
|
||||||
AppendVPrintf(Message, a_Format, argList, argListCopy);
|
AppendVPrintf(Message, a_Format, argList);
|
||||||
|
|
||||||
time_t rawtime;
|
time_t rawtime;
|
||||||
time ( &rawtime );
|
time ( &rawtime );
|
||||||
@ -149,11 +149,9 @@ void cLog::Log(const char * a_Format, va_list argList, va_list argListCopy)
|
|||||||
|
|
||||||
void cLog::Log(const char * a_Format, ...)
|
void cLog::Log(const char * a_Format, ...)
|
||||||
{
|
{
|
||||||
va_list argList, argListCopy;
|
va_list argList;
|
||||||
va_start(argList, a_Format);
|
va_start(argList, a_Format);
|
||||||
va_start(argListCopy, a_Format);
|
Log(a_Format, argList);
|
||||||
Log(a_Format, argList, argListCopy);
|
|
||||||
va_end(argListCopy);
|
|
||||||
va_end(argList);
|
va_end(argList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
cLog(const AString & a_FileName);
|
cLog(const AString & a_FileName);
|
||||||
~cLog();
|
~cLog();
|
||||||
void Log(const char * a_Format, va_list argList, va_list argListCopy);
|
void Log(const char * a_Format, va_list argList);
|
||||||
void Log(const char * a_Format, ...);
|
void Log(const char * a_Format, ...);
|
||||||
// tolua_begin
|
// tolua_begin
|
||||||
void SimpleLog(const char * a_String);
|
void SimpleLog(const char * a_String);
|
||||||
|
@ -440,11 +440,9 @@ AString cFile::ReadWholeFile(const AString & a_FileName)
|
|||||||
int cFile::Printf(const char * a_Fmt, ...)
|
int cFile::Printf(const char * a_Fmt, ...)
|
||||||
{
|
{
|
||||||
AString buf;
|
AString buf;
|
||||||
va_list args, argsCopy;
|
va_list args;
|
||||||
va_start(args, a_Fmt);
|
va_start(args, a_Fmt);
|
||||||
va_start(argsCopy, a_Fmt);
|
AppendVPrintf(buf, a_Fmt, args);
|
||||||
AppendVPrintf(buf, a_Fmt, args, argsCopy);
|
|
||||||
va_end(argsCopy);
|
|
||||||
va_end(args);
|
va_end(args);
|
||||||
return Write(buf.c_str(), buf.length());
|
return Write(buf.c_str(), buf.length());
|
||||||
}
|
}
|
||||||
|
@ -1037,11 +1037,18 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
HandlePacket(bb, PacketType);
|
if (!HandlePacket(bb, PacketType))
|
||||||
|
{
|
||||||
|
// Unknown packet, already been reported, just bail out
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (bb.GetReadableSpace() != 1)
|
if (bb.GetReadableSpace() != 1)
|
||||||
{
|
{
|
||||||
// Read more or less than packet length, report as error
|
// Read more or less than packet length, report as error
|
||||||
|
LOGWARNING("Protocol 1.7: Wrong number of bytes read for packet 0x%x. Read %u bytes, packet contained %u bytes",
|
||||||
|
PacketType, bb.GetUsedSpace() - bb.GetReadableSpace(), PacketLen
|
||||||
|
);
|
||||||
ASSERT(!"Read wrong number of bytes!");
|
ASSERT(!"Read wrong number of bytes!");
|
||||||
m_Client->PacketError(PacketType);
|
m_Client->PacketError(PacketType);
|
||||||
}
|
}
|
||||||
@ -1051,7 +1058,7 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cProtocol172::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType)
|
bool cProtocol172::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType)
|
||||||
{
|
{
|
||||||
switch (m_State)
|
switch (m_State)
|
||||||
{
|
{
|
||||||
@ -1060,8 +1067,8 @@ void cProtocol172::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType)
|
|||||||
// Status
|
// Status
|
||||||
switch (a_PacketType)
|
switch (a_PacketType)
|
||||||
{
|
{
|
||||||
case 0x00: HandlePacketStatusRequest(a_ByteBuffer); return;
|
case 0x00: HandlePacketStatusRequest(a_ByteBuffer); return true;
|
||||||
case 0x01: HandlePacketStatusPing (a_ByteBuffer); return;
|
case 0x01: HandlePacketStatusPing (a_ByteBuffer); return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1071,8 +1078,8 @@ void cProtocol172::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType)
|
|||||||
// Login
|
// Login
|
||||||
switch (a_PacketType)
|
switch (a_PacketType)
|
||||||
{
|
{
|
||||||
case 0x00: HandlePacketLoginStart (a_ByteBuffer); return;
|
case 0x00: HandlePacketLoginStart (a_ByteBuffer); return true;
|
||||||
case 0x01: HandlePacketLoginEncryptionResponse(a_ByteBuffer); return;
|
case 0x01: HandlePacketLoginEncryptionResponse(a_ByteBuffer); return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1082,29 +1089,29 @@ void cProtocol172::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType)
|
|||||||
// Game
|
// Game
|
||||||
switch (a_PacketType)
|
switch (a_PacketType)
|
||||||
{
|
{
|
||||||
case 0x00: HandlePacketKeepAlive (a_ByteBuffer); return;
|
case 0x00: HandlePacketKeepAlive (a_ByteBuffer); return true;
|
||||||
case 0x01: HandlePacketChatMessage (a_ByteBuffer); return;
|
case 0x01: HandlePacketChatMessage (a_ByteBuffer); return true;
|
||||||
case 0x02: HandlePacketUseEntity (a_ByteBuffer); return;
|
case 0x02: HandlePacketUseEntity (a_ByteBuffer); return true;
|
||||||
case 0x03: HandlePacketPlayer (a_ByteBuffer); return;
|
case 0x03: HandlePacketPlayer (a_ByteBuffer); return true;
|
||||||
case 0x04: HandlePacketPlayerPos (a_ByteBuffer); return;
|
case 0x04: HandlePacketPlayerPos (a_ByteBuffer); return true;
|
||||||
case 0x05: HandlePacketPlayerLook (a_ByteBuffer); return;
|
case 0x05: HandlePacketPlayerLook (a_ByteBuffer); return true;
|
||||||
case 0x06: HandlePacketPlayerPosLook (a_ByteBuffer); return;
|
case 0x06: HandlePacketPlayerPosLook (a_ByteBuffer); return true;
|
||||||
case 0x07: HandlePacketBlockDig (a_ByteBuffer); return;
|
case 0x07: HandlePacketBlockDig (a_ByteBuffer); return true;
|
||||||
case 0x08: HandlePacketBlockPlace (a_ByteBuffer); return;
|
case 0x08: HandlePacketBlockPlace (a_ByteBuffer); return true;
|
||||||
case 0x09: HandlePacketSlotSelect (a_ByteBuffer); return;
|
case 0x09: HandlePacketSlotSelect (a_ByteBuffer); return true;
|
||||||
case 0x0a: HandlePacketAnimation (a_ByteBuffer); return;
|
case 0x0a: HandlePacketAnimation (a_ByteBuffer); return true;
|
||||||
case 0x0b: HandlePacketEntityAction (a_ByteBuffer); return;
|
case 0x0b: HandlePacketEntityAction (a_ByteBuffer); return true;
|
||||||
case 0x0c: HandlePacketSteerVehicle (a_ByteBuffer); return;
|
case 0x0c: HandlePacketSteerVehicle (a_ByteBuffer); return true;
|
||||||
case 0x0d: HandlePacketWindowClose (a_ByteBuffer); return;
|
case 0x0d: HandlePacketWindowClose (a_ByteBuffer); return true;
|
||||||
case 0x0e: HandlePacketWindowClick (a_ByteBuffer); return;
|
case 0x0e: HandlePacketWindowClick (a_ByteBuffer); return true;
|
||||||
case 0x0f: // Confirm transaction - not used in MCS
|
case 0x0f: // Confirm transaction - not used in MCS
|
||||||
case 0x10: HandlePacketCreativeInventoryAction(a_ByteBuffer); return;
|
case 0x10: HandlePacketCreativeInventoryAction(a_ByteBuffer); return true;
|
||||||
case 0x12: HandlePacketUpdateSign (a_ByteBuffer); return;
|
case 0x12: HandlePacketUpdateSign (a_ByteBuffer); return true;
|
||||||
case 0x13: HandlePacketPlayerAbilities (a_ByteBuffer); return;
|
case 0x13: HandlePacketPlayerAbilities (a_ByteBuffer); return true;
|
||||||
case 0x14: HandlePacketTabComplete (a_ByteBuffer); return;
|
case 0x14: HandlePacketTabComplete (a_ByteBuffer); return true;
|
||||||
case 0x15: HandlePacketClientSettings (a_ByteBuffer); return;
|
case 0x15: HandlePacketClientSettings (a_ByteBuffer); return true;
|
||||||
case 0x16: HandlePacketClientStatus (a_ByteBuffer); return;
|
case 0x16: HandlePacketClientStatus (a_ByteBuffer); return true;
|
||||||
case 0x17: HandlePacketPluginMessage (a_ByteBuffer); return;
|
case 0x17: HandlePacketPluginMessage (a_ByteBuffer); return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1112,6 +1119,7 @@ void cProtocol172::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType)
|
|||||||
|
|
||||||
// Unknown packet type, report to the client:
|
// Unknown packet type, report to the client:
|
||||||
m_Client->PacketUnknown(a_PacketType);
|
m_Client->PacketUnknown(a_PacketType);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -222,8 +222,10 @@ protected:
|
|||||||
/// Adds the received (unencrypted) data to m_ReceivedData, parses complete packets
|
/// Adds the received (unencrypted) data to m_ReceivedData, parses complete packets
|
||||||
void AddReceivedData(const char * a_Data, int a_Size);
|
void AddReceivedData(const char * a_Data, int a_Size);
|
||||||
|
|
||||||
/// Reads and handles the packet. The packet length and type have already been read.
|
/** Reads and handles the packet. The packet length and type have already been read.
|
||||||
void HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType);
|
Returns true if the packet was understood, false if it was an unknown packet
|
||||||
|
*/
|
||||||
|
bool HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType);
|
||||||
|
|
||||||
// Packet handlers while in the Status state (m_State == 1):
|
// Packet handlers while in the Status state (m_State == 1):
|
||||||
void HandlePacketStatusPing (cByteBuffer & a_ByteBuffer);
|
void HandlePacketStatusPing (cByteBuffer & a_ByteBuffer);
|
||||||
|
@ -18,27 +18,40 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
AString & AppendVPrintf(AString & str, const char *format, va_list args, va_list argsCopy)
|
AString & AppendVPrintf(AString & str, const char * format, va_list args)
|
||||||
{
|
{
|
||||||
ASSERT(format != NULL);
|
ASSERT(format != NULL);
|
||||||
|
|
||||||
char buffer[2048];
|
char buffer[2048];
|
||||||
size_t len;
|
size_t len;
|
||||||
|
#ifdef va_copy
|
||||||
|
va_list argsCopy;
|
||||||
|
va_copy(argsCopy, args);
|
||||||
|
#else
|
||||||
|
#define argsCopy args
|
||||||
|
#endif
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
// MS CRT provides secure printf that doesn't behave like in the C99 standard
|
// MS CRT provides secure printf that doesn't behave like in the C99 standard
|
||||||
if ((len = _vsnprintf_s(buffer, ARRAYCOUNT(buffer), _TRUNCATE, format, args)) != -1)
|
if ((len = _vsnprintf_s(buffer, ARRAYCOUNT(buffer), _TRUNCATE, format, argsCopy)) != -1)
|
||||||
#else // _MSC_VER
|
#else // _MSC_VER
|
||||||
if ((len = vsnprintf(buffer, ARRAYCOUNT(buffer), format, args)) < ARRAYCOUNT(buffer))
|
if ((len = vsnprintf(buffer, ARRAYCOUNT(buffer), format, argsCopy)) < ARRAYCOUNT(buffer))
|
||||||
#endif // else _MSC_VER
|
#endif // else _MSC_VER
|
||||||
{
|
{
|
||||||
// The result did fit into the static buffer
|
// The result did fit into the static buffer
|
||||||
|
#ifdef va_copy
|
||||||
|
va_end(argsCopy);
|
||||||
|
#endif
|
||||||
str.append(buffer, len);
|
str.append(buffer, len);
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
#ifdef va_copy
|
||||||
|
va_end(argsCopy);
|
||||||
|
#endif
|
||||||
|
|
||||||
// The result did not fit into the static buffer
|
// The result did not fit into the static buffer, use a dynamic buffer:
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
// for MS CRT, we need to calculate the result length
|
// for MS CRT, we need to calculate the result length
|
||||||
|
// MS doesn't have va_copy() and does nod need it at all
|
||||||
len = _vscprintf(format, args);
|
len = _vscprintf(format, args);
|
||||||
if (len == -1)
|
if (len == -1)
|
||||||
{
|
{
|
||||||
@ -47,6 +60,9 @@ AString & AppendVPrintf(AString & str, const char *format, va_list args, va_list
|
|||||||
#endif // _MSC_VER
|
#endif // _MSC_VER
|
||||||
|
|
||||||
// Allocate a buffer and printf into it:
|
// Allocate a buffer and printf into it:
|
||||||
|
#ifdef va_copy
|
||||||
|
va_copy(argsCopy, args);
|
||||||
|
#endif
|
||||||
std::vector<char> Buffer(len + 1);
|
std::vector<char> Buffer(len + 1);
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
vsprintf_s((char *)&(Buffer.front()), Buffer.size(), format, argsCopy);
|
vsprintf_s((char *)&(Buffer.front()), Buffer.size(), format, argsCopy);
|
||||||
@ -54,6 +70,9 @@ AString & AppendVPrintf(AString & str, const char *format, va_list args, va_list
|
|||||||
vsnprintf((char *)&(Buffer.front()), Buffer.size(), format, argsCopy);
|
vsnprintf((char *)&(Buffer.front()), Buffer.size(), format, argsCopy);
|
||||||
#endif // else _MSC_VER
|
#endif // else _MSC_VER
|
||||||
str.append(&(Buffer.front()), Buffer.size() - 1);
|
str.append(&(Buffer.front()), Buffer.size() - 1);
|
||||||
|
#ifdef va_copy
|
||||||
|
va_end(argsCopy);
|
||||||
|
#endif
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,11 +83,9 @@ AString & AppendVPrintf(AString & str, const char *format, va_list args, va_list
|
|||||||
AString & Printf(AString & str, const char * format, ...)
|
AString & Printf(AString & str, const char * format, ...)
|
||||||
{
|
{
|
||||||
str.clear();
|
str.clear();
|
||||||
va_list args, argsCopy;
|
va_list args;
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
va_start(argsCopy, format);
|
std::string &retval = AppendVPrintf(str, format, args);
|
||||||
std::string &retval = AppendVPrintf(str, format, args, argsCopy);
|
|
||||||
va_end(argsCopy);
|
|
||||||
va_end(args);
|
va_end(args);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
@ -80,11 +97,9 @@ AString & Printf(AString & str, const char * format, ...)
|
|||||||
AString Printf(const char * format, ...)
|
AString Printf(const char * format, ...)
|
||||||
{
|
{
|
||||||
AString res;
|
AString res;
|
||||||
va_list args, argsCopy;
|
va_list args;
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
va_start(argsCopy, format);
|
AppendVPrintf(res, format, args);
|
||||||
AppendVPrintf(res, format, args, argsCopy);
|
|
||||||
va_end(argsCopy);
|
|
||||||
va_end(args);
|
va_end(args);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -93,13 +108,11 @@ AString Printf(const char * format, ...)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
AString & AppendPrintf(AString &str, const char *format, ...)
|
AString & AppendPrintf(AString &str, const char * format, ...)
|
||||||
{
|
{
|
||||||
va_list args, argsCopy;
|
va_list args;
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
va_start(argsCopy, format);
|
std::string &retval = AppendVPrintf(str, format, args);
|
||||||
std::string &retval = AppendVPrintf(str, format, args, argsCopy);
|
|
||||||
va_end(argsCopy);
|
|
||||||
va_end(args);
|
va_end(args);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -21,12 +21,8 @@ typedef std::list<AString> AStringList;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Add the formated string to the existing data in the string
|
/** Add the formated string to the existing data in the string */
|
||||||
It is silly to need to specify the arguments twice, but it is required for x64 / GCC:
|
extern AString & AppendVPrintf(AString & str, const char * format, va_list args);
|
||||||
Ref.: issue #541, http://www.bailopan.net/blog/?p=30
|
|
||||||
va_copy is not available until C++11, so we need to make do with passing a duplicate.
|
|
||||||
*/
|
|
||||||
extern AString & AppendVPrintf(AString & str, const char * format, va_list args, va_list argsCopy);
|
|
||||||
|
|
||||||
/// Output the formatted text into the string
|
/// Output the formatted text into the string
|
||||||
extern AString & Printf (AString & str, const char * format, ...);
|
extern AString & Printf (AString & str, const char * format, ...);
|
||||||
|
Loading…
Reference in New Issue
Block a user