Various small changes and helper functions

- Fix typo for int32_t and int64_t
- Add new helper functions to convert v2i to v2 and back
- Add DqnRect_ClipRect to restrict rect to some specified clip-rect
- Improve I32ToStr and StrToI32 to support up to I64
This commit is contained in:
Doyle Thai 2017-05-15 17:45:53 +10:00
parent 73f0fd448c
commit 5c06410929
3 changed files with 253 additions and 111 deletions

214
dqn.h
View File

@ -28,9 +28,9 @@ typedef uint32_t u32;
typedef uint16_t u16;
typedef uint8_t u8;
typedef int32_t i64;
typedef int64_t i64;
typedef int32_t i32;
typedef int64_t i16;
typedef int16_t i16;
typedef double f64;
typedef float f32;
@ -48,14 +48,14 @@ typedef float f32;
#define DQN_ASSERT(expr) if (!(expr)) { (*((i32 *)0)) = 0; }
#define DQN_PI 3.14159265359f
#define DQN_SQUARED(x) ((x) * (x))
#define DQN_ABS(x) (((x) < 0) ? (-(x)) : (x))
#define DQN_DEGREES_TO_RADIANS(x) ((x * (DQN_PI / 180.0f)))
#define DQN_RADIANS_TO_DEGREES(x) ((x * (180.0f / DQN_PI)))
#define DQN_MAX(a, b) ((a) < (b) ? (b) : (a))
#define DQN_MIN(a, b) ((a) < (b) ? (a) : (b))
#define DQN_SQUARED(x) ((x) * (x))
#define DQN_SWAP(type, a, b) do { type tmp = a; a = b; b = tmp; } while(0)
////////////////////////////////////////////////////////////////////////////////
// DqnMem - Memory
////////////////////////////////////////////////////////////////////////////////
@ -419,7 +419,7 @@ bool DqnArray_RemoveStable(DqnArray<T> *array, u64 index)
////////////////////////////////////////////////////////////////////////////////
// Math
////////////////////////////////////////////////////////////////////////////////
DQN_FILE_SCOPE f32 DqnMath_Lerp(f32 a, f32 t, f32 b);
DQN_FILE_SCOPE f32 DqnMath_Lerp (f32 a, f32 t, f32 b);
DQN_FILE_SCOPE f32 DqnMath_Sqrtf(f32 a);
////////////////////////////////////////////////////////////////////////////////
@ -432,9 +432,17 @@ typedef union DqnV2 {
f32 e[2];
} DqnV2;
typedef union DqnV2i {
struct { i32 x, y; };
struct { i32 w, h; };
struct { i32 min, max; };
i32 e[2];
} DqnV2i;
DQN_FILE_SCOPE DqnV2 DqnV2_2i(i32 x, i32 y); // Typecasts 2 integers to 2 floats
DQN_FILE_SCOPE DqnV2 DqnV2_2f(f32 x, f32 y);
// DqnV2
DQN_FILE_SCOPE DqnV2 DqnV2_2i (i32 x, i32 y); // Typecasts 2 integers to 2 floats
DQN_FILE_SCOPE DqnV2 DqnV2_2f (f32 x, f32 y);
DQN_FILE_SCOPE DqnV2 DqnV2_V2i(DqnV2i a);
DQN_FILE_SCOPE DqnV2 DqnV2_Add (DqnV2 a, DqnV2 b);
DQN_FILE_SCOPE DqnV2 DqnV2_Sub (DqnV2 a, DqnV2 b);
@ -464,15 +472,10 @@ DQN_FILE_SCOPE inline DqnV2 &operator-=(DqnV2 &a, DqnV2 b) { return (a = DqnV2_S
DQN_FILE_SCOPE inline DqnV2 &operator+=(DqnV2 &a, DqnV2 b) { return (a = DqnV2_Add (a, b)); }
DQN_FILE_SCOPE inline bool operator==(DqnV2 a, DqnV2 b) { return DqnV2_Equals (a, b); }
typedef union DqnV2i {
struct { i32 x, y; };
struct { i32 w, h; };
struct { i32 min, max; };
i32 e[2];
} DqnV2i;
// DqnV2i
DQN_FILE_SCOPE DqnV2i DqnV2i_2i(i32 x, i32 y);
DQN_FILE_SCOPE DqnV2i DqnV2i_2f(f32 x, f32 y); // Typecasts 2 floats to 2 integers
DQN_FILE_SCOPE DqnV2i DqnV2i_V2(DqnV2 a); // Typecasts the floats to integers
DQN_FILE_SCOPE DqnV2i DqnV2i_Add (DqnV2i a, DqnV2i b);
DQN_FILE_SCOPE DqnV2i DqnV2i_Sub (DqnV2i a, DqnV2i b);
@ -589,10 +592,14 @@ typedef struct DqnRect
DqnV2 max;
} DqnRect;
DQN_FILE_SCOPE DqnRect DqnRect_4f (f32 minX, f32 minY, f32 maxX, f32 maxY);
DQN_FILE_SCOPE DqnRect DqnRect_4i (i32 minX, i32 minY, i32 maxX, i32 maxY);
DQN_FILE_SCOPE DqnRect DqnRect_Init (DqnV2 origin, DqnV2 size);
DQN_FILE_SCOPE void DqnRect_GetSize2f(DqnRect rect, f32 *width, f32 *height);
DQN_FILE_SCOPE DqnV2 DqnRect_GetSizev2(DqnRect rect);
DQN_FILE_SCOPE void DqnRect_GetSize2i(DqnRect rect, i32 *width, i32 *height); // TODO(doyle): Is this even worth it. Purposely losing precision, i.e. using rect as integers not floats
DQN_FILE_SCOPE DqnV2 DqnRect_GetSizeV2(DqnRect rect);
DQN_FILE_SCOPE DqnV2 DqnRect_GetCenter(DqnRect rect);
DQN_FILE_SCOPE DqnRect DqnRect_ClipRect (DqnRect rect, DqnRect clip);
DQN_FILE_SCOPE DqnRect DqnRect_Move (DqnRect rect, DqnV2 shift);
DQN_FILE_SCOPE bool DqnRect_ContainsP(DqnRect rect, DqnV2 p);
@ -611,14 +618,16 @@ DQN_FILE_SCOPE i32 Dqn_strlen (const char *a);
DQN_FILE_SCOPE i32 Dqn_strlenDelimitWith(const char *a, const char delimiter);
DQN_FILE_SCOPE char *Dqn_strncpy (char *dest, const char *src, i32 numChars);
#define DQN_I32_TO_STR_MAX_BUF_SIZE 11
DQN_FILE_SCOPE bool Dqn_StrReverse (char *buf, const i32 bufSize);
DQN_FILE_SCOPE i32 Dqn_StrFindFirstOccurence(const char *const src, const i32 srcLen, const char *const find, const i32 findLen);
DQN_FILE_SCOPE bool Dqn_StrHasSubstring (const char *const src, const i32 srcLen, const char *const find, const i32 findLen);
DQN_FILE_SCOPE i32 Dqn_StrToI32(const char *const buf, const i32 bufSize);
// Return the len of the derived string
DQN_FILE_SCOPE i32 Dqn_I32ToStr(i32 value, char *buf, i32 bufSize);
#define DQN_32BIT_NUM_MAX_STR_SIZE 11
#define DQN_64BIT_NUM_MAX_STR_SIZE 20
// Return the len of the derived string. If buf is NULL and or bufSize is 0 the
// function returns the required string length for the integer.
DQN_FILE_SCOPE i32 Dqn_I64ToStr(i64 value, char *const buf, const i32 bufSize);
DQN_FILE_SCOPE i64 Dqn_StrToI64(const char *const buf, const i32 bufSize);
// Both return the number of bytes read, return 0 if invalid codepoint or UTF8
DQN_FILE_SCOPE u32 Dqn_UCSToUTF8(u32 *dest, u32 character);
@ -723,7 +732,6 @@ DQN_FILE_SCOPE i32 DqnRnd_PCGRange(DqnRandPCGState *pcg, i32 min, i32 max);
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#define DQN_WIN32_ERROR_BOX(text, title) MessageBoxA(NULL, text, title, MB_OK);
// Out is a pointer to the buffer to receive the characters.
// outLen is the length/capacity of the out buffer
@ -736,7 +744,6 @@ DQN_FILE_SCOPE void DqnWin32_DisplayLastError(const char *const errorPrefix);
DQN_FILE_SCOPE void DqnWin32_DisplayErrorCode(const DWORD error, const char *const errorPrefix);
#endif /* DQN_WIN32_IMPLEMENTATION */
#ifndef DQN_INI_H
#define DQN_INI_H
////////////////////////////////////////////////////////////////////////////////
@ -1704,6 +1711,12 @@ DQN_FILE_SCOPE f32 DqnMath_Sqrtf(f32 a)
////////////////////////////////////////////////////////////////////////////////
// Vec2
////////////////////////////////////////////////////////////////////////////////
DQN_FILE_SCOPE DqnV2 DqnV2_2i(i32 x, i32 y)
{
DqnV2 result = DqnV2_2f((f32)x, (f32)y);
return result;
}
DQN_FILE_SCOPE DqnV2 DqnV2_2f(f32 x, f32 y)
{
DqnV2 result = {};
@ -1713,9 +1726,12 @@ DQN_FILE_SCOPE DqnV2 DqnV2_2f(f32 x, f32 y)
return result;
}
DQN_FILE_SCOPE DqnV2 DqnV2_2i(i32 x, i32 y)
DQN_FILE_SCOPE DqnV2 DqnV2_V2i(DqnV2i a)
{
DqnV2 result = DqnV2_2f((f32)x, (f32)y);
DqnV2 result = {};
result.x = (f32)a.x;
result.y = (f32)a.y;
return result;
}
@ -1869,6 +1885,14 @@ DQN_FILE_SCOPE DqnV2i DqnV2i_2f(f32 x, f32 y)
return result;
}
DQN_FILE_SCOPE DqnV2i DqnV2i_V2(DqnV2 a)
{
DqnV2i result = {};
result.x = (i32)a.x;
result.y = (i32)a.y;
return result;
}
DQN_FILE_SCOPE DqnV2i DqnV2i_Add(DqnV2i a, DqnV2i b)
{
DqnV2i result = {};
@ -2229,6 +2253,24 @@ DQN_FILE_SCOPE DqnV4 DqnMat4_MulV4(DqnMat4 a, DqnV4 b)
////////////////////////////////////////////////////////////////////////////////
// Rect
////////////////////////////////////////////////////////////////////////////////
DQN_FILE_SCOPE DqnRect DqnRect_4f(f32 minX, f32 minY, f32 maxX, f32 maxY)
{
DqnRect result = {};
result.min = DqnV2_2f(minX, minY);
result.max = DqnV2_2f(maxX, maxY);
return result;
}
DQN_FILE_SCOPE DqnRect DqnRect_4i(i32 minX, i32 minY, i32 maxX, i32 maxY)
{
DqnRect result = {};
result.min = DqnV2_2i(minX, minY);
result.max = DqnV2_2i(maxX, maxY);
return result;
}
DQN_FILE_SCOPE DqnRect DqnRect_Init(DqnV2 origin, DqnV2 size)
{
DqnRect result = {};
@ -2244,6 +2286,12 @@ DQN_FILE_SCOPE void DqnRect_GetSize2f(DqnRect rect, f32 *width, f32 *height)
*height = DQN_ABS(rect.max.y - rect.min.y);
}
DQN_FILE_SCOPE void DqnRect_GetSize2i(DqnRect rect, i32 *width, i32 *height)
{
*width = (i32)DQN_ABS(rect.max.x - rect.min.x);
*height = (i32)DQN_ABS(rect.max.y - rect.min.y);
}
DQN_FILE_SCOPE DqnV2 DqnRect_GetSizeV2(DqnRect rect)
{
f32 width = DQN_ABS(rect.max.x - rect.min.x);
@ -2261,6 +2309,18 @@ DQN_FILE_SCOPE DqnV2 DqnRect_GetCentre(DqnRect rect)
return result;
}
DQN_FILE_SCOPE DqnRect DqnRect_ClipRect(DqnRect rect, DqnRect clip)
{
DqnRect result = {};
DqnV2 clipSize = DqnRect_GetSizeV2(clip);
result.max.x = DQN_MIN(rect.max.x, clipSize.w);
result.max.y = DQN_MIN(rect.max.y, clipSize.h);
result.min.x = DQN_MAX(clip.min.x, rect.min.x);
result.min.y = DQN_MAX(clip.min.y, rect.min.y);
return result;
}
DQN_FILE_SCOPE DqnRect DqnRect_Move(DqnRect rect, DqnV2 shift)
{
DqnRect result = {0};
@ -2435,7 +2495,64 @@ DQN_FILE_SCOPE bool Dqn_StrHasSubstring(const char *const src, const i32 srcLen,
return true;
}
DQN_FILE_SCOPE i32 Dqn_StrToI32(const char *const buf, const i32 bufSize)
DQN_FILE_SCOPE i32 Dqn_I64ToStr(i64 value, char *const buf, const i32 bufSize)
{
bool validBuffer = true;
if (!buf || bufSize == 0) validBuffer = false;
if (value == 0)
{
if (validBuffer) buf[0] = '0';
return 1;
}
// NOTE(doyle): Max 32bit integer (+-)2147483647
i32 charIndex = 0;
bool negative = false;
if (value < 0) negative = true;
if (negative)
{
if (validBuffer) buf[charIndex] = '-';
charIndex++;
value *= -1;
}
if (validBuffer)
{
while (value != 0 && charIndex < bufSize)
{
i32 rem = value % 10;
buf[charIndex++] = (u8)rem + '0';
value /= 10;
}
// NOTE(doyle): If string is negative, we only want to reverse starting
// from the second character, so we don't put the negative sign at the
// end
if (negative)
{
Dqn_StrReverse(buf + 1, charIndex - 1);
}
else
{
Dqn_StrReverse(buf, charIndex);
}
}
else
{
while (value != 0)
{
i32 rem = value % 10;
value /= 10;
charIndex++;
}
}
return charIndex;
}
DQN_FILE_SCOPE i64 Dqn_StrToI64(const char *const buf, const i32 bufSize)
{
if (!buf || bufSize == 0) return 0;
@ -2451,7 +2568,7 @@ DQN_FILE_SCOPE i32 Dqn_StrToI32(const char *const buf, const i32 bufSize)
return 0;
}
i32 result = 0;
i64 result = 0;
for (i32 i = index; i < bufSize; i++)
{
if (DqnChar_IsDigit(buf[i]))
@ -2470,45 +2587,6 @@ DQN_FILE_SCOPE i32 Dqn_StrToI32(const char *const buf, const i32 bufSize)
return result;
}
DQN_FILE_SCOPE i32 Dqn_I32ToStr(i32 value, char *buf, i32 bufSize)
{
if (!buf || bufSize == 0) return 0;
if (value == 0)
{
buf[0] = '0';
return 0;
}
// NOTE(doyle): Max 32bit integer (+-)2147483647
i32 charIndex = 0;
bool negative = false;
if (value < 0) negative = true;
if (negative) buf[charIndex++] = '-';
i32 val = DQN_ABS(value);
while (val != 0 && charIndex < bufSize)
{
i32 rem = val % 10;
buf[charIndex++] = (u8)rem + '0';
val /= 10;
}
// NOTE(doyle): If string is negative, we only want to reverse starting
// from the second character, so we don't put the negative sign at the end
if (negative)
{
Dqn_StrReverse(buf + 1, charIndex - 1);
}
else
{
Dqn_StrReverse(buf, charIndex);
}
return charIndex;
}
/*
Encoding
The following byte sequences are used to represent a character. The sequence
@ -3163,12 +3241,14 @@ FILE_SCOPE f64 DqnWin32_QueryPerfCounterTimeInSInternal()
f64 DqnTime_NowInS()
{
f64 result;
#ifdef DQN_WIN32_IMPLEMENTATION
return DqnWin32_QueryPerfCounterTimeInSInternal();
result = DQN_MAX(DqnWin32_QueryPerfCounterTimeInSInternal(), 0);
#else
result = 0;
DQN_ASSERT(DQN_INVALID_CODE_PATH);
return 0;
#endif
return result;
};
f64 DqnTime_NowInMs() { return DqnTime_NowInS() * 1000.0f; }

View File

@ -178,41 +178,58 @@ void StringsTest()
"StringsTest(): StrReverse: Completed successfully\n");
}
// StrToI32
const u64 LARGEST_NUM = (u64)-1;
const i64 SMALLEST_NUM = -9223372036854775808LL;
// StrToI64
{
char *a = "123";
DQN_ASSERT(Dqn_StrToI32(a, Dqn_strlen(a)) == 123);
DQN_ASSERT(Dqn_StrToI64(a, Dqn_strlen(a)) == 123);
char *b = "-123";
DQN_ASSERT(Dqn_StrToI32(b, Dqn_strlen(b)) == -123);
DQN_ASSERT(Dqn_StrToI32(b, 1) == 0);
DQN_ASSERT(Dqn_StrToI32(&b[1], Dqn_strlen(&b[1])) == 123);
DQN_ASSERT(Dqn_StrToI64(b, Dqn_strlen(b)) == -123);
DQN_ASSERT(Dqn_StrToI64(b, 1) == 0);
char *c = "-0";
DQN_ASSERT(Dqn_StrToI32(c, Dqn_strlen(c)) == 0);
DQN_ASSERT(Dqn_StrToI64(c, Dqn_strlen(c)) == 0);
char *d = "+123";
DQN_ASSERT(Dqn_StrToI32(d, Dqn_strlen(d)) == 123);
DQN_ASSERT(Dqn_StrToI32(&d[1], Dqn_strlen(&d[1])) == 123);
DQN_ASSERT(Dqn_StrToI64(d, Dqn_strlen(d)) == 123);
printf("StringsTest(): StrToI32: Completed successfully\n");
// TODO(doyle): Unsigned conversion
#if 0
char *e = "18446744073709551615";
DQN_ASSERT((u64)(Dqn_StrToI64(e, Dqn_strlen(e))) == LARGEST_NUM);
#endif
char *f = "-9223372036854775808";
DQN_ASSERT(Dqn_StrToI64(f, Dqn_strlen(f)) == SMALLEST_NUM);
printf("StringsTest(): StrToI64: Completed successfully\n");
}
// i32_to_str
// i64 to str
{
char a[DQN_I32_TO_STR_MAX_BUF_SIZE] = {};
Dqn_I32ToStr(+100, a, DQN_ARRAY_COUNT(a));
char a[DQN_64BIT_NUM_MAX_STR_SIZE] = {};
Dqn_I64ToStr(+100, a, DQN_ARRAY_COUNT(a));
DQN_ASSERT(Dqn_strcmp(a, "100") == 0);
char b[DQN_I32_TO_STR_MAX_BUF_SIZE] = {};
Dqn_I32ToStr(-100, b, DQN_ARRAY_COUNT(b));
char b[DQN_64BIT_NUM_MAX_STR_SIZE] = {};
Dqn_I64ToStr(-100, b, DQN_ARRAY_COUNT(b));
DQN_ASSERT(Dqn_strcmp(b, "-100") == 0);
char c[DQN_I32_TO_STR_MAX_BUF_SIZE] = {};
Dqn_I32ToStr(0, c, DQN_ARRAY_COUNT(c));
char c[DQN_64BIT_NUM_MAX_STR_SIZE] = {};
Dqn_I64ToStr(0, c, DQN_ARRAY_COUNT(c));
DQN_ASSERT(Dqn_strcmp(c, "0") == 0);
printf("StringsTest(): StrToI32: Completed successfully\n");
char d[DQN_64BIT_NUM_MAX_STR_SIZE] = {};
Dqn_I64ToStr(LARGEST_NUM, d, DQN_ARRAY_COUNT(d));
DQN_ASSERT(Dqn_strcmp(d, "18446744073709551615") == 0);
char e[DQN_64BIT_NUM_MAX_STR_SIZE] = {};
Dqn_I64ToStr(SMALLEST_NUM, e, DQN_ARRAY_COUNT(e));
DQN_ASSERT(Dqn_strcmp(e, "-9223372036854775808") == 0);
printf("StringsTest(): I64ToStr: Completed successfully\n");
}
}
@ -394,7 +411,7 @@ void VecTest()
DQN_ASSERT(vec.w == 5.5f && vec.h == 5.0f);
}
// V2i Creating
// V2 with 2 integers
{
DqnV2 vec = DqnV2_2i(3, 5);
DQN_ASSERT(vec.x == 3 && vec.y == 5.0f);
@ -425,7 +442,7 @@ void VecTest()
DQN_ASSERT(dotResult == 55);
}
// Test operator overloadign
// Test operator overloading
{
DqnV2 vecA = DqnV2_2f(5, 10);
DqnV2 vecB = DqnV2_2i(2, 3);
@ -452,7 +469,6 @@ void VecTest()
DQN_ASSERT((result == DqnV2_2f(250, 25)) == true);
}
// V2 Properties
{
DqnV2 a = DqnV2_2f(0, 0);
@ -629,9 +645,27 @@ void VecTest()
// Rect
{
// Test rect init functions
{
DqnRect rect4f = DqnRect_4f(1.1f, 2.2f, 3.3f, 4.4f);
DqnRect rect4i = DqnRect_4i(1, 2, 3, 4);
DQN_ASSERT(rect4i.min.x == 1 && rect4i.min.y == 2);
DQN_ASSERT(rect4i.max.x == 3 && rect4i.max.y == 4);
DQN_ASSERT(rect4f.min.x == 1.1f && rect4f.min.y == 2.2f);
DQN_ASSERT(rect4f.max.x == 3.3f && rect4f.max.y == 4.4f);
DqnRect rect = DqnRect_Init(DqnV2_2f(-10, -10), DqnV2_2f(20, 20));
DQN_ASSERT(DqnV2_Equals(rect.min, DqnV2_2f(-10, -10)));
DQN_ASSERT(DqnV2_Equals(rect.max, DqnV2_2f(10, 10)));
}
// Test rect get size function
{
// Test float rect
{
DqnRect rect =
DqnRect_Init(DqnV2_2f(-10, -10), DqnV2_2f(20, 20));
f32 width, height;
DqnRect_GetSize2f(rect, &width, &height);
@ -640,27 +674,55 @@ void VecTest()
DqnV2 dim = DqnRect_GetSizeV2(rect);
DQN_ASSERT(DqnV2_Equals(dim, DqnV2_2f(20, 20)));
}
// Test rect with float values and GetSize as 2 integers
{
DqnRect rect = DqnRect_Init(DqnV2_2f(-10.5f, -10.5f),
DqnV2_2f(20.5f, 20.5f));
i32 width, height;
DqnRect_GetSize2i(rect, &width, &height);
DQN_ASSERT(width == 20);
DQN_ASSERT(height == 20);
}
}
// Test rect get centre
DqnRect rect = DqnRect_Init(DqnV2_2f(-10, -10), DqnV2_2f(20, 20));
DqnV2 rectCenter = DqnRect_GetCentre(rect);
DQN_ASSERT(DqnV2_Equals(rectCenter, DqnV2_2f(0, 0)));
// Test clipping rect get centre
DqnRect clipRect = DqnRect_4i(-15, -15, 10, 10);
DqnRect clipResult = DqnRect_ClipRect(rect, clipRect);
DQN_ASSERT(clipResult.min.x == -10 && clipResult.min.y == -10);
DQN_ASSERT(clipResult.max.x == 10 && clipResult.max.y == 10);
// Test shifting rect
{
DqnRect shiftedRect = DqnRect_Move(rect, DqnV2_2f(10, 0));
DQN_ASSERT(DqnV2_Equals(shiftedRect.min, DqnV2_2f(0, -10)));
DQN_ASSERT(DqnV2_Equals(shiftedRect.max, DqnV2_2f(20, 10)));
// Ensure dimensions have remained the same
{
f32 width, height;
DqnRect_GetSize2f(shiftedRect, &width, &height);
DQN_ASSERT(width == 20);
DQN_ASSERT(height == 20);
dim = DqnRect_GetSizeV2(shiftedRect);
DqnV2 dim = DqnRect_GetSizeV2(shiftedRect);
DQN_ASSERT(DqnV2_Equals(dim, DqnV2_2f(20, 20)));
}
// Test rect contains p
{
DqnV2 inP = DqnV2_2f(5, 5);
DqnV2 outP = DqnV2_2f(100, 100);
DQN_ASSERT(DqnRect_ContainsP(shiftedRect, inP));
DQN_ASSERT(!DqnRect_ContainsP(shiftedRect, outP));
}
}
printf("VecTest(): Rect: Completed successfully\n");
}

View File

@ -21,7 +21,7 @@ Global
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{87785192-6F49-4F85-AA0D-F0AFA5CCCDDA}.Release|x86.ActiveCfg = Release|x86
{87785192-6F49-4F85-AA0D-F0AFA5CCCDDA}.Release|x86.ActiveCfg = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE