10 Nov 2007
This commit is contained in:
parent
f5f108aa02
commit
3bb2588593
|
@ -0,0 +1,172 @@
|
|||
//=======================================================================
|
||||
// Copyright XashXT Group 2007 ©
|
||||
// crclib.c - generate crc stuff
|
||||
//=======================================================================
|
||||
|
||||
#include "launcher.h"
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
this is a 16 bit, non-reflected CRC using the polynomial 0x1021
|
||||
and the initial and final xor values shown below... in other words, the
|
||||
CCITT standard CRC used by XMODEM
|
||||
=============================================================================
|
||||
*/
|
||||
#define CRC_INIT_VALUE 0xffff
|
||||
#define CRC_XOR_VALUE 0x0000
|
||||
|
||||
static word crctable[256] =
|
||||
{
|
||||
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
|
||||
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
|
||||
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
|
||||
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
|
||||
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
|
||||
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
|
||||
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
|
||||
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
|
||||
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
|
||||
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
|
||||
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
|
||||
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
|
||||
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
|
||||
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
|
||||
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
|
||||
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
|
||||
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
|
||||
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
|
||||
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
|
||||
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
|
||||
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
|
||||
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
|
||||
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
|
||||
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
|
||||
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
|
||||
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
|
||||
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
|
||||
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
|
||||
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
|
||||
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
|
||||
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
|
||||
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
|
||||
};
|
||||
|
||||
static byte chktbl[1024] =
|
||||
{
|
||||
0x84, 0x47, 0x51, 0xc1, 0x93, 0x22, 0x21, 0x24, 0x2f, 0x66, 0x60, 0x4d, 0xb0, 0x7c, 0xda,
|
||||
0x88, 0x54, 0x15, 0x2b, 0xc6, 0x6c, 0x89, 0xc5, 0x9d, 0x48, 0xee, 0xe6, 0x8a, 0xb5, 0xf4,
|
||||
0xcb, 0xfb, 0xf1, 0x0c, 0x2e, 0xa0, 0xd7, 0xc9, 0x1f, 0xd6, 0x06, 0x9a, 0x09, 0x41, 0x54,
|
||||
0x67, 0x46, 0xc7, 0x74, 0xe3, 0xc8, 0xb6, 0x5d, 0xa6, 0x36, 0xc4, 0xab, 0x2c, 0x7e, 0x85,
|
||||
0xa8, 0xa4, 0xa6, 0x4d, 0x96, 0x19, 0x19, 0x9a, 0xcc, 0xd8, 0xac, 0x39, 0x5e, 0x3c, 0xf2,
|
||||
0xf5, 0x5a, 0x72, 0xe5, 0xa9, 0xd1, 0xb3, 0x23, 0x82, 0x6f, 0x29, 0xcb, 0xd1, 0xcc, 0x71,
|
||||
0xfb, 0xea, 0x92, 0xeb, 0x1c, 0xca, 0x4c, 0x70, 0xfe, 0x4d, 0xc9, 0x67, 0x43, 0x47, 0x94,
|
||||
0xb9, 0x47, 0xbc, 0x3f, 0x01, 0xab, 0x7b, 0xa6, 0xe2, 0x76, 0xef, 0x5a, 0x7a, 0x29, 0x0b,
|
||||
0x51, 0x54, 0x67, 0xd8, 0x1c, 0x14, 0x3e, 0x29, 0xec, 0xe9, 0x2d, 0x48, 0x67, 0xff, 0xed,
|
||||
0x54, 0x4f, 0x48, 0xc0, 0xaa, 0x61, 0xf7, 0x78, 0x12, 0x03, 0x7a, 0x9e, 0x8b, 0xcf, 0x83,
|
||||
0x7b, 0xae, 0xca, 0x7b, 0xd9, 0xe9, 0x53, 0x2a, 0xeb, 0xd2, 0xd8, 0xcd, 0xa3, 0x10, 0x25,
|
||||
0x78, 0x5a, 0xb5, 0x23, 0x06, 0x93, 0xb7, 0x84, 0xd2, 0xbd, 0x96, 0x75, 0xa5, 0x5e, 0xcf,
|
||||
0x4e, 0xe9, 0x50, 0xa1, 0xe6, 0x9d, 0xb1, 0xe3, 0x85, 0x66, 0x28, 0x4e, 0x43, 0xdc, 0x6e,
|
||||
0xbb, 0x33, 0x9e, 0xf3, 0x0d, 0x00, 0xc1, 0xcf, 0x67, 0x34, 0x06, 0x7c, 0x71, 0xe3, 0x63,
|
||||
0xb7, 0xb7, 0xdf, 0x92, 0xc4, 0xc2, 0x25, 0x5c, 0xff, 0xc3, 0x6e, 0xfc, 0xaa, 0x1e, 0x2a,
|
||||
0x48, 0x11, 0x1c, 0x36, 0x68, 0x78, 0x86, 0x79, 0x30, 0xc3, 0xd6, 0xde, 0xbc, 0x3a, 0x2a,
|
||||
0x6d, 0x1e, 0x46, 0xdd, 0xe0, 0x80, 0x1e, 0x44, 0x3b, 0x6f, 0xaf, 0x31, 0xda, 0xa2, 0xbd,
|
||||
0x77, 0x06, 0x56, 0xc0, 0xb7, 0x92, 0x4b, 0x37, 0xc0, 0xfc, 0xc2, 0xd5, 0xfb, 0xa8, 0xda,
|
||||
0xf5, 0x57, 0xa8, 0x18, 0xc0, 0xdf, 0xe7, 0xaa, 0x2a, 0xe0, 0x7c, 0x6f, 0x77, 0xb1, 0x26,
|
||||
0xba, 0xf9, 0x2e, 0x1d, 0x16, 0xcb, 0xb8, 0xa2, 0x44, 0xd5, 0x2f, 0x1a, 0x79, 0x74, 0x87,
|
||||
0x4b, 0x00, 0xc9, 0x4a, 0x3a, 0x65, 0x8f, 0xe6, 0x5d, 0xe5, 0x0a, 0x77, 0xd8, 0x1a, 0x14,
|
||||
0x41, 0x75, 0xb1, 0xe2, 0x50, 0x2c, 0x93, 0x38, 0x2b, 0x6d, 0xf3, 0xf6, 0xdb, 0x1f, 0xcd,
|
||||
0xff, 0x14, 0x70, 0xe7, 0x16, 0xe8, 0x3d, 0xf0, 0xe3, 0xbc, 0x5e, 0xb6, 0x3f, 0xcc, 0x81,
|
||||
0x24, 0x67, 0xf3, 0x97, 0x3b, 0xfe, 0x3a, 0x96, 0x85, 0xdf, 0xe4, 0x6e, 0x3c, 0x85, 0x05,
|
||||
0x0e, 0xa3, 0x2b, 0x07, 0xc8, 0xbf, 0xe5, 0x13, 0x82, 0x62, 0x08, 0x61, 0x69, 0x4b, 0x47,
|
||||
0x62, 0x73, 0x44, 0x64, 0x8e, 0xe2, 0x91, 0xa6, 0x9a, 0xb7, 0xe9, 0x04, 0xb6, 0x54, 0x0c,
|
||||
0xc5, 0xa9, 0x47, 0xa6, 0xc9, 0x08, 0xfe, 0x4e, 0xa6, 0xcc, 0x8a, 0x5b, 0x90, 0x6f, 0x2b,
|
||||
0x3f, 0xb6, 0x0a, 0x96, 0xc0, 0x78, 0x58, 0x3c, 0x76, 0x6d, 0x94, 0x1a, 0xe4, 0x4e, 0xb8,
|
||||
0x38, 0xbb, 0xf5, 0xeb, 0x29, 0xd8, 0xb0, 0xf3, 0x15, 0x1e, 0x99, 0x96, 0x3c, 0x5d, 0x63,
|
||||
0xd5, 0xb1, 0xad, 0x52, 0xb8, 0x55, 0x70, 0x75, 0x3e, 0x1a, 0xd5, 0xda, 0xf6, 0x7a, 0x48,
|
||||
0x7d, 0x44, 0x41, 0xf9, 0x11, 0xce, 0xd7, 0xca, 0xa5, 0x3d, 0x7a, 0x79, 0x7e, 0x7d, 0x25,
|
||||
0x1b, 0x77, 0xbc, 0xf7, 0xc7, 0x0f, 0x84, 0x95, 0x10, 0x92, 0x67, 0x15, 0x11, 0x5a, 0x5e,
|
||||
0x41, 0x66, 0x0f, 0x38, 0x03, 0xb2, 0xf1, 0x5d, 0xf8, 0xab, 0xc0, 0x02, 0x76, 0x84, 0x28,
|
||||
0xf4, 0x9d, 0x56, 0x46, 0x60, 0x20, 0xdb, 0x68, 0xa7, 0xbb, 0xee, 0xac, 0x15, 0x01, 0x2f,
|
||||
0x20, 0x09, 0xdb, 0xc0, 0x16, 0xa1, 0x89, 0xf9, 0x94, 0x59, 0x00, 0xc1, 0x76, 0xbf, 0xc1,
|
||||
0x4d, 0x5d, 0x2d, 0xa9, 0x85, 0x2c, 0xd6, 0xd3, 0x14, 0xcc, 0x02, 0xc3, 0xc2, 0xfa, 0x6b,
|
||||
0xb7, 0xa6, 0xef, 0xdd, 0x12, 0x26, 0xa4, 0x63, 0xe3, 0x62, 0xbd, 0x56, 0x8a, 0x52, 0x2b,
|
||||
0xb9, 0xdf, 0x09, 0xbc, 0x0e, 0x97, 0xa9, 0xb0, 0x82, 0x46, 0x08, 0xd5, 0x1a, 0x8e, 0x1b,
|
||||
0xa7, 0x90, 0x98, 0xb9, 0xbb, 0x3c, 0x17, 0x9a, 0xf2, 0x82, 0xba, 0x64, 0x0a, 0x7f, 0xca,
|
||||
0x5a, 0x8c, 0x7c, 0xd3, 0x79, 0x09, 0x5b, 0x26, 0xbb, 0xbd, 0x25, 0xdf, 0x3d, 0x6f, 0x9a,
|
||||
0x8f, 0xee, 0x21, 0x66, 0xb0, 0x8d, 0x84, 0x4c, 0x91, 0x45, 0xd4, 0x77, 0x4f, 0xb3, 0x8c,
|
||||
0xbc, 0xa8, 0x99, 0xaa, 0x19, 0x53, 0x7c, 0x02, 0x87, 0xbb, 0x0b, 0x7c, 0x1a, 0x2d, 0xdf,
|
||||
0x48, 0x44, 0x06, 0xd6, 0x7d, 0x0c, 0x2d, 0x35, 0x76, 0xae, 0xc4, 0x5f, 0x71, 0x85, 0x97,
|
||||
0xc4, 0x3d, 0xef, 0x52, 0xbe, 0x00, 0xe4, 0xcd, 0x49, 0xd1, 0xd1, 0x1c, 0x3c, 0xd0, 0x1c,
|
||||
0x42, 0xaf, 0xd4, 0xbd, 0x58, 0x34, 0x07, 0x32, 0xee, 0xb9, 0xb5, 0xea, 0xff, 0xd7, 0x8c,
|
||||
0x0d, 0x2e, 0x2f, 0xaf, 0x87, 0xbb, 0xe6, 0x52, 0x71, 0x22, 0xf5, 0x25, 0x17, 0xa1, 0x82,
|
||||
0x04, 0xc2, 0x4a, 0xbd, 0x57, 0xc6, 0xab, 0xc8, 0x35, 0x0c, 0x3c, 0xd9, 0xc2, 0x43, 0xdb,
|
||||
0x27, 0x92, 0xcf, 0xb8, 0x25, 0x60, 0xfa, 0x21, 0x3b, 0x04, 0x52, 0xc8, 0x96, 0xba, 0x74,
|
||||
0xe3, 0x67, 0x3e, 0x8e, 0x8d, 0x61, 0x90, 0x92, 0x59, 0xb6, 0x1a, 0x1c, 0x5e, 0x21, 0xc1,
|
||||
0x65, 0xe5, 0xa6, 0x34, 0x05, 0x6f, 0xc5, 0x60, 0xb1, 0x83, 0xc1, 0xd5, 0xd5, 0xed, 0xd9,
|
||||
0xc7, 0x11, 0x7b, 0x49, 0x7a, 0xf9, 0xf9, 0x84, 0x47, 0x9b, 0xe2, 0xa5, 0x82, 0xe0, 0xc2,
|
||||
0x88, 0xd0, 0xb2, 0x58, 0x88, 0x7f, 0x45, 0x09, 0x67, 0x74, 0x61, 0xbf, 0xe6, 0x40, 0xe2,
|
||||
0x9d, 0xc2, 0x47, 0x05, 0x89, 0xed, 0xcb, 0xbb, 0xb7, 0x27, 0xe7, 0xdc, 0x7a, 0xfd, 0xbf,
|
||||
0xa8, 0xd0, 0xaa, 0x10, 0x39, 0x3c, 0x20, 0xf0, 0xd3, 0x6e, 0xb1, 0x72, 0xf8, 0xe6, 0x0f,
|
||||
0xef, 0x37, 0xe5, 0x09, 0x33, 0x5a, 0x83, 0x43, 0x80, 0x4f, 0x65, 0x2f, 0x7c, 0x8c, 0x6a,
|
||||
0xa0, 0x82, 0x0c, 0xd4, 0xd4, 0xfa, 0x81, 0x60, 0x3d, 0xdf, 0x06, 0xf1, 0x5f, 0x08, 0x0d,
|
||||
0x6d, 0x43, 0xf2, 0xe3, 0x11, 0x7d, 0x80, 0x32, 0xc5, 0xfb, 0xc5, 0xd9, 0x27, 0xec, 0xc6,
|
||||
0x4e, 0x65, 0x27, 0x76, 0x87, 0xa6, 0xee, 0xee, 0xd7, 0x8b, 0xd1, 0xa0, 0x5c, 0xb0, 0x42,
|
||||
0x13, 0x0e, 0x95, 0x4a, 0xf2, 0x06, 0xc6, 0x43, 0x33, 0xf4, 0xc7, 0xf8, 0xe7, 0x1f, 0xdd,
|
||||
0xe4, 0x46, 0x4a, 0x70, 0x39, 0x6c, 0xd0, 0xed, 0xca, 0xbe, 0x60, 0x3b, 0xd1, 0x7b, 0x57,
|
||||
0x48, 0xe5, 0x3a, 0x79, 0xc1, 0x69, 0x33, 0x53, 0x1b, 0x80, 0xb8, 0x91, 0x7d, 0xb4, 0xf6,
|
||||
0x17, 0x1a, 0x1d, 0x5a, 0x32, 0xd6, 0xcc, 0x71, 0x29, 0x3f, 0x28, 0xbb, 0xf3, 0x5e, 0x71,
|
||||
0xb8, 0x43, 0xaf, 0xf8, 0xb9, 0x64, 0xef, 0xc4, 0xa5, 0x6c, 0x08, 0x53, 0xc7, 0x00, 0x10,
|
||||
0x39, 0x4f, 0xdd, 0xe4, 0xb6, 0x19, 0x27, 0xfb, 0xb8, 0xf5, 0x32, 0x73, 0xe5, 0xcb, 0x32
|
||||
};
|
||||
|
||||
void CRC_Init(word *crcvalue)
|
||||
{
|
||||
*crcvalue = CRC_INIT_VALUE;
|
||||
}
|
||||
|
||||
void CRC_ProcessByte(word *crcvalue, byte data)
|
||||
{
|
||||
*crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
|
||||
}
|
||||
|
||||
word CRC_Block (byte *start, int count)
|
||||
{
|
||||
word crc;
|
||||
|
||||
CRC_Init (&crc);
|
||||
while(count--) CRC_ProcessByte( &crc, *start++ );
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CRC_BlockSequence
|
||||
|
||||
For proxy protecting
|
||||
====================
|
||||
*/
|
||||
byte CRC_BlockSequence(byte *base, int length, int sequence)
|
||||
{
|
||||
int n, x;
|
||||
word crc;
|
||||
byte *p, chkb[60 + 4];
|
||||
|
||||
if (sequence < 0) sequence = abs(sequence);
|
||||
p = chktbl + (sequence % (sizeof(chktbl) - 4));
|
||||
|
||||
if (length > 60) length = 60;
|
||||
memcpy(chkb, base, length);
|
||||
|
||||
chkb[length] = p[0];
|
||||
chkb[length + 1] = p[1];
|
||||
chkb[length + 2] = p[2];
|
||||
chkb[length + 3] = p[3];
|
||||
length += 4;
|
||||
|
||||
crc = CRC_Block(chkb, length);
|
||||
for (x = 0, n = 0; n < length; n++) x += chkb[n];
|
||||
crc = (crc ^ x) & 0xff;
|
||||
|
||||
return crc;
|
||||
}
|
|
@ -0,0 +1,393 @@
|
|||
//=======================================================================
|
||||
// Copyright XashXT Group 2007 ©
|
||||
// memory.c - zone memory allocation from DarkPlaces
|
||||
//=======================================================================
|
||||
|
||||
#include "launcher.h"
|
||||
|
||||
#define MEMCLUMPSIZE (65536 - 1536) // give malloc padding so we can't waste most of a page at the end
|
||||
#define MEMUNIT 8 // smallest unit we care about is this many bytes
|
||||
#define MEMBITS (MEMCLUMPSIZE / MEMUNIT)
|
||||
#define MEMBITINTS (MEMBITS / 32)
|
||||
|
||||
#define MEMCLUMP_SENTINEL 0xABADCAFE
|
||||
#define MEMHEADER_SENTINEL1 0xDEADF00D
|
||||
#define MEMHEADER_SENTINEL2 0xDF
|
||||
|
||||
typedef struct memheader_s
|
||||
{
|
||||
struct memheader_s *next; // next and previous memheaders in chain belonging to pool
|
||||
struct memheader_s *prev;
|
||||
struct mempool_s *pool; // pool this memheader belongs to
|
||||
struct memclump_s *clump; // clump this memheader lives in, NULL if not in a clump
|
||||
size_t size; // size of the memory after the header (excluding header and sentinel2)
|
||||
const char *filename; // file name and line where Mem_Alloc was called
|
||||
uint fileline;
|
||||
uint sentinel1; // should always be MEMHEADER_SENTINEL1
|
||||
|
||||
// immediately followed by data, which is followed by a MEMHEADER_SENTINEL2 byte
|
||||
}
|
||||
memheader_t;
|
||||
|
||||
typedef struct memclump_s
|
||||
{
|
||||
byte block[MEMCLUMPSIZE];// contents of the clump
|
||||
uint sentinel1; // should always be MEMCLUMP_SENTINEL
|
||||
int bits[MEMBITINTS]; // if a bit is on, it means that the MEMUNIT bytes it represents are allocated, otherwise free
|
||||
uint sentinel2; // should always be MEMCLUMP_SENTINEL
|
||||
size_t blocksinuse; // if this drops to 0, the clump is freed
|
||||
size_t largestavailable; // largest block of memory available
|
||||
struct memclump_s *chain; // next clump in the chain
|
||||
}
|
||||
memclump_t;
|
||||
|
||||
typedef struct mempool_s
|
||||
{
|
||||
uint sentinel1; // should always be MEMHEADER_SENTINEL1
|
||||
struct memheader_s *chain; // chain of individual memory allocations
|
||||
struct memclump_s *clumpchain; // chain of clumps (if any)
|
||||
size_t totalsize; // total memory allocated in this pool (inside memheaders)
|
||||
size_t realsize; // total memory allocated in this pool (actual malloc total)
|
||||
size_t lastchecksize; // updated each time the pool is displayed by memlist
|
||||
struct mempool_s *next; // linked into global mempool list
|
||||
const char *filename; // file name and line where Mem_AllocPool was called
|
||||
int fileline;
|
||||
char name[MAX_QPATH]; // name of the pool
|
||||
uint sentinel2; // should always be MEMHEADER_SENTINEL1
|
||||
}
|
||||
mempool_t;
|
||||
|
||||
mempool_t *poolchain = NULL;
|
||||
|
||||
void _mem_copy(void *dest, void *src, size_t size, const char *filename, int fileline)
|
||||
{
|
||||
if (src == NULL || size <= 0) return; // nothing to copy
|
||||
if (dest == NULL) Sys_Error("Mem_Copy: dest == NULL (called at %s:%i)", filename, fileline);
|
||||
|
||||
// copy block
|
||||
memcpy( dest, src, size );
|
||||
}
|
||||
|
||||
void _mem_set(void *dest, int set, size_t size, const char *filename, int fileline)
|
||||
{
|
||||
if(size <= 0) return; // nothing to set
|
||||
if(dest == NULL) Sys_Error("Mem_Set: dest == NULL (called at %s:%i)", filename, fileline);
|
||||
|
||||
// fill block
|
||||
memset( dest, set, size );
|
||||
}
|
||||
|
||||
void *_mem_alloc(byte *poolptr, size_t size, const char *filename, int fileline)
|
||||
{
|
||||
int i, j, k, needed, endbit, largest;
|
||||
memclump_t *clump, **clumpchainpointer;
|
||||
memheader_t *mem;
|
||||
mempool_t *pool = (mempool_t *)((byte *)poolptr);
|
||||
if (size <= 0) return NULL;
|
||||
|
||||
if (poolptr == NULL) Sys_Error("Mem_Alloc: pool == NULL (alloc at %s:%i)", filename, fileline);
|
||||
pool->totalsize += size;
|
||||
|
||||
if (size < 4096)
|
||||
{
|
||||
// clumping
|
||||
needed = (sizeof(memheader_t) + size + sizeof(int) + (MEMUNIT - 1)) / MEMUNIT;
|
||||
endbit = MEMBITS - needed;
|
||||
for (clumpchainpointer = &pool->clumpchain;*clumpchainpointer;clumpchainpointer = &(*clumpchainpointer)->chain)
|
||||
{
|
||||
clump = *clumpchainpointer;
|
||||
if (clump->sentinel1 != MEMCLUMP_SENTINEL)
|
||||
Sys_Error("Mem_Alloc: trashed clump sentinel 1 (alloc at %s:%d)", filename, fileline);
|
||||
if (clump->sentinel2 != MEMCLUMP_SENTINEL)
|
||||
Sys_Error("Mem_Alloc: trashed clump sentinel 2 (alloc at %s:%d)", filename, fileline);
|
||||
if (clump->largestavailable >= needed)
|
||||
{
|
||||
largest = 0;
|
||||
for (i = 0;i < endbit;i++)
|
||||
{
|
||||
if (clump->bits[i >> 5] & (1 << (i & 31)))
|
||||
continue;
|
||||
k = i + needed;
|
||||
for (j = i;i < k;i++)
|
||||
if (clump->bits[i >> 5] & (1 << (i & 31)))
|
||||
goto loopcontinue;
|
||||
goto choseclump;
|
||||
loopcontinue:;
|
||||
if (largest < j - i)
|
||||
largest = j - i;
|
||||
}
|
||||
// since clump falsely advertised enough space (nothing wrong
|
||||
// with that), update largest count to avoid wasting time in
|
||||
// later allocations
|
||||
clump->largestavailable = largest;
|
||||
}
|
||||
}
|
||||
pool->realsize += sizeof(memclump_t);
|
||||
clump = malloc(sizeof(memclump_t));
|
||||
if (clump == NULL) Sys_Error("Mem_Alloc: out of memory (alloc at %s:%i)", filename, fileline);
|
||||
memset(clump, 0, sizeof(memclump_t));
|
||||
*clumpchainpointer = clump;
|
||||
clump->sentinel1 = MEMCLUMP_SENTINEL;
|
||||
clump->sentinel2 = MEMCLUMP_SENTINEL;
|
||||
clump->chain = NULL;
|
||||
clump->blocksinuse = 0;
|
||||
clump->largestavailable = MEMBITS - needed;
|
||||
j = 0;
|
||||
choseclump:
|
||||
mem = (memheader_t *)((byte *) clump->block + j * MEMUNIT);
|
||||
mem->clump = clump;
|
||||
clump->blocksinuse += needed;
|
||||
for (i = j + needed;j < i;j++) clump->bits[j >> 5] |= (1 << (j & 31));
|
||||
}
|
||||
else
|
||||
{
|
||||
// big allocations are not clumped
|
||||
pool->realsize += sizeof(memheader_t) + size + sizeof(int);
|
||||
mem = (memheader_t *)malloc(sizeof(memheader_t) + size + sizeof(int));
|
||||
if (mem == NULL) Sys_Error("Mem_Alloc: out of memory (alloc at %s:%i)", filename, fileline);
|
||||
mem->clump = NULL;
|
||||
}
|
||||
|
||||
mem->filename = filename;
|
||||
mem->fileline = fileline;
|
||||
mem->size = size;
|
||||
mem->pool = pool;
|
||||
mem->sentinel1 = MEMHEADER_SENTINEL1;
|
||||
// we have to use only a single byte for this sentinel, because it may not be aligned
|
||||
// and some platforms can't use unaligned accesses
|
||||
*((byte *) mem + sizeof(memheader_t) + mem->size) = MEMHEADER_SENTINEL2;
|
||||
// append to head of list
|
||||
mem->next = pool->chain;
|
||||
mem->prev = NULL;
|
||||
pool->chain = mem;
|
||||
if (mem->next) mem->next->prev = mem;
|
||||
memset((void *)((byte *) mem + sizeof(memheader_t)), 0, mem->size);
|
||||
return (void *)((byte *) mem + sizeof(memheader_t));
|
||||
}
|
||||
|
||||
static void _mem_freeblock(memheader_t *mem, const char *filename, int fileline)
|
||||
{
|
||||
int i, firstblock, endblock;
|
||||
memclump_t *clump, **clumpchainpointer;
|
||||
mempool_t *pool;
|
||||
|
||||
if (mem->sentinel1 != MEMHEADER_SENTINEL1) Sys_Error("Mem_Free: trashed header sentinel 1 (alloc at %s:%i, free at %s:%i)", mem->filename, mem->fileline, filename, fileline);
|
||||
if (*((byte *) mem + sizeof(memheader_t) + mem->size) != MEMHEADER_SENTINEL2)
|
||||
Sys_Error("Mem_Free: trashed header sentinel 2 (alloc at %s:%i, free at %s:%i)", mem->filename, mem->fileline, filename, fileline);
|
||||
pool = mem->pool;
|
||||
// unlink memheader from doubly linked list
|
||||
if ((mem->prev ? mem->prev->next != mem : pool->chain != mem) || (mem->next && mem->next->prev != mem))
|
||||
Sys_Error("Mem_Free: not allocated or double freed (free at %s:%i)", filename, fileline);
|
||||
if (mem->prev) mem->prev->next = mem->next;
|
||||
else pool->chain = mem->next;
|
||||
if (mem->next) mem->next->prev = mem->prev;
|
||||
// memheader has been unlinked, do the actual free now
|
||||
pool->totalsize -= mem->size;
|
||||
|
||||
if ((clump = mem->clump))
|
||||
{
|
||||
if (clump->sentinel1 != MEMCLUMP_SENTINEL)
|
||||
Sys_Error("Mem_Free: trashed clump sentinel 1 (free at %s:%i)", filename, fileline);
|
||||
if (clump->sentinel2 != MEMCLUMP_SENTINEL)
|
||||
Sys_Error("Mem_Free: trashed clump sentinel 2 (free at %s:%i)", filename, fileline);
|
||||
firstblock = ((byte *) mem - (byte *) clump->block);
|
||||
if (firstblock & (MEMUNIT - 1))
|
||||
Sys_Error("Mem_Free: address not valid in clump (free at %s:%i)", filename, fileline);
|
||||
firstblock /= MEMUNIT;
|
||||
endblock = firstblock + ((sizeof(memheader_t) + mem->size + sizeof(int) + (MEMUNIT - 1)) / MEMUNIT);
|
||||
clump->blocksinuse -= endblock - firstblock;
|
||||
// could use &, but we know the bit is set
|
||||
for (i = firstblock;i < endblock;i++)
|
||||
clump->bits[i >> 5] -= (1 << (i & 31));
|
||||
if (clump->blocksinuse <= 0)
|
||||
{
|
||||
// unlink from chain
|
||||
for (clumpchainpointer = &pool->clumpchain;*clumpchainpointer;clumpchainpointer = &(*clumpchainpointer)->chain)
|
||||
{
|
||||
if (*clumpchainpointer == clump)
|
||||
{
|
||||
*clumpchainpointer = clump->chain;
|
||||
break;
|
||||
}
|
||||
}
|
||||
pool->realsize -= sizeof(memclump_t);
|
||||
memset(clump, 0xBF, sizeof(memclump_t));
|
||||
free(clump);
|
||||
}
|
||||
else
|
||||
{
|
||||
// clump still has some allocations
|
||||
// force re-check of largest available space on next alloc
|
||||
clump->largestavailable = MEMBITS - clump->blocksinuse;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pool->realsize -= sizeof(memheader_t) + mem->size + sizeof(int);
|
||||
free(mem);
|
||||
}
|
||||
}
|
||||
|
||||
void _mem_free(void *data, const char *filename, int fileline)
|
||||
{
|
||||
if (data == NULL) Sys_Error("Mem_Free: data == NULL (called at %s:%i)", filename, fileline);
|
||||
_mem_freeblock((memheader_t *)((byte *) data - sizeof(memheader_t)), filename, fileline);
|
||||
}
|
||||
|
||||
void *_mem_realloc(byte *poolptr, void *memptr, size_t size, const char *filename, int fileline)
|
||||
{
|
||||
char *nb;
|
||||
memheader_t *memhdr;
|
||||
|
||||
if (size <= 0) return memptr; // no need to reallocate
|
||||
nb = _mem_alloc(poolptr, size, filename, fileline);
|
||||
|
||||
if( memptr ) // first allocate?
|
||||
{
|
||||
// get size of old block
|
||||
memhdr = (memheader_t *)((byte *)memptr - sizeof(memheader_t));
|
||||
_mem_copy( nb, memptr, memhdr->size, filename, fileline );
|
||||
_mem_free( memptr, filename, fileline); // free unused old block
|
||||
}
|
||||
|
||||
return (void *)nb;
|
||||
}
|
||||
|
||||
void _mem_move(byte *poolptr, void **dest, void *src, size_t size, const char *filename, int fileline)
|
||||
{
|
||||
memheader_t *mem;
|
||||
void *memptr = *dest;
|
||||
|
||||
if(!memptr) Sys_Error("Mem_Move: dest == NULL (called at %s:%i)", filename, fileline);
|
||||
if(!src) Sys_Error("Mem_Move: src == NULL (called at %s:%i)", filename, fileline);
|
||||
|
||||
if (size <= 0)
|
||||
{
|
||||
// just free memory
|
||||
_mem_free( memptr, filename, fileline );
|
||||
*dest = src; // swap blocks
|
||||
return;
|
||||
}
|
||||
|
||||
mem = (memheader_t *)((byte *) memptr - sizeof(memheader_t)); // get size of old block
|
||||
if(mem->size != size)
|
||||
{
|
||||
_mem_free( memptr, filename, fileline ); // release old buffer
|
||||
memptr = _mem_alloc( poolptr, size, filename, fileline ); // alloc new size
|
||||
}
|
||||
else _mem_set( memptr, 0, size, filename, fileline ); // no need to reallocate buffer
|
||||
|
||||
_mem_copy( memptr, src, size, filename, fileline ); // move memory...
|
||||
_mem_free( src, filename, fileline ); // ...and free old pointer
|
||||
|
||||
*dest = memptr;
|
||||
}
|
||||
|
||||
byte *_mem_allocpool(const char *name, const char *filename, int fileline)
|
||||
{
|
||||
mempool_t *pool;
|
||||
pool = (mempool_t *)malloc(sizeof(mempool_t));
|
||||
if (pool == NULL) Sys_Error("Mem_AllocPool: out of memory (allocpool at %s:%i)", filename, fileline);
|
||||
_mem_set(pool, 0, sizeof(mempool_t), filename, fileline );
|
||||
|
||||
// fill header
|
||||
pool->sentinel1 = MEMHEADER_SENTINEL1;
|
||||
pool->sentinel2 = MEMHEADER_SENTINEL1;
|
||||
pool->filename = filename;
|
||||
pool->fileline = fileline;
|
||||
pool->chain = NULL;
|
||||
pool->totalsize = 0;
|
||||
pool->realsize = sizeof(mempool_t);
|
||||
strlcpy (pool->name, name, sizeof (pool->name));
|
||||
pool->next = poolchain;
|
||||
poolchain = pool;
|
||||
return (byte *)((mempool_t *)pool);
|
||||
}
|
||||
|
||||
void _mem_freepool(byte **poolptr, const char *filename, int fileline)
|
||||
{
|
||||
mempool_t *pool = (mempool_t *)((byte *) *poolptr);
|
||||
mempool_t **chainaddress;
|
||||
|
||||
if (pool)
|
||||
{
|
||||
// unlink pool from chain
|
||||
for (chainaddress = &poolchain;*chainaddress && *chainaddress != pool;chainaddress = &((*chainaddress)->next));
|
||||
if (*chainaddress != pool) Sys_Error("Mem_FreePool: pool already free (freepool at %s:%i)", filename, fileline);
|
||||
if (pool->sentinel1 != MEMHEADER_SENTINEL1) Sys_Error("Mem_FreePool: trashed pool sentinel 1 (allocpool at %s:%i, freepool at %s:%i)", pool->filename, pool->fileline, filename, fileline);
|
||||
if (pool->sentinel2 != MEMHEADER_SENTINEL1) Sys_Error("Mem_FreePool: trashed pool sentinel 2 (allocpool at %s:%i, freepool at %s:%i)", pool->filename, pool->fileline, filename, fileline);
|
||||
*chainaddress = pool->next;
|
||||
|
||||
// free memory owned by the pool
|
||||
while (pool->chain) _mem_freeblock(pool->chain, filename, fileline);
|
||||
// free the pool itself
|
||||
_mem_set(pool, 0xBF, sizeof(mempool_t), filename, fileline);
|
||||
free(pool);
|
||||
*poolptr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void _mem_emptypool(byte *poolptr, const char *filename, int fileline)
|
||||
{
|
||||
mempool_t *pool = (mempool_t *)((byte *)poolptr);
|
||||
if (poolptr == NULL) Sys_Error("Mem_EmptyPool: pool == NULL (emptypool at %s:%i)", filename, fileline);
|
||||
|
||||
if (pool->sentinel1 != MEMHEADER_SENTINEL1) Sys_Error("Mem_EmptyPool: trashed pool sentinel 1 (allocpool at %s:%i, emptypool at %s:%i)", pool->filename, pool->fileline, filename, fileline);
|
||||
if (pool->sentinel2 != MEMHEADER_SENTINEL1) Sys_Error("Mem_EmptyPool: trashed pool sentinel 2 (allocpool at %s:%i, emptypool at %s:%i)", pool->filename, pool->fileline, filename, fileline);
|
||||
|
||||
// free memory owned by the pool
|
||||
while (pool->chain) _mem_freeblock(pool->chain, filename, fileline);
|
||||
}
|
||||
|
||||
void _mem_checkheadersentinels(void *data, const char *filename, int fileline)
|
||||
{
|
||||
memheader_t *mem;
|
||||
|
||||
if (data == NULL) Sys_Error("Mem_CheckSentinels: data == NULL (sentinel check at %s:%i)", filename, fileline);
|
||||
mem = (memheader_t *)((byte *) data - sizeof(memheader_t));
|
||||
if (mem->sentinel1 != MEMHEADER_SENTINEL1)
|
||||
Sys_Error("Mem_CheckSentinels: trashed header sentinel 1 (block allocated at %s:%i, sentinel check at %s:%i)", mem->filename, mem->fileline, filename, fileline);
|
||||
if (*((byte *) mem + sizeof(memheader_t) + mem->size) != MEMHEADER_SENTINEL2)
|
||||
Sys_Error("Mem_CheckSentinels: trashed header sentinel 2 (block allocated at %s:%i, sentinel check at %s:%i)", mem->filename, mem->fileline, filename, fileline);
|
||||
}
|
||||
|
||||
static void _mem_checkclumpsentinels(memclump_t *clump, const char *filename, int fileline)
|
||||
{
|
||||
// this isn't really very useful
|
||||
if (clump->sentinel1 != MEMCLUMP_SENTINEL)
|
||||
Sys_Error("Mem_CheckClumpSentinels: trashed sentinel 1 (sentinel check at %s:%i)", filename, fileline);
|
||||
if (clump->sentinel2 != MEMCLUMP_SENTINEL)
|
||||
Sys_Error("Mem_CheckClumpSentinels: trashed sentinel 2 (sentinel check at %s:%i)", filename, fileline);
|
||||
}
|
||||
|
||||
void _mem_check(const char *filename, int fileline)
|
||||
{
|
||||
memheader_t *mem;
|
||||
mempool_t *pool;
|
||||
memclump_t *clump;
|
||||
|
||||
for (pool = poolchain;pool;pool = pool->next)
|
||||
{
|
||||
if (pool->sentinel1 != MEMHEADER_SENTINEL1)
|
||||
Sys_Error("Mem_CheckSentinelsGlobal: trashed pool sentinel 1 (allocpool at %s:%i, sentinel check at %s:%i)", pool->filename, pool->fileline, filename, fileline);
|
||||
if (pool->sentinel2 != MEMHEADER_SENTINEL1)
|
||||
Sys_Error("Mem_CheckSentinelsGlobal: trashed pool sentinel 2 (allocpool at %s:%i, sentinel check at %s:%i)", pool->filename, pool->fileline, filename, fileline);
|
||||
}
|
||||
for (pool = poolchain;pool;pool = pool->next)
|
||||
for (mem = pool->chain;mem;mem = mem->next)
|
||||
_mem_checkheadersentinels((void *)((byte *) mem + sizeof(memheader_t)), filename, fileline);
|
||||
|
||||
for (pool = poolchain;pool;pool = pool->next)
|
||||
for (clump = pool->clumpchain;clump;clump = clump->chain)
|
||||
_mem_checkclumpsentinels(clump, filename, fileline);
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
Memory_Init
|
||||
========================
|
||||
*/
|
||||
void InitMemory (void)
|
||||
{
|
||||
poolchain = NULL;//init mem chain
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
//=======================================================================
|
||||
// Copyright XashXT Group 2007 ©
|
||||
// basemem.h - base memory manager
|
||||
//=======================================================================
|
||||
#ifndef BASEMEMORY_H
|
||||
#define BASEMEMORY_H
|
||||
|
||||
// give malloc padding so we can't waste most of a page at the end
|
||||
#define MEMCLUMPSIZE (65536 - 1536)
|
||||
// smallest unit we care about is this many bytes
|
||||
#define MEMUNIT 8
|
||||
#define MEMBITS (MEMCLUMPSIZE / MEMUNIT)
|
||||
#define MEMBITINTS (MEMBITS / 32)
|
||||
#define MEMCLUMP_SENTINEL 0xABADCAFE
|
||||
|
||||
#define MEMHEADER_SENTINEL1 0xDEADF00D
|
||||
#define MEMHEADER_SENTINEL2 0xDF
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
typedef struct memheader_s
|
||||
{
|
||||
// next and previous memheaders in chain belonging to pool
|
||||
struct memheader_s *next;
|
||||
struct memheader_s *prev;
|
||||
struct mempool_s *pool;// pool this memheader belongs to
|
||||
|
||||
// clump this memheader lives in, NULL if not in a clump
|
||||
struct memclump_s *clump;
|
||||
|
||||
size_t size; // size of the memory after the header (excluding header and sentinel2)
|
||||
const char *filename;// file name and line where Mem_Alloc was called
|
||||
int fileline;
|
||||
uint sentinel1;// should always be MEMHEADER_SENTINEL1
|
||||
// immediately followed by data, which is followed by a MEMHEADER_SENTINEL2 byte
|
||||
}
|
||||
memheader_t;
|
||||
|
||||
typedef struct memclump_s
|
||||
{
|
||||
// contents of the clump
|
||||
byte block[MEMCLUMPSIZE];
|
||||
// should always be MEMCLUMP_SENTINEL
|
||||
unsigned int sentinel1;
|
||||
// if a bit is on, it means that the MEMUNIT bytes it represents are
|
||||
// allocated, otherwise free
|
||||
int bits[MEMBITINTS];
|
||||
// should always be MEMCLUMP_SENTINEL
|
||||
unsigned int sentinel2;
|
||||
// if this drops to 0, the clump is freed
|
||||
size_t blocksinuse;
|
||||
// largest block of memory available (this is reset to an optimistic
|
||||
// number when anything is freed, and updated when alloc fails the clump)
|
||||
size_t largestavailable;
|
||||
// next clump in the chain
|
||||
struct memclump_s *chain;
|
||||
}
|
||||
memclump_t;
|
||||
|
||||
typedef struct mempool_s
|
||||
{
|
||||
|
||||
unsigned int sentinel1;// should always be MEMHEADER_SENTINEL1
|
||||
struct memheader_s *chain;// chain of individual memory allocations
|
||||
struct memclump_s *clumpchain;// chain of clumps (if any)
|
||||
size_t totalsize;// total memory allocated in this pool (inside memheaders)
|
||||
size_t realsize;// total memory allocated in this pool (actual malloc total)
|
||||
// updated each time the pool is displayed by memlist, shows change from previous time (unless pool was freed)
|
||||
size_t lastchecksize;
|
||||
struct mempool_s *next;// linked into global mempool list
|
||||
const char *filename;// file name and line where Mem_AllocPool was called
|
||||
int fileline;
|
||||
char name[128];// name of the pool
|
||||
unsigned int sentinel2;// should always be MEMHEADER_SENTINEL1
|
||||
}
|
||||
mempool_t;
|
||||
|
||||
extern byte *basepool;
|
||||
extern byte *zonepool;
|
||||
|
||||
#endif//BASEMEMORY_H
|
346
launch/stdlib.c
346
launch/stdlib.c
|
@ -5,16 +5,107 @@
|
|||
|
||||
#include "launcher.h"
|
||||
|
||||
char *strupper(char *start)
|
||||
void strupper(const char *in, char *out, size_t size_out)
|
||||
{
|
||||
char *in;
|
||||
in = start;
|
||||
while (*in)
|
||||
if (size_out == 0) return;
|
||||
|
||||
while (*in && size_out > 1)
|
||||
{
|
||||
*in = toupper(*in);
|
||||
in++;
|
||||
if (*in >= 'a' && *in <= 'z')
|
||||
*out++ = *in++ + 'A' - 'a';
|
||||
else *out++ = *in++;
|
||||
size_out--;
|
||||
}
|
||||
return start;
|
||||
*out = '\0';
|
||||
}
|
||||
|
||||
void strlower(const char *in, char *out, size_t size_out)
|
||||
{
|
||||
if (size_out == 0) return;
|
||||
|
||||
while (*in && size_out > 1)
|
||||
{
|
||||
if (*in >= 'A' && *in <= 'Z')
|
||||
*out++ = *in++ + 'a' - 'A';
|
||||
else *out++ = *in++;
|
||||
size_out--;
|
||||
}
|
||||
*out = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
strlength
|
||||
|
||||
returned string length
|
||||
============
|
||||
*/
|
||||
int strlength( const char *string )
|
||||
{
|
||||
int len;
|
||||
const char *p;
|
||||
|
||||
if( !string ) return 0;
|
||||
|
||||
len = 0;
|
||||
p = string;
|
||||
while( *p )
|
||||
{
|
||||
p++;
|
||||
len++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
qstrlength
|
||||
|
||||
skipped color prefixes
|
||||
============
|
||||
*/
|
||||
int qstrlength( const char *string )
|
||||
{
|
||||
int len;
|
||||
const char *p;
|
||||
|
||||
if( !string ) return 0;
|
||||
|
||||
len = 0;
|
||||
p = string;
|
||||
while( *p )
|
||||
{
|
||||
if(IsColorString( p ))
|
||||
{
|
||||
p += 2;
|
||||
continue;
|
||||
}
|
||||
p++;
|
||||
len++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
char caseupper(const char in )
|
||||
{
|
||||
char out;
|
||||
|
||||
if (in >= 'a' && in <= 'z')
|
||||
out = in + 'A' - 'a';
|
||||
else out = in;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
char caselower(const char in )
|
||||
{
|
||||
char out;
|
||||
|
||||
if (in >= 'A' && in <= 'Z')
|
||||
out = in + 'a' - 'A';
|
||||
else out = in;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
size_t strlcat(char *dst, const char *src, size_t siz)
|
||||
|
@ -29,7 +120,7 @@ size_t strlcat(char *dst, const char *src, size_t siz)
|
|||
dlen = d - dst;
|
||||
n = siz - dlen;
|
||||
|
||||
if (n == 0) return(dlen + strlen(s));
|
||||
if (n == 0) return(dlen + strlength(s));
|
||||
while (*s != '\0')
|
||||
{
|
||||
if (n != 1)
|
||||
|
@ -60,15 +151,188 @@ size_t strlcpy(char *dst, const char *src, size_t siz)
|
|||
} while (--n != 0);
|
||||
}
|
||||
|
||||
// Not enough room in dst, add NUL and traverse rest of src
|
||||
// Not enough room in dst, add NULL and traverse rest of src
|
||||
if (n == 0)
|
||||
{
|
||||
if (siz != 0) *d = '\0'; //NUL-terminate dst
|
||||
if (siz != 0) *d = '\0'; //NULL-terminate dst
|
||||
while (*s++);
|
||||
}
|
||||
return(s - src - 1); //count does not include NUL
|
||||
return(s - src - 1); // count does not include NULL
|
||||
}
|
||||
|
||||
int strtoint(const char *str)
|
||||
{
|
||||
int val = 0;
|
||||
int c, sign;
|
||||
|
||||
if( !str ) return 0;
|
||||
|
||||
if(*str == '-')
|
||||
{
|
||||
sign = -1;
|
||||
str++;
|
||||
}
|
||||
else sign = 1;
|
||||
|
||||
// check for hex
|
||||
if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') )
|
||||
{
|
||||
str += 2;
|
||||
while(1)
|
||||
{
|
||||
c = *str++;
|
||||
if (c >= '0' && c <= '9') val = (val<<4) + c - '0';
|
||||
else if (c >= 'a' && c <= 'f') val = (val<<4) + c - 'a' + 10;
|
||||
else if (c >= 'A' && c <= 'F') val = (val<<4) + c - 'A' + 10;
|
||||
else return val * sign;
|
||||
}
|
||||
}
|
||||
|
||||
// check for character
|
||||
if (str[0] == '\'') return sign * str[1];
|
||||
|
||||
// assume decimal
|
||||
while (1)
|
||||
{
|
||||
c = *str++;
|
||||
if (c <'0' || c > '9')
|
||||
return val * sign;
|
||||
val = val*10 + c - '0';
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
float strtofloat(const char *str)
|
||||
{
|
||||
double val = 0;
|
||||
int c, sign, decimal, total;
|
||||
|
||||
if( !str ) return 0.0f;
|
||||
|
||||
if (*str == '-')
|
||||
{
|
||||
sign = -1;
|
||||
str++;
|
||||
}
|
||||
else sign = 1;
|
||||
|
||||
// check for hex
|
||||
if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
|
||||
{
|
||||
str += 2;
|
||||
while (1)
|
||||
{
|
||||
c = *str++;
|
||||
if (c >= '0' && c <= '9') val = (val * 16) + c - '0';
|
||||
else if (c >= 'a' && c <= 'f') val = (val * 16) + c - 'a' + 10;
|
||||
else if (c >= 'A' && c <= 'F') val = (val * 16) + c - 'A' + 10;
|
||||
else return val * sign;
|
||||
}
|
||||
}
|
||||
|
||||
// check for character
|
||||
if (str[0] == '\'') return sign * str[1];
|
||||
|
||||
// assume decimal
|
||||
decimal = -1;
|
||||
total = 0;
|
||||
while (1)
|
||||
{
|
||||
c = *str++;
|
||||
if (c == '.')
|
||||
{
|
||||
decimal = total;
|
||||
continue;
|
||||
}
|
||||
if (c <'0' || c > '9') break;
|
||||
val = val*10 + c - '0';
|
||||
total++;
|
||||
}
|
||||
|
||||
if(decimal == -1) return val * sign;
|
||||
while (total > decimal)
|
||||
{
|
||||
val /= 10;
|
||||
total--;
|
||||
}
|
||||
|
||||
return val * sign;
|
||||
}
|
||||
|
||||
void strtovec( float *vec, const char *str )
|
||||
{
|
||||
char *pstr, *pfront, buffer[MAX_QPATH];
|
||||
int j;
|
||||
|
||||
strlcpy( buffer, str, MAX_QPATH );
|
||||
pstr = pfront = buffer;
|
||||
|
||||
for ( j = 0; j < 3; j++ )
|
||||
{
|
||||
vec[j] = strtofloat( pfront );
|
||||
|
||||
// valid separator is space or ,
|
||||
while( *pstr && (*pstr != ' ' || *pstr != ',' ))
|
||||
pstr++;
|
||||
|
||||
if (!*pstr) break;
|
||||
pstr++;
|
||||
pfront = pstr;
|
||||
}
|
||||
if (j < 2) memset( vec, 0, sizeof(vec3_t));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
strlchr
|
||||
|
||||
find one charcster in string
|
||||
============
|
||||
*/
|
||||
char *strlchr(const char *s, char c)
|
||||
{
|
||||
int len = strlength(s);
|
||||
s += len;
|
||||
while(len--) if(*--s == c) return (char *)s;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int strlcasecmp(const char *s1, const char *s2, int n)
|
||||
{
|
||||
int c1, c2;
|
||||
|
||||
while (1)
|
||||
{
|
||||
c1 = *s1++;
|
||||
c2 = *s2++;
|
||||
|
||||
if (!n--) return 0; // strings are equal until end point
|
||||
|
||||
if (c1 != c2)
|
||||
{
|
||||
if (c1 >= 'a' && c1 <= 'z') c1 -= ('a' - 'A');
|
||||
if (c2 >= 'a' && c2 <= 'z') c2 -= ('a' - 'A');
|
||||
if (c1 != c2) return -1; // strings not equal
|
||||
}
|
||||
if (!c1) return 0; // strings are equal
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int strlcmp (const char *s1, const char *s2, int n)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
if (!n--) return 0;
|
||||
if (*s1 != *s2) return -1; // strings not equal
|
||||
if (!*s1) return 0; // strings are equal
|
||||
s1++, s2++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
timestamp
|
||||
|
@ -107,30 +371,37 @@ const char* tstamp( int format )
|
|||
return timestamp;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
va
|
||||
strcasestr
|
||||
|
||||
does a varargs printf into a temp buffer, so I don't need to have
|
||||
varargs versions of all text functions.
|
||||
FIXME: make this buffer size safe someday
|
||||
search case - insensitive for string2 in string
|
||||
============
|
||||
*/
|
||||
char *_va(const char *format, ...)
|
||||
char *strcasestr( const char *string, const char *string2 )
|
||||
{
|
||||
va_list argptr;
|
||||
static char string[8][1024], *s;
|
||||
static int stringindex = 0;
|
||||
int c, len;
|
||||
|
||||
s = string[stringindex];
|
||||
stringindex = (stringindex + 1) & 7;
|
||||
va_start (argptr, format);
|
||||
vsprintf (s, format, argptr);
|
||||
va_end (argptr);
|
||||
return s;
|
||||
if (!string || !string2) return NULL;
|
||||
|
||||
c = caselower( *string2 );
|
||||
len = strlength( string2 );
|
||||
|
||||
while (string)
|
||||
{
|
||||
for ( ; *string && caselower( *string ) != c; string++ );
|
||||
if (*string)
|
||||
{
|
||||
if(!strlcasecmp( string, string2, len ))
|
||||
break;
|
||||
string++;
|
||||
}
|
||||
else return NULL;
|
||||
}
|
||||
return (char *)string;
|
||||
}
|
||||
|
||||
|
||||
int vslprintf(char *buffer, size_t buffersize, const char *format, va_list args)
|
||||
{
|
||||
int result;
|
||||
|
@ -155,4 +426,27 @@ int slprintf(char *buffer, size_t buffersize, const char *format, ...)
|
|||
va_end (args);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
va
|
||||
|
||||
does a varargs printf into a temp buffer, so I don't need to have
|
||||
varargs versions of all text functions.
|
||||
FIXME: make this buffer size safe someday
|
||||
============
|
||||
*/
|
||||
char *_va(const char *format, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
static char string[8][1024], *s;
|
||||
static int stringindex = 0;
|
||||
|
||||
s = string[stringindex];
|
||||
stringindex = (stringindex + 1) & 7;
|
||||
va_start (argptr, format);
|
||||
vslprintf (s, sizeof (string[0]), format, argptr);
|
||||
va_end (argptr);
|
||||
return s;
|
||||
}
|
Reference in New Issue