Building for windows

This commit is contained in:
Anthony Wang 2020-05-20 14:14:37 -05:00
parent 9a85d09f29
commit 551f9fb5b0
75 changed files with 7310 additions and 16 deletions

3
.gitignore vendored
View file

@ -1,3 +1,6 @@
.sconsign.dblite
laines
*.o
roms
*.nes
*.exe

View file

@ -54,6 +54,11 @@ scons
./laines
```
### Windows
```sh
g++ *.cpp -o laines -IC:\mingw\include\SDL2 -LC:\mingw\lib -w -Wl,-subsystem,windows -lmingw32 -lSDL2main -lSDL2 -lSDL2_ttf -lSDL2_image -O3
```
## Usage
The emulator comes bundled with a simple GUI to navigate the filesystem and set preferences. Use arrow keys and Enter to operate it. ESC toggles between emulation and menu.

@ -1 +0,0 @@
Subproject commit 03e27b27901c8e12fef6daeddc18a9a3e217dea4

13
src/.travis.yml Normal file
View file

@ -0,0 +1,13 @@
language: cpp
os:
- linux
- osx
compiler:
- gcc
- clang
script:
- make all
- make test

539
src/ConvertUTF.c Normal file
View file

@ -0,0 +1,539 @@
/*
* Copyright 2001-2004 Unicode, Inc.
*
* Disclaimer
*
* This source code is provided as is by Unicode, Inc. No claims are
* made as to fitness for any particular purpose. No warranties of any
* kind are expressed or implied. The recipient agrees to determine
* applicability of information provided. If this file has been
* purchased on magnetic or optical media from Unicode, Inc., the
* sole remedy for any claim will be exchange of defective media
* within 90 days of receipt.
*
* Limitations on Rights to Redistribute This Code
*
* Unicode, Inc. hereby grants the right to freely use the information
* supplied in this file in the creation of products supporting the
* Unicode Standard, and to make copies of this file in any form
* for internal or external distribution as long as this notice
* remains attached.
*/
/* ---------------------------------------------------------------------
Conversions between UTF32, UTF-16, and UTF-8. Source code file.
Author: Mark E. Davis, 1994.
Rev History: Rick McGowan, fixes & updates May 2001.
Sept 2001: fixed const & error conditions per
mods suggested by S. Parent & A. Lillich.
June 2002: Tim Dodd added detection and handling of incomplete
source sequences, enhanced error detection, added casts
to eliminate compiler warnings.
July 2003: slight mods to back out aggressive FFFE detection.
Jan 2004: updated switches in from-UTF8 conversions.
Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions.
See the header file "ConvertUTF.h" for complete documentation.
------------------------------------------------------------------------ */
#include "ConvertUTF.h"
#ifdef CVTUTF_DEBUG
#include <stdio.h>
#endif
static const int halfShift = 10; /* used for shifting by 10 bits */
static const UTF32 halfBase = 0x0010000UL;
static const UTF32 halfMask = 0x3FFUL;
#define UNI_SUR_HIGH_START (UTF32)0xD800
#define UNI_SUR_HIGH_END (UTF32)0xDBFF
#define UNI_SUR_LOW_START (UTF32)0xDC00
#define UNI_SUR_LOW_END (UTF32)0xDFFF
#define false 0
#define true 1
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF32toUTF16 (
const UTF32** sourceStart, const UTF32* sourceEnd,
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF32* source = *sourceStart;
UTF16* target = *targetStart;
while (source < sourceEnd) {
UTF32 ch;
if (target >= targetEnd) {
result = targetExhausted; break;
}
ch = *source++;
if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
/* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
if (flags == strictConversion) {
--source; /* return to the illegal value itself */
result = sourceIllegal;
break;
} else {
*target++ = UNI_REPLACEMENT_CHAR;
}
} else {
*target++ = (UTF16)ch; /* normal case */
}
} else if (ch > UNI_MAX_LEGAL_UTF32) {
if (flags == strictConversion) {
result = sourceIllegal;
} else {
*target++ = UNI_REPLACEMENT_CHAR;
}
} else {
/* target is a character in range 0xFFFF - 0x10FFFF. */
if (target + 1 >= targetEnd) {
--source; /* Back up source pointer! */
result = targetExhausted; break;
}
ch -= halfBase;
*target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
*target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
}
}
*sourceStart = source;
*targetStart = target;
return result;
}
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF16toUTF32 (
const UTF16** sourceStart, const UTF16* sourceEnd,
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF16* source = *sourceStart;
UTF32* target = *targetStart;
UTF32 ch, ch2;
while (source < sourceEnd) {
const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
ch = *source++;
/* If we have a surrogate pair, convert to UTF32 first. */
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
/* If the 16 bits following the high surrogate are in the source buffer... */
if (source < sourceEnd) {
ch2 = *source;
/* If it's a low surrogate, convert to UTF32. */
if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
+ (ch2 - UNI_SUR_LOW_START) + halfBase;
++source;
} else if (flags == strictConversion) { /* it's an unpaired high surrogate */
--source; /* return to the illegal value itself */
result = sourceIllegal;
break;
}
} else { /* We don't have the 16 bits following the high surrogate. */
--source; /* return to the high surrogate */
result = sourceExhausted;
break;
}
} else if (flags == strictConversion) {
/* UTF-16 surrogate values are illegal in UTF-32 */
if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
--source; /* return to the illegal value itself */
result = sourceIllegal;
break;
}
}
if (target >= targetEnd) {
source = oldSource; /* Back up source pointer! */
result = targetExhausted; break;
}
*target++ = ch;
}
*sourceStart = source;
*targetStart = target;
#ifdef CVTUTF_DEBUG
if (result == sourceIllegal) {
fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2);
fflush(stderr);
}
#endif
return result;
}
/* --------------------------------------------------------------------- */
/*
* Index into the table below with the first byte of a UTF-8 sequence to
* get the number of trailing bytes that are supposed to follow it.
* Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is
* left as-is for anyone who may want to do such conversion, which was
* allowed in earlier algorithms.
*/
static const char trailingBytesForUTF8[256] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
};
/*
* Magic values subtracted from a buffer value during UTF8 conversion.
* This table contains as many values as there might be trailing bytes
* in a UTF-8 sequence.
*/
static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,
0x03C82080UL, 0xFA082080UL, 0x82082080UL };
/*
* Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
* into the first byte, depending on how many bytes follow. There are
* as many entries in this table as there are UTF-8 sequence types.
* (I.e., one byte sequence, two byte... etc.). Remember that sequencs
* for *legal* UTF-8 will be 4 or fewer bytes total.
*/
static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
/* --------------------------------------------------------------------- */
/* The interface converts a whole buffer to avoid function-call overhead.
* Constants have been gathered. Loops & conditionals have been removed as
* much as possible for efficiency, in favor of drop-through switches.
* (See "Note A" at the bottom of the file for equivalent code.)
* If your compiler supports it, the "isLegalUTF8" call can be turned
* into an inline function.
*/
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF16toUTF8 (
const UTF16** sourceStart, const UTF16* sourceEnd,
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF16* source = *sourceStart;
UTF8* target = *targetStart;
while (source < sourceEnd) {
UTF32 ch;
unsigned short bytesToWrite = 0;
const UTF32 byteMask = 0xBF;
const UTF32 byteMark = 0x80;
const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
ch = *source++;
/* If we have a surrogate pair, convert to UTF32 first. */
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
/* If the 16 bits following the high surrogate are in the source buffer... */
if (source < sourceEnd) {
UTF32 ch2 = *source;
/* If it's a low surrogate, convert to UTF32. */
if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
+ (ch2 - UNI_SUR_LOW_START) + halfBase;
++source;
} else if (flags == strictConversion) { /* it's an unpaired high surrogate */
--source; /* return to the illegal value itself */
result = sourceIllegal;
break;
}
} else { /* We don't have the 16 bits following the high surrogate. */
--source; /* return to the high surrogate */
result = sourceExhausted;
break;
}
} else if (flags == strictConversion) {
/* UTF-16 surrogate values are illegal in UTF-32 */
if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
--source; /* return to the illegal value itself */
result = sourceIllegal;
break;
}
}
/* Figure out how many bytes the result will require */
if (ch < (UTF32)0x80) { bytesToWrite = 1;
} else if (ch < (UTF32)0x800) { bytesToWrite = 2;
} else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
} else if (ch < (UTF32)0x110000) { bytesToWrite = 4;
} else { bytesToWrite = 3;
ch = UNI_REPLACEMENT_CHAR;
}
target += bytesToWrite;
if (target > targetEnd) {
source = oldSource; /* Back up source pointer! */
target -= bytesToWrite; result = targetExhausted; break;
}
switch (bytesToWrite) { /* note: everything falls through. */
case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]);
}
target += bytesToWrite;
}
*sourceStart = source;
*targetStart = target;
return result;
}
/* --------------------------------------------------------------------- */
/*
* Utility routine to tell whether a sequence of bytes is legal UTF-8.
* This must be called with the length pre-determined by the first byte.
* If not calling this from ConvertUTF8to*, then the length can be set by:
* length = trailingBytesForUTF8[*source]+1;
* and the sequence is illegal right away if there aren't that many bytes
* available.
* If presented with a length > 4, this returns false. The Unicode
* definition of UTF-8 goes up to 4-byte sequences.
*/
static Boolean isLegalUTF8(const UTF8 *source, int length) {
UTF8 a;
const UTF8 *srcptr = source+length;
switch (length) {
default: return false;
/* Everything else falls through when "true"... */
case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
case 2: if ((a = (*--srcptr)) > 0xBF) return false;
switch (*source) {
/* no fall-through in this inner switch */
case 0xE0: if (a < 0xA0) return false; break;
case 0xED: if (a > 0x9F) return false; break;
case 0xF0: if (a < 0x90) return false; break;
case 0xF4: if (a > 0x8F) return false; break;
default: if (a < 0x80) return false;
}
case 1: if (*source >= 0x80 && *source < 0xC2) return false;
}
if (*source > 0xF4) return false;
return true;
}
/* --------------------------------------------------------------------- */
/*
* Exported function to return whether a UTF-8 sequence is legal or not.
* This is not used here; it's just exported.
*/
Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) {
int length = trailingBytesForUTF8[*source]+1;
if (source+length > sourceEnd) {
return false;
}
return isLegalUTF8(source, length);
}
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF8toUTF16 (
const UTF8** sourceStart, const UTF8* sourceEnd,
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF8* source = *sourceStart;
UTF16* target = *targetStart;
while (source < sourceEnd) {
UTF32 ch = 0;
unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
if (source + extraBytesToRead >= sourceEnd) {
result = sourceExhausted; break;
}
/* Do this check whether lenient or strict */
if (! isLegalUTF8(source, extraBytesToRead+1)) {
result = sourceIllegal;
break;
}
/*
* The cases all fall through. See "Note A" below.
*/
switch (extraBytesToRead) {
case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
case 3: ch += *source++; ch <<= 6;
case 2: ch += *source++; ch <<= 6;
case 1: ch += *source++; ch <<= 6;
case 0: ch += *source++;
}
ch -= offsetsFromUTF8[extraBytesToRead];
if (target >= targetEnd) {
source -= (extraBytesToRead+1); /* Back up source pointer! */
result = targetExhausted; break;
}
if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
/* UTF-16 surrogate values are illegal in UTF-32 */
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
if (flags == strictConversion) {
source -= (extraBytesToRead+1); /* return to the illegal value itself */
result = sourceIllegal;
break;
} else {
*target++ = UNI_REPLACEMENT_CHAR;
}
} else {
*target++ = (UTF16)ch; /* normal case */
}
} else if (ch > UNI_MAX_UTF16) {
if (flags == strictConversion) {
result = sourceIllegal;
source -= (extraBytesToRead+1); /* return to the start */
break; /* Bail out; shouldn't continue */
} else {
*target++ = UNI_REPLACEMENT_CHAR;
}
} else {
/* target is a character in range 0xFFFF - 0x10FFFF. */
if (target + 1 >= targetEnd) {
source -= (extraBytesToRead+1); /* Back up source pointer! */
result = targetExhausted; break;
}
ch -= halfBase;
*target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
*target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
}
}
*sourceStart = source;
*targetStart = target;
return result;
}
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF32toUTF8 (
const UTF32** sourceStart, const UTF32* sourceEnd,
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF32* source = *sourceStart;
UTF8* target = *targetStart;
while (source < sourceEnd) {
UTF32 ch;
unsigned short bytesToWrite = 0;
const UTF32 byteMask = 0xBF;
const UTF32 byteMark = 0x80;
ch = *source++;
if (flags == strictConversion ) {
/* UTF-16 surrogate values are illegal in UTF-32 */
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
--source; /* return to the illegal value itself */
result = sourceIllegal;
break;
}
}
/*
* Figure out how many bytes the result will require. Turn any
* illegally large UTF32 things (> Plane 17) into replacement chars.
*/
if (ch < (UTF32)0x80) { bytesToWrite = 1;
} else if (ch < (UTF32)0x800) { bytesToWrite = 2;
} else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
} else if (ch <= UNI_MAX_LEGAL_UTF32) { bytesToWrite = 4;
} else { bytesToWrite = 3;
ch = UNI_REPLACEMENT_CHAR;
result = sourceIllegal;
}
target += bytesToWrite;
if (target > targetEnd) {
--source; /* Back up source pointer! */
target -= bytesToWrite; result = targetExhausted; break;
}
switch (bytesToWrite) { /* note: everything falls through. */
case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]);
}
target += bytesToWrite;
}
*sourceStart = source;
*targetStart = target;
return result;
}
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF8toUTF32 (
const UTF8** sourceStart, const UTF8* sourceEnd,
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF8* source = *sourceStart;
UTF32* target = *targetStart;
while (source < sourceEnd) {
UTF32 ch = 0;
unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
if (source + extraBytesToRead >= sourceEnd) {
result = sourceExhausted; break;
}
/* Do this check whether lenient or strict */
if (! isLegalUTF8(source, extraBytesToRead+1)) {
result = sourceIllegal;
break;
}
/*
* The cases all fall through. See "Note A" below.
*/
switch (extraBytesToRead) {
case 5: ch += *source++; ch <<= 6;
case 4: ch += *source++; ch <<= 6;
case 3: ch += *source++; ch <<= 6;
case 2: ch += *source++; ch <<= 6;
case 1: ch += *source++; ch <<= 6;
case 0: ch += *source++;
}
ch -= offsetsFromUTF8[extraBytesToRead];
if (target >= targetEnd) {
source -= (extraBytesToRead+1); /* Back up the source pointer! */
result = targetExhausted; break;
}
if (ch <= UNI_MAX_LEGAL_UTF32) {
/*
* UTF-16 surrogate values are illegal in UTF-32, and anything
* over Plane 17 (> 0x10FFFF) is illegal.
*/
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
if (flags == strictConversion) {
source -= (extraBytesToRead+1); /* return to the illegal value itself */
result = sourceIllegal;
break;
} else {
*target++ = UNI_REPLACEMENT_CHAR;
}
} else {
*target++ = ch;
}
} else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */
result = sourceIllegal;
*target++ = UNI_REPLACEMENT_CHAR;
}
}
*sourceStart = source;
*targetStart = target;
return result;
}
/* ---------------------------------------------------------------------
Note A.
The fall-through switches in UTF-8 reading code save a
temp variable, some decrements & conditionals. The switches
are equivalent to the following loop:
{
int tmpBytesToRead = extraBytesToRead+1;
do {
ch += *source++;
--tmpBytesToRead;
if (tmpBytesToRead) ch <<= 6;
} while (tmpBytesToRead > 0);
}
In UTF-8 writing code, the switches on "bytesToWrite" are
similarly unrolled loops.
--------------------------------------------------------------------- */

149
src/ConvertUTF.h Normal file
View file

@ -0,0 +1,149 @@
/*
* Copyright 2001-2004 Unicode, Inc.
*
* Disclaimer
*
* This source code is provided as is by Unicode, Inc. No claims are
* made as to fitness for any particular purpose. No warranties of any
* kind are expressed or implied. The recipient agrees to determine
* applicability of information provided. If this file has been
* purchased on magnetic or optical media from Unicode, Inc., the
* sole remedy for any claim will be exchange of defective media
* within 90 days of receipt.
*
* Limitations on Rights to Redistribute This Code
*
* Unicode, Inc. hereby grants the right to freely use the information
* supplied in this file in the creation of products supporting the
* Unicode Standard, and to make copies of this file in any form
* for internal or external distribution as long as this notice
* remains attached.
*/
/* ---------------------------------------------------------------------
Conversions between UTF32, UTF-16, and UTF-8. Header file.
Several funtions are included here, forming a complete set of
conversions between the three formats. UTF-7 is not included
here, but is handled in a separate source file.
Each of these routines takes pointers to input buffers and output
buffers. The input buffers are const.
Each routine converts the text between *sourceStart and sourceEnd,
putting the result into the buffer between *targetStart and
targetEnd. Note: the end pointers are *after* the last item: e.g.
*(sourceEnd - 1) is the last item.
The return result indicates whether the conversion was successful,
and if not, whether the problem was in the source or target buffers.
(Only the first encountered problem is indicated.)
After the conversion, *sourceStart and *targetStart are both
updated to point to the end of last text successfully converted in
the respective buffers.
Input parameters:
sourceStart - pointer to a pointer to the source buffer.
The contents of this are modified on return so that
it points at the next thing to be converted.
targetStart - similarly, pointer to pointer to the target buffer.
sourceEnd, targetEnd - respectively pointers to the ends of the
two buffers, for overflow checking only.
These conversion functions take a ConversionFlags argument. When this
flag is set to strict, both irregular sequences and isolated surrogates
will cause an error. When the flag is set to lenient, both irregular
sequences and isolated surrogates are converted.
Whether the flag is strict or lenient, all illegal sequences will cause
an error return. This includes sequences such as: <F4 90 80 80>, <C0 80>,
or <A0> in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code
must check for illegal sequences.
When the flag is set to lenient, characters over 0x10FFFF are converted
to the replacement character; otherwise (when the flag is set to strict)
they constitute an error.
Output parameters:
The value "sourceIllegal" is returned from some routines if the input
sequence is malformed. When "sourceIllegal" is returned, the source
value will point to the illegal value that caused the problem. E.g.,
in UTF-8 when a sequence is malformed, it points to the start of the
malformed sequence.
Author: Mark E. Davis, 1994.
Rev History: Rick McGowan, fixes & updates May 2001.
Fixes & updates, Sept 2001.
------------------------------------------------------------------------ */
/* ---------------------------------------------------------------------
The following 4 definitions are compiler-specific.
The C standard does not guarantee that wchar_t has at least
16 bits, so wchar_t is no less portable than unsigned short!
All should be unsigned values to avoid sign extension during
bit mask & shift operations.
------------------------------------------------------------------------ */
typedef unsigned int UTF32; /* at least 32 bits */
typedef unsigned short UTF16; /* at least 16 bits */
typedef unsigned char UTF8; /* typically 8 bits */
typedef unsigned char Boolean; /* 0 or 1 */
/* Some fundamental constants */
#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD
#define UNI_MAX_BMP (UTF32)0x0000FFFF
#define UNI_MAX_UTF16 (UTF32)0x0010FFFF
#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF
#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF
typedef enum {
conversionOK, /* conversion successful */
sourceExhausted, /* partial character in source, but hit end */
targetExhausted, /* insuff. room in target for conversion */
sourceIllegal /* source sequence is illegal/malformed */
} ConversionResult;
typedef enum {
strictConversion = 0,
lenientConversion
} ConversionFlags;
/* This is for C++ and does no harm in C */
#ifdef __cplusplus
extern "C" {
#endif
ConversionResult ConvertUTF8toUTF16 (
const UTF8** sourceStart, const UTF8* sourceEnd,
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
ConversionResult ConvertUTF16toUTF8 (
const UTF16** sourceStart, const UTF16* sourceEnd,
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
ConversionResult ConvertUTF8toUTF32 (
const UTF8** sourceStart, const UTF8* sourceEnd,
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
ConversionResult ConvertUTF32toUTF8 (
const UTF32** sourceStart, const UTF32* sourceEnd,
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
ConversionResult ConvertUTF16toUTF32 (
const UTF16** sourceStart, const UTF16* sourceEnd,
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
ConversionResult ConvertUTF32toUTF16 (
const UTF32** sourceStart, const UTF32* sourceEnd,
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd);
#ifdef __cplusplus
}
#endif
/* --------------------------------------------------------------------- */

20
src/LICENCE.txt Normal file
View file

@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2006-2013 Brodie Thiesfield
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

28
src/Makefile Normal file
View file

@ -0,0 +1,28 @@
CC=g++
CFLAGS=-Wall
CPPFLAGS=-Wall
OBJS=testsi.o test1.o snippets.o ConvertUTF.o
help:
@echo This makefile is just for the test program \(use \"make clean all test\"\)
@echo Just include the SimpleIni.h header file to use it.
all: $(OBJS)
$(CC) -o testsi $(OBJS)
clean:
rm -f core *.o testsi
data:
sed 's/\r\n$$/\n/g' < test1-expected.ini > unix.out
mv unix.out test1-expected.ini
test: testsi
./testsi -u -m -l test1-input.ini > test1-blah.ini
diff test1-output.ini test1-expected.ini
install:
@echo No install required. Just include the SimpleIni.h header file to use it.
testsi.o test1.o snippets.o : SimpleIni.h

152
src/README.md Normal file
View file

@ -0,0 +1,152 @@
simpleini
=========
[![TravisCI Status](https://travis-ci.org/brofield/simpleini.svg?branch=master)](https://travis-ci.org/brofield/simpleini)
A cross-platform library that provides a simple API to read and write INI-style configuration files. It supports data files in ASCII, MBCS and Unicode. It is designed explicitly to be portable to any platform and has been tested on Windows, WinCE and Linux. Released as open-source and free using the MIT licence.
# Feature Summary
- MIT Licence allows free use in all software (including GPL and commercial)
- multi-platform (Windows 95/98/ME/NT/2K/XP/2003, Windows CE, Linux, Unix)
- loading and saving of INI-style configuration files
- configuration files can have any newline format on all platforms
- liberal acceptance of file format
* key/values with no section
* removal of whitespace around sections, keys and values
- support for multi-line values (values with embedded newline characters)
- optional support for multiple keys with the same name
- optional case-insensitive sections and keys (for ASCII characters only)
- saves files with sections and keys in the same order as they were loaded
- preserves comments on the file, section and keys where possible.
- supports both char or wchar_t programming interfaces
- supports both MBCS (system locale) and UTF-8 file encodings
- system locale does not need to be UTF-8 on Linux/Unix to load UTF-8 file
- support for non-ASCII characters in section, keys, values and comments
- support for non-standard character types or file encodings via user-written converter classes
- support for adding/modifying values programmatically
- compiles cleanly in the following compilers:
* Windows/VC6 (warning level 3)
* Windows/VC.NET 2003 (warning level 4)
* Windows/VC 2005 (warning level 4)
* Linux/gcc (-Wall)
* Windows/MinGW GCC
# Documentation
Full documentation of the interface is available in doxygen format.
# Examples
These snippets are included with the distribution in the file snippets.cpp.
### SIMPLE USAGE
```c++
CSimpleIniA ini;
ini.SetUnicode();
ini.LoadFile("myfile.ini");
const char * pVal = ini.GetValue("section", "key", "default");
ini.SetValue("section", "key", "newvalue");
```
### LOADING DATA
```c++
// load from a data file
CSimpleIniA ini(a_bIsUtf8, a_bUseMultiKey, a_bUseMultiLine);
SI_Error rc = ini.LoadFile(a_pszFile);
if (rc < 0) return false;
// load from a string
std::string strData;
rc = ini.LoadData(strData.c_str(), strData.size());
if (rc < 0) return false;
```
### GETTING SECTIONS AND KEYS
```c++
// get all sections
CSimpleIniA::TNamesDepend sections;
ini.GetAllSections(sections);
// get all keys in a section
CSimpleIniA::TNamesDepend keys;
ini.GetAllKeys("section-name", keys);
```
### GETTING VALUES
```c++
// get the value of a key
const char * pszValue = ini.GetValue("section-name",
"key-name", NULL /*default*/);
// get the value of a key which may have multiple
// values. If bHasMultipleValues is true, then just
// one value has been returned
bool bHasMultipleValues;
pszValue = ini.GetValue("section-name", "key-name",
NULL /*default*/, &amp;bHasMultipleValues);
// get all values of a key with multiple values
CSimpleIniA::TNamesDepend values;
ini.GetAllValues("section-name", "key-name", values);
// sort the values into the original load order
values.sort(CSimpleIniA::Entry::LoadOrder());
// output all of the items
CSimpleIniA::TNamesDepend::const_iterator i;
for (i = values.begin(); i != values.end(); ++i) {
printf("key-name = '%s'\n", i->pItem);
}
```
### MODIFYING DATA
```c++
// adding a new section
rc = ini.SetValue("new-section", NULL, NULL);
if (rc < 0) return false;
printf("section: %s\n", rc == SI_INSERTED ?
"inserted" : "updated");
// adding a new key ("new-section" will be added
// automatically if it doesn't already exist)
rc = ini.SetValue("new-section", "new-key", "value");
if (rc < 0) return false;
printf("key: %s\n", rc == SI_INSERTED ?
"inserted" : "updated");
// changing the value of a key
rc = ini.SetValue("section", "key", "updated-value");
if (rc < 0) return false;
printf("key: %s\n", rc == SI_INSERTED ?
"inserted" : "updated");
```
### DELETING DATA
```c++
// deleting a key from a section. Optionally the entire
// section may be deleted if it is now empty.
ini.Delete("section-name", "key-name",
true /*delete the section if empty*/);
// deleting an entire section and all keys in it
ini.Delete("section-name", NULL);
```
### SAVING DATA
```c++
// save the data to a string
rc = ini.Save(strData);
if (rc < 0) return false;
// save the data back to the file
rc = ini.SaveFile(a_pszFile);
if (rc < 0) return false;
```

3442
src/SimpleIni.h Normal file

File diff suppressed because it is too large Load diff

29
src/SimpleIni.sln Normal file
View file

@ -0,0 +1,29 @@
Microsoft Visual Studio Solution File, Format Version 8.00
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleIni", "SimpleIni.vcproj", "{C23240A6-AA9D-4827-AF06-C98E97CA6DFB}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfiguration) = preSolution
Debug = Debug
Debug Unicode = Debug Unicode
Release = Release
Release Unicode = Release Unicode
EndGlobalSection
GlobalSection(ProjectDependencies) = postSolution
EndGlobalSection
GlobalSection(ProjectConfiguration) = postSolution
{C23240A6-AA9D-4827-AF06-C98E97CA6DFB}.Debug.ActiveCfg = Debug|Win32
{C23240A6-AA9D-4827-AF06-C98E97CA6DFB}.Debug.Build.0 = Debug|Win32
{C23240A6-AA9D-4827-AF06-C98E97CA6DFB}.Debug Unicode.ActiveCfg = Debug Unicode|Win32
{C23240A6-AA9D-4827-AF06-C98E97CA6DFB}.Debug Unicode.Build.0 = Debug Unicode|Win32
{C23240A6-AA9D-4827-AF06-C98E97CA6DFB}.Release.ActiveCfg = Release|Win32
{C23240A6-AA9D-4827-AF06-C98E97CA6DFB}.Release.Build.0 = Release|Win32
{C23240A6-AA9D-4827-AF06-C98E97CA6DFB}.Release Unicode.ActiveCfg = Release Unicode|Win32
{C23240A6-AA9D-4827-AF06-C98E97CA6DFB}.Release Unicode.Build.0 = Release Unicode|Win32
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection
GlobalSection(ExtensibilityAddIns) = postSolution
EndGlobalSection
EndGlobal

291
src/SimpleIni.vcproj Normal file
View file

@ -0,0 +1,291 @@
<?xml version="1.0" encoding="shift_jis"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="SimpleIni"
ProjectGUID="{C23240A6-AA9D-4827-AF06-C98E97CA6DFB}"
RootNamespace="SimpleIni"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
IntermediateDirectory="Debug"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="5"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/testsi.exe"
LinkIncremental="2"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/SimpleIni.pdb"
SubSystem="1"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
IntermediateDirectory="Release"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="4"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/testsi.exe"
LinkIncremental="1"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Debug Unicode|Win32"
OutputDirectory="$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="5"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/testsi.exe"
LinkIncremental="2"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/SimpleIni.pdb"
SubSystem="1"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release Unicode|Win32"
OutputDirectory="$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1">
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="4"
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/testsi.exe"
LinkIncremental="1"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
<File
RelativePath=".\snippets.cpp">
</File>
<File
RelativePath=".\test1.cpp">
</File>
<File
RelativePath=".\testsi.cpp">
</File>
</Filter>
<Filter
Name="Library Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
<File
RelativePath=".\SimpleIni.h">
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
<File
RelativePath=".\Makefile">
</File>
<File
RelativePath=".\testsi-EUCJP.ini">
</File>
<File
RelativePath=".\testsi-SJIS.ini">
</File>
<File
RelativePath=".\testsi-UTF8.ini">
</File>
</Filter>
<Filter
Name="Conversion Files"
Filter="">
<File
RelativePath=".\ConvertUTF.c">
</File>
<File
RelativePath=".\ConvertUTF.h">
</File>
</Filter>
<Filter
Name="Documentation"
Filter="">
<File
RelativePath=".\simpleini.doxy">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
CommandLine="if not exist &quot;C:\Program Files\doxygen\bin\doxygen.exe&quot; goto done
echo Generating documentation...
&quot;C:\Program Files\doxygen\bin\doxygen.exe&quot; $(InputDir)simpleini.doxy
:done
"
Outputs="d:\src\simpleini-doc\html\index.html"/>
</FileConfiguration>
</File>
</Filter>
<Filter
Name="Tests"
Filter="">
<File
RelativePath=".\test1-expected.ini">
</File>
<File
RelativePath=".\test1-input.ini">
</File>
<File
RelativePath=".\test1-output.ini">
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View file

@ -1,11 +1,11 @@
#include <cstdio>
#include "apu.hpp"
#include "cpu.hpp"
#include "mappers/mapper0.hpp"
#include "mappers/mapper1.hpp"
#include "mappers/mapper2.hpp"
#include "mappers/mapper3.hpp"
#include "mappers/mapper4.hpp"
#include "mapper0.hpp"
#include "mapper1.hpp"
#include "mapper2.hpp"
#include "mapper3.hpp"
#include "mapper4.hpp"
#include "ppu.hpp"
#include "cartridge.hpp"

View file

@ -1,5 +1,6 @@
#include <direct.h>
#include <cstdlib>
#include <SimpleIni.h>
#include "SimpleIni.h"
#include "config.hpp"
#include "gui.hpp"
@ -49,7 +50,7 @@ const char* get_config_path(char* buf, int buflen)
snprintf(homepath, sizeof(homepath), "%s/.config", home);
/* Then, .config as a folder */
int res = mkdir(homepath, CONFIG_DIR_DEFAULT_MODE);
int res = _mkdir(homepath);
int err = errno;
if (res == -1 && err != EEXIST)
@ -58,7 +59,7 @@ const char* get_config_path(char* buf, int buflen)
snprintf(path, sizeof(path), "%s/%s", homepath, CONFIG_DIR_NAME);
/* Finally, CONFIG_DIR_NAME as a sub-folder */
res = mkdir(path, CONFIG_DIR_DEFAULT_MODE);
res = _mkdir(path);
err = errno;
if (res == -1 && err != EEXIST)

View file

@ -3,7 +3,7 @@
#include <sys/stat.h>
#include <SDL2/SDL.h>
#define CONFIG_DIR_DEFAULT_MODE S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH
#define CONFIG_DIR_DEFAULT_MODE _S_IREAD | _S_IWRITE
#define USE_CONFIG_DIR true
#define CONFIG_DIR_NAME "LaiNES"
#define CONFIG_FALLBACK ".laines-settings"

View file

@ -1,6 +1,6 @@
#pragma once
#include "common.hpp"
#include <Nes_Apu.h>
#include "Nes_Apu.h"
namespace CPU {

View file

@ -1,7 +1,7 @@
#pragma once
#include <SDL2/SDL.h>
#include <string>
#include <Nes_Apu.h>
#include "Nes_Apu.h"
#include "common.hpp"
namespace GUI {

36
src/ini.syn Normal file
View file

@ -0,0 +1,36 @@
; Syntax file for ini files - contributed by Brodie Thiesfield
;
; Suggested Colors:
; Comments (;#) Comments, Comments 2 Green
; Sections Characters Red
; Values Strings Blue
C=1
[Syntax]
Namespace1 = 6
IgnoreCase = Yes
KeyWordLength = 1
BracketChars =
OperatorChars =
PreprocStart =
SyntaxStart =
SyntaxEnd =
HexPrefix =
CommentStart =
CommentEnd =
CommentStartAlt =
CommentEndAlt =
SingleComment = #
SingleCommentCol =
SingleCommentAlt = ;
SingleCommentColAlt =
SingleCommentEsc =
StringsSpanLines = No
StringStart =
StringEnd =
StringAlt = =
StringEsc =
CharStart = [
CharEnd = ]
CharEsc =

View file

@ -1,5 +1,5 @@
#include "ppu.hpp"
#include "mappers/mapper1.hpp"
#include "mapper1.hpp"
/* Apply the registers state */

View file

@ -1,5 +1,5 @@
#include "ppu.hpp"
#include "mappers/mapper2.hpp"
#include "mapper2.hpp"
/* Based off of https://wiki.nesdev.com/w/index.php/UxROM */

View file

@ -1,5 +1,5 @@
#include "ppu.hpp"
#include "mappers/mapper3.hpp"
#include "mapper3.hpp"
/* Based off of https://wiki.nesdev.com/w/index.php/INES_Mapper_003 */

View file

@ -1,6 +1,6 @@
#include "cpu.hpp"
#include "ppu.hpp"
#include "mappers/mapper4.hpp"
#include "mapper4.hpp"
void Mapper4::apply()

26
src/package.cmd Normal file
View file

@ -0,0 +1,26 @@
set VERSION=4.15
set SEVENZIP="C:\Program Files\7-Zip\7z.exe"
FOR /F "tokens=*" %%G IN ('DIR /AD /B /S Debug*') DO (
DEL /S /Q "%%G"
RD "%%G"
)
FOR /F "tokens=*" %%G IN ('DIR /AD /B /S Release*') DO (
DEL /S /Q "%%G"
RD "%%G"
)
DEL /Q "SimpleIni.ncb"
ATTRIB -H "SimpleIni.suo"
DEL /Q "SimpleIni.suo"
DEL /Q "SimpleIni.opt"
DEL /Q testsi-out*.ini
DEL /Q test1-blah.ini
DEL /Q test1-output.ini
START "Generate documentation" /WAIT "C:\Program Files (x86)\doxygen\bin\doxygen.exe" SimpleIni.doxy
cd ..
del simpleini-%VERSION%.zip
%SEVENZIP% a -tzip -r- -x!simpleini\.svn simpleini-%VERSION%.zip simpleini\*
del simpleini-doc.zip
%SEVENZIP% a -tzip -r simpleini-doc.zip simpleini-doc\*
cd simpleini

View file

@ -2,6 +2,7 @@
#include "cpu.hpp"
#include "gui.hpp"
#include "ppu.hpp"
#include <cstring>
namespace PPU {
#include "palette.inc"

View file

Before

Width:  |  Height:  |  Size: 408 KiB

After

Width:  |  Height:  |  Size: 408 KiB

1321
src/simpleini.doxy Normal file

File diff suppressed because it is too large Load diff

178
src/simpleini.dsp Normal file
View file

@ -0,0 +1,178 @@
# Microsoft Developer Studio Project File - Name="simpleini" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=simpleini - Win32 Debug Unicode
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "simpleini.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "simpleini.mak" CFG="simpleini - Win32 Debug Unicode"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "simpleini - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "simpleini - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE "simpleini - Win32 Debug Unicode" (based on "Win32 (x86) Console Application")
!MESSAGE "simpleini - Win32 Release Unicode" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "simpleini - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0xc09 /d "NDEBUG"
# ADD RSC /l 0xc09 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/testsi.exe"
!ELSEIF "$(CFG)" == "simpleini - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "simpleini___Win32_Debug"
# PROP BASE Intermediate_Dir "simpleini___Win32_Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c
# SUBTRACT CPP /Fr /YX
# ADD BASE RSC /l 0xc09 /d "_DEBUG"
# ADD RSC /l 0xc09 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/testsi.exe" /pdbtype:sept
!ELSEIF "$(CFG)" == "simpleini - Win32 Debug Unicode"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug Unicode"
# PROP BASE Intermediate_Dir "Debug Unicode"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug Unicode"
# PROP Intermediate_Dir "Debug Unicode"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /D "SI_USE_GENERIC_CONVERSION" /FD /GZ /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0xc09 /d "_DEBUG"
# ADD RSC /l 0xc09 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug Unicode/testsi.exe" /pdbtype:sept
!ELSEIF "$(CFG)" == "simpleini - Win32 Release Unicode"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release Unicode"
# PROP BASE Intermediate_Dir "Release Unicode"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release Unicode"
# PROP Intermediate_Dir "Release Unicode"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /D "SI_USE_GENERIC_CONVERSION" /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0xc09 /d "NDEBUG"
# ADD RSC /l 0xc09 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release Unicode/testsi.exe"
!ENDIF
# Begin Target
# Name "simpleini - Win32 Release"
# Name "simpleini - Win32 Debug"
# Name "simpleini - Win32 Debug Unicode"
# Name "simpleini - Win32 Release Unicode"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\snippets.cpp
# End Source File
# Begin Source File
SOURCE=.\test1.cpp
# End Source File
# Begin Source File
SOURCE=.\testsi.cpp
# End Source File
# End Group
# Begin Group "Library Files"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\SimpleIni.h
# End Source File
# End Group
# Begin Group "Generic Files"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\ConvertUTF.c
# End Source File
# Begin Source File
SOURCE=.\ConvertUTF.h
# End Source File
# End Group
# End Target
# End Project

29
src/simpleini.dsw Normal file
View file

@ -0,0 +1,29 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "simpleini"=.\simpleini.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

128
src/snippets.cpp Normal file
View file

@ -0,0 +1,128 @@
// File: snippets.cpp
// Library: SimpleIni
// Author: Brodie Thiesfield <code@jellycan.com>
// Source: http://code.jellycan.com/simpleini/
//
// Snippets that are used on the website
#ifdef _WIN32
# pragma warning(disable: 4786)
#endif
#ifndef _WIN32
# include <unistd.h>
#endif
#include <fstream>
#define SI_SUPPORT_IOSTREAMS
#include "SimpleIni.h"
bool
snippets(
const char * a_pszFile,
bool a_bIsUtf8,
bool a_bUseMultiKey,
bool a_bUseMultiLine
)
{
// LOADING DATA
// load from a data file
CSimpleIniA ini(a_bIsUtf8, a_bUseMultiKey, a_bUseMultiLine);
SI_Error rc = ini.LoadFile(a_pszFile);
if (rc < 0) return false;
// load from a string
std::string strData;
rc = ini.LoadData(strData.c_str(), strData.size());
if (rc < 0) return false;
// GETTING SECTIONS AND KEYS
// get all sections
CSimpleIniA::TNamesDepend sections;
ini.GetAllSections(sections);
// get all keys in a section
CSimpleIniA::TNamesDepend keys;
ini.GetAllKeys("section-name", keys);
// GETTING VALUES
// get the value of a key
const char * pszValue = ini.GetValue("section-name",
"key-name", NULL /*default*/);
// get the value of a key which may have multiple
// values. If bHasMultipleValues is true, then just
// one value has been returned
bool bHasMultipleValues;
pszValue = ini.GetValue("section-name", "key-name",
NULL /*default*/, &bHasMultipleValues);
// get all values of a key with multiple values
CSimpleIniA::TNamesDepend values;
ini.GetAllValues("section-name", "key-name", values);
// sort the values into the original load order
#if defined(_MSC_VER) && _MSC_VER <= 1200
/** STL of VC6 doesn't allow me to specify my own comparator for list::sort() */
values.sort();
#else
values.sort(CSimpleIniA::Entry::LoadOrder());
#endif
// output all of the items
CSimpleIniA::TNamesDepend::const_iterator i;
for (i = values.begin(); i != values.end(); ++i) {
printf("key-name = '%s'\n", i->pItem);
}
// MODIFYING DATA
// adding a new section
rc = ini.SetValue("new-section", NULL, NULL);
if (rc < 0) return false;
printf("section: %s\n", rc == SI_INSERTED ?
"inserted" : "updated");
// adding a new key ("new-section" will be added
// automatically if it doesn't already exist.
rc = ini.SetValue("new-section", "new-key", "value");
if (rc < 0) return false;
printf("key: %s\n", rc == SI_INSERTED ?
"inserted" : "updated");
// changing the value of a key
rc = ini.SetValue("section", "key", "updated-value");
if (rc < 0) return false;
printf("key: %s\n", rc == SI_INSERTED ?
"inserted" : "updated");
// DELETING DATA
// deleting a key with a value from a section.
// Optionally the entire section may be deleted if
// it is now empty.
ini.DeleteValue("section-name", "key-name", "value",
true /*delete the section if empty*/);
// deleting a key with any value from a section.
ini.Delete("section-name", "key-name",
true /*delete the section if empty*/);
// deleting an entire section and all keys in it
ini.Delete("section-name", NULL);
// SAVING DATA
// save the data to a string
rc = ini.Save(strData);
if (rc < 0) return false;
// save the data back to the file
rc = ini.SaveFile(a_pszFile);
if (rc < 0) return false;
return true;
}

24
src/test.cmd Normal file
View file

@ -0,0 +1,24 @@
@echo off
Debug\testsi.exe -u -m -l test1-input.ini > test1-blah.ini
fc test1-expected.ini test1-output.ini
if errorlevel 1 goto error
"Debug Unicode\testsi.exe" -u -m -l test1-input.ini > test1-blah.ini
fc test1-expected.ini test1-output.ini
if errorlevel 1 goto error
Release\testsi.exe -u -m -l test1-input.ini > test1-blah.ini
fc test1-expected.ini test1-output.ini
if errorlevel 1 goto error
"Release Unicode\testsi.exe" -u -m -l test1-input.ini > test1-blah.ini
fc test1-expected.ini test1-output.ini
if errorlevel 1 goto error
exit /b 0
:error
echo Failed during test run. Output file doesn't match expected file.
pause
exit /b 1

85
src/test1-expected.ini Normal file
View file

@ -0,0 +1,85 @@
; testsi-UTF8-std.ini : standard UTF-8 test file for SimpleIni automated testing
;
; The number after a section or key is the order that it is defined in this file
; to make it easier to see if it has been written out correctly. This file should
; be loaded with Unicode / MultiKey / MultiLine turned on.
; This comment should be joined on to the one below it about the key
; with no section.
; Key with no section
lonely-key = nosection
another = nosection either
; This key has no value
empty =
; This should be joined with the comment below about japanese.
; Another line which will be un-indented.
; This is a section of keys showing the word Japanese in different syllabies.
[ordered-1]
a-1 = blah
; this is in kanji
japanese-2 = 日本語
; this is in hiragana
japanese-3 = にほんご
; this is in katakana
japanese-4 = ニホンゴ
; this is in romaji
japanese-5 = nihongo
; kanji as the key
日本語-6 = japanese
[multi-2]
; value a
test = a
; value b
test = b
; value c
test = c
; value d
test = d
[multiline-3]
; This is obviously a multi-line entry
multiline-1 = <<<END_OF_TEXT
This is a multi-line comment. It
will continue until we have the word MULTI
on a line by itself.
日本語も。
END_OF_TEXT
; This looks like multi-line, but because the newline following the last
; line is discarded, it will be converted into a single line entry.
another-2 = This is not a multiline entry.
; If you wanted a multiline entry with a single line, you need to add
; an extra line to it.
another-3 = <<<END_OF_TEXT
This is a multiline entry.
END_OF_TEXT
[integer]
dec = 42
hex = 0x2a

76
src/test1-input.ini Normal file
View file

@ -0,0 +1,76 @@
; testsi-UTF8-std.ini : standard UTF-8 test file for SimpleIni automated testing
;
; The number after a section or key is the order that it is defined in this file
; to make it easier to see if it has been written out correctly. This file should
; be loaded with Unicode / MultiKey / MultiLine turned on.
; This comment should be joined on to the one below it about the key
; with no section.
; Key with no section
lonely-key = nosection
another = nosection either
; This key has no value
empty =
; This should be joined with the comment below about japanese.
; Another line which will be un-indented.
; This is a section of keys showing the word Japanese in different syllabies.
[ordered-1]
a-1 = blah
; this is in kanji
japanese-2 = 日本語
; this is in hiragana
japanese-3 = にほんご
; this is in katakana
japanese-4 = ニホンゴ
; this is in romaji
japanese-5 = nihongo
; kanji as the key
日本語-6 = japanese
[multi-2]
; value a
test = a
; value b
test = b
; value c
test = c
; value d
test = d
[multiline-3]
; This is obviously a multi-line entry
multiline-1 = <<<MULTI
This is a multi-line comment. It
will continue until we have the word MULTI
on a line by itself.
日本語も。
MULTI
; This looks like multi-line, but because the newline following the last
; line is discarded, it will be converted into a single line entry.
another-2 = <<<MULTI
This is not a multiline entry.
MULTI
; If you wanted a multiline entry with a single line, you need to add
; an extra line to it.
another-3 = <<<MULTI
This is a multiline entry.
MULTI
[integer]
dec = 42
hex = 0x2a

85
src/test1-output.ini Normal file
View file

@ -0,0 +1,85 @@
; testsi-UTF8-std.ini : standard UTF-8 test file for SimpleIni automated testing
;
; The number after a section or key is the order that it is defined in this file
; to make it easier to see if it has been written out correctly. This file should
; be loaded with Unicode / MultiKey / MultiLine turned on.
; This comment should be joined on to the one below it about the key
; with no section.
; Key with no section
lonely-key = nosection
another = nosection either
; This key has no value
empty =
; This should be joined with the comment below about japanese.
; Another line which will be un-indented.
; This is a section of keys showing the word Japanese in different syllabies.
[ordered-1]
a-1 = blah
; this is in kanji
japanese-2 = 日本語
; this is in hiragana
japanese-3 = にほんご
; this is in katakana
japanese-4 = ニホンゴ
; this is in romaji
japanese-5 = nihongo
; kanji as the key
日本語-6 = japanese
[multi-2]
; value a
test = a
; value b
test = b
; value c
test = c
; value d
test = d
[multiline-3]
; This is obviously a multi-line entry
multiline-1 = <<<END_OF_TEXT
This is a multi-line comment. It
will continue until we have the word MULTI
on a line by itself.
日本語も。
END_OF_TEXT
; This looks like multi-line, but because the newline following the last
; line is discarded, it will be converted into a single line entry.
another-2 = This is not a multiline entry.
; If you wanted a multiline entry with a single line, you need to add
; an extra line to it.
another-3 = <<<END_OF_TEXT
This is a multiline entry.
END_OF_TEXT
[integer]
dec = 42
hex = 0x2a

166
src/test1.cpp Normal file
View file

@ -0,0 +1,166 @@
// File: test1.cpp
// Library: SimpleIni
// Author: Brodie Thiesfield <code@jellycan.com>
// Source: http://code.jellycan.com/simpleini/
//
// Automated testing for SimpleIni streams
#ifdef _WIN32
# pragma warning(disable: 4786)
#endif
#ifdef _WIN32
# include <windows.h>
# define DELETE_FILE DeleteFileA
#else
# include <unistd.h>
# define DELETE_FILE unlink
#endif
#include <fstream>
#define SI_SUPPORT_IOSTREAMS
#include "SimpleIni.h"
class Test
{
std::string m_strTest;
public:
Test(const char * a_pszName)
: m_strTest(a_pszName)
{
printf("%s: test starting\n", m_strTest.c_str());
}
bool Success()
{
printf("%s: test succeeded\n", m_strTest.c_str());
return false;
}
bool Failure(const char * pszReason)
{
printf("%s: test FAILED (%s)\n", m_strTest.c_str(), pszReason);
return false;
}
};
bool FileComparisonTest(const char * a_pszFile1, const char * a_pszFile2) {
// ensure that the two files are the same
try {
std::string strFile1, strFile2;
char szBuf[1024];
FILE * fp = NULL;
#if __STDC_WANT_SECURE_LIB__
fopen_s(&fp, a_pszFile1, "rb");
#else
fp = fopen(a_pszFile1, "rb");
#endif
if (!fp) throw false;
while (!feof(fp)) {
size_t n = fread(szBuf, 1, sizeof(szBuf), fp);
strFile1.append(szBuf, n);
}
fclose(fp);
fp = NULL;
#if __STDC_WANT_SECURE_LIB__
fopen_s(&fp, a_pszFile2, "rb");
#else
fp = fopen(a_pszFile2, "rb");
#endif
if (!fp) throw false;
while (!feof(fp)) {
size_t n = fread(szBuf, 1, sizeof(szBuf), fp);
strFile2.append(szBuf, n);
}
fclose(fp);
if (strFile1 != strFile2) throw false;
}
catch (...) {
return false;
}
return true;
}
bool FileLoadTest(const char * a_pszFile1, const char * a_pszFile2) {
// ensure that the two files load into simpleini the same
CSimpleIniA ini(true, true, true);
bool b;
try {
ini.Reset();
if (ini.LoadFile(a_pszFile1) < 0) throw "Load failed for file 1";
if (ini.SaveFile("test1.ini") < 0) throw "Save failed for file 1";
ini.Reset();
if (ini.LoadFile(a_pszFile2) < 0) throw "Load failed for file 2";
if (ini.SaveFile("test2.ini") < 0) throw "Save failed for file 2";
b = FileComparisonTest("test1.ini", "test2.ini");
DELETE_FILE("test1.ini");
DELETE_FILE("test2.ini");
if (!b) throw "File comparison failed in FileLoadTest";
}
catch (...) {
return false;
}
return true;
}
bool TestStreams()
{
const char * rgszTestFile[3] = {
"test1-input.ini",
"test1-output.ini",
"test1-expected.ini"
};
Test oTest("TestStreams");
CSimpleIniW ini;
ini.SetUnicode(true);
ini.SetMultiKey(true);
ini.SetMultiLine(true);
// load the file
try {
std::ifstream instream;
instream.open(rgszTestFile[0], std::ifstream::in | std::ifstream::binary);
if (ini.LoadData(instream) < 0) throw false;
instream.close();
}
catch (...) {
return oTest.Failure("Failed to load file");
}
// standard contents test
//if (!StandardContentsTest(ini, oTest)) {
// return false;
//}
// save the file
try {
std::ofstream outfile;
outfile.open(rgszTestFile[1], std::ofstream::out | std::ofstream::binary);
if (ini.Save(outfile, true) < 0) throw false;
outfile.close();
}
catch (...) {
return oTest.Failure("Failed to save file");
}
// file comparison test
if (!FileComparisonTest(rgszTestFile[1], rgszTestFile[2])) {
return oTest.Failure("Failed file comparison");
}
if (!FileLoadTest(rgszTestFile[1], rgszTestFile[2])) {
return oTest.Failure("Failed file load comparison");
}
return oTest.Success();
}

52
src/testsi-EUCJP.ini Normal file
View file

@ -0,0 +1,52 @@
; test file for SimpleIni
nosection=ok
NOSECTION=still ok
whitespace = ok
[standard]
foo=foo1
standard-1=foo
日本語=ok1
[Standard]
Foo=foo2
standard-2=foo
日本語=ok2
[ Whitespace ]
a=
[ whitespace in section name ]
whitespace in key name = whitespace in value name
; comments
; more comments
invalid
=invalid
====invalid
[Japanese]
nihongo = 日本語
日本語 = 日本語
[日本語]
nihongo = 日本語
日本語 = 日本語
[]
more=no section name
[MultiLine]
single = This is a single line.
multi = <<<MULTI
This is a multi-line value. It continues until the MULTI tag is found
on a line by itself with no whitespace before or after it. This value
will be returned to the user with all newlines and whitespace.
MULTI

51
src/testsi-SJIS.ini Normal file
View file

@ -0,0 +1,51 @@
; test file for SimpleIni
nosection=ok
NOSECTION=still ok
whitespace = ok
[standard]
foo=foo1
standard-1=foo
日本語=ok1
[Standard]
Foo=foo2
standard-2=foo
日本語=ok2
[ Whitespace ]
a=
[ whitespace in section name ]
whitespace in key name = whitespace in value name
; comments
; more comments
invalid
=invalid
====invalid
[Japanese]
nihongo = 日本語
日本語 = 日本語
[日本語]
nihongo = 日本語
日本語 = 日本語
[]
more=no section name
[MultiLine]
single = This is a single line.
multi = <<<MULTI
This is a multi-line value. It continues until the MULTI tag is found
on a line by itself with no whitespace before or after it. This value
will be returned to the user with all newlines and whitespace.
MULTI

50
src/testsi-UTF8.ini Normal file
View file

@ -0,0 +1,50 @@
; test file for SimpleIni
whitespace = ok
nosection=ok
NOSECTION=still ok
[standard]
foo=foo1
standard-1=foo
日本語=ok1
[Standard]
Foo=foo2
standard-2=foo
日本語=ok2
[ Whitespace ]
a=
[ whitespace in section name ]
whitespace in key name = whitespace in value name
; comments
; more comments
invalid
=invalid
====invalid
[Japanese]
nihongo = 日本語
日本語 = 日本語
[日本語]
nihongo = 日本語
日本語 = 日本語
[]
more=no section name
[MultiLine]
single = This is a single line.
multi = <<<MULTI
This is a multi-line value. It continues until the MULTI tag is found
on a line by itself with no whitespace before or after it. This value
will be returned to the user with all newlines and whitespace.
MULTI

315
src/testsi.cpp Normal file
View file

@ -0,0 +1,315 @@
// File: testsi.cpp
// Library: SimpleIni
// Author: Brodie Thiesfield <code@jellycan.com>
// Source: http://code.jellycan.com/simpleini/
//
// Demo of usage
#ifdef _WIN32
# pragma warning(disable: 4786)
#endif
#include <locale.h>
#include <stdio.h>
#include <cassert>
#define SI_SUPPORT_IOSTREAMS
#if defined(SI_SUPPORT_IOSTREAMS) && !defined(_UNICODE)
# include <fstream>
#endif
//#define SI_CONVERT_GENERIC
//#define SI_CONVERT_ICU
//#define SI_CONVERT_WIN32
#include "SimpleIni.h"
#ifdef SI_CONVERT_ICU
// if converting using ICU then we need the ICU library
# pragma comment(lib, "icuuc.lib")
#endif
#ifdef _WIN32
# include <tchar.h>
#else // !_WIN32
# define TCHAR char
# define _T(x) x
# define _tprintf printf
# define _tmain main
#endif // _WIN32
static void
Test(
CSimpleIni & ini
)
{
const TCHAR *pszSection = 0;
const TCHAR *pItem = 0;
const TCHAR *pszVal = 0;
// get the value of the key "foo" in section "standard"
bool bHasMulti;
pszVal = ini.GetValue(_T("standard"), _T("foo"), 0, &bHasMulti);
_tprintf(_T("\n-- Value of standard::foo is '%s' (hasMulti = %d)\n"),
pszVal ? pszVal : _T("(null)"), bHasMulti);
// set the value of the key "foo" in section "standard"
ini.SetValue(_T("standard"), _T("foo"), _T("wibble"));
pszVal = ini.GetValue(_T("standard"), _T("foo"), 0, &bHasMulti);
_tprintf(_T("\n-- Value of standard::foo is '%s' (hasMulti = %d)\n"),
pszVal ? pszVal : _T("(null)"), bHasMulti);
// get all values of the key "foo" in section "standard"
CSimpleIni::TNamesDepend values;
if (ini.GetAllValues(_T("standard"), _T("foo"), values)) {
_tprintf(_T("\n-- Values of standard::foo are:\n"));
CSimpleIni::TNamesDepend::const_iterator i = values.begin();
for (; i != values.end(); ++i) {
pszVal = i->pItem;
_tprintf(_T(" -> '%s'\n"), pszVal);
}
}
// get the size of the section [standard]
_tprintf(_T("\n-- Number of keys in section [standard] = %d\n"),
ini.GetSectionSize(_T("standard")));
// delete the key "foo" in section "standard", if it has value "bar"
ini.DeleteValue(_T("standard"), _T("foo"), _T("bar"));
pszVal = ini.GetValue(_T("standard"), _T("foo"), 0);
_tprintf(_T("\n-- Value of standard::foo is now '%s'\n"),
pszVal ? pszVal : _T("(null)"));
// delete the key "foo" in section "standard"
ini.Delete(_T("standard"), _T("foo"));
pszVal = ini.GetValue(_T("standard"), _T("foo"), 0);
_tprintf(_T("\n-- Value of standard::foo is now '%s'\n"),
pszVal ? pszVal : _T("(null)"));
// get the size of the section [standard]
_tprintf(_T("\n-- Number of keys in section [standard] = %d\n"),
ini.GetSectionSize(_T("standard")));
// get the list of all key names for the section "standard"
_tprintf(_T("\n-- Dumping keys of section: [standard]\n"));
CSimpleIni::TNamesDepend keys;
ini.GetAllKeys(_T("standard"), keys);
// dump all of the key names
CSimpleIni::TNamesDepend::const_iterator iKey = keys.begin();
for ( ; iKey != keys.end(); ++iKey ) {
pItem = iKey->pItem;
_tprintf(_T("Key: %s\n"), pItem);
}
// add a decimal value
ini.SetLongValue(_T("integer"), _T("dec"), 42, NULL, false);
ini.SetLongValue(_T("integer"), _T("hex"), 42, NULL, true);
// add some bool values
ini.SetBoolValue(_T("bool"), _T("t"), true);
ini.SetBoolValue(_T("bool"), _T("f"), false);
// get the values back
assert(42 == ini.GetLongValue(_T("integer"), _T("dec")));
assert(42 == ini.GetLongValue(_T("integer"), _T("hex")));
assert(true == ini.GetBoolValue(_T("bool"), _T("t")));
assert(false == ini.GetBoolValue(_T("bool"), _T("f")));
// delete the section "standard"
ini.Delete(_T("standard"), NULL);
_tprintf(_T("\n-- Number of keys in section [standard] = %d\n"),
ini.GetSectionSize(_T("standard")));
// iterate through every section in the file
_tprintf(_T("\n-- Dumping all sections\n"));
CSimpleIni::TNamesDepend sections;
ini.GetAllSections(sections);
CSimpleIni::TNamesDepend::const_iterator iSection = sections.begin();
for ( ; iSection != sections.end(); ++iSection ) {
pszSection = iSection->pItem;
// print the section name
printf("\n");
if (*pszSection) {
_tprintf(_T("[%s]\n"), pszSection);
}
// if there are keys and values...
const CSimpleIni::TKeyVal * pSectionData = ini.GetSection(pszSection);
if (pSectionData) {
// iterate over all keys and dump the key name and value
CSimpleIni::TKeyVal::const_iterator iKeyVal = pSectionData->begin();
for ( ;iKeyVal != pSectionData->end(); ++iKeyVal) {
pItem = iKeyVal->first.pItem;
pszVal = iKeyVal->second;
_tprintf(_T("%s=%s\n"), pItem, pszVal);
}
}
}
}
#if defined(SI_SUPPORT_IOSTREAMS) && !defined(_UNICODE)
static bool
TestStreams(
const TCHAR * a_pszFile,
bool a_bIsUtf8,
bool a_bUseMultiKey,
bool a_bUseMultiLine
)
{
// load the file
CSimpleIni ini(a_bIsUtf8, a_bUseMultiKey, a_bUseMultiLine);
_tprintf(_T("Loading file: %s\n"), a_pszFile);
std::ifstream instream;
instream.open(a_pszFile, std::ifstream::in | std::ifstream::binary);
SI_Error rc = ini.LoadData(instream);
instream.close();
if (rc < 0) {
printf("Failed to open file.\n");
return false;
}
Test(ini);
// save the file (simple)
_tprintf(_T("\n-- Saving file to: testsi-out-streams.ini\n"));
std::ofstream outstream;
outstream.open("testsi-out-streams.ini", std::ofstream::out | std::ofstream::binary);
ini.Save(outstream);
outstream.close();
return true;
}
#endif // SI_SUPPORT_IOSTREAMS
static bool
TestFile(
const TCHAR * a_pszFile,
bool a_bIsUtf8,
bool a_bUseMultiKey,
bool a_bUseMultiLine
)
{
// load the file
CSimpleIni ini(a_bIsUtf8, a_bUseMultiKey, a_bUseMultiLine);
_tprintf(_T("Loading file: %s\n"), a_pszFile);
SI_Error rc = ini.LoadFile(a_pszFile);
if (rc < 0) {
printf("Failed to open file.\n");
return false;
}
// run the tests
Test(ini);
// save the file (simple)
_tprintf(_T("\n-- Saving file to: testsi-out.ini\n"));
ini.SaveFile("testsi-out.ini");
// save the file (with comments)
// Note: to save the file and add a comment to the beginning, use
// code such as the following.
_tprintf(_T("\n-- Saving file to: testsi-out-comment.ini\n"));
FILE * fp = NULL;
#if __STDC_WANT_SECURE_LIB__
fopen_s(&fp, "testsi-out-comment.ini", "wb");
#else
fp = fopen("testsi-out-comment.ini", "wb");
#endif
if (fp) {
CSimpleIni::FileWriter writer(fp);
if (a_bIsUtf8) {
writer.Write(SI_UTF8_SIGNATURE);
}
// add a string to the file in the correct text format
CSimpleIni::Converter convert = ini.GetConverter();
convert.ConvertToStore(_T("; output from testsi.cpp test program")
SI_NEWLINE SI_NEWLINE);
writer.Write(convert.Data());
ini.Save(writer, false);
fclose(fp);
}
return true;
}
static bool
ParseCommandLine(
int argc,
TCHAR * argv[],
const TCHAR * & a_pszFile,
bool & a_bIsUtf8,
bool & a_bUseMultiKey,
bool & a_bUseMultiLine
)
{
a_pszFile = 0;
a_bIsUtf8 = false;
a_bUseMultiKey = false;
a_bUseMultiLine = false;
for (--argc; argc > 0; --argc) {
if (argv[argc][0] == '-') {
switch (argv[argc][1]) {
case TCHAR('u'):
a_bIsUtf8 = true;
break;
case TCHAR('m'):
a_bUseMultiKey = true;
break;
case TCHAR('l'):
a_bUseMultiLine = true;
break;
}
}
else {
a_pszFile = argv[argc];
}
}
if (!a_pszFile) {
_tprintf(
_T("Usage: testsi [-u] [-m] [-l] iniFile\n")
_T(" -u Load file as UTF-8 (Default is to use system locale)\n")
_T(" -m Enable multiple keys\n")
_T(" -l Enable multiple line values\n")
);
return false;
}
return true;
}
extern bool TestStreams();
int
_tmain(
int argc,
TCHAR * argv[]
)
{
setlocale(LC_ALL, "");
// start of automated testing...
TestStreams();
// parse the command line
const TCHAR * pszFile;
bool bIsUtf8, bUseMultiKey, bUseMultiLine;
if (!ParseCommandLine(argc, argv, pszFile, bIsUtf8, bUseMultiKey, bUseMultiLine)) {
return 1;
}
// run the test
if (!TestFile(pszFile, bIsUtf8, bUseMultiKey, bUseMultiLine)) {
return 1;
}
#if defined(SI_SUPPORT_IOSTREAMS) && !defined(_UNICODE)
if (!TestStreams(pszFile, bIsUtf8, bUseMultiKey, bUseMultiLine)) {
return 1;
}
#endif
return 0;
}