. split up lib.h/.cpp, include the remnants from PCH, remove (pretty much universal) include of it.
. timer, config: fix definition of ALLOW_RDTSC . add movsx_be64 (for whirlpool), revise implementation, move to byte_order, add test . MAX -> std::max, remove those macros . add timestamp to system_info as requested by philip This was SVN commit r5050.
This commit is contained in:
parent
78d950e419
commit
a34b759720
@ -3,6 +3,7 @@
|
||||
#include "ColladaManager.h"
|
||||
|
||||
#include "graphics/ModelDef.h"
|
||||
#include "lib/fnv_hash.h"
|
||||
#include "lib/res/file/vfs.h"
|
||||
#include "lib/res/handle.h"
|
||||
#include "ps/CLogger.h"
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include "graphics/Unit.h"
|
||||
#include "graphics/UnitManager.h"
|
||||
#include "lib/input.h"
|
||||
#include "lib/lib.h"
|
||||
#include "lib/timer.h"
|
||||
#include "maths/Bound.h"
|
||||
#include "maths/MathUtil.h"
|
||||
|
@ -61,7 +61,7 @@ void CMapWriter::SaveMap(const char* filename, CTerrain* pTerrain,
|
||||
// handle isn't in list
|
||||
static u16 GetHandleIndex(const Handle handle, const std::vector<Handle>& handles)
|
||||
{
|
||||
const uint limit = MIN((uint)handles.size(), 0xFFFE); // paranoia
|
||||
const uint limit = std::min((uint)handles.size(), 0xFFFEu); // paranoia
|
||||
for (uint i=0;i<limit;i++) {
|
||||
if (handles[i]==handle) {
|
||||
return (u16)i;
|
||||
|
@ -8,8 +8,6 @@
|
||||
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "lib/lib.h"
|
||||
|
||||
#include "Patch.h"
|
||||
#include "MiniPatch.h"
|
||||
#include "Terrain.h"
|
||||
@ -38,3 +36,4 @@ void CMiniPatch::GetTileIndex(u32& x,u32& z)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -30,6 +30,7 @@ CGUI
|
||||
|
||||
#include "ps/Pyrogenesis.h"
|
||||
#include "lib/input.h"
|
||||
#include "lib/bits.h"
|
||||
// TODO Gee: Whatever include CRect/CPos/CSize
|
||||
#include "ps/Overlay.h"
|
||||
|
||||
@ -708,7 +709,7 @@ SGUIText CGUI::GenerateText(const CGUIString &string,
|
||||
// after the last image, like a stack downwards.
|
||||
float _y;
|
||||
if (Images[j].size() > 0)
|
||||
_y = MAX(y, Images[j].back().m_YTo);
|
||||
_y = std::max(y, Images[j].back().m_YTo);
|
||||
else
|
||||
_y = y;
|
||||
|
||||
@ -719,7 +720,7 @@ SGUIText CGUI::GenerateText(const CGUIString &string,
|
||||
Image.SetupSpriteCall((j==CGUIString::SFeedback::Left), SpriteCall, Width, _y, size, icon.m_SpriteName, BufferZone, icon.m_CellID);
|
||||
|
||||
// Check if image is the lowest thing.
|
||||
Text.m_Size.cy = MAX(Text.m_Size.cy, Image.m_YTo);
|
||||
Text.m_Size.cy = std::max(Text.m_Size.cy, Image.m_YTo);
|
||||
|
||||
Images[j].push_back(Image);
|
||||
Text.m_SpriteCalls.push_back(SpriteCall);
|
||||
@ -727,10 +728,10 @@ SGUIText CGUI::GenerateText(const CGUIString &string,
|
||||
}
|
||||
}
|
||||
|
||||
pos_last_img = MAX(pos_last_img, i);
|
||||
pos_last_img = std::max(pos_last_img, i);
|
||||
|
||||
x += Feedback.m_Size.cx;
|
||||
prelim_line_height = MAX(prelim_line_height, Feedback.m_Size.cy);
|
||||
prelim_line_height = std::max(prelim_line_height, Feedback.m_Size.cy);
|
||||
|
||||
// If Width is 0, then there's no word-wrapping, disable NewLine.
|
||||
if ((WordWrapping && (x > Width-BufferZone || Feedback.m_NewLine)) || i == (int)string.m_Words.size()-2)
|
||||
@ -766,16 +767,16 @@ SGUIText CGUI::GenerateText(const CGUIString &string,
|
||||
// let's find the union of these two.
|
||||
float union_from, union_to;
|
||||
|
||||
union_from = MAX(y, it->m_YFrom);
|
||||
union_to = MIN(y+prelim_line_height, it->m_YTo);
|
||||
union_from = std::max(y, it->m_YFrom);
|
||||
union_to = std::min(y+prelim_line_height, it->m_YTo);
|
||||
|
||||
// The union is not empty
|
||||
if (union_to > union_from)
|
||||
{
|
||||
if (j == From)
|
||||
width_range[From] = MAX(width_range[From], it->m_Indentation);
|
||||
width_range[From] = std::max(width_range[From], it->m_Indentation);
|
||||
else
|
||||
width_range[To] = MIN(width_range[To], Width - it->m_Indentation);
|
||||
width_range[To] = std::min(width_range[To], Width - it->m_Indentation);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -811,7 +812,7 @@ SGUIText CGUI::GenerateText(const CGUIString &string,
|
||||
break;
|
||||
|
||||
// Let line_height be the maximum m_Height we encounter.
|
||||
line_height = MAX(line_height, Feedback2.m_Size.cy);
|
||||
line_height = std::max(line_height, Feedback2.m_Size.cy);
|
||||
|
||||
if (WordWrapping && Feedback2.m_NewLine)
|
||||
break;
|
||||
@ -856,7 +857,7 @@ SGUIText CGUI::GenerateText(const CGUIString &string,
|
||||
// Append X value.
|
||||
x += Feedback2.m_Size.cx;
|
||||
|
||||
Text.m_Size.cx = MAX(Text.m_Size.cx, x+BufferZone);
|
||||
Text.m_Size.cx = std::max(Text.m_Size.cx, x+BufferZone);
|
||||
|
||||
// The first word overrides the width limit, what we
|
||||
// do, in those cases, are just drawing that word even
|
||||
@ -898,7 +899,7 @@ SGUIText CGUI::GenerateText(const CGUIString &string,
|
||||
x = 0.f;
|
||||
|
||||
// Update height of all
|
||||
Text.m_Size.cy = MAX(Text.m_Size.cy, y+BufferZone);
|
||||
Text.m_Size.cy = std::max(Text.m_Size.cy, y+BufferZone);
|
||||
|
||||
FirstLine = false;
|
||||
|
||||
|
@ -257,7 +257,7 @@ public:
|
||||
* Set content length
|
||||
* @param range Maximum scrollable range
|
||||
*/
|
||||
void SetScrollRange(const float &range) { m_ScrollRange = MAX(range, 1.f); SetupBarSize(); UpdatePosBoundaries(); }
|
||||
void SetScrollRange(const float &range) { m_ScrollRange = std::max(range, 1.f); SetupBarSize(); UpdatePosBoundaries(); }
|
||||
|
||||
/**
|
||||
* Set space that is visible in the scrollable control.
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "graphics/UnitManager.h"
|
||||
#include "lib/ogl.h"
|
||||
#include "lib/external_libraries/sdl.h"
|
||||
#include "lib/bits.h"
|
||||
#include "lib/timer.h"
|
||||
#include "network/NetMessage.h"
|
||||
#include "ps/Game.h"
|
||||
|
@ -11,6 +11,9 @@
|
||||
#ifndef INCLUDED_ADTS
|
||||
#define INCLUDED_ADTS
|
||||
|
||||
#include "lib/fnv_hash.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// dynamic (grow-able) hash table
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "lib/posix/posix.h" // sysconf
|
||||
#include "lib/sysdep/cpu.h" // CAS
|
||||
#include "byte_order.h"
|
||||
#include "bits.h"
|
||||
|
||||
|
||||
|
||||
|
40
source/lib/base32.cpp
Normal file
40
source/lib/base32.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
/**
|
||||
* =========================================================================
|
||||
* File : base32.cpp
|
||||
* Project : 0 A.D.
|
||||
* Description : base32 conversion
|
||||
* =========================================================================
|
||||
*/
|
||||
|
||||
// license: GPL; see lib/license.txt
|
||||
|
||||
#include "precompiled.h"
|
||||
|
||||
|
||||
// big endian!
|
||||
void base32(const size_t in_len, const u8* in, u8* out)
|
||||
{
|
||||
u32 pool = 0; // of bits from buffer
|
||||
uint pool_bits = 0; // # bits currently in buffer
|
||||
|
||||
static const u8 tbl[33] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
||||
|
||||
size_t in_bytes_left = in_len; // to avoid overrunning input buffer
|
||||
const size_t out_chars = (in_len*8 + 4) / 5; // = ceil(# 5-bit blocks)
|
||||
for(size_t i = 0; i < out_chars; i++)
|
||||
{
|
||||
if(pool_bits < 5 && in_bytes_left)
|
||||
{
|
||||
pool <<= 8;
|
||||
pool |= *in++;
|
||||
pool_bits += 8;
|
||||
in_bytes_left--;
|
||||
}
|
||||
|
||||
pool_bits -= 5;
|
||||
const uint c = (pool >> pool_bits) & 31;
|
||||
*out++ = tbl[c];
|
||||
}
|
||||
|
||||
*out++ = '\0';
|
||||
}
|
24
source/lib/base32.h
Normal file
24
source/lib/base32.h
Normal file
@ -0,0 +1,24 @@
|
||||
/**
|
||||
* =========================================================================
|
||||
* File : base32.h
|
||||
* Project : 0 A.D.
|
||||
* Description : base32 conversion
|
||||
* =========================================================================
|
||||
*/
|
||||
|
||||
// license: GPL; see lib/license.txt
|
||||
|
||||
#ifndef INCLUDED_BASE32
|
||||
#define INCLUDED_BASE32
|
||||
|
||||
/**
|
||||
* generate the base32 textual representation of a buffer.
|
||||
*
|
||||
* @param len size [bytes] of input
|
||||
* @param big-endian input data (assumed to be integral number of bytes)
|
||||
* @param output string; zero-terminated. must be big enough
|
||||
* (i.e. at least ceil(len*CHAR_BIT/5) + 1 chars)
|
||||
**/
|
||||
extern void base32(const size_t len, const u8* in, u8* out);
|
||||
|
||||
#endif // #ifndef INCLUDED_BASE32
|
106
source/lib/bits.cpp
Normal file
106
source/lib/bits.cpp
Normal file
@ -0,0 +1,106 @@
|
||||
/**
|
||||
* =========================================================================
|
||||
* File : bits.cpp
|
||||
* Project : 0 A.D.
|
||||
* Description : bit-twiddling.
|
||||
* =========================================================================
|
||||
*/
|
||||
|
||||
// license: GPL; see lib/license.txt
|
||||
|
||||
#include "precompiled.h"
|
||||
|
||||
#if CPU_IA32
|
||||
# include "lib/sysdep/ia32/ia32_asm.h" // ia32_asm_log2_of_pow2
|
||||
#endif
|
||||
|
||||
|
||||
bool is_pow2(uint n)
|
||||
{
|
||||
// 0 would pass the test below but isn't a POT.
|
||||
if(n == 0)
|
||||
return false;
|
||||
return (n & (n-1ul)) == 0;
|
||||
}
|
||||
|
||||
|
||||
int log2_of_pow2(uint n)
|
||||
{
|
||||
int bit_index;
|
||||
|
||||
#if CPU_IA32
|
||||
bit_index = ia32_asm_log2_of_pow2(n);
|
||||
#else
|
||||
if(!is_pow2(n))
|
||||
bit_index = -1;
|
||||
else
|
||||
{
|
||||
bit_index = 0;
|
||||
// note: compare against n directly because it is known to be a POT.
|
||||
for(uint bit_value = 1; bit_value != n; bit_value *= 2)
|
||||
bit_index++;
|
||||
}
|
||||
#endif
|
||||
|
||||
debug_assert(-1 <= bit_index && bit_index < (int)sizeof(int)*CHAR_BIT);
|
||||
debug_assert(bit_index == -1 || n == (1u << bit_index));
|
||||
return bit_index;
|
||||
}
|
||||
|
||||
|
||||
uint ceil_log2(uint x)
|
||||
{
|
||||
uint bit = 1;
|
||||
uint l = 0;
|
||||
while(bit < x && bit != 0) // must detect overflow
|
||||
{
|
||||
l++;
|
||||
bit += bit;
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
int floor_log2(const float x)
|
||||
{
|
||||
const u32 i = *(u32*)&x;
|
||||
u32 biased_exp = (i >> 23) & 0xFF;
|
||||
return (int)biased_exp - 127;
|
||||
}
|
||||
|
||||
|
||||
// round_up_to_pow2 implementation assumes 32-bit int.
|
||||
// if 64, add "x |= (x >> 32);"
|
||||
cassert(sizeof(int)*CHAR_BIT == 32);
|
||||
|
||||
uint round_up_to_pow2(uint x)
|
||||
{
|
||||
// fold upper bit into lower bits; leaves same MSB set but
|
||||
// everything below it 1. adding 1 yields next POT.
|
||||
x |= (x >> 1);
|
||||
x |= (x >> 2);
|
||||
x |= (x >> 4);
|
||||
x |= (x >> 8);
|
||||
x |= (x >> 16);
|
||||
return x+1;
|
||||
}
|
||||
|
||||
|
||||
// multiple must be a power of two.
|
||||
uintptr_t round_up(const uintptr_t n, const uintptr_t multiple)
|
||||
{
|
||||
debug_assert(is_pow2((long)multiple));
|
||||
const uintptr_t result = (n + multiple-1) & ~(multiple-1);
|
||||
debug_assert(n <= result && result < n+multiple);
|
||||
return result;
|
||||
}
|
||||
|
||||
// multiple must be a power of two.
|
||||
uintptr_t round_down(const uintptr_t n, const uintptr_t multiple)
|
||||
{
|
||||
debug_assert(is_pow2((long)multiple));
|
||||
const uintptr_t result = n & ~(multiple-1);
|
||||
debug_assert(result <= n && n < result+multiple);
|
||||
return result;
|
||||
}
|
103
source/lib/bits.h
Normal file
103
source/lib/bits.h
Normal file
@ -0,0 +1,103 @@
|
||||
/**
|
||||
* =========================================================================
|
||||
* File : bits.h
|
||||
* Project : 0 A.D.
|
||||
* Description : bit-twiddling.
|
||||
* =========================================================================
|
||||
*/
|
||||
|
||||
// license: GPL; see lib/license.txt
|
||||
|
||||
#ifndef INCLUDED_BITS
|
||||
#define INCLUDED_BITS
|
||||
|
||||
/**
|
||||
* value of bit number <n> as unsigned long.
|
||||
*
|
||||
* @param n bit index (0..CHAR_BIT*sizeof(int)-1)
|
||||
**/
|
||||
#define BIT(n) (1ul << (n))
|
||||
|
||||
/**
|
||||
* value of bit number <n> as unsigned long long.
|
||||
*
|
||||
* @param n bit index (0..CHAR_BIT*sizeof(int)-1)
|
||||
**/
|
||||
#define BIT64(n) (1ull << (n))
|
||||
|
||||
|
||||
// these are declared in the header and inlined to aid compiler optimizations
|
||||
// (they can easily end up being time-critical).
|
||||
// note: GCC can't inline extern functions, while VC's "Whole Program
|
||||
// Optimization" can.
|
||||
|
||||
/**
|
||||
* a mask that includes the lowest N bits
|
||||
*
|
||||
* @param num_bits number of bits in mask
|
||||
**/
|
||||
inline uint bit_mask(uint num_bits)
|
||||
{
|
||||
return (1u << num_bits)-1;
|
||||
}
|
||||
|
||||
/**
|
||||
* extract the value of bits hi_idx:lo_idx within num
|
||||
*
|
||||
* example: bits(0x69, 2, 5) == 0x0A
|
||||
*
|
||||
* @param num number whose bits are to be extracted
|
||||
* @param lo_idx bit index of lowest bit to include
|
||||
* @param hi_idx bit index of highest bit to include
|
||||
* @return value of extracted bits.
|
||||
**/
|
||||
inline uint bits(uint num, uint lo_idx, uint hi_idx)
|
||||
{
|
||||
const uint count = (hi_idx - lo_idx)+1; // # bits to return
|
||||
uint result = num >> lo_idx;
|
||||
result &= bit_mask(count);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether the given number is a power of two.
|
||||
**/
|
||||
extern bool is_pow2(uint n);
|
||||
|
||||
/**
|
||||
* @return the (integral) base 2 logarithm, or -1 if the number
|
||||
* is not a power-of-two.
|
||||
**/
|
||||
extern int log2_of_pow2(uint n);
|
||||
|
||||
/**
|
||||
* ceil(log2(n))
|
||||
*
|
||||
* @param n (integer) input; MUST be > 0, else results are undefined.
|
||||
* @return ceiling of the base-2 logarithm (i.e. rounded up).
|
||||
**/
|
||||
extern uint ceil_log2(uint x);
|
||||
|
||||
/**
|
||||
* floor(log2(f))
|
||||
* fast, uses the FPU normalization hardware.
|
||||
*
|
||||
* @param f (float) input; MUST be > 0, else results are undefined.
|
||||
* @return floor of the base-2 logarithm (i.e. rounded down).
|
||||
**/
|
||||
extern int floor_log2(const float x);
|
||||
|
||||
/**
|
||||
* round up to next larger power of two.
|
||||
**/
|
||||
extern uint round_up_to_pow2(uint x);
|
||||
|
||||
/**
|
||||
* round number up/down to the next given multiple.
|
||||
*
|
||||
* @param multiple: must be a power of two.
|
||||
**/
|
||||
extern uintptr_t round_up (uintptr_t n, uintptr_t multiple);
|
||||
extern uintptr_t round_down(uintptr_t n, uintptr_t multiple);
|
||||
|
||||
#endif // #ifndef INCLUDED_BITS
|
@ -11,6 +11,7 @@
|
||||
#include "precompiled.h"
|
||||
#include "byte_order.h"
|
||||
|
||||
#include "bits.h"
|
||||
|
||||
#ifndef swap16
|
||||
|
||||
@ -161,3 +162,58 @@ void write_be64(void* p, u64 x)
|
||||
{
|
||||
*(u64*)p = to_be64(x);
|
||||
}
|
||||
|
||||
|
||||
u64 movzx_le64(const u8* p, size_t size_bytes)
|
||||
{
|
||||
u64 number = 0;
|
||||
for(uint i = 0; i < std::min(size_bytes, 8u); i++)
|
||||
number |= ((u64)p[i]) << (i*8);
|
||||
|
||||
return number;
|
||||
}
|
||||
|
||||
u64 movzx_be64(const u8* p, size_t size_bytes)
|
||||
{
|
||||
u64 number = 0;
|
||||
for(uint i = 0; i < std::min(size_bytes, 8u); i++)
|
||||
{
|
||||
number <<= 8;
|
||||
number |= p[i];
|
||||
}
|
||||
|
||||
return number;
|
||||
}
|
||||
|
||||
|
||||
static inline i64 SignExtend(u64 bits, size_t size_bytes)
|
||||
{
|
||||
// no point in sign-extending if >= 8 bytes were requested
|
||||
if(size_bytes < 8)
|
||||
{
|
||||
const u64 sign_bit = BIT64((size_bytes*8)-1);
|
||||
|
||||
// number would be negative in the smaller type,
|
||||
// so sign-extend, i.e. set all more significant bits.
|
||||
if(bits & sign_bit)
|
||||
{
|
||||
const u64 valid_bit_mask = (sign_bit+sign_bit)-1;
|
||||
bits |= ~valid_bit_mask;
|
||||
}
|
||||
}
|
||||
|
||||
const i64 number = static_cast<i64>(bits);
|
||||
return number;
|
||||
}
|
||||
|
||||
i64 movsx_le64(const u8* p, size_t size_bytes)
|
||||
{
|
||||
const u64 number = movzx_le64(p, size_bytes);
|
||||
return SignExtend(number, size_bytes);
|
||||
}
|
||||
|
||||
i64 movsx_be64(const u8* p, size_t size_bytes)
|
||||
{
|
||||
const u64 number = movzx_be64(p, size_bytes);
|
||||
return SignExtend(number, size_bytes);
|
||||
}
|
||||
|
@ -75,6 +75,20 @@ extern void write_be16(void* p, u16 x);
|
||||
extern void write_be32(void* p, u32 x); /// see write_be16
|
||||
extern void write_be64(void* p, u64 x); /// see write_be16
|
||||
|
||||
/**
|
||||
* zero-extend <size> (truncated to 8) bytes of little-endian data to u64,
|
||||
* starting at address <p> (need not be aligned).
|
||||
**/
|
||||
extern u64 movzx_le64(const u8* p, size_t size);
|
||||
extern u64 movzx_be64(const u8* p, size_t size);
|
||||
|
||||
/**
|
||||
* sign-extend <size> (truncated to 8) bytes of little-endian data to i64,
|
||||
* starting at address <p> (need not be aligned).
|
||||
**/
|
||||
extern i64 movsx_le64(const u8* p, size_t size);
|
||||
extern i64 movsx_be64(const u8* p, size_t size);
|
||||
|
||||
|
||||
// Debug-mode ICC doesn't like the intrinsics, so only use them
|
||||
// for MSVC and non-debug ICC.
|
||||
|
@ -147,7 +147,7 @@ public:
|
||||
|
||||
void notify_decreased(const Entry& entry)
|
||||
{
|
||||
min_credit_density = MIN(min_credit_density, entry.credit_density());
|
||||
min_credit_density = std::min(min_credit_density, entry.credit_density());
|
||||
}
|
||||
|
||||
void notify_impending_increase_or_remove(const Entry& entry)
|
||||
|
152
source/lib/code_annotation.h
Normal file
152
source/lib/code_annotation.h
Normal file
@ -0,0 +1,152 @@
|
||||
/**
|
||||
* =========================================================================
|
||||
* File : code_annotation.h
|
||||
* Project : 0 A.D.
|
||||
* Description : macros for code annotation.
|
||||
* =========================================================================
|
||||
*/
|
||||
|
||||
// license: GPL; see lib/license.txt
|
||||
|
||||
#ifndef INCLUDED_CODE_ANNOTATION
|
||||
#define INCLUDED_CODE_ANNOTATION
|
||||
|
||||
/**
|
||||
* mark a function local variable or parameter as unused and avoid
|
||||
* the corresponding compiler warning.
|
||||
* use inside the function body, e.g. void f(int x) { UNUSED2(x); }
|
||||
**/
|
||||
#define UNUSED2(param) (void)param;
|
||||
|
||||
/**
|
||||
* mark a function parameter as unused and avoid
|
||||
* the corresponding compiler warning.
|
||||
* wrap around the parameter name, e.g. void f(int UNUSED(x))
|
||||
**/
|
||||
#define UNUSED(param)
|
||||
|
||||
|
||||
/**
|
||||
"unreachable code" helpers
|
||||
|
||||
unreachable lines of code are often the source or symptom of subtle bugs.
|
||||
they are flagged by compiler warnings; however, the opposite problem -
|
||||
erroneously reaching certain spots (e.g. due to missing return statement)
|
||||
is worse and not detected automatically.
|
||||
|
||||
to defend against this, the programmer can annotate their code to
|
||||
indicate to humans that a particular spot should never be reached.
|
||||
however, that isn't much help; better is a sentinel that raises an
|
||||
error if if it is actually reached. hence, the UNREACHABLE macro.
|
||||
|
||||
ironically, if the code guarded by UNREACHABLE works as it should,
|
||||
compilers may flag the macro's code as unreachable. this would
|
||||
distract from genuine warnings, which is unacceptable.
|
||||
|
||||
even worse, compilers differ in their code checking: GCC only complains if
|
||||
non-void functions end without returning a value (i.e. missing return
|
||||
statement), while VC checks if lines are unreachable (e.g. if they are
|
||||
preceded by a return on all paths).
|
||||
|
||||
our implementation of UNREACHABLE solves this dilemna as follows:
|
||||
- on GCC: call abort(); since it has the noreturn attributes, the
|
||||
"non-void" warning disappears.
|
||||
- on VC: avoid generating any code. we allow the compiler to assume the
|
||||
spot is actually unreachable, which incidentally helps optimization.
|
||||
if reached after all, a crash usually results. in that case, compile with
|
||||
CONFIG_PARANOIA, which will cause an error message to be displayed.
|
||||
|
||||
this approach still allows for the possiblity of automated
|
||||
checking, but does not cause any compiler warnings.
|
||||
**/
|
||||
#define UNREACHABLE // actually defined below.. this is for
|
||||
# undef UNREACHABLE // CppDoc's benefit only.
|
||||
|
||||
// 1) final build: optimize assuming this location cannot be reached.
|
||||
// may crash if that turns out to be untrue, but removes checking overhead.
|
||||
#if CONFIG_FINAL
|
||||
# define UNREACHABLE ASSUME_UNREACHABLE
|
||||
// 2) normal build:
|
||||
#else
|
||||
// a) normal implementation: includes "abort", which is declared with
|
||||
// noreturn attribute and therefore avoids GCC's "execution reaches
|
||||
// end of non-void function" warning.
|
||||
# if !MSC_VERSION || CONFIG_PARANOIA
|
||||
# define UNREACHABLE\
|
||||
STMT(\
|
||||
debug_warn("hit supposedly unreachable code");\
|
||||
abort();\
|
||||
)
|
||||
// b) VC only: don't generate any code; squelch the warning and optimize.
|
||||
# else
|
||||
# define UNREACHABLE ASSUME_UNREACHABLE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
convenient specialization of UNREACHABLE for switch statements whose
|
||||
default can never be reached. example usage:
|
||||
int x;
|
||||
switch(x % 2)
|
||||
{
|
||||
case 0: break;
|
||||
case 1: break;
|
||||
NODEFAULT;
|
||||
}
|
||||
**/
|
||||
#define NODEFAULT default: UNREACHABLE
|
||||
|
||||
|
||||
/**
|
||||
* equivalent to strcpy, but indicates that the programmer checked usage and
|
||||
* promises it is safe.
|
||||
*
|
||||
* (this macro prevents actually-safe instances of the function from
|
||||
* showing up in searches)
|
||||
**/
|
||||
#define SAFE_STRCPY str##cpy
|
||||
#define SAFE_WCSCPY wcs##cpy
|
||||
|
||||
|
||||
// generate a symbol containing the line number of the macro invocation.
|
||||
// used to give a unique name (per file) to types made by cassert.
|
||||
// we can't prepend __FILE__ to make it globally unique - the filename
|
||||
// may be enclosed in quotes. PASTE3_HIDDEN__ is needed to make sure
|
||||
// __LINE__ is expanded correctly.
|
||||
#define PASTE3_HIDDEN__(a, b, c) a ## b ## c
|
||||
#define PASTE3__(a, b, c) PASTE3_HIDDEN__(a, b, c)
|
||||
#define UID__ PASTE3__(LINE_, __LINE__, _)
|
||||
#define UID2__ PASTE3__(LINE_, __LINE__, _2)
|
||||
|
||||
/**
|
||||
* compile-time debug_assert. causes a compile error if the expression
|
||||
* evaluates to zero/false.
|
||||
*
|
||||
* no runtime overhead; may be used anywhere, including file scope.
|
||||
* especially useful for testing sizeof types.
|
||||
*
|
||||
* this version has a more descriptive error message, but may cause a
|
||||
* struct redefinition warning if used from the same line in different files.
|
||||
*
|
||||
* note: alternative method in C++: specialize a struct only for true;
|
||||
* using it will raise 'incomplete type' errors if instantiated with false.
|
||||
*
|
||||
* @param expression that is expected to evaluate to non-zero at compile-time.
|
||||
**/
|
||||
#define cassert(expr) struct UID__ { int CASSERT_FAILURE: (expr); }
|
||||
|
||||
/**
|
||||
* compile-time debug_assert. causes a compile error if the expression
|
||||
* evaluates to zero/false.
|
||||
*
|
||||
* no runtime overhead; may be used anywhere, including file scope.
|
||||
* especially useful for testing sizeof types.
|
||||
*
|
||||
* this version has a less helpful error message, but redefinition doesn't
|
||||
* trigger warnings.
|
||||
*
|
||||
* @param expression that is expected to evaluate to non-zero at compile-time.
|
||||
**/
|
||||
#define cassert2(expr) extern char CASSERT_FAILURE[1][(expr)]
|
||||
|
||||
#endif // #ifndef INCLUDED_CODE_ANNOTATION
|
@ -46,7 +46,11 @@
|
||||
// allow use of RDTSC for raw tick counts (otherwise, the slower but
|
||||
// more reliable on MP systems wall-clock will be used).
|
||||
#ifndef CONFIG_TIMER_ALLOW_RDTSC
|
||||
# define CONFIG_TIMER_ALLOW_RDTSC 1
|
||||
# if CPU_IA32
|
||||
# define CONFIG_TIMER_ALLOW_RDTSC 1
|
||||
# else
|
||||
# define CONFIG_TIMER_ALLOW_RDTSC 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// this enables/disables the actual checking done by OverrunProtector-s
|
||||
|
@ -14,11 +14,11 @@
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lib.h"
|
||||
#include "app_hooks.h"
|
||||
#include "path_util.h"
|
||||
#include "debug_stl.h"
|
||||
#include "allocators.h"
|
||||
#include "fnv_hash.h"
|
||||
#include "lib/posix/posix_pthread.h"
|
||||
#include "lib/sysdep/cpu.h" // CAS
|
||||
#include "lib/sysdep/sysdep.h"
|
||||
|
@ -11,7 +11,6 @@
|
||||
#ifndef INCLUDED_DEBUG
|
||||
#define INCLUDED_DEBUG
|
||||
|
||||
#include "lib.h" // STMT
|
||||
#if OS_WIN
|
||||
# include "lib/sysdep/win/wdbg.h"
|
||||
#else
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include <set>
|
||||
#include <cassert>
|
||||
|
||||
#include "lib.h" // match_wildcard
|
||||
#include "regex.h"
|
||||
|
||||
|
||||
AT_STARTUP(\
|
||||
@ -251,7 +251,7 @@ class Any_deque : public std::deque<int>
|
||||
const u8* get_item(size_t i, size_t el_size) const
|
||||
{
|
||||
const u8** map = (const u8**)_Map;
|
||||
const size_t el_per_bucket = MAX(16 / el_size, 1);
|
||||
const size_t el_per_bucket = std::max(16u / el_size, 1u);
|
||||
const size_t bucket_idx = i / el_per_bucket;
|
||||
const size_t idx_in_bucket = i - bucket_idx * el_per_bucket;
|
||||
const u8* bucket = map[bucket_idx];
|
||||
@ -266,7 +266,7 @@ public:
|
||||
#if STL_DINKUMWARE
|
||||
if(!container_valid(_Map, _Mysize))
|
||||
return false;
|
||||
const size_t el_per_bucket = MAX(16 / el_size, 1); // see _DEQUESIZ
|
||||
const size_t el_per_bucket = std::max(16u / el_size, 1u); // see _DEQUESIZ
|
||||
// initial element is beyond end of first bucket
|
||||
if(_Myoff >= el_per_bucket)
|
||||
return false;
|
||||
|
117
source/lib/fnv_hash.cpp
Normal file
117
source/lib/fnv_hash.cpp
Normal file
@ -0,0 +1,117 @@
|
||||
/**
|
||||
* =========================================================================
|
||||
* File : fnv_hash.h
|
||||
* Project : 0 A.D.
|
||||
* Description : Fowler/Noll/Vo string hash
|
||||
* =========================================================================
|
||||
*/
|
||||
|
||||
// license: GPL; see lib/license.txt
|
||||
|
||||
#include "precompiled.h"
|
||||
|
||||
|
||||
// FNV1-A hash - good for strings.
|
||||
// if len = 0 (default), treat buf as a C-string;
|
||||
// otherwise, hash <len> bytes of buf.
|
||||
u32 fnv_hash(const void* buf, size_t len)
|
||||
{
|
||||
u32 h = 0x811c9dc5u;
|
||||
// give distinct values for different length 0 buffers.
|
||||
// value taken from FNV; it has no special significance.
|
||||
|
||||
const u8* p = (const u8*)buf;
|
||||
|
||||
// expected case: string
|
||||
if(!len)
|
||||
{
|
||||
while(*p)
|
||||
{
|
||||
h ^= *p++;
|
||||
h *= 0x01000193u;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t bytes_left = len;
|
||||
while(bytes_left != 0)
|
||||
{
|
||||
h ^= *p++;
|
||||
h *= 0x01000193u;
|
||||
|
||||
bytes_left--;
|
||||
}
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
// FNV1-A hash - good for strings.
|
||||
// if len = 0 (default), treat buf as a C-string;
|
||||
// otherwise, hash <len> bytes of buf.
|
||||
u64 fnv_hash64(const void* buf, size_t len)
|
||||
{
|
||||
u64 h = 0xCBF29CE484222325ull;
|
||||
// give distinct values for different length 0 buffers.
|
||||
// value taken from FNV; it has no special significance.
|
||||
|
||||
const u8* p = (const u8*)buf;
|
||||
|
||||
// expected case: string
|
||||
if(!len)
|
||||
{
|
||||
while(*p)
|
||||
{
|
||||
h ^= *p++;
|
||||
h *= 0x100000001B3ull;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t bytes_left = len;
|
||||
while(bytes_left != 0)
|
||||
{
|
||||
h ^= *p++;
|
||||
h *= 0x100000001B3ull;
|
||||
|
||||
bytes_left--;
|
||||
}
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
// special version for strings: first converts to lowercase
|
||||
// (useful for comparing mixed-case filenames).
|
||||
// note: still need <len>, e.g. to support non-0-terminated strings
|
||||
u32 fnv_lc_hash(const char* str, size_t len)
|
||||
{
|
||||
u32 h = 0x811c9dc5u;
|
||||
// give distinct values for different length 0 buffers.
|
||||
// value taken from FNV; it has no special significance.
|
||||
|
||||
// expected case: string
|
||||
if(!len)
|
||||
{
|
||||
while(*str)
|
||||
{
|
||||
h ^= tolower(*str++);
|
||||
h *= 0x01000193u;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t bytes_left = len;
|
||||
while(bytes_left != 0)
|
||||
{
|
||||
h ^= tolower(*str++);
|
||||
h *= 0x01000193u;
|
||||
|
||||
bytes_left--;
|
||||
}
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
39
source/lib/fnv_hash.h
Normal file
39
source/lib/fnv_hash.h
Normal file
@ -0,0 +1,39 @@
|
||||
/**
|
||||
* =========================================================================
|
||||
* File : fnv_hash.h
|
||||
* Project : 0 A.D.
|
||||
* Description : Fowler/Noll/Vo string hash
|
||||
* =========================================================================
|
||||
*/
|
||||
|
||||
// license: GPL; see lib/license.txt
|
||||
|
||||
#ifndef INCLUDED_FNV_HASH
|
||||
#define INCLUDED_FNV_HASH
|
||||
|
||||
/**
|
||||
* rationale: this algorithm was chosen because it delivers 'good' results
|
||||
* for string data and is relatively simple. other good alternatives exist;
|
||||
* see Ozan Yigit's hash roundup.
|
||||
**/
|
||||
|
||||
/**
|
||||
* calculate FNV1-A hash.
|
||||
*
|
||||
* @param buf input buffer.
|
||||
* @param len if 0 (default), treat buf as a C-string; otherwise,
|
||||
* indicates how many bytes of buffer to hash.
|
||||
* @return hash result. note: results are distinct for buffers containing
|
||||
* differing amounts of zero bytes because the hash value is seeded.
|
||||
**/
|
||||
extern u32 fnv_hash(const void* buf, size_t len = 0);
|
||||
/// 64-bit version of fnv_hash.
|
||||
extern u64 fnv_hash64(const void* buf, size_t len = 0);
|
||||
|
||||
/**
|
||||
* special version of fnv_hash for strings: first converts to lowercase
|
||||
* (useful for comparing mixed-case filenames)
|
||||
**/
|
||||
extern u32 fnv_lc_hash(const char* str, size_t len = 0);
|
||||
|
||||
#endif // #ifndef INCLUDED_FNV_HASH
|
@ -15,7 +15,6 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "lib.h"
|
||||
#include "lib/external_libraries/sdl.h"
|
||||
#include "lib/res/file/file.h"
|
||||
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include <algorithm>
|
||||
#include <limits.h>
|
||||
|
||||
#include "lib.h"
|
||||
#include "posix.h"
|
||||
#include "lib/sysdep/cpu.h"
|
||||
#include "lockfree.h"
|
||||
@ -296,7 +295,7 @@ static void* MallocFromActive(ProcHeap* heap)
|
||||
new_anchor.state = FULL;
|
||||
else
|
||||
{
|
||||
more_credits = MIN(old_anchor.count, MAX_CREDITS);
|
||||
more_credits = std::min(old_anchor.count, MAX_CREDITS);
|
||||
new_anchor.count -= more_credits;
|
||||
}
|
||||
}
|
||||
@ -332,7 +331,7 @@ retry:
|
||||
}
|
||||
// old_anchor state must be PARTIAL
|
||||
// old_anchor count must be > 0
|
||||
more_credits = MIN(old_anchor.count-1, MAX_CREDITS);
|
||||
more_credits = std::min(old_anchor.count-1, MAX_CREDITS);
|
||||
new_anchor.count -= more_credits+1;
|
||||
new_anchor.state = (more_credits > 0)? ACTIVE : FULL;
|
||||
}
|
||||
@ -370,7 +369,7 @@ static void* MallocFromNewSB(ProcHeap* heap)
|
||||
desc->sz = heap->sc->sz;
|
||||
desc->maxcount = (uint)(heap->sc->sb_size/desc->sz);
|
||||
Active new_active = (Active)desc;
|
||||
new_active.credits = MIN(desc->maxcount-1, MAX_CREDITS)-1;
|
||||
new_active.credits = std::min(desc->maxcount-1, MAX_CREDITS)-1;
|
||||
desc->anchor.count = (desc->maxcount-1)-(new_active.credits+1);
|
||||
desc->anchor.state = ACTIVE;
|
||||
cpu_MemoryFence();
|
||||
|
@ -18,131 +18,17 @@
|
||||
#include "lib/app_hooks.h"
|
||||
#include "lib/sysdep/sysdep.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// bit bashing
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool is_pow2(uint n)
|
||||
{
|
||||
// 0 would pass the test below but isn't a POT.
|
||||
if(n == 0)
|
||||
return false;
|
||||
return (n & (n-1l)) == 0;
|
||||
}
|
||||
|
||||
|
||||
// return -1 if not an integral power of 2,
|
||||
// otherwise the base2 logarithm
|
||||
|
||||
int ilog2(uint n)
|
||||
{
|
||||
int bit_index; // return value
|
||||
|
||||
#if CPU_IA32 && HAVE_MS_ASM
|
||||
|
||||
__asm
|
||||
{
|
||||
mov ecx, [n]
|
||||
or eax, -1 // return value if not a POT
|
||||
test ecx, ecx
|
||||
jz not_pot
|
||||
lea edx, [ecx-1]
|
||||
test ecx, edx
|
||||
jnz not_pot
|
||||
bsf eax, ecx
|
||||
not_pot:
|
||||
mov [bit_index], eax
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
if(!is_pow2(n))
|
||||
return -1;
|
||||
|
||||
bit_index = 0;
|
||||
// note: compare against n directly because it is known to be a POT.
|
||||
for(uint bit_value = 1; bit_value != n; bit_value *= 2)
|
||||
bit_index++;
|
||||
|
||||
#endif
|
||||
|
||||
debug_assert(-1 <= bit_index && bit_index < (int)sizeof(int)*CHAR_BIT);
|
||||
debug_assert(bit_index == -1 || n == (1u << bit_index));
|
||||
return bit_index;
|
||||
}
|
||||
|
||||
// return log base 2, rounded up.
|
||||
uint log2(uint x)
|
||||
{
|
||||
uint bit = 1;
|
||||
uint l = 0;
|
||||
while(bit < x && bit != 0) // must detect overflow
|
||||
{
|
||||
l++;
|
||||
bit += bit;
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
int ilog2(const float x)
|
||||
{
|
||||
const u32 i = *(u32*)&x;
|
||||
u32 biased_exp = (i >> 23) & 0xff;
|
||||
return (int)biased_exp - 127;
|
||||
}
|
||||
|
||||
|
||||
// round_up_to_pow2 implementation assumes 32-bit int.
|
||||
// if 64, add "x |= (x >> 32);"
|
||||
cassert(sizeof(int)*CHAR_BIT == 32);
|
||||
|
||||
uint round_up_to_pow2(uint x)
|
||||
{
|
||||
// fold upper bit into lower bits; leaves same MSB set but
|
||||
// everything below it 1. adding 1 yields next POT.
|
||||
x |= (x >> 1);
|
||||
x |= (x >> 2);
|
||||
x |= (x >> 4);
|
||||
x |= (x >> 8);
|
||||
x |= (x >> 16);
|
||||
return x+1;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// misc arithmetic
|
||||
|
||||
|
||||
// multiple must be a power of two.
|
||||
uintptr_t round_up(const uintptr_t n, const uintptr_t multiple)
|
||||
{
|
||||
debug_assert(is_pow2((long)multiple));
|
||||
const uintptr_t result = (n + multiple-1) & ~(multiple-1);
|
||||
debug_assert(n <= result && result < n+multiple);
|
||||
return result;
|
||||
}
|
||||
|
||||
// multiple must be a power of two.
|
||||
uintptr_t round_down(const uintptr_t n, const uintptr_t multiple)
|
||||
{
|
||||
debug_assert(is_pow2((long)multiple));
|
||||
const uintptr_t result = n & ~(multiple-1);
|
||||
debug_assert(result <= n && n < result+multiple);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
u16 addusw(u16 x, u16 y)
|
||||
{
|
||||
u32 t = x;
|
||||
return (u16)MIN(t+y, 0xffffu);
|
||||
return (u16)std::min(t+y, 0xFFFFu);
|
||||
}
|
||||
|
||||
u16 subusw(u16 x, u16 y)
|
||||
{
|
||||
long t = x;
|
||||
return (u16)(MAX(t-y, 0));
|
||||
return (u16)(std::max(t-y, 0l));
|
||||
}
|
||||
|
||||
|
||||
@ -245,49 +131,8 @@ u32 u32_from_u16(u16 hi, u16 lo)
|
||||
}
|
||||
|
||||
|
||||
// zero-extend <size> (truncated to 8) bytes of little-endian data to u64,
|
||||
// starting at address <p> (need not be aligned).
|
||||
u64 movzx_64le(const u8* p, size_t size)
|
||||
{
|
||||
size = MIN(size, 8);
|
||||
|
||||
u64 data = 0;
|
||||
for(u64 i = 0; i < size; i++)
|
||||
data |= ((u64)p[i]) << (i*8);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
// sign-extend <size> (truncated to 8) bytes of little-endian data to i64,
|
||||
// starting at address <p> (need not be aligned).
|
||||
i64 movsx_64le(const u8* p, size_t size)
|
||||
{
|
||||
size = MIN(size, 8);
|
||||
|
||||
u64 data = movzx_64le(p, size);
|
||||
|
||||
// no point in sign-extending if >= 8 bytes were requested
|
||||
if(size < 8)
|
||||
{
|
||||
u64 sign_bit = 1;
|
||||
sign_bit <<= (size*8)-1;
|
||||
// be sure that we don't shift more than variable's bit width
|
||||
|
||||
// number would be negative in the smaller type,
|
||||
// so sign-extend, i.e. set all more significant bits.
|
||||
if(data & sign_bit)
|
||||
{
|
||||
const u64 size_mask = (sign_bit+sign_bit)-1;
|
||||
data |= ~size_mask;
|
||||
}
|
||||
}
|
||||
|
||||
return (i64)data;
|
||||
}
|
||||
|
||||
|
||||
// input in [0, 1); convert to u8 range
|
||||
u8 fp_to_u8(double in)
|
||||
u8 u8_from_double(double in)
|
||||
{
|
||||
if(!(0.0 <= in && in < 1.0))
|
||||
{
|
||||
@ -301,7 +146,7 @@ u8 fp_to_u8(double in)
|
||||
}
|
||||
|
||||
// input in [0, 1); convert to u16 range
|
||||
u16 fp_to_u16(double in)
|
||||
u16 u16_from_double(double in)
|
||||
{
|
||||
if(!(0.0 <= in && in < 1.0))
|
||||
{
|
||||
@ -315,242 +160,6 @@ u16 fp_to_u16(double in)
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// string processing
|
||||
|
||||
// big endian!
|
||||
void base32(const size_t in_len, const u8* in, u8* out)
|
||||
{
|
||||
u32 pool = 0; // of bits from buffer
|
||||
uint pool_bits = 0; // # bits currently in buffer
|
||||
|
||||
static const u8 tbl[33] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
||||
|
||||
size_t in_bytes_left = in_len; // to avoid overrunning input buffer
|
||||
const size_t out_chars = (in_len*8 + 4) / 5; // = ceil(# 5-bit blocks)
|
||||
for(size_t i = 0; i < out_chars; i++)
|
||||
{
|
||||
if(pool_bits < 5 && in_bytes_left)
|
||||
{
|
||||
pool <<= 8;
|
||||
pool |= *in++;
|
||||
pool_bits += 8;
|
||||
in_bytes_left--;
|
||||
}
|
||||
|
||||
pool_bits -= 5;
|
||||
const uint c = (pool >> pool_bits) & 31;
|
||||
*out++ = tbl[c];
|
||||
}
|
||||
|
||||
*out++ = '\0';
|
||||
}
|
||||
|
||||
|
||||
int match_wildcard(const char* s, const char* w)
|
||||
{
|
||||
if(!w)
|
||||
return 1;
|
||||
|
||||
// saved position in both strings, used to expand '*':
|
||||
// s2 is advanced until match.
|
||||
// initially 0 - we abort on mismatch before the first '*'.
|
||||
const char* s2 = 0;
|
||||
const char* w2 = 0;
|
||||
|
||||
while(*s)
|
||||
{
|
||||
const int wc = *w;
|
||||
if(wc == '*')
|
||||
{
|
||||
// wildcard string ended with * => match.
|
||||
if(*++w == '\0')
|
||||
return 1;
|
||||
|
||||
w2 = w;
|
||||
s2 = s+1;
|
||||
}
|
||||
// match one character
|
||||
else if(toupper(wc) == toupper(*s) || wc == '?')
|
||||
{
|
||||
w++;
|
||||
s++;
|
||||
}
|
||||
// mismatched character
|
||||
else
|
||||
{
|
||||
// no '*' found yet => mismatch.
|
||||
if(!s2)
|
||||
return 0;
|
||||
|
||||
// resume at previous position+1
|
||||
w = w2;
|
||||
s = s2++;
|
||||
}
|
||||
}
|
||||
|
||||
// strip trailing * in wildcard string
|
||||
while(*w == '*')
|
||||
w++;
|
||||
|
||||
return (*w == '\0');
|
||||
}
|
||||
|
||||
int match_wildcardw(const wchar_t* s, const wchar_t* w)
|
||||
{
|
||||
if(!w)
|
||||
return 1;
|
||||
|
||||
// saved position in both strings, used to expand '*':
|
||||
// s2 is advanced until match.
|
||||
// initially 0 - we abort on mismatch before the first '*'.
|
||||
const wchar_t* s2 = 0;
|
||||
const wchar_t* w2 = 0;
|
||||
|
||||
while(*s)
|
||||
{
|
||||
const wchar_t wc = *w;
|
||||
if(wc == '*')
|
||||
{
|
||||
// wildcard string ended with * => match.
|
||||
if(*++w == '\0')
|
||||
return 1;
|
||||
|
||||
w2 = w;
|
||||
s2 = s+1;
|
||||
}
|
||||
// match one character
|
||||
else if(towupper(wc) == towupper(*s) || wc == '?')
|
||||
{
|
||||
w++;
|
||||
s++;
|
||||
}
|
||||
// mismatched character
|
||||
else
|
||||
{
|
||||
// no '*' found yet => mismatch.
|
||||
if(!s2)
|
||||
return 0;
|
||||
|
||||
// resume at previous position+1
|
||||
w = w2;
|
||||
s = s2++;
|
||||
}
|
||||
}
|
||||
|
||||
// strip trailing * in wildcard string
|
||||
while(*w == '*')
|
||||
w++;
|
||||
|
||||
return (*w == '\0');
|
||||
}
|
||||
|
||||
|
||||
// FNV1-A hash - good for strings.
|
||||
// if len = 0 (default), treat buf as a C-string;
|
||||
// otherwise, hash <len> bytes of buf.
|
||||
u32 fnv_hash(const void* buf, size_t len)
|
||||
{
|
||||
u32 h = 0x811c9dc5u;
|
||||
// give distinct values for different length 0 buffers.
|
||||
// value taken from FNV; it has no special significance.
|
||||
|
||||
const u8* p = (const u8*)buf;
|
||||
|
||||
// expected case: string
|
||||
if(!len)
|
||||
{
|
||||
while(*p)
|
||||
{
|
||||
h ^= *p++;
|
||||
h *= 0x01000193u;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t bytes_left = len;
|
||||
while(bytes_left != 0)
|
||||
{
|
||||
h ^= *p++;
|
||||
h *= 0x01000193u;
|
||||
|
||||
bytes_left--;
|
||||
}
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
// FNV1-A hash - good for strings.
|
||||
// if len = 0 (default), treat buf as a C-string;
|
||||
// otherwise, hash <len> bytes of buf.
|
||||
u64 fnv_hash64(const void* buf, size_t len)
|
||||
{
|
||||
u64 h = 0xCBF29CE484222325ull;
|
||||
// give distinct values for different length 0 buffers.
|
||||
// value taken from FNV; it has no special significance.
|
||||
|
||||
const u8* p = (const u8*)buf;
|
||||
|
||||
// expected case: string
|
||||
if(!len)
|
||||
{
|
||||
while(*p)
|
||||
{
|
||||
h ^= *p++;
|
||||
h *= 0x100000001B3ull;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t bytes_left = len;
|
||||
while(bytes_left != 0)
|
||||
{
|
||||
h ^= *p++;
|
||||
h *= 0x100000001B3ull;
|
||||
|
||||
bytes_left--;
|
||||
}
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
// special version for strings: first converts to lowercase
|
||||
// (useful for comparing mixed-case filenames).
|
||||
// note: still need <len>, e.g. to support non-0-terminated strings
|
||||
u32 fnv_lc_hash(const char* str, size_t len)
|
||||
{
|
||||
u32 h = 0x811c9dc5u;
|
||||
// give distinct values for different length 0 buffers.
|
||||
// value taken from FNV; it has no special significance.
|
||||
|
||||
// expected case: string
|
||||
if(!len)
|
||||
{
|
||||
while(*str)
|
||||
{
|
||||
h ^= tolower(*str++);
|
||||
h *= 0x01000193u;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t bytes_left = len;
|
||||
while(bytes_left != 0)
|
||||
{
|
||||
h ^= tolower(*str++);
|
||||
h *= 0x01000193u;
|
||||
|
||||
bytes_left--;
|
||||
}
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// helpers for module init
|
||||
|
||||
|
316
source/lib/lib.h
316
source/lib/lib.h
@ -49,19 +49,14 @@ scope
|
||||
|
||||
#include "config.h"
|
||||
|
||||
|
||||
const size_t KiB = 1ul << 10;
|
||||
const size_t MiB = 1ul << 20;
|
||||
const size_t GiB = 1ul << 30;
|
||||
|
||||
// generate a symbol containing the line number of the macro invocation.
|
||||
// used to give a unique name (per file) to types made by cassert.
|
||||
// we can't prepend __FILE__ to make it globally unique - the filename
|
||||
// may be enclosed in quotes. PASTE3_HIDDEN__ is needed to make sure
|
||||
// __LINE__ is expanded correctly.
|
||||
#define PASTE3_HIDDEN__(a, b, c) a ## b ## c
|
||||
#define PASTE3__(a, b, c) PASTE3_HIDDEN__(a, b, c)
|
||||
#define UID__ PASTE3__(LINE_, __LINE__, _)
|
||||
#define UID2__ PASTE3__(LINE_, __LINE__, _2)
|
||||
|
||||
/// number of array elements
|
||||
#define ARRAY_SIZE(name) (sizeof(name) / sizeof(name[0]))
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -85,9 +80,6 @@ const size_t GiB = 1ul << 30;
|
||||
**/
|
||||
#define STMT(STMT_code__) do { STMT_code__; } while(false)
|
||||
|
||||
// must come after definition of STMT
|
||||
#include "lib/lib_errors.h"
|
||||
|
||||
/**
|
||||
* execute the code passed as a parameter only the first time this is
|
||||
* reached.
|
||||
@ -184,225 +176,6 @@ STMT(\
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// source code annotation
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* mark a function local variable or parameter as unused and avoid
|
||||
* the corresponding compiler warning.
|
||||
* use inside the function body, e.g. void f(int x) { UNUSED2(x); }
|
||||
**/
|
||||
#define UNUSED2(param) (void)param;
|
||||
|
||||
/**
|
||||
* mark a function parameter as unused and avoid
|
||||
* the corresponding compiler warning.
|
||||
* wrap around the parameter name, e.g. void f(int UNUSED(x))
|
||||
**/
|
||||
#define UNUSED(param)
|
||||
|
||||
|
||||
/**
|
||||
"unreachable code" helpers
|
||||
|
||||
unreachable lines of code are often the source or symptom of subtle bugs.
|
||||
they are flagged by compiler warnings; however, the opposite problem -
|
||||
erroneously reaching certain spots (e.g. due to missing return statement)
|
||||
is worse and not detected automatically.
|
||||
|
||||
to defend against this, the programmer can annotate their code to
|
||||
indicate to humans that a particular spot should never be reached.
|
||||
however, that isn't much help; better is a sentinel that raises an
|
||||
error if if it is actually reached. hence, the UNREACHABLE macro.
|
||||
|
||||
ironically, if the code guarded by UNREACHABLE works as it should,
|
||||
compilers may flag the macro's code as unreachable. this would
|
||||
distract from genuine warnings, which is unacceptable.
|
||||
|
||||
even worse, compilers differ in their code checking: GCC only complains if
|
||||
non-void functions end without returning a value (i.e. missing return
|
||||
statement), while VC checks if lines are unreachable (e.g. if they are
|
||||
preceded by a return on all paths).
|
||||
|
||||
our implementation of UNREACHABLE solves this dilemna as follows:
|
||||
- on GCC: call abort(); since it has the noreturn attributes, the
|
||||
"non-void" warning disappears.
|
||||
- on VC: avoid generating any code. we allow the compiler to assume the
|
||||
spot is actually unreachable, which incidentally helps optimization.
|
||||
if reached after all, a crash usually results. in that case, compile with
|
||||
CONFIG_PARANOIA, which will cause an error message to be displayed.
|
||||
|
||||
this approach still allows for the possiblity of automated
|
||||
checking, but does not cause any compiler warnings.
|
||||
**/
|
||||
#define UNREACHABLE // actually defined below.. this is for
|
||||
# undef UNREACHABLE // CppDoc's benefit only.
|
||||
|
||||
// 1) final build: optimize assuming this location cannot be reached.
|
||||
// may crash if that turns out to be untrue, but removes checking overhead.
|
||||
#if CONFIG_FINAL
|
||||
# define UNREACHABLE ASSUME_UNREACHABLE
|
||||
// 2) normal build:
|
||||
#else
|
||||
// a) normal implementation: includes "abort", which is declared with
|
||||
// noreturn attribute and therefore avoids GCC's "execution reaches
|
||||
// end of non-void function" warning.
|
||||
# if !MSC_VERSION || CONFIG_PARANOIA
|
||||
# define UNREACHABLE\
|
||||
STMT(\
|
||||
debug_warn("hit supposedly unreachable code");\
|
||||
abort();\
|
||||
)
|
||||
// b) VC only: don't generate any code; squelch the warning and optimize.
|
||||
# else
|
||||
# define UNREACHABLE ASSUME_UNREACHABLE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
convenient specialization of UNREACHABLE for switch statements whose
|
||||
default can never be reached. example usage:
|
||||
int x;
|
||||
switch(x % 2)
|
||||
{
|
||||
case 0: break;
|
||||
case 1: break;
|
||||
NODEFAULT;
|
||||
}
|
||||
**/
|
||||
#define NODEFAULT default: UNREACHABLE
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// cassert
|
||||
|
||||
/**
|
||||
* compile-time debug_assert. causes a compile error if the expression
|
||||
* evaluates to zero/false.
|
||||
*
|
||||
* no runtime overhead; may be used anywhere, including file scope.
|
||||
* especially useful for testing sizeof types.
|
||||
*
|
||||
* this version has a more descriptive error message, but may cause a
|
||||
* struct redefinition warning if used from the same line in different files.
|
||||
*
|
||||
* note: alternative method in C++: specialize a struct only for true;
|
||||
* using it will raise 'incomplete type' errors if instantiated with false.
|
||||
*
|
||||
* @param expression that is expected to evaluate to non-zero at compile-time.
|
||||
**/
|
||||
#define cassert(expr) struct UID__ { int CASSERT_FAILURE: (expr); }
|
||||
|
||||
/**
|
||||
* compile-time debug_assert. causes a compile error if the expression
|
||||
* evaluates to zero/false.
|
||||
*
|
||||
* no runtime overhead; may be used anywhere, including file scope.
|
||||
* especially useful for testing sizeof types.
|
||||
*
|
||||
* this version has a less helpful error message, but redefinition doesn't
|
||||
* trigger warnings.
|
||||
*
|
||||
* @param expression that is expected to evaluate to non-zero at compile-time.
|
||||
**/
|
||||
#define cassert2(expr) extern char CASSERT_FAILURE[1][(expr)]
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// bit bashing
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* value of bit number <n>.
|
||||
*
|
||||
* @param n bit index (0..CHAR_BIT*sizeof(int)-1)
|
||||
**/
|
||||
#define BIT(n) (1ul << (n))
|
||||
|
||||
|
||||
// these are declared in the header and inlined to aid compiler optimizations
|
||||
// (they can easily end up being time-critical).
|
||||
// note: GCC can't inline extern functions, while VC's "Whole Program
|
||||
// Optimization" can.
|
||||
|
||||
/**
|
||||
* a mask that includes the lowest N bits
|
||||
*
|
||||
* @param num_bits number of bits in mask
|
||||
**/
|
||||
inline uint bit_mask(uint num_bits)
|
||||
{
|
||||
return (1u << num_bits)-1;
|
||||
}
|
||||
|
||||
/**
|
||||
* extract the value of bits hi_idx:lo_idx within num
|
||||
*
|
||||
* example: bits(0x69, 2, 5) == 0x0A
|
||||
*
|
||||
* @param num number whose bits are to be extracted
|
||||
* @param lo_idx bit index of lowest bit to include
|
||||
* @param hi_idx bit index of highest bit to include
|
||||
* @return value of extracted bits.
|
||||
**/
|
||||
inline uint bits(uint num, uint lo_idx, uint hi_idx)
|
||||
{
|
||||
const uint count = (hi_idx - lo_idx)+1; // # bits to return
|
||||
uint result = num >> lo_idx;
|
||||
result &= bit_mask(count);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// is the given number a power of two?
|
||||
extern bool is_pow2(uint n);
|
||||
|
||||
/**
|
||||
* base-2 logarithm; return -1 for non-integral powers of 2.
|
||||
**/
|
||||
extern int ilog2(uint n);
|
||||
|
||||
/**
|
||||
* base-2 logarithm, rounded up.
|
||||
*
|
||||
* @param n input; MUST be > 0, else results are undefined.
|
||||
**/
|
||||
extern uint log2(uint x);
|
||||
|
||||
/**
|
||||
* base-2 logarithm (uses the FPU normalization hardware).
|
||||
*
|
||||
* @param n input; MUST be > 0, else results are undefined.
|
||||
**/
|
||||
extern int ilog2(const float x);
|
||||
|
||||
/**
|
||||
* round up to next larger power of two.
|
||||
**/
|
||||
extern uint round_up_to_pow2(uint x);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// misc arithmetic
|
||||
|
||||
/// canonical minimum macro
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) (((a) < (b))? (a) : (b))
|
||||
#endif
|
||||
|
||||
/// canonical maximum macro
|
||||
#ifndef MAX
|
||||
#define MAX(a, b) (((a) > (b))? (a) : (b))
|
||||
#endif
|
||||
|
||||
/// number of array elements
|
||||
#define ARRAY_SIZE(name) (sizeof(name) / sizeof(name[0]))
|
||||
|
||||
/**
|
||||
* round number up/down to the next given multiple.
|
||||
*
|
||||
* @param multiple: must be a power of two.
|
||||
**/
|
||||
extern uintptr_t round_up (uintptr_t n, uintptr_t multiple);
|
||||
extern uintptr_t round_down(uintptr_t n, uintptr_t multiple);
|
||||
|
||||
/// 16-bit saturating (does not overflow) addition.
|
||||
extern u16 addusw(u16 x, u16 y);
|
||||
@ -457,87 +230,10 @@ extern u16 u32_lo(u32 x); /// return lower 16-bits
|
||||
extern u64 u64_from_u32(u32 hi, u32 lo); /// assemble u64 from u32
|
||||
extern u32 u32_from_u16(u16 hi, u16 lo); /// assemble u32 from u16
|
||||
|
||||
/**
|
||||
* zero-extend <size> (truncated to 8) bytes of little-endian data to u64,
|
||||
* starting at address <p> (need not be aligned).
|
||||
**/
|
||||
extern u64 movzx_64le(const u8* p, size_t size);
|
||||
|
||||
/**
|
||||
* sign-extend <size> (truncated to 8) bytes of little-endian data to i64,
|
||||
* starting at address <p> (need not be aligned).
|
||||
**/
|
||||
extern i64 movsx_64le(const u8* p, size_t size);
|
||||
|
||||
/// convert double to u8; verifies number is in range.
|
||||
extern u8 fp_to_u8 (double in);
|
||||
extern u8 u8_from_double(double in);
|
||||
/// convert double to u16; verifies number is in range.
|
||||
extern u16 fp_to_u16(double in);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// string processing
|
||||
|
||||
/**
|
||||
* this is strcpy, but indicates that the programmer checked usage and
|
||||
* promises it is safe.
|
||||
*
|
||||
* (this macro prevents actually-safe instances of the function from
|
||||
* showing up in searches)
|
||||
**/
|
||||
#define SAFE_STRCPY str##cpy
|
||||
#define SAFE_WCSCPY wcs##cpy
|
||||
|
||||
|
||||
/**
|
||||
* generate the base32 textual representation of a buffer.
|
||||
*
|
||||
* @param len size [bytes] of input
|
||||
* @param big-endian input data (assumed to be integral number of bytes)
|
||||
* @param output string; zero-terminated. must be big enough
|
||||
* (i.e. at least ceil(len*CHAR_BIT/5) + 1 chars)
|
||||
**/
|
||||
extern void base32(const size_t len, const u8* in, u8* out);
|
||||
|
||||
|
||||
/**
|
||||
* partial regex implementation: see if string matches pattern.
|
||||
*
|
||||
* @param s input string
|
||||
* @param w pseudo-regex to match against. case-insensitive;
|
||||
* may contain '?' and/or '*' wildcards. if NULL, matches everything.
|
||||
*
|
||||
* @return 1 if they match, otherwise 0.
|
||||
*
|
||||
* algorithmfrom http://www.codeproject.com/string/wildcmp.asp.
|
||||
**/
|
||||
extern int match_wildcard(const char* s, const char* w);
|
||||
/// unicode version of match_wildcard.
|
||||
extern int match_wildcardw(const wchar_t* s, const wchar_t* w);
|
||||
|
||||
|
||||
/**
|
||||
* calculate FNV1-A hash.
|
||||
*
|
||||
* @param buf input buffer.
|
||||
* @param len if 0 (default), treat buf as a C-string; otherwise,
|
||||
* indicates how many bytes of buffer to hash.
|
||||
* @return hash result. note: results are distinct for buffers containing
|
||||
* differing amounts of zero bytes because the hash value is seeded.
|
||||
*
|
||||
* rationale: this algorithm was chosen because it delivers 'good' results
|
||||
* for string data and is relatively simple. other good alternatives exist;
|
||||
* see Ozan Yigit's hash roundup.
|
||||
**/
|
||||
extern u32 fnv_hash(const void* buf, size_t len = 0);
|
||||
/// 64-bit version of fnv_hash.
|
||||
extern u64 fnv_hash64(const void* buf, size_t len = 0);
|
||||
|
||||
/**
|
||||
* special version of fnv_hash for strings: first converts to lowercase
|
||||
* (useful for comparing mixed-case filenames)
|
||||
**/
|
||||
extern u32 fnv_lc_hash(const char* str, size_t len = 0);
|
||||
extern u16 u16_from_double(double in);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "lib/posix/posix_pthread.h"
|
||||
#include "lib.h"
|
||||
#include "lib/bits.h"
|
||||
#include "lib/sysdep/cpu.h"
|
||||
#include "lib/sysdep/sysdep.h"
|
||||
#include "timer.h"
|
||||
|
@ -31,7 +31,6 @@ AT_STARTUP(\
|
||||
#include <stdarg.h>
|
||||
#include <new>
|
||||
|
||||
#include "lib.h"
|
||||
#include "posix/posix.h"
|
||||
#include "debug.h"
|
||||
|
||||
@ -507,9 +506,9 @@ static void stats_add(const Alloc* a)
|
||||
stats.total_mem += size;
|
||||
stats.total_allocs++;
|
||||
|
||||
stats.peak_user_mem = MAX(stats.peak_user_mem, stats.cur_user_mem);
|
||||
stats.peak_mem = MAX(stats.peak_mem, stats.cur_mem);
|
||||
stats.peak_allocs = MAX(stats.peak_allocs, stats.cur_allocs);
|
||||
stats.peak_user_mem = std::max(stats.peak_user_mem, stats.cur_user_mem);
|
||||
stats.peak_mem = std::max(stats.peak_mem, stats.cur_mem);
|
||||
stats.peak_allocs = std::max(stats.peak_allocs, stats.cur_allocs);
|
||||
}
|
||||
|
||||
static void stats_remove(const Alloc* a)
|
||||
@ -1212,7 +1211,7 @@ void* realloc_dbg(const void* user_p, size_t user_size, AllocType type, const ch
|
||||
// old_size should only be non-zero if the Alloc security checks all passed
|
||||
// If the old buffer was actually zero bytes large, do nothing :P
|
||||
if (old_size && ret)
|
||||
cpu_memcpy(ret, user_p, MIN(old_size, user_size));
|
||||
cpu_memcpy(ret, user_p, std::min(old_size, user_size));
|
||||
|
||||
if(user_p)
|
||||
free_dbg(user_p, AT_FREE, file,line,func, stack_frames+1);
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "lib.h"
|
||||
#include "lib/external_libraries/sdl.h"
|
||||
#include "debug.h"
|
||||
#include "lib/sysdep/gfx.h"
|
||||
|
@ -14,8 +14,6 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "lib.h"
|
||||
|
||||
|
||||
AT_STARTUP(\
|
||||
error_setDescription(ERR::PATH_LENGTH, "Path exceeds PATH_MAX characters");\
|
||||
@ -236,7 +234,7 @@ const char* path_name_only(const char* path)
|
||||
return path;
|
||||
|
||||
// return name, i.e. component after the last portable or platform slash
|
||||
return MAX(slash1, slash2)+1;
|
||||
return std::max(slash1, slash2)+1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -44,9 +44,11 @@
|
||||
//
|
||||
|
||||
#include "lib/types.h"
|
||||
#include "lib/lib.h"
|
||||
#include "lib/lib_errors.h"
|
||||
#include "lib/string_s.h" // CRT secure string
|
||||
#include "lib/debug.h"
|
||||
#include "lib/code_annotation.h"
|
||||
#include "lib/sysdep/compiler.h"
|
||||
#include "lib/sysdep/stl.h"
|
||||
#include "lib/posix/posix.h"
|
||||
|
110
source/lib/regex.cpp
Normal file
110
source/lib/regex.cpp
Normal file
@ -0,0 +1,110 @@
|
||||
/**
|
||||
* =========================================================================
|
||||
* File : regex.cpp
|
||||
* Project : 0 A.D.
|
||||
* Description : minimal regex implementation
|
||||
* =========================================================================
|
||||
*/
|
||||
|
||||
// license: GPL; see lib/license.txt
|
||||
|
||||
#include "precompiled.h"
|
||||
|
||||
|
||||
int match_wildcard(const char* s, const char* w)
|
||||
{
|
||||
if(!w)
|
||||
return 1;
|
||||
|
||||
// saved position in both strings, used to expand '*':
|
||||
// s2 is advanced until match.
|
||||
// initially 0 - we abort on mismatch before the first '*'.
|
||||
const char* s2 = 0;
|
||||
const char* w2 = 0;
|
||||
|
||||
while(*s)
|
||||
{
|
||||
const int wc = *w;
|
||||
if(wc == '*')
|
||||
{
|
||||
// wildcard string ended with * => match.
|
||||
if(*++w == '\0')
|
||||
return 1;
|
||||
|
||||
w2 = w;
|
||||
s2 = s+1;
|
||||
}
|
||||
// match one character
|
||||
else if(toupper(wc) == toupper(*s) || wc == '?')
|
||||
{
|
||||
w++;
|
||||
s++;
|
||||
}
|
||||
// mismatched character
|
||||
else
|
||||
{
|
||||
// no '*' found yet => mismatch.
|
||||
if(!s2)
|
||||
return 0;
|
||||
|
||||
// resume at previous position+1
|
||||
w = w2;
|
||||
s = s2++;
|
||||
}
|
||||
}
|
||||
|
||||
// strip trailing * in wildcard string
|
||||
while(*w == '*')
|
||||
w++;
|
||||
|
||||
return (*w == '\0');
|
||||
}
|
||||
|
||||
int match_wildcardw(const wchar_t* s, const wchar_t* w)
|
||||
{
|
||||
if(!w)
|
||||
return 1;
|
||||
|
||||
// saved position in both strings, used to expand '*':
|
||||
// s2 is advanced until match.
|
||||
// initially 0 - we abort on mismatch before the first '*'.
|
||||
const wchar_t* s2 = 0;
|
||||
const wchar_t* w2 = 0;
|
||||
|
||||
while(*s)
|
||||
{
|
||||
const wchar_t wc = *w;
|
||||
if(wc == '*')
|
||||
{
|
||||
// wildcard string ended with * => match.
|
||||
if(*++w == '\0')
|
||||
return 1;
|
||||
|
||||
w2 = w;
|
||||
s2 = s+1;
|
||||
}
|
||||
// match one character
|
||||
else if(towupper(wc) == towupper(*s) || wc == '?')
|
||||
{
|
||||
w++;
|
||||
s++;
|
||||
}
|
||||
// mismatched character
|
||||
else
|
||||
{
|
||||
// no '*' found yet => mismatch.
|
||||
if(!s2)
|
||||
return 0;
|
||||
|
||||
// resume at previous position+1
|
||||
w = w2;
|
||||
s = s2++;
|
||||
}
|
||||
}
|
||||
|
||||
// strip trailing * in wildcard string
|
||||
while(*w == '*')
|
||||
w++;
|
||||
|
||||
return (*w == '\0');
|
||||
}
|
29
source/lib/regex.h
Normal file
29
source/lib/regex.h
Normal file
@ -0,0 +1,29 @@
|
||||
/**
|
||||
* =========================================================================
|
||||
* File : regex.h
|
||||
* Project : 0 A.D.
|
||||
* Description : minimal regex implementation
|
||||
* =========================================================================
|
||||
*/
|
||||
|
||||
// license: GPL; see lib/license.txt
|
||||
|
||||
#ifndef INCLUDED_REGEX
|
||||
#define INCLUDED_REGEX
|
||||
|
||||
/**
|
||||
* see if string matches pattern.
|
||||
*
|
||||
* @param s input string
|
||||
* @param w pseudo-regex to match against. case-insensitive;
|
||||
* may contain '?' and/or '*' wildcards. if NULL, matches everything.
|
||||
*
|
||||
* @return 1 if they match, otherwise 0.
|
||||
*
|
||||
* algorithmfrom http://www.codeproject.com/string/wildcmp.asp.
|
||||
**/
|
||||
extern int match_wildcard(const char* s, const char* w);
|
||||
/// unicode version of match_wildcard.
|
||||
extern int match_wildcardw(const wchar_t* s, const wchar_t* w);
|
||||
|
||||
#endif // #ifndef INCLUDED_REGEX
|
@ -432,7 +432,7 @@ LibError afile_io_issue(File* f, off_t user_ofs, size_t max_output_size, void* u
|
||||
// less work for aio) or up to EOF.
|
||||
const ssize_t left_in_chunk = CHUNK_SIZE - (cofs % CHUNK_SIZE);
|
||||
const ssize_t left_in_file = af->csize - cofs;
|
||||
const size_t csize = MIN(left_in_chunk, left_in_file);
|
||||
const size_t csize = std::min(left_in_chunk, left_in_file);
|
||||
|
||||
void* cbuf = mem_alloc(csize, 4*KiB);
|
||||
if(!cbuf)
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include "precompiled.h"
|
||||
#include "archive_builder.h"
|
||||
|
||||
#include "lib/lib.h"
|
||||
#include "lib/timer.h"
|
||||
#include "file_internal.h"
|
||||
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include "lib/posix/posix_filesystem.h"
|
||||
#include "lib/posix/posix_aio.h"
|
||||
#include "lib/posix/posix_mman.h"
|
||||
#include "lib/lib.h"
|
||||
#include "lib/adts.h"
|
||||
#include "lib/sysdep/sysdep.h"
|
||||
#include "lib/byte_order.h"
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include "lib/posix/posix_mman.h"
|
||||
#include "lib/allocators.h"
|
||||
#include "lib/bits.h"
|
||||
#include "lib/byte_order.h"
|
||||
#include "lib/cache_adt.h"
|
||||
#include "file_internal.h"
|
||||
@ -499,7 +500,7 @@ private:
|
||||
// except for i=0, which corresponds to size=1.
|
||||
static uint size_class_of(size_t size_pa)
|
||||
{
|
||||
return log2((uint)size_pa);
|
||||
return ceil_log2((uint)size_pa);
|
||||
}
|
||||
|
||||
// value of LSB 1-bit.
|
||||
|
@ -14,7 +14,7 @@
|
||||
#include <deque>
|
||||
|
||||
#include "lib/posix/posix_aio.h"
|
||||
#include "lib/lib.h"
|
||||
#include "lib/bits.h"
|
||||
#include "lib/allocators.h"
|
||||
#include "lib/adts.h"
|
||||
#include "file_internal.h"
|
||||
@ -434,7 +434,7 @@ class IOManager
|
||||
const off_t bytes_left = f->size - start_ofs;
|
||||
if(bytes_left < 0)
|
||||
WARN_RETURN(ERR::IO_EOF);
|
||||
size = MIN(size, (size_t)bytes_left);
|
||||
size = std::min(size, (size_t)bytes_left);
|
||||
|
||||
// and round back up to sector size.
|
||||
// see rationale in file_io_issue.
|
||||
@ -450,7 +450,7 @@ class IOManager
|
||||
{
|
||||
const off_t ofs = start_ofs+(off_t)total_issued;
|
||||
// for both reads and writes, do not issue beyond end of file/data
|
||||
const size_t issue_size = MIN(FILE_BLOCK_SIZE, size - total_issued);
|
||||
const size_t issue_size = std::min(FILE_BLOCK_SIZE, size - total_issued);
|
||||
// try to grab whole blocks (so we can put them in the cache).
|
||||
// any excess data (can only be within first or last) is
|
||||
// discarded in wait().
|
||||
|
@ -119,7 +119,7 @@ void stats_unique_name(size_t name_len)
|
||||
void stats_open(const char* atom_fn, size_t file_size)
|
||||
{
|
||||
open_files_cur++;
|
||||
open_files_max = MAX(open_files_max, open_files_cur);
|
||||
open_files_max = std::max(open_files_max, open_files_cur);
|
||||
|
||||
PairIB ret = opened_files.insert(atom_fn);
|
||||
// hadn't been opened yet
|
||||
@ -141,7 +141,7 @@ void stats_close()
|
||||
void stats_buf_alloc(size_t user_size, size_t padded_size)
|
||||
{
|
||||
extant_bufs_cur++;
|
||||
extant_bufs_max = MAX(extant_bufs_max, extant_bufs_cur);
|
||||
extant_bufs_max = std::max(extant_bufs_max, extant_bufs_cur);
|
||||
extant_bufs_total++;
|
||||
|
||||
buf_user_size_total += user_size;
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include <queue>
|
||||
|
||||
#include "lib/regex.h"
|
||||
#include "file_internal.h"
|
||||
|
||||
|
||||
@ -285,7 +286,7 @@ void next_numbered_filename(const char* fn_fmt,
|
||||
while(vfs_dir_next_ent(hd, &ent, 0) == INFO::OK)
|
||||
{
|
||||
if(!DIRENT_IS_DIR(&ent) && sscanf(ent.name, name_fmt, &num) == 1)
|
||||
max_num = MAX(num, max_num);
|
||||
max_num = std::max(num, max_num);
|
||||
}
|
||||
(void)vfs_dir_close(hd);
|
||||
}
|
||||
@ -297,7 +298,7 @@ void next_numbered_filename(const char* fn_fmt,
|
||||
{
|
||||
while(dir_next_ent(&it, &ent) == INFO::OK)
|
||||
if(!DIRENT_IS_DIR(&ent) && sscanf(ent.name, name_fmt, &num) == 1)
|
||||
max_num = MAX(num, max_num);
|
||||
max_num = std::max(num, max_num);
|
||||
(void)dir_close(&it);
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "lib/posix/posix_filesystem.h"
|
||||
#include "lib/lib.h"
|
||||
#include "lib/adts.h"
|
||||
#include "lib/allocators.h"
|
||||
#include "lib/sysdep/sysdep.h"
|
||||
|
@ -11,8 +11,6 @@
|
||||
#ifndef INCLUDED_PATH
|
||||
#define INCLUDED_PATH
|
||||
|
||||
#include "lib/lib.h"
|
||||
|
||||
|
||||
namespace ERR
|
||||
{
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "lib/self_test.h"
|
||||
|
||||
#include "lib/base32.h"
|
||||
#include "lib/res/file/path.h"
|
||||
#include "lib/res/file/file.h"
|
||||
#include "lib/res/file/file_cache.h"
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include "lib/self_test.h"
|
||||
|
||||
#include "lib/lib.h"
|
||||
#include "lib/self_test.h"
|
||||
#include "lib/res/file/compression.h"
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include "lib/self_test.h"
|
||||
|
||||
#include "lib/lib.h"
|
||||
#include "lib/res/file/file_cache.h"
|
||||
|
||||
class TestFileCache : public CxxTest::TestSuite
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include "lib/self_test.h"
|
||||
|
||||
#include "lib/lib.h"
|
||||
#include "lib/self_test.h"
|
||||
#include "lib/res/file/path.h"
|
||||
#include "lib/res/file/file.h"
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "lib/lib.h"
|
||||
#include "lib/res/file/zip.h"
|
||||
|
||||
class TestZip : public CxxTest::TestSuite
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
#include "lib/lib.h"
|
||||
#include "lib/adts.h"
|
||||
#include "lib/timer.h"
|
||||
#include "lib/res/res.h"
|
||||
|
@ -498,7 +498,7 @@ static bool should_rebuild_main_archive(const char* trace_filename,
|
||||
// note: a loop is more convenient than std::for_each, which would
|
||||
// require referencing the returned functor (since param is a copy).
|
||||
for(DirEnts::const_iterator it = existing_archives.begin(); it != existing_archives.end(); ++it)
|
||||
most_recent_archive_mtime = MAX(it->mtime, most_recent_archive_mtime);
|
||||
most_recent_archive_mtime = std::max(it->mtime, most_recent_archive_mtime);
|
||||
// .. no archive yet OR 'lots' of them: rebuild so that they'll be
|
||||
// merged into one archive and the rest deleted.
|
||||
if(existing_archives.empty() || existing_archives.size() >= 4)
|
||||
|
@ -56,7 +56,7 @@ static void* node_alloc();
|
||||
static time_t most_recent_mtime;
|
||||
static void set_most_recent_if_newer(time_t mtime)
|
||||
{
|
||||
most_recent_mtime = MAX(most_recent_mtime, mtime);
|
||||
most_recent_mtime = std::max(most_recent_mtime, mtime);
|
||||
}
|
||||
time_t tree_most_recent_mtime()
|
||||
{
|
||||
@ -316,7 +316,7 @@ static Pool node_pool;
|
||||
|
||||
static inline void node_init()
|
||||
{
|
||||
const size_t el_size = MAX(sizeof(TDir), sizeof(TFile));
|
||||
const size_t el_size = std::max(sizeof(TDir), sizeof(TFile));
|
||||
(void)pool_create(&node_pool, VFS_MAX_FILES*el_size, el_size);
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
#include <time.h>
|
||||
#include <limits>
|
||||
|
||||
#include "lib/lib.h"
|
||||
#include "lib/bits.h"
|
||||
#include "lib/byte_order.h"
|
||||
#include "lib/allocators.h"
|
||||
#include "lib/timer.h"
|
||||
@ -361,7 +361,7 @@ static LibError za_find_ecdr(File* f, size_t max_scan_amount, ECDR* dst_ecdr_le)
|
||||
{
|
||||
// don't scan more than the entire file
|
||||
const size_t file_size = f->size;
|
||||
const size_t scan_amount = MIN(max_scan_amount, file_size);
|
||||
const size_t scan_amount = std::min(max_scan_amount, file_size);
|
||||
|
||||
// read desired chunk of file into memory
|
||||
const off_t ofs = (off_t)(file_size - scan_amount);
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include "precompiled.h"
|
||||
#include "ogl_shader.h"
|
||||
|
||||
#include "lib/lib.h"
|
||||
#include "lib/res/res.h"
|
||||
#include "lib/ogl.h"
|
||||
|
||||
|
@ -12,9 +12,9 @@
|
||||
#include "precompiled.h"
|
||||
#include "ogl_tex.h"
|
||||
|
||||
#include "lib/lib.h"
|
||||
#include "lib/app_hooks.h"
|
||||
#include "lib/ogl.h"
|
||||
#include "lib/bits.h"
|
||||
#include "lib/sysdep/gfx.h"
|
||||
#include "lib/res/res.h"
|
||||
#include "tex.h"
|
||||
@ -741,7 +741,7 @@ static LibError get_mipmaps(Tex* t, GLint filter, uint q_flags, int* plevels_to_
|
||||
// require uploading unused levels, which is wasteful.
|
||||
// .. can be expanded to reduce to 1/4, 1/8 by encoding factor in q_flags.
|
||||
const uint reduce = (q_flags & OGL_TEX_HALF_RES)? 2 : 1;
|
||||
*plevels_to_skip = log2(reduce);
|
||||
*plevels_to_skip = ceil_log2(reduce);
|
||||
}
|
||||
|
||||
return INFO::OK;
|
||||
|
@ -15,8 +15,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include "lib/lib.h"
|
||||
#include "lib/timer.h"
|
||||
#include "lib/bits.h"
|
||||
#include "lib/res/res.h"
|
||||
|
||||
#include "tex_codec.h"
|
||||
@ -192,7 +192,7 @@ static void create_level(uint level, uint level_w, uint level_h,
|
||||
// image is either a horizontal or vertical line.
|
||||
// their memory layout is the same (packed pixels), so no special
|
||||
// handling is needed; just pick max dimension.
|
||||
for(uint y = 0; y < MAX(src_w, src_h); y += 2)
|
||||
for(uint y = 0; y < std::max(src_w, src_h); y += 2)
|
||||
{
|
||||
for(uint i = 0; i < num_components; i++)
|
||||
{
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include "lib/byte_order.h"
|
||||
#include "tex_codec.h"
|
||||
#include "lib/bits.h"
|
||||
|
||||
// NOTE: the convention is bottom-up for DDS, but there's no way to tell.
|
||||
|
||||
@ -549,7 +550,7 @@ static LibError decode_sd(const DDSURFACEDESC2* sd, uint* w_, uint* h_,
|
||||
{
|
||||
// mipmap chain is incomplete
|
||||
// note: DDS includes the base level in its count, hence +1.
|
||||
if(mipmap_count != log2(MAX(w,h))+1)
|
||||
if(mipmap_count != ceil_log2(std::max(w,h))+1)
|
||||
WARN_RETURN(ERR::TEX_FMT_INVALID);
|
||||
flags |= TEX_MIPMAPS;
|
||||
}
|
||||
|
@ -16,7 +16,6 @@ extern "C" {
|
||||
#include <jerror.h>
|
||||
}
|
||||
|
||||
#include "lib/lib.h"
|
||||
#include "lib/res/res.h"
|
||||
#include "tex_codec.h"
|
||||
#include <setjmp.h>
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
#include "lib/byte_order.h"
|
||||
#include "tex_codec.h"
|
||||
|
||||
#include "lib/bits.h"
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include <sstream>
|
||||
#include <map>
|
||||
|
||||
#include "lib/lib.h"
|
||||
#include "lib/ogl.h"
|
||||
#include "lib/res/res.h"
|
||||
#include "ogl_tex.h"
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <new> // std::bad_alloc
|
||||
|
||||
#include "lib/lib.h"
|
||||
#include "lib/fnv_hash.h"
|
||||
#include "lib/allocators.h"
|
||||
|
||||
|
||||
|
@ -232,8 +232,6 @@ we could switch H_DEREF to throwing an exception on error.
|
||||
|
||||
#include <stdarg.h> // type init routines get va_list of args
|
||||
|
||||
#include "lib/lib.h"
|
||||
|
||||
#ifndef INCLUDED_HANDLE
|
||||
#include "handle.h"
|
||||
#endif
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include <map>
|
||||
|
||||
#include "lib/posix/posix_pthread.h"
|
||||
#include "lib/lib.h"
|
||||
#include "lib/bits.h"
|
||||
#include "lib/allocators.h" // OverrunProtector
|
||||
#include "h_mgr.h"
|
||||
|
||||
|
@ -2376,7 +2376,7 @@ static LibError vm_update()
|
||||
// partition list; the first al_src_cap will be granted a source
|
||||
// (if they don't have one already), after reclaiming all sources from
|
||||
// the remainder of the VSrc list entries.
|
||||
uint first_unimportant = MIN((uint)vsrcs.size(), al_src_cap);
|
||||
uint first_unimportant = std::min((uint)vsrcs.size(), al_src_cap);
|
||||
list_foreach(reclaim, first_unimportant, 0);
|
||||
list_foreach(grant, 0, first_unimportant);
|
||||
|
||||
|
@ -27,9 +27,9 @@ Guidelines
|
||||
What makes a good self-test?
|
||||
- They belong in the module being tested to ensure they are kept in
|
||||
sync with it.
|
||||
- It is easiest to attach them to low-level functions, e.g. ilog2, rather
|
||||
than verifying the module's final result (e.g. checking renderer output by
|
||||
comparing pictures).
|
||||
- It is easiest to attach them to low-level functions, e.g. log2_of_pow2,
|
||||
rather than verifying the module's final result (e.g. checking renderer
|
||||
output by comparing pictures).
|
||||
- You should cover all cases: expected failures ("does it fail as expected?"),
|
||||
bad inputs ("does it reject those?"), and successes ("did it have the
|
||||
expected result?").
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "lib.h"
|
||||
#include "posix/posix_types.h" // SIZE_MAX
|
||||
|
||||
// we were included from wstring_s.cpp; skip all stuff that
|
||||
@ -127,7 +126,7 @@ int tncpy_s(tchar* dst, size_t max_dst_chars, const tchar* src, size_t max_src_c
|
||||
// optimized for size (less comparisons than MS impl) and
|
||||
// speed (due to well-predicted jumps; we don't bother unrolling).
|
||||
tchar* p = dst;
|
||||
size_t chars_left = MIN(max_dst_chars, max_src_chars);
|
||||
size_t chars_left = std::min(max_dst_chars, max_src_chars);
|
||||
while(chars_left != 0)
|
||||
{
|
||||
// success: reached end of string normally.
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include "precompiled.h"
|
||||
#include "cpu.h"
|
||||
|
||||
#include "lib/lib.h"
|
||||
#include "lib/bits.h"
|
||||
#include "lib/posix/posix.h"
|
||||
#if CPU_IA32
|
||||
# include "lib/sysdep/ia32/ia32.h"
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include "precompiled.h"
|
||||
#include "gfx.h"
|
||||
|
||||
#include "lib/lib.h"
|
||||
#include "lib/external_libraries/sdl.h"
|
||||
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "lib/posix/posix_pthread.h"
|
||||
#include "lib/lib.h"
|
||||
#include "lib/bits.h"
|
||||
#include "lib/timer.h"
|
||||
#include "lib/sysdep/cpu.h"
|
||||
|
||||
@ -456,7 +456,7 @@ static void StoreApicId(void* param)
|
||||
// used to gather e.g. all core IDs from all APIC IDs.
|
||||
static void ExtractFieldsIntoSet(const Ids& apic_ids, uint& bit_pos, uint num_values, IdSet& ids)
|
||||
{
|
||||
const uint id_bits = log2(num_values); // (rounded up)
|
||||
const uint id_bits = ceil_log2(num_values);
|
||||
if(id_bits == 0)
|
||||
return;
|
||||
|
||||
|
@ -297,6 +297,21 @@ sym(ia32_asm_rdtsc_edx_eax):
|
||||
ret
|
||||
|
||||
|
||||
; extern "C" int ia32_asm_log2_of_pow2(uint n)
|
||||
global sym(ia32_asm_log2_of_pow2)
|
||||
sym(ia32_asm_log2_of_pow2):
|
||||
mov ecx, [esp+4] ; n
|
||||
or eax, -1 ; return value if not a POT
|
||||
test ecx, ecx
|
||||
jz .not_pot
|
||||
lea edx, [ecx-1]
|
||||
test ecx, edx
|
||||
jnz .not_pot
|
||||
bsf eax, ecx
|
||||
.not_pot:
|
||||
ret
|
||||
|
||||
|
||||
; write the current execution state (e.g. all register values) into
|
||||
; (Win32::CONTEXT*)pcontext (defined as void* to avoid dependency).
|
||||
; optimized for size; this must be straight asm because ; extern "C"
|
||||
|
@ -76,6 +76,14 @@ extern float ia32_asm_fminf(float, float);
|
||||
extern float ia32_asm_fmaxf(float, float);
|
||||
|
||||
|
||||
// misc
|
||||
|
||||
/**
|
||||
* @return the (integral) base 2 logarithm, or -1 if the number
|
||||
* is not a power-of-two.
|
||||
**/
|
||||
extern int ia32_asm_log2_of_pow2(uint n);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include "precompiled.h"
|
||||
#include "snd.h"
|
||||
|
||||
#include "lib/lib.h"
|
||||
|
||||
char snd_card[SND_CARD_LEN];
|
||||
char snd_drv_ver[SND_DRV_VER_LEN];
|
||||
|
@ -1,4 +1,3 @@
|
||||
#include "lib/lib.h"
|
||||
#include "lib/self_test.h"
|
||||
|
||||
#include "lib/sysdep/sysdep.h"
|
||||
|
@ -3,7 +3,6 @@
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "lib/lib.h"
|
||||
#include "lib/res/file/file.h"
|
||||
#include "lib/sysdep/sysdep.h"
|
||||
#include "ps/CLogger.h"
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "lib/lib.h"
|
||||
#include "lib/timer.h"
|
||||
#include "lib/sysdep/sysdep.h"
|
||||
#include "lib/debug.h"
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include <wchar.h>
|
||||
|
||||
#include "lib/sdl.h"
|
||||
#include "lib/lib.h"
|
||||
#include "lib/sysdep/sysdep.h"
|
||||
#include "udbg.h"
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <Xatom.h>
|
||||
|
||||
#include "lib/lib.h"
|
||||
#include "lib/debug.h"
|
||||
#include "lib/sysdep/gfx.h"
|
||||
#include "SDL/SDL.h"
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include "lib/self_test.h"
|
||||
|
||||
#include "lib/lib.h"
|
||||
#include "lib/sysdep/ia32/ia32.h"
|
||||
|
||||
// note: ia32_i??_from_*, ia32_rint*, ia32_fm??f are all tested within
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include "precompiled.h"
|
||||
#include "wcpu.h"
|
||||
|
||||
#include "lib/lib.h"
|
||||
#include "lib/posix/posix_pthread.h"
|
||||
#include "lib/posix/posix_time.h"
|
||||
#include "win.h"
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include <stdio.h>
|
||||
#include <typeinfo>
|
||||
|
||||
#include "lib/lib.h"
|
||||
#include "lib/bits.h"
|
||||
#include "lib/posix/posix_pthread.h"
|
||||
#include "lib/byte_order.h" // FOURCC
|
||||
#include "lib/app_hooks.h"
|
||||
@ -802,3 +802,4 @@ bool debug_is_stack_ptr(void* p)
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include <stdio.h>
|
||||
#include <set>
|
||||
|
||||
#include "lib/lib.h"
|
||||
#include "lib/byte_order.h"
|
||||
#include "lib/sysdep/cpu.h"
|
||||
|
||||
#include "lib/debug_stl.h"
|
||||
@ -141,10 +141,10 @@ struct TI_FINDCHILDREN_PARAMS2
|
||||
TI_FINDCHILDREN_PARAMS2(DWORD num_children)
|
||||
{
|
||||
p.Start = 0;
|
||||
p.Count = MIN(num_children, MAX_CHILDREN);
|
||||
p.Count = std::min(num_children, MAX_CHILDREN);
|
||||
}
|
||||
|
||||
static const size_t MAX_CHILDREN = 400;
|
||||
static const DWORD MAX_CHILDREN = 400;
|
||||
TI_FINDCHILDREN_PARAMS p;
|
||||
DWORD additional_children[MAX_CHILDREN-1];
|
||||
};
|
||||
@ -787,17 +787,17 @@ static void seq_determine_formatting(size_t el_size, size_t el_count,
|
||||
if(el_size == sizeof(char))
|
||||
{
|
||||
*fits_on_one_line = el_count <= 16;
|
||||
*num_elements_to_show = MIN(16, el_count);
|
||||
*num_elements_to_show = std::min(16u, el_count);
|
||||
}
|
||||
else if(el_size <= sizeof(int))
|
||||
{
|
||||
*fits_on_one_line = el_count <= 8;
|
||||
*num_elements_to_show = MIN(12, el_count);
|
||||
*num_elements_to_show = std::min(12u, el_count);
|
||||
}
|
||||
else
|
||||
{
|
||||
*fits_on_one_line = false;
|
||||
*num_elements_to_show = MIN(8, el_count);
|
||||
*num_elements_to_show = std::min(8u, el_count);
|
||||
}
|
||||
|
||||
// make sure empty containers are displayed with [0] {}, otherwise
|
||||
@ -1035,7 +1035,7 @@ static LibError dump_sym_base_type(DWORD type_id, const u8* p, DumpState state)
|
||||
// must be declared before goto to avoid W4 warning.
|
||||
const wchar_t* fmt = L"";
|
||||
|
||||
u64 data = movzx_64le(p, size);
|
||||
u64 data = movzx_le64(p, size);
|
||||
// if value is 0xCC..CC (uninitialized mem), we display as hex.
|
||||
// the output would otherwise be garbage; this makes it obvious.
|
||||
// note: be very careful to correctly handle size=0 (e.g. void*).
|
||||
@ -1074,7 +1074,7 @@ static LibError dump_sym_base_type(DWORD type_id, const u8* p, DumpState state)
|
||||
if(size != 1 && size != 2 && size != 4 && size != 8)
|
||||
debug_warn("dump_sym_base_type: invalid int size");
|
||||
// need to re-load and sign-extend, because we output 64 bits.
|
||||
data = movsx_64le(p, size);
|
||||
data = movsx_le64(p, size);
|
||||
fmt = L"%I64d";
|
||||
break;
|
||||
|
||||
@ -1223,7 +1223,7 @@ static LibError dump_sym_enum(DWORD type_id, const u8* p, DumpState UNUSED(state
|
||||
WARN_RETURN(ERR::SYM_TYPE_INFO_UNAVAILABLE);
|
||||
const size_t size = (size_t)size_;
|
||||
|
||||
const i64 enum_value = movsx_64le(p, size);
|
||||
const i64 enum_value = movsx_le64(p, size);
|
||||
|
||||
// get array of child symbols (enumerants).
|
||||
DWORD num_children;
|
||||
@ -1337,7 +1337,7 @@ static LibError dump_sym_pointer(DWORD type_id, const u8* p, DumpState state)
|
||||
const size_t size = (size_t)size_;
|
||||
|
||||
// read+output pointer's value.
|
||||
p = (const u8*)movzx_64le(p, size);
|
||||
p = (const u8*)movzx_le64(p, size);
|
||||
out(L"0x%p", p);
|
||||
|
||||
// bail if it's obvious the pointer is bogus
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
||||
#include "lib/lib.h"
|
||||
#include "lib/path_util.h"
|
||||
#include "lib/res/file/file.h" // path_is_subpath
|
||||
#include "win.h"
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "wfilesystem.h" // mode_t
|
||||
#include "wtime.h" // timespec
|
||||
#include "lib/sysdep/cpu.h"
|
||||
#include "lib/bits.h"
|
||||
|
||||
|
||||
#pragma SECTION_PRE_LIBC(J)
|
||||
@ -56,9 +57,9 @@ WIN_REGISTER_FUNC(waio_shutdown);
|
||||
size_t sys_max_sector_size()
|
||||
{
|
||||
// users may call us more than once, so cache the results.
|
||||
static size_t cached_sector_size;
|
||||
static DWORD cached_sector_size;
|
||||
if(cached_sector_size)
|
||||
return cached_sector_size;
|
||||
return static_cast<size_t>(cached_sector_size);
|
||||
|
||||
// currently disabled: DVDs have 2..4KB, but this causes
|
||||
// waio to unnecessarily align some file transfers (when at EOF)
|
||||
@ -88,7 +89,7 @@ size_t sys_max_sector_size()
|
||||
DWORD spc, nfc, tnc; // don't need these
|
||||
DWORD cur_sector_size;
|
||||
if(GetDiskFreeSpace(drive_str, &spc, &cur_sector_size, &nfc, &tnc))
|
||||
cached_sector_size = MAX(cached_sector_size, cur_sector_size);
|
||||
cached_sector_size = std::max(cached_sector_size, cur_sector_size);
|
||||
// otherwise, it's probably an empty CD drive. ignore the
|
||||
// BoundsChecker error; GetDiskFreeSpace seems to be the
|
||||
// only way of getting at the sector size.
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
#include "wposix_internal.h"
|
||||
#include "crt_posix.h" // _getcwd
|
||||
#include "lib/bits.h"
|
||||
|
||||
|
||||
long sysconf(int name)
|
||||
|
@ -1,7 +1,6 @@
|
||||
#ifndef INCLUDED_WPOSIX_INTERNAL
|
||||
#define INCLUDED_WPOSIX_INTERNAL
|
||||
|
||||
#include "lib/lib.h"
|
||||
#include "lib/sysdep/win/win.h"
|
||||
#include "lib/sysdep/win/winit.h"
|
||||
#include "lib/sysdep/win/wutil.h"
|
||||
|
@ -215,11 +215,11 @@ IMP(ssize_t, recvfrom, (int, void*, size_t, int, struct sockaddr*, socklen_t*))
|
||||
|
||||
// WSAAsyncSelect event bits
|
||||
// (values taken from winsock2.h - do not change!)
|
||||
#define FD_READ BIT(0)
|
||||
#define FD_WRITE BIT(1)
|
||||
#define FD_ACCEPT BIT(3)
|
||||
#define FD_CONNECT BIT(4)
|
||||
#define FD_CLOSE BIT(5)
|
||||
#define FD_READ 0x01
|
||||
#define FD_WRITE 0x02
|
||||
#define FD_ACCEPT 0x08
|
||||
#define FD_CONNECT 0x10
|
||||
#define FD_CLOSE 0x20
|
||||
|
||||
|
||||
#undef IMP
|
||||
|
@ -22,7 +22,6 @@
|
||||
#include <WindowsX.h> // message crackers
|
||||
|
||||
#include "lib/posix/posix_pthread.h"
|
||||
#include "lib/lib.h"
|
||||
#include "lib/ogl.h" // needed to pull in the delay-loaded opengl32.dll
|
||||
#include "winit.h"
|
||||
#include "wutil.h"
|
||||
@ -100,7 +99,7 @@ static LibError calc_gamma_ramp(float gamma, u16* ramp)
|
||||
// don't add 1/256 - this isn't time-critical and
|
||||
// accuracy is more important.
|
||||
// need a temp variable to disambiguate pow() argument type.
|
||||
ramp[i] = fp_to_u16(pow(frac, inv_gamma));
|
||||
ramp[i] = u16_from_double(pow(frac, inv_gamma));
|
||||
}
|
||||
|
||||
return INFO::OK;
|
||||
@ -924,7 +923,7 @@ static LRESULT OnMouseButton(HWND UNUSED(hWnd), UINT uMsg, int screen_x, int scr
|
||||
// false due to its window-on-top check, so we better not
|
||||
// ignore messages based on that. it is safest to clamp coords to
|
||||
// what the app can handle.
|
||||
uint x = MAX(client_x, 0), y = MAX(client_y, 0);
|
||||
uint x = std::max(client_x, 0), y = std::max(client_y, 0);
|
||||
queue_button_event(button, state, x, y);
|
||||
return 0;
|
||||
}
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include "win.h" // includes windows.h; must come before shlobj
|
||||
#include <shlobj.h> // pick_dir
|
||||
|
||||
#include "lib/lib.h"
|
||||
#include "error_dialog.h"
|
||||
#include "wutil.h"
|
||||
|
||||
@ -609,3 +608,4 @@ LibError sys_pick_directory(char* path, size_t buf_size)
|
||||
|
||||
|
||||
|
||||
|
||||
|
17
source/lib/tests/test_base32.h
Normal file
17
source/lib/tests/test_base32.h
Normal file
@ -0,0 +1,17 @@
|
||||
#include "lib/self_test.h"
|
||||
|
||||
#include "lib/base32.h"
|
||||
|
||||
class TestLib : public CxxTest::TestSuite
|
||||
{
|
||||
public:
|
||||
void test_base32()
|
||||
{
|
||||
// compare against previous output (generated via this base32() call)
|
||||
const u8 in[] = { 0x12, 0x57, 0x85, 0xA2, 0xF9, 0x41, 0xCD, 0x57, 0xF3 };
|
||||
u8 out[20] = {0};
|
||||
base32(ARRAY_SIZE(in), in, out);
|
||||
const u8 correct_out[] = "CJLYLIXZIHGVP4C";
|
||||
TS_ASSERT_SAME_DATA(out, correct_out, ARRAY_SIZE(correct_out));
|
||||
}
|
||||
};
|
74
source/lib/tests/test_bits.h
Normal file
74
source/lib/tests/test_bits.h
Normal file
@ -0,0 +1,74 @@
|
||||
#include "lib/self_test.h"
|
||||
|
||||
#include "lib/bits.h"
|
||||
|
||||
class TestLib : public CxxTest::TestSuite
|
||||
{
|
||||
public:
|
||||
void test_is_pow2()
|
||||
{
|
||||
TS_ASSERT_EQUALS(is_pow2(0u), false);
|
||||
TS_ASSERT_EQUALS(is_pow2(~0u), false);
|
||||
TS_ASSERT_EQUALS(is_pow2(0x80000001), false);
|
||||
TS_ASSERT_EQUALS(is_pow2(1), true);
|
||||
TS_ASSERT_EQUALS(is_pow2(1u << 31), true);
|
||||
}
|
||||
|
||||
void test_log2_of_pow2()
|
||||
{
|
||||
TS_ASSERT_EQUALS(log2_of_pow2(0u), -1);
|
||||
TS_ASSERT_EQUALS(log2_of_pow2(3u), -1);
|
||||
TS_ASSERT_EQUALS(log2_of_pow2(0xffffffffu), -1);
|
||||
TS_ASSERT_EQUALS(log2_of_pow2(1u), 0);
|
||||
TS_ASSERT_EQUALS(log2_of_pow2(256u), 8);
|
||||
TS_ASSERT_EQUALS(log2_of_pow2(0x80000000u), 31);
|
||||
}
|
||||
|
||||
void test_ceil_log2()
|
||||
{
|
||||
TS_ASSERT_EQUALS(ceil_log2(3u), 2u);
|
||||
TS_ASSERT_EQUALS(ceil_log2(0xffffffffu), 32u);
|
||||
TS_ASSERT_EQUALS(ceil_log2(1u), 0u);
|
||||
TS_ASSERT_EQUALS(ceil_log2(256u), 8u);
|
||||
TS_ASSERT_EQUALS(ceil_log2(0x80000000u), 31u);
|
||||
}
|
||||
|
||||
void test_ilog2f()
|
||||
{
|
||||
TS_ASSERT_EQUALS(ilog2(1.f), 0);
|
||||
TS_ASSERT_EQUALS(ilog2(3.f), 1);
|
||||
TS_ASSERT_EQUALS(ilog2(256.f), 8);
|
||||
}
|
||||
|
||||
void test_round_up_to_pow2()
|
||||
{
|
||||
TS_ASSERT_EQUALS(round_up_to_pow2(0u), 1u);
|
||||
TS_ASSERT_EQUALS(round_up_to_pow2(1u), 2u);
|
||||
TS_ASSERT_EQUALS(round_up_to_pow2(127u), 128u);
|
||||
TS_ASSERT_EQUALS(round_up_to_pow2(128u), 256u);
|
||||
TS_ASSERT_EQUALS(round_up_to_pow2(129u), 256u);
|
||||
}
|
||||
|
||||
void test_round_up()
|
||||
{
|
||||
TS_ASSERT_EQUALS(round_up( 0u, 16u), 0u);
|
||||
TS_ASSERT_EQUALS(round_up( 4u, 16u), 16u);
|
||||
TS_ASSERT_EQUALS(round_up(15u, 16u), 16u);
|
||||
TS_ASSERT_EQUALS(round_up(20u, 32u), 32u);
|
||||
TS_ASSERT_EQUALS(round_up(29u, 32u), 32u);
|
||||
TS_ASSERT_EQUALS(round_up(0x1000u, 0x1000u), 0x1000u);
|
||||
TS_ASSERT_EQUALS(round_up(0x1001u, 0x1000u), 0x2000u);
|
||||
TS_ASSERT_EQUALS(round_up(0x1900u, 0x1000u), 0x2000u);
|
||||
}
|
||||
|
||||
void test_round_down()
|
||||
{
|
||||
TS_ASSERT_EQUALS(round_down( 0u, 16u), 0u);
|
||||
TS_ASSERT_EQUALS(round_down( 4u, 16u), 0u);
|
||||
TS_ASSERT_EQUALS(round_down(15u, 16u), 0u);
|
||||
TS_ASSERT_EQUALS(round_down(20u, 16u), 16u);
|
||||
TS_ASSERT_EQUALS(round_down(29u, 16u), 16u);
|
||||
TS_ASSERT_EQUALS(round_down(0x1900u, 0x1000u), 0x1000u);
|
||||
TS_ASSERT_EQUALS(round_down(0x2001u, 0x2000u), 0x2000u);
|
||||
}
|
||||
};
|
@ -37,4 +37,39 @@ public:
|
||||
// note: no need to test read_?e* / write_?e* - they are
|
||||
// trivial wrappers on top of to_?e*.
|
||||
}
|
||||
|
||||
void test_movzx()
|
||||
{
|
||||
const u8 d1[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
|
||||
const u8 d2[] = { 0x43, 0x12, 0x23, 0xA4 };
|
||||
|
||||
TS_ASSERT_EQUALS(movzx_le64(d1, 1), 0x01ull);
|
||||
TS_ASSERT_EQUALS(movzx_le64(d1, 2), 0x0201ull);
|
||||
TS_ASSERT_EQUALS(movzx_le64(d1, 8), 0x0807060504030201ull);
|
||||
TS_ASSERT_EQUALS(movzx_le64(d2, 4), 0xA4231243ull);
|
||||
TS_ASSERT_EQUALS(movzx_le64(d2+3, 1), 0xA4ull);
|
||||
|
||||
TS_ASSERT_EQUALS(movzx_be64(d1, 1), 0x01ull);
|
||||
TS_ASSERT_EQUALS(movzx_be64(d1, 2), 0x0102ull);
|
||||
TS_ASSERT_EQUALS(movzx_be64(d1, 8), 0x0102030405060708ull);
|
||||
TS_ASSERT_EQUALS(movzx_be64(d2, 4), 0x431223A4ull);
|
||||
TS_ASSERT_EQUALS(movzx_be64(d2+3, 1), 0xA4ull);
|
||||
}
|
||||
|
||||
void test_movsx()
|
||||
{
|
||||
const u8 d1[] = { 0x09, 0xFE };
|
||||
const u8 d2[] = { 0xD9, 0x2C, 0xDD, 0x8F };
|
||||
const u8 d3[] = { 0x92, 0x26, 0x88, 0xF1, 0x35, 0xAC, 0x01, 0x83 };
|
||||
|
||||
TS_ASSERT_EQUALS(movsx_le64(d1, 1), 0x09ull);
|
||||
TS_ASSERT_EQUALS(movsx_le64(d1, 2), 0xFFFFFFFFFFFFFE09ull);
|
||||
TS_ASSERT_EQUALS(movsx_le64(d2, 4), 0xFFFFFFFF8FDD2CD9ull);
|
||||
TS_ASSERT_EQUALS(movsx_le64(d3, 8), 0x8301AC35F1882692ull);
|
||||
|
||||
TS_ASSERT_EQUALS(movsx_be64(d1, 1), 0x09ull);
|
||||
TS_ASSERT_EQUALS(movsx_be64(d1, 2), 0x00000000000009FEull);
|
||||
TS_ASSERT_EQUALS(movsx_be64(d2, 4), 0xFFFFFFFFD92CDD8Full);
|
||||
TS_ASSERT_EQUALS(movsx_be64(d3, 8), 0x922688F135AC0183ull);
|
||||
}
|
||||
};
|
||||
|
21
source/lib/tests/test_fnv_hash.h
Normal file
21
source/lib/tests/test_fnv_hash.h
Normal file
@ -0,0 +1,21 @@
|
||||
#include "lib/self_test.h"
|
||||
|
||||
#include "lib/fnv_hash.h"
|
||||
|
||||
class TestLib : public CxxTest::TestSuite
|
||||
{
|
||||
public:
|
||||
void test_fnv_hash()
|
||||
{
|
||||
TS_ASSERT_EQUALS(fnv_hash(""), 0x811C9DC5u); // verify initial value
|
||||
const u32 h1 = fnv_hash("abcdef");
|
||||
TS_ASSERT_EQUALS(h1, 0xFF478A2A); // verify value for simple string
|
||||
TS_ASSERT_EQUALS(fnv_hash ("abcdef", 6), h1); // same result if hashing buffer
|
||||
TS_ASSERT_EQUALS(fnv_lc_hash("ABcDeF", 6), h1); // same result if case differs
|
||||
|
||||
TS_ASSERT_EQUALS(fnv_hash64(""), 0xCBF29CE484222325ull); // verify initial value
|
||||
const u64 h2 = fnv_hash64("abcdef");
|
||||
TS_ASSERT_EQUALS(h2, 0xD80BDA3FBE244A0Aull); // verify value for simple string
|
||||
TS_ASSERT_EQUALS(fnv_hash64("abcdef", 6), h2); // same result if hashing buffer
|
||||
}
|
||||
};
|
@ -5,87 +5,6 @@
|
||||
class TestLib : public CxxTest::TestSuite
|
||||
{
|
||||
public:
|
||||
void test_fnv_hash()
|
||||
{
|
||||
TS_ASSERT_EQUALS(fnv_hash(""), 0x811C9DC5u); // verify initial value
|
||||
const u32 h1 = fnv_hash("abcdef");
|
||||
TS_ASSERT_EQUALS(h1, 0xFF478A2A); // verify value for simple string
|
||||
TS_ASSERT_EQUALS(fnv_hash ("abcdef", 6), h1); // same result if hashing buffer
|
||||
TS_ASSERT_EQUALS(fnv_lc_hash("ABcDeF", 6), h1); // same result if case differs
|
||||
|
||||
TS_ASSERT_EQUALS(fnv_hash64(""), 0xCBF29CE484222325ull); // verify initial value
|
||||
const u64 h2 = fnv_hash64("abcdef");
|
||||
TS_ASSERT_EQUALS(h2, 0xD80BDA3FBE244A0Aull); // verify value for simple string
|
||||
TS_ASSERT_EQUALS(fnv_hash64("abcdef", 6), h2); // same result if hashing buffer
|
||||
}
|
||||
|
||||
void test_is_pow2()
|
||||
{
|
||||
TS_ASSERT_EQUALS(is_pow2(0u), false);
|
||||
TS_ASSERT_EQUALS(is_pow2(~0u), false);
|
||||
TS_ASSERT_EQUALS(is_pow2(0x80000001), false);
|
||||
TS_ASSERT_EQUALS(is_pow2(1), true);
|
||||
TS_ASSERT_EQUALS(is_pow2(1u << 31), true);
|
||||
}
|
||||
|
||||
void test_ilog2()
|
||||
{
|
||||
TS_ASSERT_EQUALS(ilog2(0u), -1);
|
||||
TS_ASSERT_EQUALS(ilog2(3u), -1);
|
||||
TS_ASSERT_EQUALS(ilog2(0xffffffffu), -1);
|
||||
TS_ASSERT_EQUALS(ilog2(1u), 0);
|
||||
TS_ASSERT_EQUALS(ilog2(256u), 8);
|
||||
TS_ASSERT_EQUALS(ilog2(0x80000000u), 31);
|
||||
}
|
||||
|
||||
void test_log2()
|
||||
{
|
||||
TS_ASSERT_EQUALS(log2(3u), 2u);
|
||||
TS_ASSERT_EQUALS(log2(0xffffffffu), 32u);
|
||||
TS_ASSERT_EQUALS(log2(1u), 0u);
|
||||
TS_ASSERT_EQUALS(log2(256u), 8u);
|
||||
TS_ASSERT_EQUALS(log2(0x80000000u), 31u);
|
||||
}
|
||||
|
||||
void test_ilog2f()
|
||||
{
|
||||
TS_ASSERT_EQUALS(ilog2(1.f), 0);
|
||||
TS_ASSERT_EQUALS(ilog2(3.f), 1);
|
||||
TS_ASSERT_EQUALS(ilog2(256.f), 8);
|
||||
}
|
||||
|
||||
void test_round_next_pow2()
|
||||
{
|
||||
TS_ASSERT_EQUALS(round_up_to_pow2(0u), 1u);
|
||||
TS_ASSERT_EQUALS(round_up_to_pow2(1u), 2u);
|
||||
TS_ASSERT_EQUALS(round_up_to_pow2(127u), 128u);
|
||||
TS_ASSERT_EQUALS(round_up_to_pow2(128u), 256u);
|
||||
TS_ASSERT_EQUALS(round_up_to_pow2(129u), 256u);
|
||||
}
|
||||
|
||||
void test_round_up()
|
||||
{
|
||||
TS_ASSERT_EQUALS(round_up( 0u, 16u), 0u);
|
||||
TS_ASSERT_EQUALS(round_up( 4u, 16u), 16u);
|
||||
TS_ASSERT_EQUALS(round_up(15u, 16u), 16u);
|
||||
TS_ASSERT_EQUALS(round_up(20u, 32u), 32u);
|
||||
TS_ASSERT_EQUALS(round_up(29u, 32u), 32u);
|
||||
TS_ASSERT_EQUALS(round_up(0x1000u, 0x1000u), 0x1000u);
|
||||
TS_ASSERT_EQUALS(round_up(0x1001u, 0x1000u), 0x2000u);
|
||||
TS_ASSERT_EQUALS(round_up(0x1900u, 0x1000u), 0x2000u);
|
||||
}
|
||||
|
||||
void test_round_down()
|
||||
{
|
||||
TS_ASSERT_EQUALS(round_down( 0u, 16u), 0u);
|
||||
TS_ASSERT_EQUALS(round_down( 4u, 16u), 0u);
|
||||
TS_ASSERT_EQUALS(round_down(15u, 16u), 0u);
|
||||
TS_ASSERT_EQUALS(round_down(20u, 16u), 16u);
|
||||
TS_ASSERT_EQUALS(round_down(29u, 16u), 16u);
|
||||
TS_ASSERT_EQUALS(round_down(0x1900u, 0x1000u), 0x1000u);
|
||||
TS_ASSERT_EQUALS(round_down(0x2001u, 0x2000u), 0x2000u);
|
||||
}
|
||||
|
||||
// 16-bit saturating arithmetic
|
||||
void test_addusw()
|
||||
{
|
||||
@ -105,28 +24,6 @@ public:
|
||||
TS_ASSERT_EQUALS(subusw(0xFFFFu, 0x0FFFu), 0xF000u);
|
||||
}
|
||||
|
||||
void test_movzx()
|
||||
{
|
||||
const u8 d1[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
|
||||
const u8 d2[] = { 0x43, 0x12, 0x23, 0xA4 };
|
||||
TS_ASSERT_EQUALS(movzx_64le(d1, 1), 0x01ull);
|
||||
TS_ASSERT_EQUALS(movzx_64le(d1, 2), 0x0201ull);
|
||||
TS_ASSERT_EQUALS(movzx_64le(d1, 8), 0x0807060504030201ull);
|
||||
TS_ASSERT_EQUALS(movzx_64le(d2, 4), 0xA4231243ull);
|
||||
TS_ASSERT_EQUALS(movzx_64le(d2+3, 1), 0xA4ull);
|
||||
}
|
||||
|
||||
void test_movsx()
|
||||
{
|
||||
const u8 d1[] = { 0x09, 0xFE };
|
||||
const u8 d2[] = { 0xD9, 0x2C, 0xDD, 0x8F };
|
||||
const u8 d3[] = { 0x92, 0x26, 0x88, 0xF1, 0x35, 0xAC, 0x01, 0x83 };
|
||||
TS_ASSERT_EQUALS(movsx_64le(d1, 1), 0x09ull);
|
||||
TS_ASSERT_EQUALS(movsx_64le(d1, 2), 0xFFFFFFFFFFFFFE09ull);
|
||||
TS_ASSERT_EQUALS(movsx_64le(d2, 4), 0xFFFFFFFF8FDD2CD9ull);
|
||||
TS_ASSERT_EQUALS(movsx_64le(d3, 8), 0x8301AC35F1882692ull);
|
||||
}
|
||||
|
||||
void test_hi_lo()
|
||||
{
|
||||
TS_ASSERT_EQUALS(u64_hi(0x0123456789ABCDEFull), 0x01234567u);
|
||||
@ -147,59 +44,6 @@ public:
|
||||
|
||||
// fp_to_u?? already validate the result.
|
||||
|
||||
void test_wildcard()
|
||||
{
|
||||
TS_ASSERT_EQUALS(match_wildcard("", ""), 1);
|
||||
TS_ASSERT_EQUALS(match_wildcard("a", 0), 1); // NULL matches everything
|
||||
|
||||
TS_ASSERT_EQUALS(match_wildcard("abc", "abc") , 1); // direct match
|
||||
TS_ASSERT_EQUALS(match_wildcard("abc", "???") , 1); // only ?
|
||||
TS_ASSERT_EQUALS(match_wildcard("abc", "*" ) , 1); // only *
|
||||
|
||||
TS_ASSERT_EQUALS(match_wildcard("ab" , "a?" ) , 1); // trailing ?
|
||||
TS_ASSERT_EQUALS(match_wildcard("abc", "a?c") , 1); // middle ?
|
||||
TS_ASSERT_EQUALS(match_wildcard("abc", "?bc") , 1); // leading ?
|
||||
|
||||
TS_ASSERT_EQUALS(match_wildcard("abc", "a*" ) , 1); // trailing *
|
||||
TS_ASSERT_EQUALS(match_wildcard("abcdef", "ab*ef"), 1); // middle *
|
||||
TS_ASSERT_EQUALS(match_wildcard("abcdef", "*f" ), 1); // leading *
|
||||
|
||||
TS_ASSERT_EQUALS(match_wildcard("abcdef", "a?cd*"), 1); // ? and *
|
||||
TS_ASSERT_EQUALS(match_wildcard("abcdef", "a*d?f"), 1); // * and ?
|
||||
TS_ASSERT_EQUALS(match_wildcard("abcdef", "a*d*" ), 1); // multiple *
|
||||
|
||||
// unicode test pasted from the above; keep in sync!
|
||||
|
||||
TS_ASSERT_EQUALS(match_wildcardw(L"", L""), 1);
|
||||
TS_ASSERT_EQUALS(match_wildcardw(L"a", 0), 1); // NULL matches everything
|
||||
|
||||
TS_ASSERT_EQUALS(match_wildcardw(L"abc", L"abc") , 1); // direct match
|
||||
TS_ASSERT_EQUALS(match_wildcardw(L"abc", L"???") , 1); // only ?
|
||||
TS_ASSERT_EQUALS(match_wildcardw(L"abc", L"*" ) , 1); // only *
|
||||
|
||||
TS_ASSERT_EQUALS(match_wildcardw(L"ab" , L"a?" ) , 1); // trailing ?
|
||||
TS_ASSERT_EQUALS(match_wildcardw(L"abc", L"a?c") , 1); // middle ?
|
||||
TS_ASSERT_EQUALS(match_wildcardw(L"abc", L"?bc") , 1); // leading ?
|
||||
|
||||
TS_ASSERT_EQUALS(match_wildcardw(L"abc", L"a*" ) , 1); // trailing *
|
||||
TS_ASSERT_EQUALS(match_wildcardw(L"abcdef", L"ab*ef"), 1); // middle *
|
||||
TS_ASSERT_EQUALS(match_wildcardw(L"abcdef", L"*f" ), 1); // leading *
|
||||
|
||||
TS_ASSERT_EQUALS(match_wildcardw(L"abcdef", L"a?cd*"), 1); // ? and *
|
||||
TS_ASSERT_EQUALS(match_wildcardw(L"abcdef", L"a*d?f"), 1); // * and ?
|
||||
TS_ASSERT_EQUALS(match_wildcardw(L"abcdef", L"a*d*" ), 1); // multiple *
|
||||
}
|
||||
|
||||
void test_base32()
|
||||
{
|
||||
// compare against previous output (generated via this base32() call)
|
||||
const u8 in[] = { 0x12, 0x57, 0x85, 0xA2, 0xF9, 0x41, 0xCD, 0x57, 0xF3 };
|
||||
u8 out[20] = {0};
|
||||
base32(ARRAY_SIZE(in), in, out);
|
||||
const u8 correct_out[] = "CJLYLIXZIHGVP4C";
|
||||
TS_ASSERT_SAME_DATA(out, correct_out, ARRAY_SIZE(correct_out));
|
||||
}
|
||||
|
||||
void test_rand()
|
||||
{
|
||||
// complain if huge interval or min > max
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include "lib/self_test.h"
|
||||
|
||||
#include "lib/lib.h"
|
||||
#include "lib/lockfree.h"
|
||||
#include "lib/sysdep/cpu.h" // atomic_add
|
||||
#include "lib/timer.h"
|
||||
|
50
source/lib/tests/test_regex.h
Normal file
50
source/lib/tests/test_regex.h
Normal file
@ -0,0 +1,50 @@
|
||||
#include "lib/self_test.h"
|
||||
|
||||
#include "lib/regex.h"
|
||||
|
||||
class TestLib : public CxxTest::TestSuite
|
||||
{
|
||||
public:
|
||||
void test_regex()
|
||||
{
|
||||
TS_ASSERT_EQUALS(match_wildcard("", ""), 1);
|
||||
TS_ASSERT_EQUALS(match_wildcard("a", 0), 1); // NULL matches everything
|
||||
|
||||
TS_ASSERT_EQUALS(match_wildcard("abc", "abc") , 1); // direct match
|
||||
TS_ASSERT_EQUALS(match_wildcard("abc", "???") , 1); // only ?
|
||||
TS_ASSERT_EQUALS(match_wildcard("abc", "*" ) , 1); // only *
|
||||
|
||||
TS_ASSERT_EQUALS(match_wildcard("ab" , "a?" ) , 1); // trailing ?
|
||||
TS_ASSERT_EQUALS(match_wildcard("abc", "a?c") , 1); // middle ?
|
||||
TS_ASSERT_EQUALS(match_wildcard("abc", "?bc") , 1); // leading ?
|
||||
|
||||
TS_ASSERT_EQUALS(match_wildcard("abc", "a*" ) , 1); // trailing *
|
||||
TS_ASSERT_EQUALS(match_wildcard("abcdef", "ab*ef"), 1); // middle *
|
||||
TS_ASSERT_EQUALS(match_wildcard("abcdef", "*f" ), 1); // leading *
|
||||
|
||||
TS_ASSERT_EQUALS(match_wildcard("abcdef", "a?cd*"), 1); // ? and *
|
||||
TS_ASSERT_EQUALS(match_wildcard("abcdef", "a*d?f"), 1); // * and ?
|
||||
TS_ASSERT_EQUALS(match_wildcard("abcdef", "a*d*" ), 1); // multiple *
|
||||
|
||||
// unicode test pasted from the above; keep in sync!
|
||||
|
||||
TS_ASSERT_EQUALS(match_wildcardw(L"", L""), 1);
|
||||
TS_ASSERT_EQUALS(match_wildcardw(L"a", 0), 1); // NULL matches everything
|
||||
|
||||
TS_ASSERT_EQUALS(match_wildcardw(L"abc", L"abc") , 1); // direct match
|
||||
TS_ASSERT_EQUALS(match_wildcardw(L"abc", L"???") , 1); // only ?
|
||||
TS_ASSERT_EQUALS(match_wildcardw(L"abc", L"*" ) , 1); // only *
|
||||
|
||||
TS_ASSERT_EQUALS(match_wildcardw(L"ab" , L"a?" ) , 1); // trailing ?
|
||||
TS_ASSERT_EQUALS(match_wildcardw(L"abc", L"a?c") , 1); // middle ?
|
||||
TS_ASSERT_EQUALS(match_wildcardw(L"abc", L"?bc") , 1); // leading ?
|
||||
|
||||
TS_ASSERT_EQUALS(match_wildcardw(L"abc", L"a*" ) , 1); // trailing *
|
||||
TS_ASSERT_EQUALS(match_wildcardw(L"abcdef", L"ab*ef"), 1); // middle *
|
||||
TS_ASSERT_EQUALS(match_wildcardw(L"abcdef", L"*f" ), 1); // leading *
|
||||
|
||||
TS_ASSERT_EQUALS(match_wildcardw(L"abcdef", L"a?cd*"), 1); // ? and *
|
||||
TS_ASSERT_EQUALS(match_wildcardw(L"abcdef", L"a*d?f"), 1); // * and ?
|
||||
TS_ASSERT_EQUALS(match_wildcardw(L"abcdef", L"a*d*" ), 1); // multiple *
|
||||
}
|
||||
};
|
@ -1,6 +1,5 @@
|
||||
#include "lib/self_test.h"
|
||||
|
||||
#include "lib/lib.h"
|
||||
#include "lib/string_s.h"
|
||||
|
||||
// note: we only test the char version. this avoids having to
|
||||
|
@ -17,12 +17,11 @@
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "lib/posix/posix_time.h"
|
||||
#include "lib.h"
|
||||
#include "adts.h"
|
||||
#include "lib/sysdep/cpu.h"
|
||||
|
||||
#if CPU_IA32
|
||||
# include "lib/sysdep/ia32/ia32.h"
|
||||
#if CONFIG_TIMER_ALLOW_RDTSC
|
||||
# include "lib/sysdep/ia32/ia32.h" // ia32_rdtsc
|
||||
#endif
|
||||
|
||||
// rationale for wrapping gettimeofday and clock_gettime, instead of emulating
|
||||
@ -205,7 +204,7 @@ void calc_fps()
|
||||
// comes closer to the average again (meaning it probably
|
||||
// wasn't really changing).
|
||||
if(same_side >= 2 && !is_close)
|
||||
bias += MIN(same_side, 4);
|
||||
bias += std::min(same_side, 4);
|
||||
}
|
||||
|
||||
// bias = 0: no change. > 0: increase (n-th root). < 0: decrease (^n)
|
||||
@ -322,7 +321,7 @@ void timer_display_client_totals()
|
||||
}
|
||||
|
||||
|
||||
#if CPU_IA32
|
||||
#if CONFIG_TIMER_ALLOW_RDTSC
|
||||
|
||||
TimerRdtsc::unit TimerRdtsc::get_timestamp() const
|
||||
{
|
||||
|
@ -54,9 +54,10 @@ extern void calc_fps(void);
|
||||
// note that overflow isn't an issue either way (63 bit cycle counts
|
||||
// at 10 GHz cover intervals of 29 years).
|
||||
|
||||
#if CPU_IA32
|
||||
#if CONFIG_TIMER_ALLOW_RDTSC
|
||||
|
||||
// fast, not usable as wall-clock (http://www.gamedev.net/reference/programming/features/timing)
|
||||
// fast, IA-32 specific, not usable as wall-clock
|
||||
// (see http://www.gamedev.net/reference/programming/features/timing)
|
||||
class TimerRdtsc
|
||||
{
|
||||
public:
|
||||
@ -76,7 +77,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#if CPU_IA32 && TIMER_ALLOW_RDTSC
|
||||
#if CONFIG_TIMER_ALLOW_RDTSC
|
||||
typedef TimerRdtsc Timer;
|
||||
#else
|
||||
typedef TimerSafe Timer;
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cmath>
|
||||
#include "lib/lib.h"
|
||||
#include "maths/Matrix3D.h"
|
||||
#include "maths/Quaternion.h"
|
||||
|
||||
@ -66,3 +65,4 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "lib/lib.h"
|
||||
|
||||
#include "scripting/DOMEvent.h"
|
||||
#include "scripting/JSConversions.h"
|
||||
#include "scripting/ScriptableObject.h"
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "lib/lib.h"
|
||||
#include <stdio.h>
|
||||
#include <map>
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user