mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2024-11-15 08:31:49 -05:00
Merge branch 'vsonnier-update_externals'
This commit is contained in:
commit
d6e18b08ef
739
external/lodepng/lodepng.cpp
vendored
739
external/lodepng/lodepng.cpp
vendored
File diff suppressed because it is too large
Load Diff
135
external/lodepng/lodepng.h
vendored
135
external/lodepng/lodepng.h
vendored
@ -1,7 +1,7 @@
|
||||
/*
|
||||
LodePNG version 20141130
|
||||
LodePNG version 20160501
|
||||
|
||||
Copyright (c) 2005-2014 Lode Vandevenne
|
||||
Copyright (c) 2005-2016 Lode Vandevenne
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@ -28,12 +28,7 @@ freely, subject to the following restrictions:
|
||||
|
||||
#include <string.h> /*for size_t*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#endif /*__cplusplus*/
|
||||
|
||||
#define LODEPNG_VERSION_STRING "20141130"
|
||||
extern const char* LODEPNG_VERSION_STRING;
|
||||
|
||||
/*
|
||||
The following #defines are used to create code sections. They can be disabled
|
||||
@ -41,6 +36,8 @@ to disable code sections, which can give faster compile time and smaller binary.
|
||||
The "NO_COMPILE" defines are designed to be used to pass as defines to the
|
||||
compiler command to disable them without modifying this header, e.g.
|
||||
-DLODEPNG_NO_COMPILE_ZLIB for gcc.
|
||||
In addition to those below, you can also define LODEPNG_NO_COMPILE_CRC to
|
||||
allow implementing a custom lodepng_crc32.
|
||||
*/
|
||||
/*deflate & zlib. If disabled, you must specify alternative zlib functions in
|
||||
the custom_zlib field of the compress and decompress settings*/
|
||||
@ -84,6 +81,11 @@ source files with custom allocators.*/
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef LODEPNG_COMPILE_CPP
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#endif /*LODEPNG_COMPILE_CPP*/
|
||||
|
||||
#ifdef LODEPNG_COMPILE_PNG
|
||||
/*The PNG color types (also used for raw).*/
|
||||
typedef enum LodePNGColorType
|
||||
@ -213,8 +215,8 @@ Same as the other decode functions, but instead takes a filename as input.
|
||||
unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
|
||||
const std::string& filename,
|
||||
LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);
|
||||
#endif //LODEPNG_COMPILE_DISK
|
||||
#endif //LODEPNG_COMPILE_DECODER
|
||||
#endif /* LODEPNG_COMPILE_DISK */
|
||||
#endif /* LODEPNG_COMPILE_DECODER */
|
||||
|
||||
#ifdef LODEPNG_COMPILE_ENCODER
|
||||
/*Same as lodepng_encode_memory, but encodes to an std::vector. colortype
|
||||
@ -237,9 +239,9 @@ unsigned encode(const std::string& filename,
|
||||
unsigned encode(const std::string& filename,
|
||||
const std::vector<unsigned char>& in, unsigned w, unsigned h,
|
||||
LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);
|
||||
#endif //LODEPNG_COMPILE_DISK
|
||||
#endif //LODEPNG_COMPILE_ENCODER
|
||||
} //namespace lodepng
|
||||
#endif /* LODEPNG_COMPILE_DISK */
|
||||
#endif /* LODEPNG_COMPILE_ENCODER */
|
||||
} /* namespace lodepng */
|
||||
#endif /*LODEPNG_COMPILE_CPP*/
|
||||
#endif /*LODEPNG_COMPILE_PNG*/
|
||||
|
||||
@ -506,7 +508,7 @@ For 16-bit per channel colors, uses big endian format like PNG does.
|
||||
Return value is LodePNG error code
|
||||
*/
|
||||
unsigned lodepng_convert(unsigned char* out, const unsigned char* in,
|
||||
LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in,
|
||||
const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in,
|
||||
unsigned w, unsigned h);
|
||||
|
||||
#ifdef LODEPNG_COMPILE_DECODER
|
||||
@ -538,7 +540,7 @@ typedef enum LodePNGFilterStrategy
|
||||
{
|
||||
/*every filter at zero*/
|
||||
LFS_ZERO,
|
||||
/*Use filter that gives minumum sum, as described in the official PNG filter heuristic.*/
|
||||
/*Use filter that gives minimum sum, as described in the official PNG filter heuristic.*/
|
||||
LFS_MINSUM,
|
||||
/*Use the filter type that gives smallest Shannon entropy for this scanline. Depending
|
||||
on the image, this is better or worse than minsum.*/
|
||||
@ -629,7 +631,7 @@ typedef struct LodePNGState
|
||||
LodePNGInfo info_png; /*info of the PNG image obtained after decoding*/
|
||||
unsigned error;
|
||||
#ifdef LODEPNG_COMPILE_CPP
|
||||
//For the lodepng::State subclass.
|
||||
/* For the lodepng::State subclass. */
|
||||
virtual ~LodePNGState(){}
|
||||
#endif
|
||||
} LodePNGState;
|
||||
@ -811,7 +813,7 @@ unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const
|
||||
#endif /*LODEPNG_COMPILE_DISK*/
|
||||
|
||||
#ifdef LODEPNG_COMPILE_CPP
|
||||
//The LodePNG C++ wrapper uses std::vectors instead of manually allocated memory buffers.
|
||||
/* The LodePNG C++ wrapper uses std::vectors instead of manually allocated memory buffers. */
|
||||
namespace lodepng
|
||||
{
|
||||
#ifdef LODEPNG_COMPILE_PNG
|
||||
@ -825,7 +827,7 @@ class State : public LodePNGState
|
||||
};
|
||||
|
||||
#ifdef LODEPNG_COMPILE_DECODER
|
||||
//Same as other lodepng::decode, but using a State for more settings and information.
|
||||
/* Same as other lodepng::decode, but using a State for more settings and information. */
|
||||
unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
|
||||
State& state,
|
||||
const unsigned char* in, size_t insize);
|
||||
@ -835,7 +837,7 @@ unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
|
||||
#endif /*LODEPNG_COMPILE_DECODER*/
|
||||
|
||||
#ifdef LODEPNG_COMPILE_ENCODER
|
||||
//Same as other lodepng::encode, but using a State for more settings and information.
|
||||
/* Same as other lodepng::encode, but using a State for more settings and information. */
|
||||
unsigned encode(std::vector<unsigned char>& out,
|
||||
const unsigned char* in, unsigned w, unsigned h,
|
||||
State& state);
|
||||
@ -846,47 +848,47 @@ unsigned encode(std::vector<unsigned char>& out,
|
||||
|
||||
#ifdef LODEPNG_COMPILE_DISK
|
||||
/*
|
||||
Load a file from disk into an std::vector. If the vector is empty, then either
|
||||
the file doesn't exist or is an empty file.
|
||||
Load a file from disk into an std::vector.
|
||||
return value: error code (0 means ok)
|
||||
*/
|
||||
void load_file(std::vector<unsigned char>& buffer, const std::string& filename);
|
||||
unsigned load_file(std::vector<unsigned char>& buffer, const std::string& filename);
|
||||
|
||||
/*
|
||||
Save the binary data in an std::vector to a file on disk. The file is overwritten
|
||||
without warning.
|
||||
*/
|
||||
void save_file(const std::vector<unsigned char>& buffer, const std::string& filename);
|
||||
#endif //LODEPNG_COMPILE_DISK
|
||||
#endif //LODEPNG_COMPILE_PNG
|
||||
unsigned save_file(const std::vector<unsigned char>& buffer, const std::string& filename);
|
||||
#endif /* LODEPNG_COMPILE_DISK */
|
||||
#endif /* LODEPNG_COMPILE_PNG */
|
||||
|
||||
#ifdef LODEPNG_COMPILE_ZLIB
|
||||
#ifdef LODEPNG_COMPILE_DECODER
|
||||
//Zlib-decompress an unsigned char buffer
|
||||
/* Zlib-decompress an unsigned char buffer */
|
||||
unsigned decompress(std::vector<unsigned char>& out, const unsigned char* in, size_t insize,
|
||||
const LodePNGDecompressSettings& settings = lodepng_default_decompress_settings);
|
||||
|
||||
//Zlib-decompress an std::vector
|
||||
/* Zlib-decompress an std::vector */
|
||||
unsigned decompress(std::vector<unsigned char>& out, const std::vector<unsigned char>& in,
|
||||
const LodePNGDecompressSettings& settings = lodepng_default_decompress_settings);
|
||||
#endif //LODEPNG_COMPILE_DECODER
|
||||
#endif /* LODEPNG_COMPILE_DECODER */
|
||||
|
||||
#ifdef LODEPNG_COMPILE_ENCODER
|
||||
//Zlib-compress an unsigned char buffer
|
||||
/* Zlib-compress an unsigned char buffer */
|
||||
unsigned compress(std::vector<unsigned char>& out, const unsigned char* in, size_t insize,
|
||||
const LodePNGCompressSettings& settings = lodepng_default_compress_settings);
|
||||
|
||||
//Zlib-compress an std::vector
|
||||
/* Zlib-compress an std::vector */
|
||||
unsigned compress(std::vector<unsigned char>& out, const std::vector<unsigned char>& in,
|
||||
const LodePNGCompressSettings& settings = lodepng_default_compress_settings);
|
||||
#endif //LODEPNG_COMPILE_ENCODER
|
||||
#endif //LODEPNG_COMPILE_ZLIB
|
||||
} //namespace lodepng
|
||||
#endif /* LODEPNG_COMPILE_ENCODER */
|
||||
#endif /* LODEPNG_COMPILE_ZLIB */
|
||||
} /* namespace lodepng */
|
||||
#endif /*LODEPNG_COMPILE_CPP*/
|
||||
|
||||
/*
|
||||
TODO:
|
||||
[.] test if there are no memory leaks or security exploits - done a lot but needs to be checked often
|
||||
[.] check compatibility with vareous compilers - done but needs to be redone for every newer version
|
||||
[.] check compatibility with various compilers - done but needs to be redone for every newer version
|
||||
[X] converting color to 16-bit per channel types
|
||||
[ ] read all public PNG chunk types (but never let the color profile and gamma ones touch RGB values)
|
||||
[ ] make sure encoder generates no chunks with size > (2^31)-1
|
||||
@ -894,8 +896,9 @@ TODO:
|
||||
[X] let the "isFullyOpaque" function check color keys and transparent palettes too
|
||||
[X] better name for the variables "codes", "codesD", "codelengthcodes", "clcl" and "lldl"
|
||||
[ ] don't stop decoding on errors like 69, 57, 58 (make warnings)
|
||||
[ ] make option to choose if the raw image with non multiple of 8 bits per scanline should have padding bits or not
|
||||
[ ] let the C++ wrapper catch exceptions coming from the standard library and return LodePNG error codes
|
||||
[ ] allow user to provide custom color conversion functions, e.g. for premultiplied alpha, padding bits or not, ...
|
||||
[ ] allow user to give data (void*) to custom allocator
|
||||
*/
|
||||
|
||||
#endif /*LODEPNG_H inclusion guard*/
|
||||
@ -925,8 +928,9 @@ LodePNG Documentation
|
||||
10. examples
|
||||
10.1. decoder C++ example
|
||||
10.2. decoder C example
|
||||
11. changes
|
||||
12. contact information
|
||||
11. state settings reference
|
||||
12. changes
|
||||
13. contact information
|
||||
|
||||
|
||||
1. about
|
||||
@ -1552,8 +1556,49 @@ int main(int argc, char *argv[])
|
||||
return 0;
|
||||
}
|
||||
|
||||
11. state settings reference
|
||||
----------------------------
|
||||
|
||||
11. changes
|
||||
A quick reference of some settings to set on the LodePNGState
|
||||
|
||||
For decoding:
|
||||
|
||||
state.decoder.zlibsettings.ignore_adler32: ignore ADLER32 checksums
|
||||
state.decoder.zlibsettings.custom_...: use custom inflate function
|
||||
state.decoder.ignore_crc: ignore CRC checksums
|
||||
state.decoder.color_convert: convert internal PNG color to chosen one
|
||||
state.decoder.read_text_chunks: whether to read in text metadata chunks
|
||||
state.decoder.remember_unknown_chunks: whether to read in unknown chunks
|
||||
state.info_raw.colortype: desired color type for decoded image
|
||||
state.info_raw.bitdepth: desired bit depth for decoded image
|
||||
state.info_raw....: more color settings, see struct LodePNGColorMode
|
||||
state.info_png....: no settings for decoder but ouput, see struct LodePNGInfo
|
||||
|
||||
For encoding:
|
||||
|
||||
state.encoder.zlibsettings.btype: disable compression by setting it to 0
|
||||
state.encoder.zlibsettings.use_lz77: use LZ77 in compression
|
||||
state.encoder.zlibsettings.windowsize: tweak LZ77 windowsize
|
||||
state.encoder.zlibsettings.minmatch: tweak min LZ77 length to match
|
||||
state.encoder.zlibsettings.nicematch: tweak LZ77 match where to stop searching
|
||||
state.encoder.zlibsettings.lazymatching: try one more LZ77 matching
|
||||
state.encoder.zlibsettings.custom_...: use custom deflate function
|
||||
state.encoder.auto_convert: choose optimal PNG color type, if 0 uses info_png
|
||||
state.encoder.filter_palette_zero: PNG filter strategy for palette
|
||||
state.encoder.filter_strategy: PNG filter strategy to encode with
|
||||
state.encoder.force_palette: add palette even if not encoding to one
|
||||
state.encoder.add_id: add LodePNG identifier and version as a text chunk
|
||||
state.encoder.text_compression: use compressed text chunks for metadata
|
||||
state.info_raw.colortype: color type of raw input image you provide
|
||||
state.info_raw.bitdepth: bit depth of raw input image you provide
|
||||
state.info_raw: more color settings, see struct LodePNGColorMode
|
||||
state.info_png.color.colortype: desired color type if auto_convert is false
|
||||
state.info_png.color.bitdepth: desired bit depth if auto_convert is false
|
||||
state.info_png.color....: more color settings, see struct LodePNGColorMode
|
||||
state.info_png....: more PNG related settings, see struct LodePNGInfo
|
||||
|
||||
|
||||
12. changes
|
||||
-----------
|
||||
|
||||
The version number of LodePNG is the date of the change given in the format
|
||||
@ -1562,6 +1607,12 @@ yyyymmdd.
|
||||
Some changes aren't backwards compatible. Those are indicated with a (!)
|
||||
symbol.
|
||||
|
||||
*) 18 apr 2016: Changed qsort to custom stable sort (for platforms w/o qsort).
|
||||
*) 09 apr 2016: Fixed colorkey usage detection, and better file loading (within
|
||||
the limits of pure C90).
|
||||
*) 08 dec 2015: Made load_file function return error if file can't be opened.
|
||||
*) 24 okt 2015: Bugfix with decoding to palette output.
|
||||
*) 18 apr 2015: Boundary PM instead of just package-merge for faster encoding.
|
||||
*) 23 aug 2014: Reduced needless memory usage of decoder.
|
||||
*) 28 jun 2014: Removed fix_png setting, always support palette OOB for
|
||||
simplicity. Made ColorProfile public.
|
||||
@ -1586,7 +1637,7 @@ symbol.
|
||||
*) 22 apr 2012 (!): Made interface more consistent, renaming a lot. Removed
|
||||
redundant C++ codec classes. Reduced amount of structs. Everything changed,
|
||||
but it is cleaner now imho and functionality remains the same. Also fixed
|
||||
several bugs and shrinked the implementation code. Made new samples.
|
||||
several bugs and shrunk the implementation code. Made new samples.
|
||||
*) 6 nov 2011 (!): By default, the encoder now automatically chooses the best
|
||||
PNG color model and bit depth, based on the amount and type of colors of the
|
||||
raw image. For this, autoLeaveOutAlphaChannel replaced by auto_choose_color.
|
||||
@ -1621,7 +1672,7 @@ symbol.
|
||||
*) 20 jan 2008: support for unknown chunks allowing using LodePNG for an editor.
|
||||
*) 18 jan 2008: support for tIME and pHYs chunks added to encoder and decoder.
|
||||
*) 17 jan 2008: ability to encode and decode compressed zTXt chunks added
|
||||
Also vareous fixes, such as in the deflate and the padding bits code.
|
||||
Also various fixes, such as in the deflate and the padding bits code.
|
||||
*) 13 jan 2008: Added ability to encode Adam7-interlaced images. Improved
|
||||
filtering code of encoder.
|
||||
*) 07 jan 2008: (!) changed LodePNG to use ISO C90 instead of C++. A
|
||||
@ -1692,7 +1743,7 @@ symbol.
|
||||
*) 12 aug 2005: Initial release (C++, decoder only)
|
||||
|
||||
|
||||
12. contact information
|
||||
13. contact information
|
||||
-----------------------
|
||||
|
||||
Feel free to contact me with suggestions, problems, comments, ... concerning
|
||||
@ -1704,5 +1755,5 @@ Domain: gmail dot com.
|
||||
Account: lode dot vandevenne.
|
||||
|
||||
|
||||
Copyright (c) 2005-2014 Lode Vandevenne
|
||||
Copyright (c) 2005-2016 Lode Vandevenne
|
||||
*/
|
||||
|
292
external/rtaudio/RtAudio.cpp
vendored
292
external/rtaudio/RtAudio.cpp
vendored
@ -10,7 +10,7 @@
|
||||
RtAudio WWW site: http://www.music.mcgill.ca/~gary/rtaudio/
|
||||
|
||||
RtAudio: realtime audio i/o C++ classes
|
||||
Copyright (c) 2001-2014 Gary P. Scavone
|
||||
Copyright (c) 2001-2016 Gary P. Scavone
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation files
|
||||
@ -38,7 +38,7 @@
|
||||
*/
|
||||
/************************************************************************/
|
||||
|
||||
// RtAudio: Version 4.1.1
|
||||
// RtAudio: Version 4.1.2
|
||||
|
||||
#include "RtAudio.h"
|
||||
#include <iostream>
|
||||
@ -59,6 +59,22 @@ const unsigned int RtApi::SAMPLE_RATES[] = {
|
||||
#define MUTEX_DESTROY(A) DeleteCriticalSection(A)
|
||||
#define MUTEX_LOCK(A) EnterCriticalSection(A)
|
||||
#define MUTEX_UNLOCK(A) LeaveCriticalSection(A)
|
||||
|
||||
#include "tchar.h"
|
||||
|
||||
static std::string convertCharPointerToStdString(const char *text)
|
||||
{
|
||||
return std::string(text);
|
||||
}
|
||||
|
||||
static std::string convertCharPointerToStdString(const wchar_t *text)
|
||||
{
|
||||
int length = WideCharToMultiByte(CP_UTF8, 0, text, -1, NULL, 0, NULL, NULL);
|
||||
std::string s( length-1, '\0' );
|
||||
WideCharToMultiByte(CP_UTF8, 0, text, -1, &s[0], length, NULL, NULL);
|
||||
return s;
|
||||
}
|
||||
|
||||
#elif defined(__LINUX_ALSA__) || defined(__LINUX_PULSE__) || defined(__UNIX_JACK__) || defined(__LINUX_OSS__) || defined(__MACOSX_CORE__)
|
||||
// pthread API
|
||||
#define MUTEX_INITIALIZE(A) pthread_mutex_init(A, NULL)
|
||||
@ -762,9 +778,14 @@ RtAudio::DeviceInfo RtApiCore :: getDeviceInfo( unsigned int device )
|
||||
bool haveValueRange = false;
|
||||
info.sampleRates.clear();
|
||||
for ( UInt32 i=0; i<nRanges; i++ ) {
|
||||
if ( rangeList[i].mMinimum == rangeList[i].mMaximum )
|
||||
info.sampleRates.push_back( (unsigned int) rangeList[i].mMinimum );
|
||||
else {
|
||||
if ( rangeList[i].mMinimum == rangeList[i].mMaximum ) {
|
||||
unsigned int tmpSr = (unsigned int) rangeList[i].mMinimum;
|
||||
info.sampleRates.push_back( tmpSr );
|
||||
|
||||
if ( !info.preferredSampleRate || ( tmpSr <= 48000 && tmpSr > info.preferredSampleRate ) )
|
||||
info.preferredSampleRate = tmpSr;
|
||||
|
||||
} else {
|
||||
haveValueRange = true;
|
||||
if ( rangeList[i].mMinimum > minimumRate ) minimumRate = rangeList[i].mMinimum;
|
||||
if ( rangeList[i].mMaximum < maximumRate ) maximumRate = rangeList[i].mMaximum;
|
||||
@ -773,8 +794,12 @@ RtAudio::DeviceInfo RtApiCore :: getDeviceInfo( unsigned int device )
|
||||
|
||||
if ( haveValueRange ) {
|
||||
for ( unsigned int k=0; k<MAX_SAMPLE_RATES; k++ ) {
|
||||
if ( SAMPLE_RATES[k] >= (unsigned int) minimumRate && SAMPLE_RATES[k] <= (unsigned int) maximumRate )
|
||||
if ( SAMPLE_RATES[k] >= (unsigned int) minimumRate && SAMPLE_RATES[k] <= (unsigned int) maximumRate ) {
|
||||
info.sampleRates.push_back( SAMPLE_RATES[k] );
|
||||
|
||||
if ( !info.preferredSampleRate || ( SAMPLE_RATES[k] <= 48000 && SAMPLE_RATES[k] > info.preferredSampleRate ) )
|
||||
info.preferredSampleRate = SAMPLE_RATES[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1381,6 +1406,18 @@ void RtApiCore :: closeStream( void )
|
||||
|
||||
CoreHandle *handle = (CoreHandle *) stream_.apiHandle;
|
||||
if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
|
||||
if (handle) {
|
||||
AudioObjectPropertyAddress property = { kAudioHardwarePropertyDevices,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
kAudioObjectPropertyElementMaster };
|
||||
|
||||
property.mSelector = kAudioDeviceProcessorOverload;
|
||||
property.mScope = kAudioObjectPropertyScopeGlobal;
|
||||
if (AudioObjectRemovePropertyListener( handle->id[0], &property, xrunListener, (void *) handle ) != noErr) {
|
||||
errorText_ = "RtApiCore::closeStream(): error removing property listener!";
|
||||
error( RtAudioError::WARNING );
|
||||
}
|
||||
}
|
||||
if ( stream_.state == STREAM_RUNNING )
|
||||
AudioDeviceStop( handle->id[0], callbackHandler );
|
||||
#if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )
|
||||
@ -1392,6 +1429,18 @@ void RtApiCore :: closeStream( void )
|
||||
}
|
||||
|
||||
if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && stream_.device[0] != stream_.device[1] ) ) {
|
||||
if (handle) {
|
||||
AudioObjectPropertyAddress property = { kAudioHardwarePropertyDevices,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
kAudioObjectPropertyElementMaster };
|
||||
|
||||
property.mSelector = kAudioDeviceProcessorOverload;
|
||||
property.mScope = kAudioObjectPropertyScopeGlobal;
|
||||
if (AudioObjectRemovePropertyListener( handle->id[1], &property, xrunListener, (void *) handle ) != noErr) {
|
||||
errorText_ = "RtApiCore::closeStream(): error removing property listener!";
|
||||
error( RtAudioError::WARNING );
|
||||
}
|
||||
}
|
||||
if ( stream_.state == STREAM_RUNNING )
|
||||
AudioDeviceStop( handle->id[1], callbackHandler );
|
||||
#if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )
|
||||
@ -1985,7 +2034,9 @@ RtAudio::DeviceInfo RtApiJack :: getDeviceInfo( unsigned int device )
|
||||
|
||||
// Get the current jack server sample rate.
|
||||
info.sampleRates.clear();
|
||||
info.sampleRates.push_back( jack_get_sample_rate( client ) );
|
||||
|
||||
info.preferredSampleRate = jack_get_sample_rate( client );
|
||||
info.sampleRates.push_back( info.preferredSampleRate );
|
||||
|
||||
// Count the available ports containing the client name as device
|
||||
// channels. Jack "input ports" equal RtAudio output channels.
|
||||
@ -2765,8 +2816,12 @@ RtAudio::DeviceInfo RtApiAsio :: getDeviceInfo( unsigned int device )
|
||||
info.sampleRates.clear();
|
||||
for ( unsigned int i=0; i<MAX_SAMPLE_RATES; i++ ) {
|
||||
result = ASIOCanSampleRate( (ASIOSampleRate) SAMPLE_RATES[i] );
|
||||
if ( result == ASE_OK )
|
||||
if ( result == ASE_OK ) {
|
||||
info.sampleRates.push_back( SAMPLE_RATES[i] );
|
||||
|
||||
if ( !info.preferredSampleRate || ( SAMPLE_RATES[i] <= 48000 && SAMPLE_RATES[i] > info.preferredSampleRate ) )
|
||||
info.preferredSampleRate = SAMPLE_RATES[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Determine supported data types ... just check first channel and assume rest are the same.
|
||||
@ -2825,9 +2880,12 @@ bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
|
||||
unsigned int firstChannel, unsigned int sampleRate,
|
||||
RtAudioFormat format, unsigned int *bufferSize,
|
||||
RtAudio::StreamOptions *options )
|
||||
{
|
||||
{////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool isDuplexInput = mode == INPUT && stream_.mode == OUTPUT;
|
||||
|
||||
// For ASIO, a duplex stream MUST use the same driver.
|
||||
if ( mode == INPUT && stream_.mode == OUTPUT && stream_.device[0] != device ) {
|
||||
if ( isDuplexInput && stream_.device[0] != device ) {
|
||||
errorText_ = "RtApiAsio::probeDeviceOpen: an ASIO duplex stream must use the same device for input and output!";
|
||||
return FAILURE;
|
||||
}
|
||||
@ -2841,7 +2899,7 @@ bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
|
||||
}
|
||||
|
||||
// Only load the driver once for duplex stream.
|
||||
if ( mode != INPUT || stream_.mode != OUTPUT ) {
|
||||
if ( !isDuplexInput ) {
|
||||
// The getDeviceInfo() function will not work when a stream is open
|
||||
// because ASIO does not allow multiple devices to run at the same
|
||||
// time. Thus, we'll probe the system before opening a stream and
|
||||
@ -2862,22 +2920,26 @@ bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
|
||||
}
|
||||
}
|
||||
|
||||
// keep them before any "goto error", they are used for error cleanup + goto device boundary checks
|
||||
bool buffersAllocated = false;
|
||||
AsioHandle *handle = (AsioHandle *) stream_.apiHandle;
|
||||
unsigned int nChannels;
|
||||
|
||||
|
||||
// Check the device channel count.
|
||||
long inputChannels, outputChannels;
|
||||
result = ASIOGetChannels( &inputChannels, &outputChannels );
|
||||
if ( result != ASE_OK ) {
|
||||
drivers.removeCurrentDriver();
|
||||
errorStream_ << "RtApiAsio::probeDeviceOpen: error (" << getAsioErrorString( result ) << ") getting channel count (" << driverName << ").";
|
||||
errorText_ = errorStream_.str();
|
||||
return FAILURE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ( ( mode == OUTPUT && (channels+firstChannel) > (unsigned int) outputChannels) ||
|
||||
( mode == INPUT && (channels+firstChannel) > (unsigned int) inputChannels) ) {
|
||||
drivers.removeCurrentDriver();
|
||||
errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") does not support requested channel count (" << channels << ") + offset (" << firstChannel << ").";
|
||||
errorText_ = errorStream_.str();
|
||||
return FAILURE;
|
||||
goto error;
|
||||
}
|
||||
stream_.nDeviceChannels[mode] = channels;
|
||||
stream_.nUserChannels[mode] = channels;
|
||||
@ -2886,30 +2948,27 @@ bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
|
||||
// Verify the sample rate is supported.
|
||||
result = ASIOCanSampleRate( (ASIOSampleRate) sampleRate );
|
||||
if ( result != ASE_OK ) {
|
||||
drivers.removeCurrentDriver();
|
||||
errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") does not support requested sample rate (" << sampleRate << ").";
|
||||
errorText_ = errorStream_.str();
|
||||
return FAILURE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Get the current sample rate
|
||||
ASIOSampleRate currentRate;
|
||||
result = ASIOGetSampleRate( ¤tRate );
|
||||
if ( result != ASE_OK ) {
|
||||
drivers.removeCurrentDriver();
|
||||
errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error getting sample rate.";
|
||||
errorText_ = errorStream_.str();
|
||||
return FAILURE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Set the sample rate only if necessary
|
||||
if ( currentRate != sampleRate ) {
|
||||
result = ASIOSetSampleRate( (ASIOSampleRate) sampleRate );
|
||||
if ( result != ASE_OK ) {
|
||||
drivers.removeCurrentDriver();
|
||||
errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error setting sample rate (" << sampleRate << ").";
|
||||
errorText_ = errorStream_.str();
|
||||
return FAILURE;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2920,10 +2979,9 @@ bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
|
||||
else channelInfo.isInput = true;
|
||||
result = ASIOGetChannelInfo( &channelInfo );
|
||||
if ( result != ASE_OK ) {
|
||||
drivers.removeCurrentDriver();
|
||||
errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error (" << getAsioErrorString( result ) << ") getting data format.";
|
||||
errorText_ = errorStream_.str();
|
||||
return FAILURE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Assuming WINDOWS host is always little-endian.
|
||||
@ -2952,10 +3010,9 @@ bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
|
||||
}
|
||||
|
||||
if ( stream_.deviceFormat[mode] == 0 ) {
|
||||
drivers.removeCurrentDriver();
|
||||
errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") data format not supported by RtAudio.";
|
||||
errorText_ = errorStream_.str();
|
||||
return FAILURE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Set the buffer size. For a duplex stream, this will end up
|
||||
@ -2964,13 +3021,23 @@ bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
|
||||
long minSize, maxSize, preferSize, granularity;
|
||||
result = ASIOGetBufferSize( &minSize, &maxSize, &preferSize, &granularity );
|
||||
if ( result != ASE_OK ) {
|
||||
drivers.removeCurrentDriver();
|
||||
errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error (" << getAsioErrorString( result ) << ") getting buffer size.";
|
||||
errorText_ = errorStream_.str();
|
||||
return FAILURE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ( *bufferSize < (unsigned int) minSize ) *bufferSize = (unsigned int) minSize;
|
||||
if ( isDuplexInput ) {
|
||||
// When this is the duplex input (output was opened before), then we have to use the same
|
||||
// buffersize as the output, because it might use the preferred buffer size, which most
|
||||
// likely wasn't passed as input to this. The buffer sizes have to be identically anyway,
|
||||
// So instead of throwing an error, make them equal. The caller uses the reference
|
||||
// to the "bufferSize" param as usual to set up processing buffers.
|
||||
|
||||
*bufferSize = stream_.bufferSize;
|
||||
|
||||
} else {
|
||||
if ( *bufferSize == 0 ) *bufferSize = preferSize;
|
||||
else if ( *bufferSize < (unsigned int) minSize ) *bufferSize = (unsigned int) minSize;
|
||||
else if ( *bufferSize > (unsigned int) maxSize ) *bufferSize = (unsigned int) maxSize;
|
||||
else if ( granularity == -1 ) {
|
||||
// Make sure bufferSize is a power of two.
|
||||
@ -3001,13 +3068,17 @@ bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
|
||||
// Set to an even multiple of granularity, rounding up.
|
||||
*bufferSize = (*bufferSize + granularity-1) / granularity * granularity;
|
||||
}
|
||||
|
||||
if ( mode == INPUT && stream_.mode == OUTPUT && stream_.bufferSize != *bufferSize ) {
|
||||
drivers.removeCurrentDriver();
|
||||
errorText_ = "RtApiAsio::probeDeviceOpen: input/output buffersize discrepancy!";
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
// we don't use it anymore, see above!
|
||||
// Just left it here for the case...
|
||||
if ( isDuplexInput && stream_.bufferSize != *bufferSize ) {
|
||||
errorText_ = "RtApiAsio::probeDeviceOpen: input/output buffersize discrepancy!";
|
||||
goto error;
|
||||
}
|
||||
*/
|
||||
|
||||
stream_.bufferSize = *bufferSize;
|
||||
stream_.nBuffers = 2;
|
||||
|
||||
@ -3018,16 +3089,13 @@ bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
|
||||
stream_.deviceInterleaved[mode] = false;
|
||||
|
||||
// Allocate, if necessary, our AsioHandle structure for the stream.
|
||||
AsioHandle *handle = (AsioHandle *) stream_.apiHandle;
|
||||
if ( handle == 0 ) {
|
||||
try {
|
||||
handle = new AsioHandle;
|
||||
}
|
||||
catch ( std::bad_alloc& ) {
|
||||
//if ( handle == NULL ) {
|
||||
drivers.removeCurrentDriver();
|
||||
errorText_ = "RtApiAsio::probeDeviceOpen: error allocating AsioHandle memory.";
|
||||
return FAILURE;
|
||||
goto error;
|
||||
}
|
||||
handle->bufferInfos = 0;
|
||||
|
||||
@ -3042,15 +3110,14 @@ bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
|
||||
// Create the ASIO internal buffers. Since RtAudio sets up input
|
||||
// and output separately, we'll have to dispose of previously
|
||||
// created output buffers for a duplex stream.
|
||||
long inputLatency, outputLatency;
|
||||
if ( mode == INPUT && stream_.mode == OUTPUT ) {
|
||||
ASIODisposeBuffers();
|
||||
if ( handle->bufferInfos ) free( handle->bufferInfos );
|
||||
}
|
||||
|
||||
// Allocate, initialize, and save the bufferInfos in our stream callbackInfo structure.
|
||||
bool buffersAllocated = false;
|
||||
unsigned int i, nChannels = stream_.nDeviceChannels[0] + stream_.nDeviceChannels[1];
|
||||
unsigned int i;
|
||||
nChannels = stream_.nDeviceChannels[0] + stream_.nDeviceChannels[1];
|
||||
handle->bufferInfos = (ASIOBufferInfo *) malloc( nChannels * sizeof(ASIOBufferInfo) );
|
||||
if ( handle->bufferInfos == NULL ) {
|
||||
errorStream_ << "RtApiAsio::probeDeviceOpen: error allocating bufferInfo memory for driver (" << driverName << ").";
|
||||
@ -3071,18 +3138,37 @@ bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
|
||||
infos->buffers[0] = infos->buffers[1] = 0;
|
||||
}
|
||||
|
||||
// prepare for callbacks
|
||||
stream_.sampleRate = sampleRate;
|
||||
stream_.device[mode] = device;
|
||||
stream_.mode = isDuplexInput ? DUPLEX : mode;
|
||||
|
||||
// store this class instance before registering callbacks, that are going to use it
|
||||
asioCallbackInfo = &stream_.callbackInfo;
|
||||
stream_.callbackInfo.object = (void *) this;
|
||||
|
||||
// Set up the ASIO callback structure and create the ASIO data buffers.
|
||||
asioCallbacks.bufferSwitch = &bufferSwitch;
|
||||
asioCallbacks.sampleRateDidChange = &sampleRateChanged;
|
||||
asioCallbacks.asioMessage = &asioMessages;
|
||||
asioCallbacks.bufferSwitchTimeInfo = NULL;
|
||||
result = ASIOCreateBuffers( handle->bufferInfos, nChannels, stream_.bufferSize, &asioCallbacks );
|
||||
if ( result != ASE_OK ) {
|
||||
// Standard method failed. This can happen with strict/misbehaving drivers that return valid buffer size ranges
|
||||
// but only accept the preferred buffer size as parameter for ASIOCreateBuffers. eg. Creatives ASIO driver
|
||||
// in that case, let's be naïve and try that instead
|
||||
*bufferSize = preferSize;
|
||||
stream_.bufferSize = *bufferSize;
|
||||
result = ASIOCreateBuffers( handle->bufferInfos, nChannels, stream_.bufferSize, &asioCallbacks );
|
||||
}
|
||||
|
||||
if ( result != ASE_OK ) {
|
||||
errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error (" << getAsioErrorString( result ) << ") creating buffers.";
|
||||
errorText_ = errorStream_.str();
|
||||
goto error;
|
||||
}
|
||||
buffersAllocated = true;
|
||||
stream_.state = STREAM_STOPPED;
|
||||
|
||||
// Set flags for buffer conversion.
|
||||
stream_.doConvertBuffer[mode] = false;
|
||||
@ -3105,12 +3191,10 @@ bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
|
||||
|
||||
bool makeBuffer = true;
|
||||
bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] );
|
||||
if ( mode == INPUT ) {
|
||||
if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) {
|
||||
if ( isDuplexInput && stream_.deviceBuffer ) {
|
||||
unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] );
|
||||
if ( bufferBytes <= bytesOut ) makeBuffer = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( makeBuffer ) {
|
||||
bufferBytes *= *bufferSize;
|
||||
@ -3123,18 +3207,8 @@ bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
|
||||
}
|
||||
}
|
||||
|
||||
stream_.sampleRate = sampleRate;
|
||||
stream_.device[mode] = device;
|
||||
stream_.state = STREAM_STOPPED;
|
||||
asioCallbackInfo = &stream_.callbackInfo;
|
||||
stream_.callbackInfo.object = (void *) this;
|
||||
if ( stream_.mode == OUTPUT && mode == INPUT )
|
||||
// We had already set up an output stream.
|
||||
stream_.mode = DUPLEX;
|
||||
else
|
||||
stream_.mode = mode;
|
||||
|
||||
// Determine device latencies
|
||||
long inputLatency, outputLatency;
|
||||
result = ASIOGetLatencies( &inputLatency, &outputLatency );
|
||||
if ( result != ASE_OK ) {
|
||||
errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error (" << getAsioErrorString( result ) << ") getting latency.";
|
||||
@ -3154,32 +3228,38 @@ bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
|
||||
return SUCCESS;
|
||||
|
||||
error:
|
||||
if ( !isDuplexInput ) {
|
||||
// the cleanup for error in the duplex input, is done by RtApi::openStream
|
||||
// So we clean up for single channel only
|
||||
|
||||
if ( buffersAllocated )
|
||||
ASIODisposeBuffers();
|
||||
|
||||
drivers.removeCurrentDriver();
|
||||
|
||||
if ( handle ) {
|
||||
CloseHandle( handle->condition );
|
||||
if ( handle->bufferInfos )
|
||||
free( handle->bufferInfos );
|
||||
|
||||
delete handle;
|
||||
stream_.apiHandle = 0;
|
||||
}
|
||||
|
||||
for ( int i=0; i<2; i++ ) {
|
||||
if ( stream_.userBuffer[i] ) {
|
||||
free( stream_.userBuffer[i] );
|
||||
stream_.userBuffer[i] = 0;
|
||||
}
|
||||
|
||||
if ( stream_.userBuffer[mode] ) {
|
||||
free( stream_.userBuffer[mode] );
|
||||
stream_.userBuffer[mode] = 0;
|
||||
}
|
||||
|
||||
if ( stream_.deviceBuffer ) {
|
||||
free( stream_.deviceBuffer );
|
||||
stream_.deviceBuffer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return FAILURE;
|
||||
}
|
||||
}////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void RtApiAsio :: closeStream()
|
||||
{
|
||||
@ -3631,12 +3711,12 @@ public:
|
||||
outIndex_( 0 ) {}
|
||||
|
||||
~WasapiBuffer() {
|
||||
delete buffer_;
|
||||
free( buffer_ );
|
||||
}
|
||||
|
||||
// sets the length of the internal ring buffer
|
||||
void setBufferSize( unsigned int bufferSize, unsigned int formatBytes ) {
|
||||
delete buffer_;
|
||||
free( buffer_ );
|
||||
|
||||
buffer_ = ( char* ) calloc( bufferSize, formatBytes );
|
||||
|
||||
@ -3795,7 +3875,7 @@ void convertBufferWasapi( char* outBuffer,
|
||||
float sampleStep = 1.0f / sampleRatio;
|
||||
float inSampleFraction = 0.0f;
|
||||
|
||||
outSampleCount = ( unsigned int ) ( inSampleCount * sampleRatio );
|
||||
outSampleCount = ( unsigned int ) roundf( inSampleCount * sampleRatio );
|
||||
|
||||
// frame-by-frame, copy each relative input sample into it's corresponding output sample
|
||||
for ( unsigned int outSample = 0; outSample < outSampleCount; outSample++ )
|
||||
@ -3941,7 +4021,6 @@ RtAudio::DeviceInfo RtApiWasapi::getDeviceInfo( unsigned int device )
|
||||
RtAudio::DeviceInfo info;
|
||||
unsigned int captureDeviceCount = 0;
|
||||
unsigned int renderDeviceCount = 0;
|
||||
std::wstring deviceName;
|
||||
std::string defaultDeviceName;
|
||||
bool isCaptureDevice = false;
|
||||
|
||||
@ -4044,8 +4123,7 @@ RtAudio::DeviceInfo RtApiWasapi::getDeviceInfo( unsigned int device )
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
deviceName = defaultDeviceNameProp.pwszVal;
|
||||
defaultDeviceName = std::string( deviceName.begin(), deviceName.end() );
|
||||
defaultDeviceName = convertCharPointerToStdString(defaultDeviceNameProp.pwszVal);
|
||||
|
||||
// name
|
||||
hr = devicePtr->OpenPropertyStore( STGM_READ, &devicePropStore );
|
||||
@ -4062,8 +4140,7 @@ RtAudio::DeviceInfo RtApiWasapi::getDeviceInfo( unsigned int device )
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
deviceName = deviceNameProp.pwszVal;
|
||||
info.name = std::string( deviceName.begin(), deviceName.end() );
|
||||
info.name =convertCharPointerToStdString(deviceNameProp.pwszVal);
|
||||
|
||||
// is default
|
||||
if ( isCaptureDevice ) {
|
||||
@ -4106,6 +4183,7 @@ RtAudio::DeviceInfo RtApiWasapi::getDeviceInfo( unsigned int device )
|
||||
for ( unsigned int i = 0; i < MAX_SAMPLE_RATES; i++ ) {
|
||||
info.sampleRates.push_back( SAMPLE_RATES[i] );
|
||||
}
|
||||
info.preferredSampleRate = deviceFormat->nSamplesPerSec;
|
||||
|
||||
// native format
|
||||
info.nativeFormats = 0;
|
||||
@ -5080,12 +5158,12 @@ void RtApiWasapi::wasapiThread()
|
||||
// if the callback buffer was pushed renderBuffer reset callbackPulled flag
|
||||
if ( callbackPushed ) {
|
||||
callbackPulled = false;
|
||||
}
|
||||
|
||||
// tick stream time
|
||||
RtApi::tickStreamTime();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Exit:
|
||||
// clean up
|
||||
CoTaskMemFree( captureFormat );
|
||||
@ -5241,14 +5319,11 @@ unsigned int RtApiDs :: getDeviceCount( void )
|
||||
error( RtAudioError::WARNING );
|
||||
}
|
||||
|
||||
// Clean out any devices that may have disappeared.
|
||||
std::vector< int > indices;
|
||||
for ( unsigned int i=0; i<dsDevices.size(); i++ )
|
||||
if ( dsDevices[i].found == false ) indices.push_back( i );
|
||||
//unsigned int nErased = 0;
|
||||
for ( unsigned int i=0; i<indices.size(); i++ )
|
||||
dsDevices.erase( dsDevices.begin()+indices[i] );
|
||||
//dsDevices.erase( dsDevices.begin()-nErased++ );
|
||||
// Clean out any devices that may have disappeared (code update submitted by Eli Zehngut).
|
||||
for ( unsigned int i=0; i<dsDevices.size(); ) {
|
||||
if ( dsDevices[i].found == false ) dsDevices.erase( dsDevices.begin() + i );
|
||||
else i++;
|
||||
}
|
||||
|
||||
return static_cast<unsigned int>(dsDevices.size());
|
||||
}
|
||||
@ -5304,8 +5379,12 @@ RtAudio::DeviceInfo RtApiDs :: getDeviceInfo( unsigned int device )
|
||||
info.sampleRates.clear();
|
||||
for ( unsigned int k=0; k<MAX_SAMPLE_RATES; k++ ) {
|
||||
if ( SAMPLE_RATES[k] >= (unsigned int) outCaps.dwMinSecondarySampleRate &&
|
||||
SAMPLE_RATES[k] <= (unsigned int) outCaps.dwMaxSecondarySampleRate )
|
||||
SAMPLE_RATES[k] <= (unsigned int) outCaps.dwMaxSecondarySampleRate ) {
|
||||
info.sampleRates.push_back( SAMPLE_RATES[k] );
|
||||
|
||||
if ( !info.preferredSampleRate || ( SAMPLE_RATES[k] <= 48000 && SAMPLE_RATES[k] > info.preferredSampleRate ) )
|
||||
info.preferredSampleRate = SAMPLE_RATES[k];
|
||||
}
|
||||
}
|
||||
|
||||
// Get format information.
|
||||
@ -6260,6 +6339,7 @@ void RtApiDs :: callbackEvent()
|
||||
if ( FAILED( result ) ) {
|
||||
errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current write position!";
|
||||
errorText_ = errorStream_.str();
|
||||
MUTEX_UNLOCK( &stream_.mutex );
|
||||
error( RtAudioError::SYSTEM_ERROR );
|
||||
return;
|
||||
}
|
||||
@ -6267,6 +6347,7 @@ void RtApiDs :: callbackEvent()
|
||||
if ( FAILED( result ) ) {
|
||||
errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current read position!";
|
||||
errorText_ = errorStream_.str();
|
||||
MUTEX_UNLOCK( &stream_.mutex );
|
||||
error( RtAudioError::SYSTEM_ERROR );
|
||||
return;
|
||||
}
|
||||
@ -6275,6 +6356,7 @@ void RtApiDs :: callbackEvent()
|
||||
if ( FAILED( result ) ) {
|
||||
errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current write position!";
|
||||
errorText_ = errorStream_.str();
|
||||
MUTEX_UNLOCK( &stream_.mutex );
|
||||
error( RtAudioError::SYSTEM_ERROR );
|
||||
return;
|
||||
}
|
||||
@ -6282,6 +6364,7 @@ void RtApiDs :: callbackEvent()
|
||||
if ( FAILED( result ) ) {
|
||||
errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current read position!";
|
||||
errorText_ = errorStream_.str();
|
||||
MUTEX_UNLOCK( &stream_.mutex );
|
||||
error( RtAudioError::SYSTEM_ERROR );
|
||||
return;
|
||||
}
|
||||
@ -6303,6 +6386,7 @@ void RtApiDs :: callbackEvent()
|
||||
if ( FAILED( result ) ) {
|
||||
errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current write position!";
|
||||
errorText_ = errorStream_.str();
|
||||
MUTEX_UNLOCK( &stream_.mutex );
|
||||
error( RtAudioError::SYSTEM_ERROR );
|
||||
return;
|
||||
}
|
||||
@ -6354,6 +6438,7 @@ void RtApiDs :: callbackEvent()
|
||||
if ( FAILED( result ) ) {
|
||||
errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current write position!";
|
||||
errorText_ = errorStream_.str();
|
||||
MUTEX_UNLOCK( &stream_.mutex );
|
||||
error( RtAudioError::SYSTEM_ERROR );
|
||||
return;
|
||||
}
|
||||
@ -6395,6 +6480,7 @@ void RtApiDs :: callbackEvent()
|
||||
if ( FAILED( result ) ) {
|
||||
errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") locking buffer during playback!";
|
||||
errorText_ = errorStream_.str();
|
||||
MUTEX_UNLOCK( &stream_.mutex );
|
||||
error( RtAudioError::SYSTEM_ERROR );
|
||||
return;
|
||||
}
|
||||
@ -6408,6 +6494,7 @@ void RtApiDs :: callbackEvent()
|
||||
if ( FAILED( result ) ) {
|
||||
errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") unlocking buffer during playback!";
|
||||
errorText_ = errorStream_.str();
|
||||
MUTEX_UNLOCK( &stream_.mutex );
|
||||
error( RtAudioError::SYSTEM_ERROR );
|
||||
return;
|
||||
}
|
||||
@ -6444,6 +6531,7 @@ void RtApiDs :: callbackEvent()
|
||||
if ( FAILED( result ) ) {
|
||||
errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current read position!";
|
||||
errorText_ = errorStream_.str();
|
||||
MUTEX_UNLOCK( &stream_.mutex );
|
||||
error( RtAudioError::SYSTEM_ERROR );
|
||||
return;
|
||||
}
|
||||
@ -6505,6 +6593,7 @@ void RtApiDs :: callbackEvent()
|
||||
if ( FAILED( result ) ) {
|
||||
errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current read position!";
|
||||
errorText_ = errorStream_.str();
|
||||
MUTEX_UNLOCK( &stream_.mutex );
|
||||
error( RtAudioError::SYSTEM_ERROR );
|
||||
return;
|
||||
}
|
||||
@ -6519,6 +6608,7 @@ void RtApiDs :: callbackEvent()
|
||||
if ( FAILED( result ) ) {
|
||||
errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") locking capture buffer!";
|
||||
errorText_ = errorStream_.str();
|
||||
MUTEX_UNLOCK( &stream_.mutex );
|
||||
error( RtAudioError::SYSTEM_ERROR );
|
||||
return;
|
||||
}
|
||||
@ -6540,6 +6630,7 @@ void RtApiDs :: callbackEvent()
|
||||
if ( FAILED( result ) ) {
|
||||
errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") unlocking capture buffer!";
|
||||
errorText_ = errorStream_.str();
|
||||
MUTEX_UNLOCK( &stream_.mutex );
|
||||
error( RtAudioError::SYSTEM_ERROR );
|
||||
return;
|
||||
}
|
||||
@ -6578,21 +6669,6 @@ static unsigned __stdcall callbackHandler( void *ptr )
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "tchar.h"
|
||||
|
||||
static std::string convertTChar( LPCTSTR name )
|
||||
{
|
||||
#if defined( UNICODE ) || defined( _UNICODE )
|
||||
int length = WideCharToMultiByte(CP_UTF8, 0, name, -1, NULL, 0, NULL, NULL);
|
||||
std::string s( length-1, '\0' );
|
||||
WideCharToMultiByte(CP_UTF8, 0, name, -1, &s[0], length, NULL, NULL);
|
||||
#else
|
||||
std::string s( name );
|
||||
#endif
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static BOOL CALLBACK deviceQueryCallback( LPGUID lpguid,
|
||||
LPCTSTR description,
|
||||
LPCTSTR /*module*/,
|
||||
@ -6634,7 +6710,7 @@ static BOOL CALLBACK deviceQueryCallback( LPGUID lpguid,
|
||||
}
|
||||
|
||||
// If good device, then save its name and guid.
|
||||
std::string name = convertTChar( description );
|
||||
std::string name = convertCharPointerToStdString( description );
|
||||
//if ( name == "Primary Sound Driver" || name == "Primary Sound Capture Driver" )
|
||||
if ( lpguid == NULL )
|
||||
name = "Default Device";
|
||||
@ -6816,6 +6892,7 @@ RtAudio::DeviceInfo RtApiAlsa :: getDeviceInfo( unsigned int device )
|
||||
|
||||
// Count cards and devices
|
||||
card = -1;
|
||||
subdevice = -1;
|
||||
snd_card_next( &card );
|
||||
while ( card >= 0 ) {
|
||||
sprintf( name, "hw:%d", card );
|
||||
@ -7029,8 +7106,12 @@ RtAudio::DeviceInfo RtApiAlsa :: getDeviceInfo( unsigned int device )
|
||||
// Test our discrete set of sample rate values.
|
||||
info.sampleRates.clear();
|
||||
for ( unsigned int i=0; i<MAX_SAMPLE_RATES; i++ ) {
|
||||
if ( snd_pcm_hw_params_test_rate( phandle, params, SAMPLE_RATES[i], 0 ) == 0 )
|
||||
if ( snd_pcm_hw_params_test_rate( phandle, params, SAMPLE_RATES[i], 0 ) == 0 ) {
|
||||
info.sampleRates.push_back( SAMPLE_RATES[i] );
|
||||
|
||||
if ( !info.preferredSampleRate || ( SAMPLE_RATES[i] <= 48000 && SAMPLE_RATES[i] > info.preferredSampleRate ) )
|
||||
info.preferredSampleRate = SAMPLE_RATES[i];
|
||||
}
|
||||
}
|
||||
if ( info.sampleRates.size() == 0 ) {
|
||||
snd_pcm_close( phandle );
|
||||
@ -7955,6 +8036,8 @@ void RtApiAlsa :: callbackEvent()
|
||||
errorStream_ << "RtApiAlsa::callbackEvent: error preparing device after underrun, " << snd_strerror( result ) << ".";
|
||||
errorText_ = errorStream_.str();
|
||||
}
|
||||
else
|
||||
errorText_ = "RtApiAlsa::callbackEvent: audio write error, underrun.";
|
||||
}
|
||||
else {
|
||||
errorStream_ << "RtApiAlsa::callbackEvent: error, current state is " << snd_pcm_state_name( state ) << ", " << snd_strerror( result ) << ".";
|
||||
@ -7988,7 +8071,7 @@ static void *alsaCallbackHandler( void *ptr )
|
||||
bool *isRunning = &info->isRunning;
|
||||
|
||||
#ifdef SCHED_RR // Undefined with some OSes (eg: NetBSD 1.6.x with GNU Pthread)
|
||||
if ( &info->doRealtime ) {
|
||||
if ( info->doRealtime ) {
|
||||
pthread_t tID = pthread_self(); // ID of this thread
|
||||
sched_param prio = { info->priority }; // scheduling priority of thread
|
||||
pthread_setschedparam( tID, SCHED_RR, &prio );
|
||||
@ -8063,6 +8146,7 @@ RtAudio::DeviceInfo RtApiPulse::getDeviceInfo( unsigned int /*device*/ )
|
||||
for ( const unsigned int *sr = SUPPORTED_SAMPLERATES; *sr; ++sr )
|
||||
info.sampleRates.push_back( *sr );
|
||||
|
||||
info.preferredSampleRate = 48000;
|
||||
info.nativeFormats = RTAUDIO_SINT16 | RTAUDIO_SINT32 | RTAUDIO_FLOAT32;
|
||||
|
||||
return info;
|
||||
@ -8425,7 +8509,7 @@ bool RtApiPulse::probeDeviceOpen( unsigned int device, StreamMode mode,
|
||||
pah = static_cast<PulseAudioHandle *>( stream_.apiHandle );
|
||||
|
||||
int error;
|
||||
if ( !options->streamName.empty() ) streamName = options->streamName;
|
||||
if ( options && !options->streamName.empty() ) streamName = options->streamName;
|
||||
switch ( mode ) {
|
||||
case INPUT:
|
||||
pa_buffer_attr buffer_attr;
|
||||
@ -8439,7 +8523,7 @@ bool RtApiPulse::probeDeviceOpen( unsigned int device, StreamMode mode,
|
||||
}
|
||||
break;
|
||||
case OUTPUT:
|
||||
pah->s_play = pa_simple_new( NULL, "RtAudio", PA_STREAM_PLAYBACK, NULL, "Playback", &ss, NULL, NULL, &error );
|
||||
pah->s_play = pa_simple_new( NULL, streamName.c_str(), PA_STREAM_PLAYBACK, NULL, "Playback", &ss, NULL, NULL, &error );
|
||||
if ( !pah->s_play ) {
|
||||
errorText_ = "RtApiPulse::probeDeviceOpen: error connecting output to PulseAudio server.";
|
||||
goto error;
|
||||
@ -8631,6 +8715,10 @@ RtAudio::DeviceInfo RtApiOss :: getDeviceInfo( unsigned int device )
|
||||
for ( unsigned int k=0; k<MAX_SAMPLE_RATES; k++ ) {
|
||||
if ( ainfo.rates[i] == SAMPLE_RATES[k] ) {
|
||||
info.sampleRates.push_back( SAMPLE_RATES[k] );
|
||||
|
||||
if ( !info.preferredSampleRate || ( SAMPLE_RATES[k] <= 48000 && SAMPLE_RATES[k] > info.preferredSampleRate ) )
|
||||
info.preferredSampleRate = SAMPLE_RATES[k];
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -8639,8 +8727,12 @@ RtAudio::DeviceInfo RtApiOss :: getDeviceInfo( unsigned int device )
|
||||
else {
|
||||
// Check min and max rate values;
|
||||
for ( unsigned int k=0; k<MAX_SAMPLE_RATES; k++ ) {
|
||||
if ( ainfo.min_rate <= (int) SAMPLE_RATES[k] && ainfo.max_rate >= (int) SAMPLE_RATES[k] )
|
||||
if ( ainfo.min_rate <= (int) SAMPLE_RATES[k] && ainfo.max_rate >= (int) SAMPLE_RATES[k] ) {
|
||||
info.sampleRates.push_back( SAMPLE_RATES[k] );
|
||||
|
||||
if ( !info.preferredSampleRate || ( SAMPLE_RATES[k] <= 48000 && SAMPLE_RATES[k] > info.preferredSampleRate ) )
|
||||
info.preferredSampleRate = SAMPLE_RATES[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
7
external/rtaudio/RtAudio.h
vendored
7
external/rtaudio/RtAudio.h
vendored
@ -10,7 +10,7 @@
|
||||
RtAudio WWW site: http://www.music.mcgill.ca/~gary/rtaudio/
|
||||
|
||||
RtAudio: realtime audio i/o C++ classes
|
||||
Copyright (c) 2001-2014 Gary P. Scavone
|
||||
Copyright (c) 2001-2016 Gary P. Scavone
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation files
|
||||
@ -45,7 +45,7 @@
|
||||
#ifndef __RTAUDIO_H
|
||||
#define __RTAUDIO_H
|
||||
|
||||
#define RTAUDIO_VERSION "4.1.1"
|
||||
#define RTAUDIO_VERSION "4.1.2"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@ -286,12 +286,13 @@ class RtAudio
|
||||
bool isDefaultOutput; /*!< true if this is the default output device. */
|
||||
bool isDefaultInput; /*!< true if this is the default input device. */
|
||||
std::vector<unsigned int> sampleRates; /*!< Supported sample rates (queried from list of standard rates). */
|
||||
unsigned int preferredSampleRate; /*!< Preferred sample rate, eg. for WASAPI the system sample rate. */
|
||||
RtAudioFormat nativeFormats; /*!< Bit mask of supported data formats. */
|
||||
|
||||
// Default constructor.
|
||||
DeviceInfo()
|
||||
:probed(false), outputChannels(0), inputChannels(0), duplexChannels(0),
|
||||
isDefaultOutput(false), isDefaultInput(false), nativeFormats(0) {}
|
||||
isDefaultOutput(false), isDefaultInput(false), preferredSampleRate(0), nativeFormats(0) {}
|
||||
};
|
||||
|
||||
//! The structure for specifying input or ouput stream parameters.
|
||||
|
6
external/rtaudio/readme
vendored
6
external/rtaudio/readme
vendored
@ -1,6 +1,6 @@
|
||||
RtAudio - a set of C++ classes that provide a common API for realtime audio input/output across Linux (native ALSA, JACK, PulseAudio and OSS), Macintosh OS X (CoreAudio and JACK), and Windows (DirectSound, ASIO and WASAPI) operating systems.
|
||||
|
||||
By Gary P. Scavone, 2001-2014.
|
||||
By Gary P. Scavone, 2001-2016.
|
||||
|
||||
This distribution of RtAudio contains the following:
|
||||
|
||||
@ -11,7 +11,7 @@ tests/Windows: Visual C++ .net test program workspace and projects
|
||||
|
||||
OVERVIEW:
|
||||
|
||||
RtAudio is a set of C++ classes that provides a common API (Application Programming Interface) for realtime audio input/output across Linux (native ALSA, JACK, and OSS), Macintosh OS X, SGI, and Windows (DirectSound, ASIO and WASAPI) operating systems. RtAudio significantly simplifies the process of interacting with computer audio hardware. It was designed with the following objectives:
|
||||
RtAudio is a set of C++ classes that provides a common API (Application Programming Interface) for realtime audio input/output across Linux (native ALSA, JACK, PulseAudio and OSS), Macintosh OS X and Windows (DirectSound, ASIO and WASAPI) operating systems. RtAudio significantly simplifies the process of interacting with computer audio hardware. It was designed with the following objectives:
|
||||
|
||||
- object-oriented C++ design
|
||||
- simple, common API across all supported platforms
|
||||
@ -34,7 +34,7 @@ LEGAL AND ETHICAL:
|
||||
The RtAudio license is similar to the MIT License.
|
||||
|
||||
RtAudio: a set of realtime audio i/o C++ classes
|
||||
Copyright (c) 2001-2014 Gary P. Scavone
|
||||
Copyright (c) 2001-2016 Gary P. Scavone
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation files
|
||||
|
5
external/tinyxml/tinystr.cpp
vendored
5
external/tinyxml/tinystr.cpp
vendored
@ -1,6 +1,5 @@
|
||||
/*
|
||||
www.sourceforge.net/projects/tinyxml
|
||||
Original file by Yves Berquin.
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
@ -22,10 +21,6 @@ must not be misrepresented as being the original software.
|
||||
distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* THIS FILE WAS ALTERED BY Tyge L?vset, 7. April 2005.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef TIXML_USE_STL
|
||||
|
||||
|
14
external/tinyxml/tinystr.h
vendored
14
external/tinyxml/tinystr.h
vendored
@ -1,6 +1,5 @@
|
||||
/*
|
||||
www.sourceforge.net/projects/tinyxml
|
||||
Original file by Yves Berquin.
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
@ -22,17 +21,6 @@ must not be misrepresented as being the original software.
|
||||
distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* THIS FILE WAS ALTERED BY Tyge Lovset, 7. April 2005.
|
||||
*
|
||||
* - completely rewritten. compact, clean, and fast implementation.
|
||||
* - sizeof(TiXmlString) = pointer size (4 bytes on 32-bit systems)
|
||||
* - fixed reserve() to work as per specification.
|
||||
* - fixed buggy compares operator==(), operator<(), and operator>()
|
||||
* - fixed operator+=() to take a const ref argument, following spec.
|
||||
* - added "copy" constructor with length, and most compare operators.
|
||||
* - added swap(), clear(), size(), capacity(), operator+().
|
||||
*/
|
||||
|
||||
#ifndef TIXML_USE_STL
|
||||
|
||||
@ -106,13 +94,11 @@ class TiXmlString
|
||||
quit();
|
||||
}
|
||||
|
||||
// = operator
|
||||
TiXmlString& operator = (const char * copy)
|
||||
{
|
||||
return assign( copy, (size_type)strlen(copy));
|
||||
}
|
||||
|
||||
// = operator
|
||||
TiXmlString& operator = (const TiXmlString & copy)
|
||||
{
|
||||
return assign(copy.start(), copy.length());
|
||||
|
442
external/tinyxml/tinyxml.cpp
vendored
442
external/tinyxml/tinyxml.cpp
vendored
@ -1,6 +1,6 @@
|
||||
/*
|
||||
www.sourceforge.net/projects/tinyxml
|
||||
Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com)
|
||||
Original code by Lee Thomason (www.grinninglizard.com)
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
@ -31,6 +31,7 @@ distribution.
|
||||
|
||||
#include "tinyxml.h"
|
||||
|
||||
FILE* TiXmlFOpen( const char* filename, const char* mode );
|
||||
|
||||
bool TiXmlBase::condenseWhiteSpace = true;
|
||||
|
||||
@ -161,6 +162,7 @@ void TiXmlNode::CopyTo( TiXmlNode* target ) const
|
||||
{
|
||||
target->SetValue (value.c_str() );
|
||||
target->userData = userData;
|
||||
target->location = location;
|
||||
}
|
||||
|
||||
|
||||
@ -186,10 +188,11 @@ TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
|
||||
assert( node->parent == 0 || node->parent == this );
|
||||
assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() );
|
||||
|
||||
if ( node->Type() == TiXmlNode::DOCUMENT )
|
||||
if ( node->Type() == TiXmlNode::TINYXML_DOCUMENT )
|
||||
{
|
||||
delete node;
|
||||
if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
|
||||
if ( GetDocument() )
|
||||
GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -210,9 +213,10 @@ TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
|
||||
|
||||
TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis )
|
||||
{
|
||||
if ( addThis.Type() == TiXmlNode::DOCUMENT )
|
||||
if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT )
|
||||
{
|
||||
if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
|
||||
if ( GetDocument() )
|
||||
GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
|
||||
return 0;
|
||||
}
|
||||
TiXmlNode* node = addThis.Clone();
|
||||
@ -228,9 +232,10 @@ TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode&
|
||||
if ( !beforeThis || beforeThis->parent != this ) {
|
||||
return 0;
|
||||
}
|
||||
if ( addThis.Type() == TiXmlNode::DOCUMENT )
|
||||
if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT )
|
||||
{
|
||||
if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
|
||||
if ( GetDocument() )
|
||||
GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -260,9 +265,10 @@ TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& a
|
||||
if ( !afterThis || afterThis->parent != this ) {
|
||||
return 0;
|
||||
}
|
||||
if ( addThis.Type() == TiXmlNode::DOCUMENT )
|
||||
if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT )
|
||||
{
|
||||
if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
|
||||
if ( GetDocument() )
|
||||
GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -289,9 +295,20 @@ TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& a
|
||||
|
||||
TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis )
|
||||
{
|
||||
if ( !replaceThis )
|
||||
return 0;
|
||||
|
||||
if ( replaceThis->parent != this )
|
||||
return 0;
|
||||
|
||||
if ( withThis.ToDocument() ) {
|
||||
// A document can never be a child. Thanks to Noam.
|
||||
TiXmlDocument* document = GetDocument();
|
||||
if ( document )
|
||||
document->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
|
||||
return 0;
|
||||
}
|
||||
|
||||
TiXmlNode* node = withThis.Clone();
|
||||
if ( !node )
|
||||
return 0;
|
||||
@ -317,6 +334,10 @@ TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& wit
|
||||
|
||||
bool TiXmlNode::RemoveChild( TiXmlNode* removeThis )
|
||||
{
|
||||
if ( !removeThis ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( removeThis->parent != this )
|
||||
{
|
||||
assert( 0 );
|
||||
@ -502,7 +523,7 @@ const TiXmlDocument* TiXmlNode::GetDocument() const
|
||||
|
||||
|
||||
TiXmlElement::TiXmlElement (const char * _value)
|
||||
: TiXmlNode( TiXmlNode::ELEMENT )
|
||||
: TiXmlNode( TiXmlNode::TINYXML_ELEMENT )
|
||||
{
|
||||
firstChild = lastChild = 0;
|
||||
value = _value;
|
||||
@ -511,7 +532,7 @@ TiXmlElement::TiXmlElement (const char * _value)
|
||||
|
||||
#ifdef TIXML_USE_STL
|
||||
TiXmlElement::TiXmlElement( const std::string& _value )
|
||||
: TiXmlNode( TiXmlNode::ELEMENT )
|
||||
: TiXmlNode( TiXmlNode::TINYXML_ELEMENT )
|
||||
{
|
||||
firstChild = lastChild = 0;
|
||||
value = _value;
|
||||
@ -520,17 +541,18 @@ TiXmlElement::TiXmlElement( const std::string& _value )
|
||||
|
||||
|
||||
TiXmlElement::TiXmlElement( const TiXmlElement& copy)
|
||||
: TiXmlNode( TiXmlNode::ELEMENT )
|
||||
: TiXmlNode( TiXmlNode::TINYXML_ELEMENT )
|
||||
{
|
||||
firstChild = lastChild = 0;
|
||||
copy.CopyTo( this );
|
||||
}
|
||||
|
||||
|
||||
void TiXmlElement::operator=( const TiXmlElement& base )
|
||||
TiXmlElement& TiXmlElement::operator=( const TiXmlElement& base )
|
||||
{
|
||||
ClearThis();
|
||||
base.CopyTo( this );
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@ -564,9 +586,9 @@ const char* TiXmlElement::Attribute( const char* name ) const
|
||||
#ifdef TIXML_USE_STL
|
||||
const std::string* TiXmlElement::Attribute( const std::string& name ) const
|
||||
{
|
||||
const TiXmlAttribute* node = attributeSet.Find( name );
|
||||
if ( node )
|
||||
return &node->ValueStr();
|
||||
const TiXmlAttribute* attrib = attributeSet.Find( name );
|
||||
if ( attrib )
|
||||
return &attrib->ValueStr();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@ -574,195 +596,202 @@ const std::string* TiXmlElement::Attribute( const std::string& name ) const
|
||||
|
||||
const char* TiXmlElement::Attribute( const char* name, int* i ) const
|
||||
{
|
||||
const char* s = Attribute( name );
|
||||
if ( i )
|
||||
{
|
||||
if ( s ) {
|
||||
*i = atoi( s );
|
||||
}
|
||||
else {
|
||||
*i = 0;
|
||||
const TiXmlAttribute* attrib = attributeSet.Find( name );
|
||||
const char* result = 0;
|
||||
|
||||
if ( attrib ) {
|
||||
result = attrib->Value();
|
||||
if ( i ) {
|
||||
attrib->QueryIntValue( i );
|
||||
}
|
||||
}
|
||||
return s;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
#ifdef TIXML_USE_STL
|
||||
const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const
|
||||
{
|
||||
const std::string* s = Attribute( name );
|
||||
if ( i )
|
||||
{
|
||||
if ( s ) {
|
||||
*i = atoi( s->c_str() );
|
||||
}
|
||||
else {
|
||||
*i = 0;
|
||||
const TiXmlAttribute* attrib = attributeSet.Find( name );
|
||||
const std::string* result = 0;
|
||||
|
||||
if ( attrib ) {
|
||||
result = &attrib->ValueStr();
|
||||
if ( i ) {
|
||||
attrib->QueryIntValue( i );
|
||||
}
|
||||
}
|
||||
return s;
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
const char* TiXmlElement::Attribute( const char* name, double* d ) const
|
||||
{
|
||||
const char* s = Attribute( name );
|
||||
if ( d )
|
||||
{
|
||||
if ( s ) {
|
||||
*d = atof( s );
|
||||
}
|
||||
else {
|
||||
*d = 0;
|
||||
const TiXmlAttribute* attrib = attributeSet.Find( name );
|
||||
const char* result = 0;
|
||||
|
||||
if ( attrib ) {
|
||||
result = attrib->Value();
|
||||
if ( d ) {
|
||||
attrib->QueryDoubleValue( d );
|
||||
}
|
||||
}
|
||||
return s;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
#ifdef TIXML_USE_STL
|
||||
const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const
|
||||
{
|
||||
const std::string* s = Attribute( name );
|
||||
if ( d )
|
||||
{
|
||||
if ( s ) {
|
||||
*d = atof( s->c_str() );
|
||||
}
|
||||
else {
|
||||
*d = 0;
|
||||
const TiXmlAttribute* attrib = attributeSet.Find( name );
|
||||
const std::string* result = 0;
|
||||
|
||||
if ( attrib ) {
|
||||
result = &attrib->ValueStr();
|
||||
if ( d ) {
|
||||
attrib->QueryDoubleValue( d );
|
||||
}
|
||||
}
|
||||
return s;
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const
|
||||
{
|
||||
const TiXmlAttribute* attrib = attributeSet.Find( name );
|
||||
if ( !attrib )
|
||||
return TIXML_NO_ATTRIBUTE;
|
||||
return attrib->QueryIntValue( ival );
|
||||
}
|
||||
|
||||
|
||||
int TiXmlElement::QueryUnsignedAttribute( const char* name, unsigned* value ) const
|
||||
{
|
||||
const TiXmlAttribute* node = attributeSet.Find( name );
|
||||
if ( !node )
|
||||
return TIXML_NO_ATTRIBUTE;
|
||||
return node->QueryIntValue( ival );
|
||||
|
||||
int ival = 0;
|
||||
int result = node->QueryIntValue( &ival );
|
||||
*value = (unsigned)ival;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int TiXmlElement::QueryBoolAttribute( const char* name, bool* bval ) const
|
||||
{
|
||||
const TiXmlAttribute* node = attributeSet.Find( name );
|
||||
if ( !node )
|
||||
return TIXML_NO_ATTRIBUTE;
|
||||
|
||||
int result = TIXML_WRONG_TYPE;
|
||||
if ( StringEqual( node->Value(), "true", true, TIXML_ENCODING_UNKNOWN )
|
||||
|| StringEqual( node->Value(), "yes", true, TIXML_ENCODING_UNKNOWN )
|
||||
|| StringEqual( node->Value(), "1", true, TIXML_ENCODING_UNKNOWN ) )
|
||||
{
|
||||
*bval = true;
|
||||
result = TIXML_SUCCESS;
|
||||
}
|
||||
else if ( StringEqual( node->Value(), "false", true, TIXML_ENCODING_UNKNOWN )
|
||||
|| StringEqual( node->Value(), "no", true, TIXML_ENCODING_UNKNOWN )
|
||||
|| StringEqual( node->Value(), "0", true, TIXML_ENCODING_UNKNOWN ) )
|
||||
{
|
||||
*bval = false;
|
||||
result = TIXML_SUCCESS;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef TIXML_USE_STL
|
||||
int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const
|
||||
{
|
||||
const TiXmlAttribute* node = attributeSet.Find( name );
|
||||
if ( !node )
|
||||
const TiXmlAttribute* attrib = attributeSet.Find( name );
|
||||
if ( !attrib )
|
||||
return TIXML_NO_ATTRIBUTE;
|
||||
return node->QueryIntValue( ival );
|
||||
return attrib->QueryIntValue( ival );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const
|
||||
{
|
||||
const TiXmlAttribute* node = attributeSet.Find( name );
|
||||
if ( !node )
|
||||
const TiXmlAttribute* attrib = attributeSet.Find( name );
|
||||
if ( !attrib )
|
||||
return TIXML_NO_ATTRIBUTE;
|
||||
return node->QueryDoubleValue( dval );
|
||||
return attrib->QueryDoubleValue( dval );
|
||||
}
|
||||
|
||||
|
||||
#ifdef TIXML_USE_STL
|
||||
int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const
|
||||
{
|
||||
const TiXmlAttribute* node = attributeSet.Find( name );
|
||||
if ( !node )
|
||||
const TiXmlAttribute* attrib = attributeSet.Find( name );
|
||||
if ( !attrib )
|
||||
return TIXML_NO_ATTRIBUTE;
|
||||
return node->QueryDoubleValue( dval );
|
||||
return attrib->QueryDoubleValue( dval );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void TiXmlElement::SetAttribute( const char * name, int val )
|
||||
{
|
||||
char buf[64];
|
||||
#if defined(TIXML_SNPRINTF)
|
||||
TIXML_SNPRINTF( buf, sizeof(buf), "%d", val );
|
||||
#else
|
||||
sprintf( buf, "%d", val );
|
||||
#endif
|
||||
SetAttribute( name, buf );
|
||||
TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
|
||||
if ( attrib ) {
|
||||
attrib->SetIntValue( val );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef TIXML_USE_STL
|
||||
void TiXmlElement::SetAttribute( const std::string& name, int val )
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << val;
|
||||
SetAttribute( name, oss.str() );
|
||||
TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
|
||||
if ( attrib ) {
|
||||
attrib->SetIntValue( val );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void TiXmlElement::SetDoubleAttribute( const char * name, double val )
|
||||
{
|
||||
char buf[256];
|
||||
#if defined(TIXML_SNPRINTF)
|
||||
TIXML_SNPRINTF( buf, sizeof(buf), "%f", val );
|
||||
#else
|
||||
sprintf( buf, "%f", val );
|
||||
#endif
|
||||
SetAttribute( name, buf );
|
||||
TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
|
||||
if ( attrib ) {
|
||||
attrib->SetDoubleValue( val );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef TIXML_USE_STL
|
||||
void TiXmlElement::SetDoubleAttribute( const std::string& name, double val )
|
||||
{
|
||||
TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
|
||||
if ( attrib ) {
|
||||
attrib->SetDoubleValue( val );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void TiXmlElement::SetAttribute( const char * cname, const char * cvalue )
|
||||
{
|
||||
#ifdef TIXML_USE_STL
|
||||
TIXML_STRING _name( cname );
|
||||
TIXML_STRING _value( cvalue );
|
||||
#else
|
||||
const char* _name = cname;
|
||||
const char* _value = cvalue;
|
||||
#endif
|
||||
|
||||
TiXmlAttribute* node = attributeSet.Find( _name );
|
||||
if ( node )
|
||||
{
|
||||
node->SetValue( _value );
|
||||
return;
|
||||
}
|
||||
|
||||
TiXmlAttribute* attrib = new TiXmlAttribute( cname, cvalue );
|
||||
if ( attrib )
|
||||
{
|
||||
attributeSet.Add( attrib );
|
||||
}
|
||||
else
|
||||
{
|
||||
TiXmlDocument* document = GetDocument();
|
||||
if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
|
||||
TiXmlAttribute* attrib = attributeSet.FindOrCreate( cname );
|
||||
if ( attrib ) {
|
||||
attrib->SetValue( cvalue );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef TIXML_USE_STL
|
||||
void TiXmlElement::SetAttribute( const std::string& name, const std::string& _value )
|
||||
void TiXmlElement::SetAttribute( const std::string& _name, const std::string& _value )
|
||||
{
|
||||
TiXmlAttribute* node = attributeSet.Find( name );
|
||||
if ( node )
|
||||
{
|
||||
node->SetValue( _value );
|
||||
return;
|
||||
}
|
||||
|
||||
TiXmlAttribute* attrib = new TiXmlAttribute( name, _value );
|
||||
if ( attrib )
|
||||
{
|
||||
attributeSet.Add( attrib );
|
||||
}
|
||||
else
|
||||
{
|
||||
TiXmlDocument* document = GetDocument();
|
||||
if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
|
||||
TiXmlAttribute* attrib = attributeSet.FindOrCreate( _name );
|
||||
if ( attrib ) {
|
||||
attrib->SetValue( _value );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -881,14 +910,14 @@ const char* TiXmlElement::GetText() const
|
||||
}
|
||||
|
||||
|
||||
TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT )
|
||||
TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT )
|
||||
{
|
||||
tabsize = 4;
|
||||
useMicrosoftBOM = false;
|
||||
ClearError();
|
||||
}
|
||||
|
||||
TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
|
||||
TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT )
|
||||
{
|
||||
tabsize = 4;
|
||||
useMicrosoftBOM = false;
|
||||
@ -898,7 +927,7 @@ TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode
|
||||
|
||||
|
||||
#ifdef TIXML_USE_STL
|
||||
TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
|
||||
TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT )
|
||||
{
|
||||
tabsize = 4;
|
||||
useMicrosoftBOM = false;
|
||||
@ -908,49 +937,33 @@ TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiX
|
||||
#endif
|
||||
|
||||
|
||||
TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT )
|
||||
TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT )
|
||||
{
|
||||
copy.CopyTo( this );
|
||||
}
|
||||
|
||||
|
||||
void TiXmlDocument::operator=( const TiXmlDocument& copy )
|
||||
TiXmlDocument& TiXmlDocument::operator=( const TiXmlDocument& copy )
|
||||
{
|
||||
Clear();
|
||||
copy.CopyTo( this );
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
bool TiXmlDocument::LoadFile( TiXmlEncoding encoding )
|
||||
{
|
||||
// See STL_STRING_BUG below.
|
||||
//StringToBuffer buf( value );
|
||||
|
||||
return LoadFile( Value(), encoding );
|
||||
}
|
||||
|
||||
|
||||
bool TiXmlDocument::SaveFile() const
|
||||
{
|
||||
// See STL_STRING_BUG below.
|
||||
// StringToBuffer buf( value );
|
||||
//
|
||||
// if ( buf.buffer && SaveFile( buf.buffer ) )
|
||||
// return true;
|
||||
//
|
||||
// return false;
|
||||
return SaveFile( Value() );
|
||||
}
|
||||
|
||||
bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding )
|
||||
{
|
||||
// There was a really terrifying little bug here. The code:
|
||||
// value = filename
|
||||
// in the STL case, cause the assignment method of the std::string to
|
||||
// be called. What is strange, is that the std::string had the same
|
||||
// address as it's c_str() method, and so bad things happen. Looks
|
||||
// like a bug in the Microsoft STL implementation.
|
||||
// Add an extra string to avoid the crash.
|
||||
TIXML_STRING filename( _filename );
|
||||
value = filename;
|
||||
|
||||
@ -995,11 +1008,6 @@ bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding )
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we have a file, assume it is all one big XML file, and read it in.
|
||||
// The document parser may decide the document ends sooner than the entire file, however.
|
||||
TIXML_STRING data;
|
||||
data.reserve( length );
|
||||
|
||||
// Subtle bug here. TinyXml did use fgets. But from the XML spec:
|
||||
// 2.11 End-of-Line Handling
|
||||
// <snip>
|
||||
@ -1030,58 +1038,46 @@ bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding )
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* lastPos = buf;
|
||||
const char* p = buf;
|
||||
// Process the buffer in place to normalize new lines. (See comment above.)
|
||||
// Copies from the 'p' to 'q' pointer, where p can advance faster if
|
||||
// a newline-carriage return is hit.
|
||||
//
|
||||
// Wikipedia:
|
||||
// Systems based on ASCII or a compatible character set use either LF (Line feed, '\n', 0x0A, 10 in decimal) or
|
||||
// CR (Carriage return, '\r', 0x0D, 13 in decimal) individually, or CR followed by LF (CR+LF, 0x0D 0x0A)...
|
||||
// * LF: Multics, Unix and Unix-like systems (GNU/Linux, AIX, Xenix, Mac OS X, FreeBSD, etc.), BeOS, Amiga, RISC OS, and others
|
||||
// * CR+LF: DEC RT-11 and most other early non-Unix, non-IBM OSes, CP/M, MP/M, DOS, OS/2, Microsoft Windows, Symbian OS
|
||||
// * CR: Commodore 8-bit machines, Apple II family, Mac OS up to version 9 and OS-9
|
||||
|
||||
const char* p = buf; // the read head
|
||||
char* q = buf; // the write head
|
||||
const char CR = 0x0d;
|
||||
const char LF = 0x0a;
|
||||
|
||||
buf[length] = 0;
|
||||
while( *p ) {
|
||||
assert( p < (buf+length) );
|
||||
if ( *p == 0xa ) {
|
||||
// Newline character. No special rules for this. Append all the characters
|
||||
// since the last string, and include the newline.
|
||||
data.append( lastPos, (p-lastPos+1) ); // append, include the newline
|
||||
++p; // move past the newline
|
||||
lastPos = p; // and point to the new buffer (may be 0)
|
||||
assert( p <= (buf+length) );
|
||||
}
|
||||
else if ( *p == 0xd ) {
|
||||
// Carriage return. Append what we have so far, then
|
||||
// handle moving forward in the buffer.
|
||||
if ( (p-lastPos) > 0 ) {
|
||||
data.append( lastPos, p-lastPos ); // do not add the CR
|
||||
}
|
||||
data += (char)0xa; // a proper newline
|
||||
assert( q <= (buf+length) );
|
||||
assert( q <= p );
|
||||
|
||||
if ( *(p+1) == 0xa ) {
|
||||
// Carriage return - new line sequence
|
||||
p += 2;
|
||||
lastPos = p;
|
||||
assert( p <= (buf+length) );
|
||||
}
|
||||
else {
|
||||
// it was followed by something else...that is presumably characters again.
|
||||
++p;
|
||||
lastPos = p;
|
||||
assert( p <= (buf+length) );
|
||||
if ( *p == CR ) {
|
||||
*q++ = LF;
|
||||
p++;
|
||||
if ( *p == LF ) { // check for CR+LF (and skip LF)
|
||||
p++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
++p;
|
||||
*q++ = *p++;
|
||||
}
|
||||
}
|
||||
// Handle any left over characters.
|
||||
if ( p-lastPos ) {
|
||||
data.append( lastPos, p-lastPos );
|
||||
}
|
||||
assert( q <= (buf+length) );
|
||||
*q = 0;
|
||||
|
||||
Parse( buf, 0, encoding );
|
||||
|
||||
delete [] buf;
|
||||
buf = 0;
|
||||
|
||||
Parse( data.c_str(), 0, encoding );
|
||||
|
||||
if ( Error() )
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
return !Error();
|
||||
}
|
||||
|
||||
|
||||
@ -1266,9 +1262,9 @@ void TiXmlAttribute::SetDoubleValue( double _value )
|
||||
{
|
||||
char buf [256];
|
||||
#if defined(TIXML_SNPRINTF)
|
||||
TIXML_SNPRINTF( buf, sizeof(buf), "%lf", _value);
|
||||
TIXML_SNPRINTF( buf, sizeof(buf), "%g", _value);
|
||||
#else
|
||||
sprintf (buf, "%lf", _value);
|
||||
sprintf (buf, "%g", _value);
|
||||
#endif
|
||||
SetValue (buf);
|
||||
}
|
||||
@ -1284,16 +1280,17 @@ double TiXmlAttribute::DoubleValue() const
|
||||
}
|
||||
|
||||
|
||||
TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT )
|
||||
TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT )
|
||||
{
|
||||
copy.CopyTo( this );
|
||||
}
|
||||
|
||||
|
||||
void TiXmlComment::operator=( const TiXmlComment& base )
|
||||
TiXmlComment& TiXmlComment::operator=( const TiXmlComment& base )
|
||||
{
|
||||
Clear();
|
||||
base.CopyTo( this );
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@ -1382,7 +1379,7 @@ TiXmlNode* TiXmlText::Clone() const
|
||||
TiXmlDeclaration::TiXmlDeclaration( const char * _version,
|
||||
const char * _encoding,
|
||||
const char * _standalone )
|
||||
: TiXmlNode( TiXmlNode::DECLARATION )
|
||||
: TiXmlNode( TiXmlNode::TINYXML_DECLARATION )
|
||||
{
|
||||
version = _version;
|
||||
encoding = _encoding;
|
||||
@ -1394,7 +1391,7 @@ TiXmlDeclaration::TiXmlDeclaration( const char * _version,
|
||||
TiXmlDeclaration::TiXmlDeclaration( const std::string& _version,
|
||||
const std::string& _encoding,
|
||||
const std::string& _standalone )
|
||||
: TiXmlNode( TiXmlNode::DECLARATION )
|
||||
: TiXmlNode( TiXmlNode::TINYXML_DECLARATION )
|
||||
{
|
||||
version = _version;
|
||||
encoding = _encoding;
|
||||
@ -1404,16 +1401,17 @@ TiXmlDeclaration::TiXmlDeclaration( const std::string& _version,
|
||||
|
||||
|
||||
TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy )
|
||||
: TiXmlNode( TiXmlNode::DECLARATION )
|
||||
: TiXmlNode( TiXmlNode::TINYXML_DECLARATION )
|
||||
{
|
||||
copy.CopyTo( this );
|
||||
}
|
||||
|
||||
|
||||
void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy )
|
||||
TiXmlDeclaration& TiXmlDeclaration::operator=( const TiXmlDeclaration& copy )
|
||||
{
|
||||
Clear();
|
||||
copy.CopyTo( this );
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@ -1548,18 +1546,7 @@ void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe )
|
||||
|
||||
|
||||
#ifdef TIXML_USE_STL
|
||||
const TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const
|
||||
{
|
||||
for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
|
||||
{
|
||||
if ( node->name == name )
|
||||
return node;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name )
|
||||
TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const
|
||||
{
|
||||
for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
|
||||
{
|
||||
@ -1568,22 +1555,21 @@ TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name )
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const std::string& _name )
|
||||
{
|
||||
TiXmlAttribute* attrib = Find( _name );
|
||||
if ( !attrib ) {
|
||||
attrib = new TiXmlAttribute();
|
||||
Add( attrib );
|
||||
attrib->SetName( _name );
|
||||
}
|
||||
return attrib;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
const TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const
|
||||
{
|
||||
for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
|
||||
{
|
||||
if ( strcmp( node->name.c_str(), name ) == 0 )
|
||||
return node;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
TiXmlAttribute* TiXmlAttributeSet::Find( const char* name )
|
||||
TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const
|
||||
{
|
||||
for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
|
||||
{
|
||||
@ -1592,7 +1578,19 @@ TiXmlAttribute* TiXmlAttributeSet::Find( const char* name )
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const char* _name )
|
||||
{
|
||||
TiXmlAttribute* attrib = Find( _name );
|
||||
if ( !attrib ) {
|
||||
attrib = new TiXmlAttribute();
|
||||
Add( attrib );
|
||||
attrib->SetName( _name );
|
||||
}
|
||||
return attrib;
|
||||
}
|
||||
|
||||
|
||||
#ifdef TIXML_USE_STL
|
||||
std::istream& operator>> (std::istream & in, TiXmlNode & base)
|
||||
|
115
external/tinyxml/tinyxml.h
vendored
115
external/tinyxml/tinyxml.h
vendored
@ -1,6 +1,6 @@
|
||||
/*
|
||||
www.sourceforge.net/projects/tinyxml
|
||||
Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com)
|
||||
Original code by Lee Thomason (www.grinninglizard.com)
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
@ -63,21 +63,19 @@ distribution.
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
|
||||
// Microsoft visual studio, version 2005 and higher.
|
||||
#define TIXML_SNPRINTF _snprintf_s
|
||||
#define TIXML_SNSCANF _snscanf_s
|
||||
#define TIXML_SSCANF sscanf_s
|
||||
#elif defined(_MSC_VER) && (_MSC_VER >= 1200 )
|
||||
// Microsoft visual studio, version 6 and higher.
|
||||
//#pragma message( "Using _sn* functions." )
|
||||
#define TIXML_SNPRINTF _snprintf
|
||||
#define TIXML_SNSCANF _snscanf
|
||||
#define TIXML_SSCANF sscanf
|
||||
#elif defined(__GNUC__) && (__GNUC__ >= 3 )
|
||||
// GCC version 3 and higher.s
|
||||
//#warning( "Using sn* functions." )
|
||||
#define TIXML_SNPRINTF snprintf
|
||||
#define TIXML_SNSCANF snscanf
|
||||
#define TIXML_SSCANF sscanf
|
||||
#else
|
||||
#define TIXML_SNPRINTF snprintf
|
||||
#define TIXML_SSCANF sscanf
|
||||
#endif
|
||||
#endif
|
||||
@ -92,8 +90,8 @@ class TiXmlDeclaration;
|
||||
class TiXmlParsingData;
|
||||
|
||||
const int TIXML_MAJOR_VERSION = 2;
|
||||
const int TIXML_MINOR_VERSION = 5;
|
||||
const int TIXML_PATCH_VERSION = 3;
|
||||
const int TIXML_MINOR_VERSION = 6;
|
||||
const int TIXML_PATCH_VERSION = 2;
|
||||
|
||||
/* Internal structure for tracking location of items
|
||||
in the XML file.
|
||||
@ -109,10 +107,11 @@ struct TiXmlCursor
|
||||
|
||||
|
||||
/**
|
||||
Implements the interface to the "Visitor pattern" (see the Accept() method.)
|
||||
If you call the Accept() method, it requires being passed a TiXmlVisitor
|
||||
class to handle callbacks. For nodes that contain other nodes (Document, Element)
|
||||
you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves
|
||||
are simple called with Visit().
|
||||
are simply called with Visit().
|
||||
|
||||
If you return 'true' from a Visit method, recursive parsing will continue. If you return
|
||||
false, <b>no children of this node or its sibilings</b> will be Visited.
|
||||
@ -147,7 +146,7 @@ public:
|
||||
virtual bool Visit( const TiXmlText& /*text*/ ) { return true; }
|
||||
/// Visit a comment node
|
||||
virtual bool Visit( const TiXmlComment& /*comment*/ ) { return true; }
|
||||
/// Visit an unknow node
|
||||
/// Visit an unknown node
|
||||
virtual bool Visit( const TiXmlUnknown& /*unknown*/ ) { return true; }
|
||||
};
|
||||
|
||||
@ -267,7 +266,6 @@ public:
|
||||
TIXML_NO_ERROR = 0,
|
||||
TIXML_ERROR,
|
||||
TIXML_ERROR_OPENING_FILE,
|
||||
TIXML_ERROR_OUT_OF_MEMORY,
|
||||
TIXML_ERROR_PARSING_ELEMENT,
|
||||
TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME,
|
||||
TIXML_ERROR_READING_ELEMENT_VALUE,
|
||||
@ -288,6 +286,7 @@ public:
|
||||
protected:
|
||||
|
||||
static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding );
|
||||
|
||||
inline static bool IsWhiteSpace( char c )
|
||||
{
|
||||
return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' );
|
||||
@ -462,13 +461,13 @@ public:
|
||||
*/
|
||||
enum NodeType
|
||||
{
|
||||
DOCUMENT,
|
||||
ELEMENT,
|
||||
COMMENT,
|
||||
UNKNOWN,
|
||||
TEXT,
|
||||
DECLARATION,
|
||||
TYPECOUNT
|
||||
TINYXML_DOCUMENT,
|
||||
TINYXML_ELEMENT,
|
||||
TINYXML_COMMENT,
|
||||
TINYXML_UNKNOWN,
|
||||
TINYXML_TEXT,
|
||||
TINYXML_DECLARATION,
|
||||
TINYXML_TYPECOUNT
|
||||
};
|
||||
|
||||
virtual ~TiXmlNode();
|
||||
@ -679,8 +678,8 @@ public:
|
||||
#endif
|
||||
|
||||
/** Query the type (as an enumerated value, above) of this node.
|
||||
The possible types are: DOCUMENT, ELEMENT, COMMENT,
|
||||
UNKNOWN, TEXT, and DECLARATION.
|
||||
The possible types are: TINYXML_DOCUMENT, TINYXML_ELEMENT, TINYXML_COMMENT,
|
||||
TINYXML_UNKNOWN, TINYXML_TEXT, and TINYXML_DECLARATION.
|
||||
*/
|
||||
int Type() const { return type; }
|
||||
|
||||
@ -915,18 +914,15 @@ public:
|
||||
const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; }
|
||||
TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; }
|
||||
|
||||
const TiXmlAttribute* Find( const char* _name ) const;
|
||||
TiXmlAttribute* Find( const char* _name ) {
|
||||
return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttributeSet* >(this))->Find( _name ) );
|
||||
}
|
||||
#ifdef TIXML_USE_STL
|
||||
const TiXmlAttribute* Find( const std::string& _name ) const;
|
||||
TiXmlAttribute* Find( const std::string& _name ) {
|
||||
return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttributeSet* >(this))->Find( _name ) );
|
||||
}
|
||||
TiXmlAttribute* Find( const char* _name ) const;
|
||||
TiXmlAttribute* FindOrCreate( const char* _name );
|
||||
|
||||
# ifdef TIXML_USE_STL
|
||||
TiXmlAttribute* Find( const std::string& _name ) const;
|
||||
TiXmlAttribute* FindOrCreate( const std::string& _name );
|
||||
# endif
|
||||
|
||||
|
||||
private:
|
||||
//*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element),
|
||||
//*ME: this class must be also use a hidden/disabled copy-constructor !!!
|
||||
@ -954,7 +950,7 @@ public:
|
||||
|
||||
TiXmlElement( const TiXmlElement& );
|
||||
|
||||
void operator=( const TiXmlElement& base );
|
||||
TiXmlElement& operator=( const TiXmlElement& base );
|
||||
|
||||
virtual ~TiXmlElement();
|
||||
|
||||
@ -987,6 +983,13 @@ public:
|
||||
does not exist, then TIXML_NO_ATTRIBUTE is returned.
|
||||
*/
|
||||
int QueryIntAttribute( const char* name, int* _value ) const;
|
||||
/// QueryUnsignedAttribute examines the attribute - see QueryIntAttribute().
|
||||
int QueryUnsignedAttribute( const char* name, unsigned* _value ) const;
|
||||
/** QueryBoolAttribute examines the attribute - see QueryIntAttribute().
|
||||
Note that '1', 'true', or 'yes' are considered true, while '0', 'false'
|
||||
and 'no' are considered false.
|
||||
*/
|
||||
int QueryBoolAttribute( const char* name, bool* _value ) const;
|
||||
/// QueryDoubleAttribute examines the attribute - see QueryIntAttribute().
|
||||
int QueryDoubleAttribute( const char* name, double* _value ) const;
|
||||
/// QueryFloatAttribute examines the attribute - see QueryIntAttribute().
|
||||
@ -1000,11 +1003,21 @@ public:
|
||||
}
|
||||
|
||||
#ifdef TIXML_USE_STL
|
||||
/// QueryStringAttribute examines the attribute - see QueryIntAttribute().
|
||||
int QueryStringAttribute( const char* name, std::string* _value ) const {
|
||||
const char* cstr = Attribute( name );
|
||||
if ( cstr ) {
|
||||
*_value = std::string( cstr );
|
||||
return TIXML_SUCCESS;
|
||||
}
|
||||
return TIXML_NO_ATTRIBUTE;
|
||||
}
|
||||
|
||||
/** Template form of the attribute query which will try to read the
|
||||
attribute into the specified type. Very easy, very powerful, but
|
||||
be careful to make sure to call this with the correct type.
|
||||
|
||||
NOTE: This method doesn't work correctly for 'string' types.
|
||||
NOTE: This method doesn't work correctly for 'string' types that contain spaces.
|
||||
|
||||
@return TIXML_SUCCESS, TIXML_WRONG_TYPE, or TIXML_NO_ATTRIBUTE
|
||||
*/
|
||||
@ -1020,13 +1033,8 @@ public:
|
||||
return TIXML_SUCCESS;
|
||||
return TIXML_WRONG_TYPE;
|
||||
}
|
||||
/*
|
||||
This is - in theory - a bug fix for "QueryValueAtribute returns truncated std::string"
|
||||
but template specialization is hard to get working cross-compiler. Leaving the bug for now.
|
||||
|
||||
// The above will fail for std::string because the space character is used as a seperator.
|
||||
// Specialize for strings. Bug [ 1695429 ] QueryValueAtribute returns truncated std::string
|
||||
template<> int QueryValueAttribute( const std::string& name, std::string* outValue ) const
|
||||
int QueryValueAttribute( const std::string& name, std::string* outValue ) const
|
||||
{
|
||||
const TiXmlAttribute* node = attributeSet.Find( name );
|
||||
if ( !node )
|
||||
@ -1034,7 +1042,6 @@ public:
|
||||
*outValue = node->ValueStr();
|
||||
return TIXML_SUCCESS;
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
|
||||
/** Sets an attribute of name to a given value. The attribute
|
||||
@ -1053,6 +1060,8 @@ public:
|
||||
void SetAttribute( const std::string& name, const std::string& _value );
|
||||
///< STL std::string form.
|
||||
void SetAttribute( const std::string& name, int _value );
|
||||
///< STL std::string form.
|
||||
void SetDoubleAttribute( const std::string& name, double value );
|
||||
#endif
|
||||
|
||||
/** Sets an attribute of name to a given value. The attribute
|
||||
@ -1144,7 +1153,6 @@ protected:
|
||||
const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding );
|
||||
|
||||
private:
|
||||
|
||||
TiXmlAttributeSet attributeSet;
|
||||
};
|
||||
|
||||
@ -1155,13 +1163,13 @@ class TiXmlComment : public TiXmlNode
|
||||
{
|
||||
public:
|
||||
/// Constructs an empty comment.
|
||||
TiXmlComment() : TiXmlNode( TiXmlNode::COMMENT ) {}
|
||||
TiXmlComment() : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) {}
|
||||
/// Construct a comment from text.
|
||||
TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::COMMENT ) {
|
||||
TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) {
|
||||
SetValue( _value );
|
||||
}
|
||||
TiXmlComment( const TiXmlComment& );
|
||||
void operator=( const TiXmlComment& base );
|
||||
TiXmlComment& operator=( const TiXmlComment& base );
|
||||
|
||||
virtual ~TiXmlComment() {}
|
||||
|
||||
@ -1209,7 +1217,7 @@ public:
|
||||
normal, encoded text. If you want it be output as a CDATA text
|
||||
element, set the parameter _cdata to 'true'
|
||||
*/
|
||||
TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TEXT)
|
||||
TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT)
|
||||
{
|
||||
SetValue( initValue );
|
||||
cdata = false;
|
||||
@ -1218,15 +1226,15 @@ public:
|
||||
|
||||
#ifdef TIXML_USE_STL
|
||||
/// Constructor.
|
||||
TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TEXT)
|
||||
TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT)
|
||||
{
|
||||
SetValue( initValue );
|
||||
cdata = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TEXT ) { copy.CopyTo( this ); }
|
||||
void operator=( const TiXmlText& base ) { base.CopyTo( this ); }
|
||||
TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TINYXML_TEXT ) { copy.CopyTo( this ); }
|
||||
TiXmlText& operator=( const TiXmlText& base ) { base.CopyTo( this ); return *this; }
|
||||
|
||||
// Write this text object to a FILE stream.
|
||||
virtual void Print( FILE* cfile, int depth ) const;
|
||||
@ -1278,7 +1286,7 @@ class TiXmlDeclaration : public TiXmlNode
|
||||
{
|
||||
public:
|
||||
/// Construct an empty declaration.
|
||||
TiXmlDeclaration() : TiXmlNode( TiXmlNode::DECLARATION ) {}
|
||||
TiXmlDeclaration() : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) {}
|
||||
|
||||
#ifdef TIXML_USE_STL
|
||||
/// Constructor.
|
||||
@ -1293,7 +1301,7 @@ public:
|
||||
const char* _standalone );
|
||||
|
||||
TiXmlDeclaration( const TiXmlDeclaration& copy );
|
||||
void operator=( const TiXmlDeclaration& copy );
|
||||
TiXmlDeclaration& operator=( const TiXmlDeclaration& copy );
|
||||
|
||||
virtual ~TiXmlDeclaration() {}
|
||||
|
||||
@ -1346,11 +1354,11 @@ private:
|
||||
class TiXmlUnknown : public TiXmlNode
|
||||
{
|
||||
public:
|
||||
TiXmlUnknown() : TiXmlNode( TiXmlNode::UNKNOWN ) {}
|
||||
TiXmlUnknown() : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) {}
|
||||
virtual ~TiXmlUnknown() {}
|
||||
|
||||
TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::UNKNOWN ) { copy.CopyTo( this ); }
|
||||
void operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); }
|
||||
TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) { copy.CopyTo( this ); }
|
||||
TiXmlUnknown& operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); return *this; }
|
||||
|
||||
/// Creates a copy of this Unknown and returns it.
|
||||
virtual TiXmlNode* Clone() const;
|
||||
@ -1396,7 +1404,7 @@ public:
|
||||
#endif
|
||||
|
||||
TiXmlDocument( const TiXmlDocument& copy );
|
||||
void operator=( const TiXmlDocument& copy );
|
||||
TiXmlDocument& operator=( const TiXmlDocument& copy );
|
||||
|
||||
virtual ~TiXmlDocument() {}
|
||||
|
||||
@ -1423,14 +1431,10 @@ public:
|
||||
#ifdef TIXML_USE_STL
|
||||
bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version.
|
||||
{
|
||||
// StringToBuffer f( filename );
|
||||
// return ( f.buffer && LoadFile( f.buffer, encoding ));
|
||||
return LoadFile( filename.c_str(), encoding );
|
||||
}
|
||||
bool SaveFile( const std::string& filename ) const ///< STL std::string version.
|
||||
{
|
||||
// StringToBuffer f( filename );
|
||||
// return ( f.buffer && SaveFile( f.buffer ));
|
||||
return SaveFile( filename.c_str() );
|
||||
}
|
||||
#endif
|
||||
@ -1638,7 +1642,7 @@ public:
|
||||
TiXmlHandle( TiXmlNode* _node ) { this->node = _node; }
|
||||
/// Copy constructor
|
||||
TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; }
|
||||
TiXmlHandle operator=( const TiXmlHandle& ref ) { this->node = ref.node; return *this; }
|
||||
TiXmlHandle operator=( const TiXmlHandle& ref ) { if ( &ref != this ) this->node = ref.node; return *this; }
|
||||
|
||||
/// Return a handle to the first child node.
|
||||
TiXmlHandle FirstChild() const;
|
||||
@ -1799,4 +1803,3 @@ private:
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
3
external/tinyxml/tinyxmlerror.cpp
vendored
3
external/tinyxml/tinyxmlerror.cpp
vendored
@ -31,12 +31,11 @@ distribution.
|
||||
// It also cleans up the code a bit.
|
||||
//
|
||||
|
||||
const char* TiXmlBase::errorString[ TIXML_ERROR_STRING_COUNT ] =
|
||||
const char* TiXmlBase::errorString[ TiXmlBase::TIXML_ERROR_STRING_COUNT ] =
|
||||
{
|
||||
"No error",
|
||||
"Error",
|
||||
"Failed to open file",
|
||||
"Memory allocation failed.",
|
||||
"Error parsing Element.",
|
||||
"Failed to read Element name",
|
||||
"Error reading Element value.",
|
||||
|
52
external/tinyxml/tinyxmlparser.cpp
vendored
52
external/tinyxml/tinyxmlparser.cpp
vendored
@ -1,6 +1,6 @@
|
||||
/*
|
||||
www.sourceforge.net/projects/tinyxml
|
||||
Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com)
|
||||
Original code by Lee Thomason (www.grinninglizard.com)
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
@ -40,7 +40,7 @@ distribution.
|
||||
// Note tha "PutString" hardcodes the same list. This
|
||||
// is less flexible than it appears. Changing the entries
|
||||
// or order will break putstring.
|
||||
TiXmlBase::Entity TiXmlBase::entity[ NUM_ENTITY ] =
|
||||
TiXmlBase::Entity TiXmlBase::entity[ TiXmlBase::NUM_ENTITY ] =
|
||||
{
|
||||
{ "&", 5, '&' },
|
||||
{ "<", 4, '<' },
|
||||
@ -174,7 +174,7 @@ class TiXmlParsingData
|
||||
public:
|
||||
void Stamp( const char* now, TiXmlEncoding encoding );
|
||||
|
||||
const TiXmlCursor& Cursor() { return cursor; }
|
||||
const TiXmlCursor& Cursor() const { return cursor; }
|
||||
|
||||
private:
|
||||
// Only used by the document!
|
||||
@ -346,7 +346,7 @@ const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding )
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) // Still using old rules for white space.
|
||||
if ( IsWhiteSpace( *p ) ) // Still using old rules for white space.
|
||||
++p;
|
||||
else
|
||||
break;
|
||||
@ -354,7 +354,7 @@ const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding )
|
||||
}
|
||||
else
|
||||
{
|
||||
while ( (*p && IsWhiteSpace( *p )) || *p == '\n' || *p =='\r' )
|
||||
while ( *p && IsWhiteSpace( *p ) )
|
||||
++p;
|
||||
}
|
||||
|
||||
@ -631,9 +631,9 @@ const char* TiXmlBase::ReadText( const char* p,
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( p )
|
||||
if ( p && *p )
|
||||
p += strlen( endTag );
|
||||
return p;
|
||||
return ( p && *p ) ? p : 0;
|
||||
}
|
||||
|
||||
#ifdef TIXML_USE_STL
|
||||
@ -825,7 +825,6 @@ TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding )
|
||||
return 0;
|
||||
}
|
||||
|
||||
TiXmlDocument* doc = GetDocument();
|
||||
p = SkipWhiteSpace( p, encoding );
|
||||
|
||||
if ( !p || !*p )
|
||||
@ -896,11 +895,6 @@ TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding )
|
||||
// Set the parent, so it can report errors
|
||||
returnNode->parent = this;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( doc )
|
||||
doc->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
|
||||
}
|
||||
return returnNode;
|
||||
}
|
||||
|
||||
@ -1083,7 +1077,6 @@ const char* TiXmlElement::Parse( const char* p, TiXmlParsingData* data, TiXmlEnc
|
||||
|
||||
TIXML_STRING endTag ("</");
|
||||
endTag += value;
|
||||
endTag += ">";
|
||||
|
||||
// Check for and read attributes. Also look for an empty
|
||||
// tag or an end tag.
|
||||
@ -1122,11 +1115,21 @@ const char* TiXmlElement::Parse( const char* p, TiXmlParsingData* data, TiXmlEnc
|
||||
}
|
||||
|
||||
// We should find the end tag now
|
||||
// note that:
|
||||
// </foo > and
|
||||
// </foo>
|
||||
// are both valid end tags.
|
||||
if ( StringEqual( p, endTag.c_str(), false, encoding ) )
|
||||
{
|
||||
p += endTag.length();
|
||||
p = SkipWhiteSpace( p, encoding );
|
||||
if ( p && *p && *p == '>' ) {
|
||||
++p;
|
||||
return p;
|
||||
}
|
||||
if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding );
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding );
|
||||
@ -1139,7 +1142,6 @@ const char* TiXmlElement::Parse( const char* p, TiXmlParsingData* data, TiXmlEnc
|
||||
TiXmlAttribute* attrib = new TiXmlAttribute();
|
||||
if ( !attrib )
|
||||
{
|
||||
if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, pErr, data, encoding );
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1162,7 +1164,7 @@ const char* TiXmlElement::Parse( const char* p, TiXmlParsingData* data, TiXmlEnc
|
||||
#endif
|
||||
if ( node )
|
||||
{
|
||||
node->SetValue( attrib->Value() );
|
||||
if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, pErr, data, encoding );
|
||||
delete attrib;
|
||||
return 0;
|
||||
}
|
||||
@ -1191,7 +1193,6 @@ const char* TiXmlElement::ReadValue( const char* p, TiXmlParsingData* data, TiXm
|
||||
|
||||
if ( !textNode )
|
||||
{
|
||||
if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, encoding );
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1297,9 +1298,10 @@ const char* TiXmlUnknown::Parse( const char* p, TiXmlParsingData* data, TiXmlEnc
|
||||
|
||||
if ( !p )
|
||||
{
|
||||
if ( document ) document->SetError( TIXML_ERROR_PARSING_UNKNOWN, 0, 0, encoding );
|
||||
if ( document )
|
||||
document->SetError( TIXML_ERROR_PARSING_UNKNOWN, 0, 0, encoding );
|
||||
}
|
||||
if ( *p == '>' )
|
||||
if ( p && *p == '>' )
|
||||
return p+1;
|
||||
return p;
|
||||
}
|
||||
@ -1349,6 +1351,7 @@ const char* TiXmlComment::Parse( const char* p, TiXmlParsingData* data, TiXmlEnc
|
||||
|
||||
if ( !StringEqual( p, startTag, false, encoding ) )
|
||||
{
|
||||
if ( document )
|
||||
document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding );
|
||||
return 0;
|
||||
}
|
||||
@ -1379,7 +1382,7 @@ const char* TiXmlComment::Parse( const char* p, TiXmlParsingData* data, TiXmlEnc
|
||||
value.append( p, 1 );
|
||||
++p;
|
||||
}
|
||||
if ( p )
|
||||
if ( p && *p )
|
||||
p += strlen( endTag );
|
||||
|
||||
return p;
|
||||
@ -1391,10 +1394,6 @@ const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlE
|
||||
p = SkipWhiteSpace( p, encoding );
|
||||
if ( !p || !*p ) return 0;
|
||||
|
||||
// int tabsize = 4;
|
||||
// if ( document )
|
||||
// tabsize = document->TabSize();
|
||||
|
||||
if ( data )
|
||||
{
|
||||
data->Stamp( p, encoding );
|
||||
@ -1446,7 +1445,7 @@ const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlE
|
||||
// its best, even without them.
|
||||
value = "";
|
||||
while ( p && *p // existence
|
||||
&& !IsWhiteSpace( *p ) && *p != '\n' && *p != '\r' // whitespace
|
||||
&& !IsWhiteSpace( *p ) // whitespace
|
||||
&& *p != '/' && *p != '>' ) // tag end
|
||||
{
|
||||
if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) {
|
||||
@ -1515,6 +1514,7 @@ const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncodi
|
||||
|
||||
if ( !StringEqual( p, startTag, false, encoding ) )
|
||||
{
|
||||
if ( document )
|
||||
document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding );
|
||||
return 0;
|
||||
}
|
||||
@ -1539,7 +1539,7 @@ const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncodi
|
||||
|
||||
const char* end = "<";
|
||||
p = ReadText( p, &value, ignoreWhite, end, false, encoding );
|
||||
if ( p )
|
||||
if ( p && *p )
|
||||
return p-1; // don't truncate the '<'
|
||||
return 0;
|
||||
}
|
||||
|
135
external/tinyxml/xmltest.cpp
vendored
135
external/tinyxml/xmltest.cpp
vendored
@ -19,11 +19,15 @@
|
||||
|
||||
#include "tinyxml.h"
|
||||
|
||||
bool XmlTest (const char* testString, const char* expected, const char* found, bool noEcho = false);
|
||||
bool XmlTest( const char* testString, int expected, int found, bool noEcho = false );
|
||||
|
||||
static int gPass = 0;
|
||||
static int gFail = 0;
|
||||
|
||||
|
||||
bool XmlTest (const char* testString, const char* expected, const char* found, bool noEcho = false)
|
||||
|
||||
bool XmlTest (const char* testString, const char* expected, const char* found, bool noEcho )
|
||||
{
|
||||
bool pass = !strcmp( expected, found );
|
||||
if ( pass )
|
||||
@ -44,7 +48,7 @@ bool XmlTest (const char* testString, const char* expected, const char* found, b
|
||||
}
|
||||
|
||||
|
||||
bool XmlTest( const char* testString, int expected, int found, bool noEcho = false )
|
||||
bool XmlTest( const char* testString, int expected, int found, bool noEcho )
|
||||
{
|
||||
bool pass = ( expected == found );
|
||||
if ( pass )
|
||||
@ -65,6 +69,17 @@ bool XmlTest( const char* testString, int expected, int found, bool noEcho = fal
|
||||
}
|
||||
|
||||
|
||||
void NullLineEndings( char* p )
|
||||
{
|
||||
while( p && *p ) {
|
||||
if ( *p == '\n' || *p == '\r' ) {
|
||||
*p = 0;
|
||||
return;
|
||||
}
|
||||
++p;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// This file demonstrates some basic functionality of TinyXml.
|
||||
// Note that the example is very contrived. It presumes you know
|
||||
@ -74,6 +89,7 @@ bool XmlTest( const char* testString, int expected, int found, bool noEcho = fal
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
//
|
||||
// We start with the 'demoStart' todo list. Process it. And
|
||||
// should hopefully end up with the todo list as illustrated.
|
||||
@ -91,8 +107,8 @@ int main()
|
||||
{
|
||||
|
||||
#ifdef TIXML_USE_STL
|
||||
/* What the todo list should look like after processing.
|
||||
In stream (no formatting) representation. */
|
||||
// What the todo list should look like after processing.
|
||||
// In stream (no formatting) representation.
|
||||
const char* demoEnd =
|
||||
"<?xml version=\"1.0\" standalone=\"no\" ?>"
|
||||
"<!-- Our to do list data -->"
|
||||
@ -425,6 +441,30 @@ int main()
|
||||
XmlTest( "Query attribute: does not exist", result, TIXML_NO_ATTRIBUTE );
|
||||
}
|
||||
|
||||
{
|
||||
const char* str = "<doc/>";
|
||||
|
||||
TiXmlDocument doc;
|
||||
doc.Parse( str );
|
||||
|
||||
TiXmlElement* ele = doc.FirstChildElement();
|
||||
|
||||
int iVal;
|
||||
double dVal;
|
||||
|
||||
ele->SetAttribute( "str", "strValue" );
|
||||
ele->SetAttribute( "int", 1 );
|
||||
ele->SetDoubleAttribute( "double", -1.0 );
|
||||
|
||||
const char* cStr = ele->Attribute( "str" );
|
||||
ele->QueryIntAttribute( "int", &iVal );
|
||||
ele->QueryDoubleAttribute( "double", &dVal );
|
||||
|
||||
XmlTest( "Attribute round trip. c-string.", "strValue", cStr );
|
||||
XmlTest( "Attribute round trip. int.", 1, iVal );
|
||||
XmlTest( "Attribute round trip. double.", -1, (int)dVal );
|
||||
}
|
||||
|
||||
{
|
||||
const char* str = "\t<?xml version=\"1.0\" standalone=\"no\" ?>\t<room doors='2'>\n"
|
||||
"</room>";
|
||||
@ -558,20 +598,30 @@ int main()
|
||||
|
||||
FILE* saved = fopen( "utf8testout.xml", "r" );
|
||||
FILE* verify = fopen( "utf8testverify.xml", "r" );
|
||||
|
||||
//bool firstLineBOM=true;
|
||||
if ( saved && verify )
|
||||
{
|
||||
while ( fgets( verifyBuf, 256, verify ) )
|
||||
{
|
||||
fgets( savedBuf, 256, saved );
|
||||
if ( strcmp( verifyBuf, savedBuf ) )
|
||||
NullLineEndings( verifyBuf );
|
||||
NullLineEndings( savedBuf );
|
||||
|
||||
if ( /*!firstLineBOM && */ strcmp( verifyBuf, savedBuf ) )
|
||||
{
|
||||
printf( "verify:%s<\n", verifyBuf );
|
||||
printf( "saved :%s<\n", savedBuf );
|
||||
okay = 0;
|
||||
break;
|
||||
}
|
||||
//firstLineBOM = false;
|
||||
}
|
||||
}
|
||||
if ( saved )
|
||||
fclose( saved );
|
||||
if ( verify )
|
||||
fclose( verify );
|
||||
}
|
||||
XmlTest( "UTF-8: Verified multi-language round trip.", 1, okay );
|
||||
|
||||
// On most Western machines, this is an element that contains
|
||||
@ -1063,8 +1113,8 @@ int main()
|
||||
TiXmlDocument doc;
|
||||
doc.Parse( doctype );
|
||||
|
||||
XmlTest( "Parsing repeated attributes.", 0, (int)doc.Error() ); // not an error to tinyxml
|
||||
XmlTest( "Parsing repeated attributes.", "blue", doc.FirstChildElement( "element" )->Attribute( "attr" ) );
|
||||
XmlTest( "Parsing repeated attributes.", true, doc.Error() ); // is an error to tinyxml (didn't use to be, but caused issues)
|
||||
//XmlTest( "Parsing repeated attributes.", "blue", doc.FirstChildElement( "element" )->Attribute( "attr" ) );
|
||||
}
|
||||
|
||||
{
|
||||
@ -1161,19 +1211,19 @@ int main()
|
||||
int i;
|
||||
float f;
|
||||
bool b;
|
||||
//std::string str;
|
||||
std::string str;
|
||||
|
||||
XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "bar", &d ), TIXML_SUCCESS );
|
||||
XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "bar", &i ), TIXML_SUCCESS );
|
||||
XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "bar", &f ), TIXML_SUCCESS );
|
||||
XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "bar", &b ), TIXML_WRONG_TYPE );
|
||||
XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "nobar", &b ), TIXML_NO_ATTRIBUTE );
|
||||
//XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "barStr", &str ), TIXML_SUCCESS );
|
||||
XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "barStr", &str ), TIXML_SUCCESS );
|
||||
|
||||
XmlTest( "QueryValueAttribute", (d==3.0), true );
|
||||
XmlTest( "QueryValueAttribute", (i==3), true );
|
||||
XmlTest( "QueryValueAttribute", (f==3.0f), true );
|
||||
//XmlTest( "QueryValueAttribute", (str==std::string( "a string" )), true );
|
||||
XmlTest( "QueryValueAttribute", (str==std::string( "a string" )), true );
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1256,15 +1306,65 @@ int main()
|
||||
XmlTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true );
|
||||
XmlTest( "Comments ignore entities.", " far & away ", c1->Value(), true );
|
||||
}
|
||||
/*
|
||||
|
||||
{
|
||||
TiXmlDocument xml;
|
||||
xml.Parse( "<Parent>"
|
||||
"<child1 att=''/>"
|
||||
"<!-- With this comment, child2 will not be parsed! -->"
|
||||
"<child2 att=''/>"
|
||||
"</Parent>" );
|
||||
int count = 0;
|
||||
|
||||
TiXmlNode* ele = 0;
|
||||
while ( (ele = xml.FirstChildElement( "Parent" )->IterateChildren( ele ) ) != 0 ) {
|
||||
++count;
|
||||
}
|
||||
XmlTest( "Comments iterate correctly.", 3, count );
|
||||
}
|
||||
|
||||
{
|
||||
// trying to repro ]1874301]. If it doesn't go into an infinite loop, all is well.
|
||||
unsigned char buf[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed><![CDATA[Test XMLblablablalblbl";
|
||||
buf[60] = 239;
|
||||
buf[61] = 0;
|
||||
|
||||
TiXmlDocument doc;
|
||||
doc.Parse( (const char*)buf);
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
// bug 1827248 Error while parsing a little bit malformed file
|
||||
// Actually not malformed - should work.
|
||||
TiXmlDocument xml;
|
||||
xml.Parse( "<attributelist> </attributelist >" );
|
||||
XmlTest( "Handle end tag whitespace", false, xml.Error() );
|
||||
}
|
||||
|
||||
{
|
||||
// This one must not result in an infinite loop
|
||||
TiXmlDocument xml;
|
||||
xml.Parse( "<infinite>loop" );
|
||||
XmlTest( "Infinite loop test.", true, true );
|
||||
}
|
||||
|
||||
{
|
||||
// 1709904 - can not repro the crash
|
||||
{
|
||||
TiXmlDocument xml;
|
||||
xml.Parse( "<tag>/</tag>" );
|
||||
xml.Print();
|
||||
xml.FirstChild()->Print( stdout, 0 );
|
||||
xml.FirstChild()->Type();
|
||||
XmlTest( "Odd XML parsing.", xml.FirstChild()->Value(), "tag" );
|
||||
}
|
||||
/* Could not repro. {
|
||||
TiXmlDocument xml;
|
||||
xml.LoadFile( "EQUI_Inventory.xml" );
|
||||
//XmlTest( "Odd XML parsing.", xml.FirstChildElement()->Value(), "XML" );
|
||||
TiXmlPrinter printer;
|
||||
xml.Accept( &printer );
|
||||
fprintf( stdout, "%s", printer.CStr() );
|
||||
}*/
|
||||
}
|
||||
*/
|
||||
|
||||
/* 1417717 experiment
|
||||
{
|
||||
@ -1278,6 +1378,7 @@ int main()
|
||||
xml.Print(stdout);
|
||||
}
|
||||
*/
|
||||
|
||||
#if defined( WIN32 ) && defined( TUNE )
|
||||
_CrtMemCheckpoint( &endMemState );
|
||||
//_CrtMemDumpStatistics( &endMemState );
|
||||
@ -1290,5 +1391,3 @@ int main()
|
||||
printf ("\nPass %d, Fail %d\n", gPass, gFail);
|
||||
return gFail;
|
||||
}
|
||||
|
||||
|
||||
|
@ -687,11 +687,11 @@ void DataTree::setFromXML(DataNode *elem, TiXmlNode *elxml, bool root_node, DT_F
|
||||
string tmp_str;
|
||||
|
||||
switch (t) {
|
||||
case TiXmlNode::DOCUMENT:
|
||||
case TiXmlNode::TINYXML_DOCUMENT:
|
||||
// printf( "Document" );
|
||||
break;
|
||||
|
||||
case TiXmlNode::ELEMENT:
|
||||
case TiXmlNode::TINYXML_ELEMENT:
|
||||
if (!root_node)
|
||||
elem = elem->newChild(elxml->Value());
|
||||
|
||||
@ -712,15 +712,15 @@ void DataTree::setFromXML(DataNode *elem, TiXmlNode *elxml, bool root_node, DT_F
|
||||
// printf( "Element \"%s\"", elxml->Value());
|
||||
break;
|
||||
|
||||
case TiXmlNode::COMMENT:
|
||||
case TiXmlNode::TINYXML_COMMENT:
|
||||
// printf( "Comment: \"%s\"", elxml->Value());
|
||||
break;
|
||||
|
||||
case TiXmlNode::UNKNOWN:
|
||||
case TiXmlNode::TINYXML_UNKNOWN:
|
||||
// printf( "Unknown" );
|
||||
break;
|
||||
|
||||
case TiXmlNode::TEXT:
|
||||
case TiXmlNode::TINYXML_TEXT:
|
||||
pText = elxml->ToText();
|
||||
|
||||
decodeXMLText(elem, pText->Value(), fpp);
|
||||
@ -729,7 +729,7 @@ void DataTree::setFromXML(DataNode *elem, TiXmlNode *elxml, bool root_node, DT_F
|
||||
// printf( "Text: [%s]", pText->Value() );
|
||||
break;
|
||||
|
||||
case TiXmlNode::DECLARATION:
|
||||
case TiXmlNode::TINYXML_DECLARATION:
|
||||
// printf( "Declaration" );
|
||||
break;
|
||||
default:
|
||||
@ -741,7 +741,7 @@ void DataTree::setFromXML(DataNode *elem, TiXmlNode *elxml, bool root_node, DT_F
|
||||
TiXmlNode * pChild;
|
||||
|
||||
if (!elxml->NoChildren()) {
|
||||
if (elxml->FirstChild()->Type() == TiXmlNode::ELEMENT) {
|
||||
if (elxml->FirstChild()->Type() == TiXmlNode::TINYXML_ELEMENT) {
|
||||
if (elxml->FirstChild()->Value() == TIXML_STRING("str")) {
|
||||
std::vector<std::string> tmp_strvect;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user