diff --git a/src/gfx/Tilesheet.png b/src/gfx/Tilesheet.png new file mode 100644 index 0000000..fd4e471 Binary files /dev/null and b/src/gfx/Tilesheet.png differ diff --git a/src/include/SFML/include/SFML/Audio.hpp b/src/include/SFML/include/SFML/Audio.hpp new file mode 100644 index 0000000..07271ec --- /dev/null +++ b/src/include/SFML/include/SFML/Audio.hpp @@ -0,0 +1,50 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_AUDIO_HPP +#define SFML_AUDIO_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include + + +#endif // SFML_AUDIO_HPP + +//////////////////////////////////////////////////////////// +/// \defgroup audio Audio module +/// +/// Sounds, streaming (musics or custom sources), recording, +/// spatialization. +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Audio/Export.hpp b/src/include/SFML/include/SFML/Audio/Export.hpp new file mode 100644 index 0000000..7c4b6ca --- /dev/null +++ b/src/include/SFML/include/SFML/Audio/Export.hpp @@ -0,0 +1,48 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_AUDIO_EXPORT_HPP +#define SFML_AUDIO_EXPORT_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +//////////////////////////////////////////////////////////// +// Define portable import / export macros +//////////////////////////////////////////////////////////// +#if defined(SFML_AUDIO_EXPORTS) + + #define SFML_AUDIO_API SFML_API_EXPORT + +#else + + #define SFML_AUDIO_API SFML_API_IMPORT + +#endif + + +#endif // SFML_AUDIO_EXPORT_HPP diff --git a/src/include/SFML/include/SFML/Audio/Listener.hpp b/src/include/SFML/include/SFML/Audio/Listener.hpp new file mode 100644 index 0000000..b371737 --- /dev/null +++ b/src/include/SFML/include/SFML/Audio/Listener.hpp @@ -0,0 +1,184 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_LISTENER_HPP +#define SFML_LISTENER_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief The audio listener is the point in the scene +/// from where all the sounds are heard +/// +//////////////////////////////////////////////////////////// +class SFML_AUDIO_API Listener +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Change the global volume of all the sounds and musics + /// + /// The volume is a number between 0 and 100; it is combined with + /// the individual volume of each sound / music. + /// The default value for the volume is 100 (maximum). + /// + /// \param volume New global volume, in the range [0, 100] + /// + /// \see getGlobalVolume + /// + //////////////////////////////////////////////////////////// + static void setGlobalVolume(float volume); + + //////////////////////////////////////////////////////////// + /// \brief Get the current value of the global volume + /// + /// \return Current global volume, in the range [0, 100] + /// + /// \see setGlobalVolume + /// + //////////////////////////////////////////////////////////// + static float getGlobalVolume(); + + //////////////////////////////////////////////////////////// + /// \brief Set the position of the listener in the scene + /// + /// The default listener's position is (0, 0, 0). + /// + /// \param x X coordinate of the listener's position + /// \param y Y coordinate of the listener's position + /// \param z Z coordinate of the listener's position + /// + /// \see getPosition, setDirection + /// + //////////////////////////////////////////////////////////// + static void setPosition(float x, float y, float z); + + //////////////////////////////////////////////////////////// + /// \brief Set the position of the listener in the scene + /// + /// The default listener's position is (0, 0, 0). + /// + /// \param position New listener's position + /// + /// \see getPosition, setDirection + /// + //////////////////////////////////////////////////////////// + static void setPosition(const Vector3f& position); + + //////////////////////////////////////////////////////////// + /// \brief Get the current position of the listener in the scene + /// + /// \return Listener's position + /// + /// \see setPosition + /// + //////////////////////////////////////////////////////////// + static Vector3f getPosition(); + + //////////////////////////////////////////////////////////// + /// \brief Set the orientation of the listener in the scene + /// + /// The orientation defines the 3D axes of the listener + /// (left, up, front) in the scene. The orientation vector + /// doesn't have to be normalized. + /// The default listener's orientation is (0, 0, -1). + /// + /// \param x X coordinate of the listener's orientation + /// \param y Y coordinate of the listener's orientation + /// \param z Z coordinate of the listener's orientation + /// + /// \see getDirection, setPosition + /// + //////////////////////////////////////////////////////////// + static void setDirection(float x, float y, float z); + + //////////////////////////////////////////////////////////// + /// \brief Set the orientation of the listener in the scene + /// + /// The orientation defines the 3D axes of the listener + /// (left, up, front) in the scene. The orientation vector + /// doesn't have to be normalized. + /// The default listener's orientation is (0, 0, -1). + /// + /// \param direction New listener's orientation + /// + /// \see getDirection, setPosition + /// + //////////////////////////////////////////////////////////// + static void setDirection(const Vector3f& direction); + + //////////////////////////////////////////////////////////// + /// \brief Get the current orientation of the listener in the scene + /// + /// \return Listener's orientation + /// + /// \see setDirection + /// + //////////////////////////////////////////////////////////// + static Vector3f getDirection(); +}; + +} // namespace sf + + +#endif // SFML_LISTENER_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Listener +/// \ingroup audio +/// +/// The audio listener defines the global properties of the +/// audio environment, it defines where and how sounds and musics +/// are heard. If sf::View is the eyes of the user, then sf::Listener +/// is his ears (by the way, they are often linked together -- +/// same position, orientation, etc.). +/// +/// sf::Listener is a simple interface, which allows to setup the +/// listener in the 3D audio environment (position and direction), +/// and to adjust the global volume. +/// +/// Because the listener is unique in the scene, sf::Listener only +/// contains static functions and doesn't have to be instanciated. +/// +/// Usage example: +/// \code +/// // Move the listener to the position (1, 0, -5) +/// sf::Listener::setPosition(1, 0, -5); +/// +/// // Make it face the right axis (1, 0, 0) +/// sf::Listener::setDirection(1, 0, 0); +/// +/// // Reduce the global volume +/// sf::Listener::setGlobalVolume(50); +/// \endcode +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Audio/Music.hpp b/src/include/SFML/include/SFML/Audio/Music.hpp new file mode 100644 index 0000000..26125fd --- /dev/null +++ b/src/include/SFML/include/SFML/Audio/Music.hpp @@ -0,0 +1,228 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_MUSIC_HPP +#define SFML_MUSIC_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include + + +namespace sf +{ +namespace priv +{ + class SoundFile; +} + +class InputStream; + +//////////////////////////////////////////////////////////// +/// \brief Streamed music played from an audio file +/// +//////////////////////////////////////////////////////////// +class SFML_AUDIO_API Music : public SoundStream +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + Music(); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~Music(); + + //////////////////////////////////////////////////////////// + /// \brief Open a music from an audio file + /// + /// This function doesn't start playing the music (call play() + /// to do so). + /// Here is a complete list of all the supported audio formats: + /// ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam, + /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. + /// + /// \param filename Path of the music file to open + /// + /// \return True if loading succeeded, false if it failed + /// + /// \see openFromMemory, openFromStream + /// + //////////////////////////////////////////////////////////// + bool openFromFile(const std::string& filename); + + //////////////////////////////////////////////////////////// + /// \brief Open a music from an audio file in memory + /// + /// This function doesn't start playing the music (call play() + /// to do so). + /// Here is a complete list of all the supported audio formats: + /// ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam, + /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. + /// Since the music is not loaded completely but rather streamed + /// continuously, the \a data must remain available as long as the + /// music is playing (ie. you can't deallocate it right after calling + /// this function). + /// + /// \param data Pointer to the file data in memory + /// \param sizeInBytes Size of the data to load, in bytes + /// + /// \return True if loading succeeded, false if it failed + /// + /// \see openFromFile, openFromStream + /// + //////////////////////////////////////////////////////////// + bool openFromMemory(const void* data, std::size_t sizeInBytes); + + //////////////////////////////////////////////////////////// + /// \brief Open a music from an audio file in a custom stream + /// + /// This function doesn't start playing the music (call play() + /// to do so). + /// Here is a complete list of all the supported audio formats: + /// ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam, + /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. + /// Since the music is not loaded completely but rather streamed + /// continuously, the \a stream must remain alive as long as the + /// music is playing (ie. you can't destroy it right after calling + /// this function). + /// + /// \param stream Source stream to read from + /// + /// \return True if loading succeeded, false if it failed + /// + /// \see openFromFile, openFromMemory + /// + //////////////////////////////////////////////////////////// + bool openFromStream(InputStream& stream); + + //////////////////////////////////////////////////////////// + /// \brief Get the total duration of the music + /// + /// \return Music duration + /// + //////////////////////////////////////////////////////////// + Time getDuration() const; + +protected : + + //////////////////////////////////////////////////////////// + /// \brief Request a new chunk of audio samples from the stream source + /// + /// This function fills the chunk from the next samples + /// to read from the audio file. + /// + /// \param data Chunk of data to fill + /// + /// \return True to continue playback, false to stop + /// + //////////////////////////////////////////////////////////// + virtual bool onGetData(Chunk& data); + + //////////////////////////////////////////////////////////// + /// \brief Change the current playing position in the stream source + /// + /// \param timeOffset New playing position, from the beginning of the music + /// + //////////////////////////////////////////////////////////// + virtual void onSeek(Time timeOffset); + +private : + + //////////////////////////////////////////////////////////// + /// \brief Initialize the internal state after loading a new music + /// + //////////////////////////////////////////////////////////// + void initialize(); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + priv::SoundFile* m_file; ///< Sound file + Time m_duration; ///< Music duration + std::vector m_samples; ///< Temporary buffer of samples + Mutex m_mutex; ///< Mutex protecting the data +}; + +} // namespace sf + + +#endif // SFML_MUSIC_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Music +/// \ingroup audio +/// +/// Musics are sounds that are streamed rather than completely +/// loaded in memory. This is especially useful for compressed +/// musics that usually take hundreds of MB when they are +/// uncompressed: by streaming it instead of loading it entirely, +/// you avoid saturating the memory and have almost no loading delay. +/// +/// Apart from that, a sf::Music has almost the same features as +/// the sf::SoundBuffer / sf::Sound pair: you can play/pause/stop +/// it, request its parameters (channels, sample rate), change +/// the way it is played (pitch, volume, 3D position, ...), etc. +/// +/// As a sound stream, a music is played in its own thread in order +/// not to block the rest of the program. This means that you can +/// leave the music alone after calling play(), it will manage itself +/// very well. +/// +/// Usage example: +/// \code +/// // Declare a new music +/// sf::Music music; +/// +/// // Open it from an audio file +/// if (!music.openFromFile("music.ogg")) +/// { +/// // error... +/// } +/// +/// // Change some parameters +/// music.setPosition(0, 1, 10); // change its 3D position +/// music.setPitch(2); // increase the pitch +/// music.setVolume(50); // reduce the volume +/// music.setLoop(true); // make it loop +/// +/// // Play it +/// music.play(); +/// \endcode +/// +/// \see sf::Sound, sf::SoundStream +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Audio/Sound.hpp b/src/include/SFML/include/SFML/Audio/Sound.hpp new file mode 100644 index 0000000..789819f --- /dev/null +++ b/src/include/SFML/include/SFML/Audio/Sound.hpp @@ -0,0 +1,262 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SOUND_HPP +#define SFML_SOUND_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include + + +namespace sf +{ +class SoundBuffer; + +//////////////////////////////////////////////////////////// +/// \brief Regular sound that can be played in the audio environment +/// +//////////////////////////////////////////////////////////// +class SFML_AUDIO_API Sound : public SoundSource +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + Sound(); + + //////////////////////////////////////////////////////////// + /// \brief Construct the sound with a buffer + /// + /// \param buffer Sound buffer containing the audio data to play with the sound + /// + //////////////////////////////////////////////////////////// + explicit Sound(const SoundBuffer& buffer); + + //////////////////////////////////////////////////////////// + /// \brief Copy constructor + /// + /// \param copy Instance to copy + /// + //////////////////////////////////////////////////////////// + Sound(const Sound& copy); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~Sound(); + + //////////////////////////////////////////////////////////// + /// \brief Start or resume playing the sound + /// + /// This function starts the stream if it was stopped, resumes + /// it if it was paused, and restarts it from beginning if it + /// was it already playing. + /// This function uses its own thread so that it doesn't block + /// the rest of the program while the sound is played. + /// + /// \see pause, stop + /// + //////////////////////////////////////////////////////////// + void play(); + + //////////////////////////////////////////////////////////// + /// \brief Pause the sound + /// + /// This function pauses the sound if it was playing, + /// otherwise (sound already paused or stopped) it has no effect. + /// + /// \see play, stop + /// + //////////////////////////////////////////////////////////// + void pause(); + + //////////////////////////////////////////////////////////// + /// \brief stop playing the sound + /// + /// This function stops the sound if it was playing or paused, + /// and does nothing if it was already stopped. + /// It also resets the playing position (unlike pause()). + /// + /// \see play, pause + /// + //////////////////////////////////////////////////////////// + void stop(); + + //////////////////////////////////////////////////////////// + /// \brief Set the source buffer containing the audio data to play + /// + /// It is important to note that the sound buffer is not copied, + /// thus the sf::SoundBuffer instance must remain alive as long + /// as it is attached to the sound. + /// + /// \param buffer Sound buffer to attach to the sound + /// + /// \see getBuffer + /// + //////////////////////////////////////////////////////////// + void setBuffer(const SoundBuffer& buffer); + + //////////////////////////////////////////////////////////// + /// \brief Set whether or not the sound should loop after reaching the end + /// + /// If set, the sound will restart from beginning after + /// reaching the end and so on, until it is stopped or + /// setLoop(false) is called. + /// The default looping state for sound is false. + /// + /// \param loop True to play in loop, false to play once + /// + /// \see getLoop + /// + //////////////////////////////////////////////////////////// + void setLoop(bool loop); + + //////////////////////////////////////////////////////////// + /// \brief Change the current playing position of the sound + /// + /// The playing position can be changed when the sound is + /// either paused or playing. + /// + /// \param timeOffset New playing position, from the beginning of the sound + /// + /// \see getPlayingOffset + /// + //////////////////////////////////////////////////////////// + void setPlayingOffset(Time timeOffset); + + //////////////////////////////////////////////////////////// + /// \brief Get the audio buffer attached to the sound + /// + /// \return Sound buffer attached to the sound (can be NULL) + /// + //////////////////////////////////////////////////////////// + const SoundBuffer* getBuffer() const; + + //////////////////////////////////////////////////////////// + /// \brief Tell whether or not the sound is in loop mode + /// + /// \return True if the sound is looping, false otherwise + /// + /// \see setLoop + /// + //////////////////////////////////////////////////////////// + bool getLoop() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the current playing position of the sound + /// + /// \return Current playing position, from the beginning of the sound + /// + /// \see setPlayingOffset + /// + //////////////////////////////////////////////////////////// + Time getPlayingOffset() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the current status of the sound (stopped, paused, playing) + /// + /// \return Current status of the sound + /// + //////////////////////////////////////////////////////////// + Status getStatus() const; + + //////////////////////////////////////////////////////////// + /// \brief Overload of assignment operator + /// + /// \param right Instance to assign + /// + /// \return Reference to self + /// + //////////////////////////////////////////////////////////// + Sound& operator =(const Sound& right); + + //////////////////////////////////////////////////////////// + /// \brief Reset the internal buffer of the sound + /// + /// This function is for internal use only, you don't have + /// to use it. It is called by the sf::SoundBuffer that + /// this sound uses, when it is destroyed in order to prevent + /// the sound from using a dead buffer. + /// + //////////////////////////////////////////////////////////// + void resetBuffer(); + +private : + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + const SoundBuffer* m_buffer; ///< Sound buffer bound to the source +}; + +} // namespace sf + + +#endif // SFML_SOUND_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Sound +/// \ingroup audio +/// +/// sf::Sound is the class to use to play sounds. +/// It provides: +/// \li Control (play, pause, stop) +/// \li Ability to modify output parameters in real-time (pitch, volume, ...) +/// \li 3D spatial features (position, attenuation, ...). +/// +/// sf::Sound is perfect for playing short sounds that can +/// fit in memory and require no latency, like foot steps or +/// gun shots. For longer sounds, like background musics +/// or long speeches, rather see sf::Music (which is based +/// on streaming). +/// +/// In order to work, a sound must be given a buffer of audio +/// data to play. Audio data (samples) is stored in sf::SoundBuffer, +/// and attached to a sound with the setBuffer() function. +/// The buffer object attached to a sound must remain alive +/// as long as the sound uses it. Note that multiple sounds +/// can use the same sound buffer at the same time. +/// +/// Usage example: +/// \code +/// sf::SoundBuffer buffer; +/// buffer.loadFromFile("sound.wav"); +/// +/// sf::Sound sound; +/// sound.setBuffer(buffer); +/// sound.play(); +/// \endcode +/// +/// \see sf::SoundBuffer, sf::Music +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Audio/SoundBuffer.hpp b/src/include/SFML/include/SFML/Audio/SoundBuffer.hpp new file mode 100644 index 0000000..e00e2c6 --- /dev/null +++ b/src/include/SFML/include/SFML/Audio/SoundBuffer.hpp @@ -0,0 +1,359 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SOUNDBUFFER_HPP +#define SFML_SOUNDBUFFER_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include + + +namespace sf +{ +namespace priv +{ + class SoundFile; +} + +class Sound; +class InputStream; + +//////////////////////////////////////////////////////////// +/// \brief Storage for audio samples defining a sound +/// +//////////////////////////////////////////////////////////// +class SFML_AUDIO_API SoundBuffer +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + SoundBuffer(); + + //////////////////////////////////////////////////////////// + /// \brief Copy constructor + /// + /// \param copy Instance to copy + /// + //////////////////////////////////////////////////////////// + SoundBuffer(const SoundBuffer& copy); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~SoundBuffer(); + + //////////////////////////////////////////////////////////// + /// \brief Load the sound buffer from a file + /// + /// Here is a complete list of all the supported audio formats: + /// ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam, + /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. + /// + /// \param filename Path of the sound file to load + /// + /// \return True if loading succeeded, false if it failed + /// + /// \see loadFromMemory, loadFromStream, loadFromSamples, saveToFile + /// + //////////////////////////////////////////////////////////// + bool loadFromFile(const std::string& filename); + + //////////////////////////////////////////////////////////// + /// \brief Load the sound buffer from a file in memory + /// + /// Here is a complete list of all the supported audio formats: + /// ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam, + /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. + /// + /// \param data Pointer to the file data in memory + /// \param sizeInBytes Size of the data to load, in bytes + /// + /// \return True if loading succeeded, false if it failed + /// + /// \see loadFromFile, loadFromStream, loadFromSamples + /// + //////////////////////////////////////////////////////////// + bool loadFromMemory(const void* data, std::size_t sizeInBytes); + + //////////////////////////////////////////////////////////// + /// \brief Load the sound buffer from a custom stream + /// + /// Here is a complete list of all the supported audio formats: + /// ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam, + /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. + /// + /// \param stream Source stream to read from + /// + /// \return True if loading succeeded, false if it failed + /// + /// \see loadFromFile, loadFromMemory, loadFromSamples + /// + //////////////////////////////////////////////////////////// + bool loadFromStream(InputStream& stream); + + //////////////////////////////////////////////////////////// + /// \brief Load the sound buffer from an array of audio samples + /// + /// The assumed format of the audio samples is 16 bits signed integer + /// (sf::Int16). + /// + /// \param samples Pointer to the array of samples in memory + /// \param sampleCount Number of samples in the array + /// \param channelCount Number of channels (1 = mono, 2 = stereo, ...) + /// \param sampleRate Sample rate (number of samples to play per second) + /// + /// \return True if loading succeeded, false if it failed + /// + /// \see loadFromFile, loadFromMemory, saveToFile + /// + //////////////////////////////////////////////////////////// + bool loadFromSamples(const Int16* samples, std::size_t sampleCount, unsigned int channelCount, unsigned int sampleRate); + + //////////////////////////////////////////////////////////// + /// \brief Save the sound buffer to an audio file + /// + /// Here is a complete list of all the supported audio formats: + /// ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam, + /// w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64. + /// + /// \param filename Path of the sound file to write + /// + /// \return True if saving succeeded, false if it failed + /// + /// \see loadFromFile, loadFromMemory, loadFromSamples + /// + //////////////////////////////////////////////////////////// + bool saveToFile(const std::string& filename) const; + + //////////////////////////////////////////////////////////// + /// \brief Get the array of audio samples stored in the buffer + /// + /// The format of the returned samples is 16 bits signed integer + /// (sf::Int16). The total number of samples in this array + /// is given by the getSampleCount() function. + /// + /// \return Read-only pointer to the array of sound samples + /// + /// \see getSampleCount + /// + //////////////////////////////////////////////////////////// + const Int16* getSamples() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the number of samples stored in the buffer + /// + /// The array of samples can be accessed with the getSamples() + /// function. + /// + /// \return Number of samples + /// + /// \see getSamples + /// + //////////////////////////////////////////////////////////// + std::size_t getSampleCount() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the sample rate of the sound + /// + /// The sample rate is the number of samples played per second. + /// The higher, the better the quality (for example, 44100 + /// samples/s is CD quality). + /// + /// \return Sample rate (number of samples per second) + /// + /// \see getChannelCount, getDuration + /// + //////////////////////////////////////////////////////////// + unsigned int getSampleRate() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the number of channels used by the sound + /// + /// If the sound is mono then the number of channels will + /// be 1, 2 for stereo, etc. + /// + /// \return Number of channels + /// + /// \see getSampleRate, getDuration + /// + //////////////////////////////////////////////////////////// + unsigned int getChannelCount() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the total duration of the sound + /// + /// \return Sound duration + /// + /// \see getSampleRate, getChannelCount + /// + //////////////////////////////////////////////////////////// + Time getDuration() const; + + //////////////////////////////////////////////////////////// + /// \brief Overload of assignment operator + /// + /// \param right Instance to assign + /// + /// \return Reference to self + /// + //////////////////////////////////////////////////////////// + SoundBuffer& operator =(const SoundBuffer& right); + +private : + + friend class Sound; + + //////////////////////////////////////////////////////////// + /// \brief Initialize the internal state after loading a new sound + /// + /// \param file Sound file providing access to the new loaded sound + /// + /// \return True on succesful initialization, false on failure + /// + //////////////////////////////////////////////////////////// + bool initialize(priv::SoundFile& file); + + //////////////////////////////////////////////////////////// + /// \brief Update the internal buffer with the cached audio samples + /// + /// \param channelCount Number of channels + /// \param sampleRate Sample rate (number of samples per second) + /// + /// \return True on success, false if any error happened + /// + //////////////////////////////////////////////////////////// + bool update(unsigned int channelCount, unsigned int sampleRate); + + //////////////////////////////////////////////////////////// + /// \brief Add a sound to the list of sounds that use this buffer + /// + /// \param sound Sound instance to attach + /// + //////////////////////////////////////////////////////////// + void attachSound(Sound* sound) const; + + //////////////////////////////////////////////////////////// + /// \brief Remove a sound from the list of sounds that use this buffer + /// + /// \param sound Sound instance to detach + /// + //////////////////////////////////////////////////////////// + void detachSound(Sound* sound) const; + + //////////////////////////////////////////////////////////// + // Types + //////////////////////////////////////////////////////////// + typedef std::set SoundList; ///< Set of unique sound instances + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + unsigned int m_buffer; ///< OpenAL buffer identifier + std::vector m_samples; ///< Samples buffer + Time m_duration; ///< Sound duration + mutable SoundList m_sounds; ///< List of sounds that are using this buffer +}; + +} // namespace sf + + +#endif // SFML_SOUNDBUFFER_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::SoundBuffer +/// \ingroup audio +/// +/// A sound buffer holds the data of a sound, which is +/// an array of audio samples. A sample is a 16 bits signed integer +/// that defines the amplitude of the sound at a given time. +/// The sound is then restituted by playing these samples at +/// a high rate (for example, 44100 samples per second is the +/// standard rate used for playing CDs). In short, audio samples +/// are like texture pixels, and a sf::SoundBuffer is similar to +/// a sf::Texture. +/// +/// A sound buffer can be loaded from a file (see loadFromFile() +/// for the complete list of supported formats), from memory, from +/// a custom stream (see sf::InputStream) or directly from an array +/// of samples. It can also be saved back to a file. +/// +/// Sound buffers alone are not very useful: they hold the audio data +/// but cannot be played. To do so, you need to use the sf::Sound class, +/// which provides functions to play/pause/stop the sound as well as +/// changing the way it is outputted (volume, pitch, 3D position, ...). +/// This separation allows more flexibility and better performances: +/// indeed a sf::SoundBuffer is a heavy resource, and any operation on it +/// is slow (often too slow for real-time applications). On the other +/// side, a sf::Sound is a lightweight object, which can use the audio data +/// of a sound buffer and change the way it is played without actually +/// modifying that data. Note that it is also possible to bind +/// several sf::Sound instances to the same sf::SoundBuffer. +/// +/// It is important to note that the sf::Sound instance doesn't +/// copy the buffer that it uses, it only keeps a reference to it. +/// Thus, a sf::SoundBuffer must not be destructed while it is +/// used by a sf::Sound (i.e. never write a function that +/// uses a local sf::SoundBuffer instance for loading a sound). +/// +/// Usage example: +/// \code +/// // Declare a new sound buffer +/// sf::SoundBuffer buffer; +/// +/// // Load it from a file +/// if (!buffer.loadFromFile("sound.wav")) +/// { +/// // error... +/// } +/// +/// // Create a sound source and bind it to the buffer +/// sf::Sound sound1; +/// sound1.setBuffer(buffer); +/// +/// // Play the sound +/// sound1.play(); +/// +/// // Create another sound source bound to the same buffer +/// sf::Sound sound2; +/// sound2.setBuffer(buffer); +/// +/// // Play it with a higher pitch -- the first sound remains unchanged +/// sound2.setPitch(2); +/// sound2.play(); +/// \endcode +/// +/// \see sf::Sound, sf::SoundBufferRecorder +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Audio/SoundBufferRecorder.hpp b/src/include/SFML/include/SFML/Audio/SoundBufferRecorder.hpp new file mode 100644 index 0000000..65f0d99 --- /dev/null +++ b/src/include/SFML/include/SFML/Audio/SoundBufferRecorder.hpp @@ -0,0 +1,138 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SOUNDBUFFERRECORDER_HPP +#define SFML_SOUNDBUFFERRECORDER_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Specialized SoundRecorder which stores the captured +/// audio data into a sound buffer +/// +//////////////////////////////////////////////////////////// +class SFML_AUDIO_API SoundBufferRecorder : public SoundRecorder +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Get the sound buffer containing the captured audio data + /// + /// The sound buffer is valid only after the capture has ended. + /// This function provides a read-only access to the internal + /// sound buffer, but it can be copied if you need to + /// make any modification to it. + /// + /// \return Read-only access to the sound buffer + /// + //////////////////////////////////////////////////////////// + const SoundBuffer& getBuffer() const; + +protected: + + //////////////////////////////////////////////////////////// + /// \brief Start capturing audio data + /// + /// \return True to start the capture, or false to abort it + /// + //////////////////////////////////////////////////////////// + virtual bool onStart(); + + //////////////////////////////////////////////////////////// + /// \brief Process a new chunk of recorded samples + /// + /// \param samples Pointer to the new chunk of recorded samples + /// \param sampleCount Number of samples pointed by \a samples + /// + /// \return True to continue the capture, or false to stop it + /// + //////////////////////////////////////////////////////////// + virtual bool onProcessSamples(const Int16* samples, std::size_t sampleCount); + + //////////////////////////////////////////////////////////// + /// \brief Stop capturing audio data + /// + //////////////////////////////////////////////////////////// + virtual void onStop(); + +private : + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + std::vector m_samples; ///< Temporary sample buffer to hold the recorded data + SoundBuffer m_buffer; ///< Sound buffer that will contain the recorded data +}; + +} // namespace sf + +#endif // SFML_SOUNDBUFFERRECORDER_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::SoundBufferRecorder +/// \ingroup audio +/// +/// sf::SoundBufferRecorder allows to access a recorded sound +/// through a sf::SoundBuffer, so that it can be played, saved +/// to a file, etc. +/// +/// It has the same simple interface as its base class (start(), stop()) +/// and adds a function to retrieve the recorded sound buffer +/// (getBuffer()). +/// +/// As usual, don't forget to call the isAvailable() function +/// before using this class (see sf::SoundRecorder for more details +/// about this). +/// +/// Usage example: +/// \code +/// if (sf::SoundBufferRecorder::isAvailable()) +/// { +/// // Record some audio data +/// sf::SoundBufferRecorder recorder; +/// recorder.start(); +/// ... +/// recorder.stop(); +/// +/// // Get the buffer containing the captured audio data +/// const sf::SoundBuffer& buffer = recorder.getBuffer(); +/// +/// // Save it to a file (for example...) +/// buffer.saveToFile("my_record.ogg"); +/// } +/// \endcode +/// +/// \see sf::SoundRecorder +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Audio/SoundRecorder.hpp b/src/include/SFML/include/SFML/Audio/SoundRecorder.hpp new file mode 100644 index 0000000..45550fe --- /dev/null +++ b/src/include/SFML/include/SFML/Audio/SoundRecorder.hpp @@ -0,0 +1,270 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SOUNDRECORDER_HPP +#define SFML_SOUNDRECORDER_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Abstract base class for capturing sound data +/// +//////////////////////////////////////////////////////////// +class SFML_AUDIO_API SoundRecorder +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief destructor + /// + //////////////////////////////////////////////////////////// + virtual ~SoundRecorder(); + + //////////////////////////////////////////////////////////// + /// \brief Start the capture + /// + /// The \a sampleRate parameter defines the number of audio samples + /// captured per second. The higher, the better the quality + /// (for example, 44100 samples/sec is CD quality). + /// This function uses its own thread so that it doesn't block + /// the rest of the program while the capture runs. + /// Please note that only one capture can happen at the same time. + /// + /// \param sampleRate Desired capture rate, in number of samples per second + /// + /// \see stop + /// + //////////////////////////////////////////////////////////// + void start(unsigned int sampleRate = 44100); + + //////////////////////////////////////////////////////////// + /// \brief Stop the capture + /// + /// \see start + /// + //////////////////////////////////////////////////////////// + void stop(); + + //////////////////////////////////////////////////////////// + /// \brief Get the sample rate + /// + /// The sample rate defines the number of audio samples + /// captured per second. The higher, the better the quality + /// (for example, 44100 samples/sec is CD quality). + /// + /// \return Sample rate, in samples per second + /// + //////////////////////////////////////////////////////////// + unsigned int getSampleRate() const; + + //////////////////////////////////////////////////////////// + /// \brief Check if the system supports audio capture + /// + /// This function should always be called before using + /// the audio capture features. If it returns false, then + /// any attempt to use sf::SoundRecorder or one of its derived + /// classes will fail. + /// + /// \return True if audio capture is supported, false otherwise + /// + //////////////////////////////////////////////////////////// + static bool isAvailable(); + +protected : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// This constructor is only meant to be called by derived classes. + /// + //////////////////////////////////////////////////////////// + SoundRecorder(); + + //////////////////////////////////////////////////////////// + /// \brief Start capturing audio data + /// + /// This virtual function may be overriden by a derived class + /// if something has to be done every time a new capture + /// starts. If not, this function can be ignored; the default + /// implementation does nothing. + /// + /// \return True to start the capture, or false to abort it + /// + //////////////////////////////////////////////////////////// + virtual bool onStart(); + + //////////////////////////////////////////////////////////// + /// \brief Process a new chunk of recorded samples + /// + /// This virtual function is called every time a new chunk of + /// recorded data is available. The derived class can then do + /// whatever it wants with it (storing it, playing it, sending + /// it over the network, etc.). + /// + /// \param samples Pointer to the new chunk of recorded samples + /// \param sampleCount Number of samples pointed by \a samples + /// + /// \return True to continue the capture, or false to stop it + /// + //////////////////////////////////////////////////////////// + virtual bool onProcessSamples(const Int16* samples, std::size_t sampleCount) = 0; + + //////////////////////////////////////////////////////////// + /// \brief Stop capturing audio data + /// + /// This virtual function may be overriden by a derived class + /// if something has to be done every time the capture + /// ends. If not, this function can be ignored; the default + /// implementation does nothing. + /// + //////////////////////////////////////////////////////////// + virtual void onStop(); + +private : + + //////////////////////////////////////////////////////////// + /// \brief Function called as the entry point of the thread + /// + /// This function starts the recording loop, and returns + /// only when the capture is stopped. + /// + //////////////////////////////////////////////////////////// + void record(); + + //////////////////////////////////////////////////////////// + /// \brief Get the new available audio samples and process them + /// + /// This function is called continuously during the + /// capture loop. It retrieves the captured samples and + /// forwards them to the derived class. + /// + //////////////////////////////////////////////////////////// + void processCapturedSamples(); + + //////////////////////////////////////////////////////////// + /// \brief Clean up the recorder's internal resources + /// + /// This function is called when the capture stops. + /// + //////////////////////////////////////////////////////////// + void cleanup(); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + Thread m_thread; ///< Thread running the background recording task + std::vector m_samples; ///< Buffer to store captured samples + unsigned int m_sampleRate; ///< Sample rate + bool m_isCapturing; ///< Capturing state +}; + +} // namespace sf + + +#endif // SFML_SOUNDRECORDER_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::SoundRecorder +/// \ingroup audio +/// +/// sf::SoundBuffer provides a simple interface to access +/// the audio recording capabilities of the computer +/// (the microphone). As an abstract base class, it only cares +/// about capturing sound samples, the task of making something +/// useful with them is left to the derived class. Note that +/// SFML provides a built-in specialization for saving the +/// captured data to a sound buffer (see sf::SoundBufferRecorder). +/// +/// A derived class has only one virtual function to override: +/// \li onProcessSamples provides the new chunks of audio samples while the capture happens +/// +/// Moreover, two additionnal virtual functions can be overriden +/// as well if necessary: +/// \li onStart is called before the capture happens, to perform custom initializations +/// \li onStop is called after the capture ends, to perform custom cleanup +/// +/// The audio capture feature may not be supported or activated +/// on every platform, thus it is recommended to check its +/// availability with the isAvailable() function. If it returns +/// false, then any attempt to use an audio recorder will fail. +/// +/// It is important to note that the audio capture happens in a +/// separate thread, so that it doesn't block the rest of the +/// program. In particular, the onProcessSamples and onStop +/// virtual functions (but not onStart) will be called +/// from this separate thread. It is important to keep this in +/// mind, because you may have to take care of synchronization +/// issues if you share data between threads. +/// +/// Usage example: +/// \code +/// class CustomRecorder : public sf::SoundRecorder +/// { +/// virtual bool onStart() // optional +/// { +/// // Initialize whatever has to be done before the capture starts +/// ... +/// +/// // Return true to start playing +/// return true; +/// } +/// +/// virtual bool onProcessSamples(const Int16* samples, std::size_t sampleCount) +/// { +/// // Do something with the new chunk of samples (store them, send them, ...) +/// ... +/// +/// // Return true to continue playing +/// return true; +/// } +/// +/// virtual void onStop() // optional +/// { +/// // Clean up whatever has to be done after the capture ends +/// ... +/// } +/// } +/// +/// // Usage +/// if (CustomRecorder::isAvailable()) +/// { +/// CustomRecorder recorder; +/// recorder.start(); +/// ... +/// recorder.stop(); +/// } +/// \endcode +/// +/// \see sf::SoundBufferRecorder +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Audio/SoundSource.hpp b/src/include/SFML/include/SFML/Audio/SoundSource.hpp new file mode 100644 index 0000000..b2a42b2 --- /dev/null +++ b/src/include/SFML/include/SFML/Audio/SoundSource.hpp @@ -0,0 +1,286 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SOUNDSOURCE_HPP +#define SFML_SOUNDSOURCE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Base class defining a sound's properties +/// +//////////////////////////////////////////////////////////// +class SFML_AUDIO_API SoundSource +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Enumeration of the sound source states + /// + //////////////////////////////////////////////////////////// + enum Status + { + Stopped, ///< Sound is not playing + Paused, ///< Sound is paused + Playing ///< Sound is playing + }; + + //////////////////////////////////////////////////////////// + /// \brief Copy constructor + /// + /// \param copy Instance to copy + /// + //////////////////////////////////////////////////////////// + SoundSource(const SoundSource& copy); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + virtual ~SoundSource(); + + //////////////////////////////////////////////////////////// + /// \brief Set the pitch of the sound + /// + /// The pitch represents the perceived fundamental frequency + /// of a sound; thus you can make a sound more acute or grave + /// by changing its pitch. A side effect of changing the pitch + /// is to modify the playing speed of the sound as well. + /// The default value for the pitch is 1. + /// + /// \param pitch New pitch to apply to the sound + /// + /// \see getPitch + /// + //////////////////////////////////////////////////////////// + void setPitch(float pitch); + + //////////////////////////////////////////////////////////// + /// \brief Set the volume of the sound + /// + /// The volume is a value between 0 (mute) and 100 (full volume). + /// The default value for the volume is 100. + /// + /// \param volume Volume of the sound + /// + /// \see getVolume + /// + //////////////////////////////////////////////////////////// + void setVolume(float volume); + + //////////////////////////////////////////////////////////// + /// \brief Set the 3D position of the sound in the audio scene + /// + /// Only sounds with one channel (mono sounds) can be + /// spatialized. + /// The default position of a sound is (0, 0, 0). + /// + /// \param x X coordinate of the position of the sound in the scene + /// \param y Y coordinate of the position of the sound in the scene + /// \param z Z coordinate of the position of the sound in the scene + /// + /// \see getPosition + /// + //////////////////////////////////////////////////////////// + void setPosition(float x, float y, float z); + + //////////////////////////////////////////////////////////// + /// \brief Set the 3D position of the sound in the audio scene + /// + /// Only sounds with one channel (mono sounds) can be + /// spatialized. + /// The default position of a sound is (0, 0, 0). + /// + /// \param position Position of the sound in the scene + /// + /// \see getPosition + /// + //////////////////////////////////////////////////////////// + void setPosition(const Vector3f& position); + + //////////////////////////////////////////////////////////// + /// \brief Make the sound's position relative to the listener or absolute + /// + /// Making a sound relative to the listener will ensure that it will always + /// be played the same way regardless the position of the listener. + /// This can be useful for non-spatialized sounds, sounds that are + /// produced by the listener, or sounds attached to it. + /// The default value is false (position is absolute). + /// + /// \param relative True to set the position relative, false to set it absolute + /// + /// \see isRelativeToListener + /// + //////////////////////////////////////////////////////////// + void setRelativeToListener(bool relative); + + //////////////////////////////////////////////////////////// + /// \brief Set the minimum distance of the sound + /// + /// The "minimum distance" of a sound is the maximum + /// distance at which it is heard at its maximum volume. Further + /// than the minimum distance, it will start to fade out according + /// to its attenuation factor. A value of 0 ("inside the head + /// of the listener") is an invalid value and is forbidden. + /// The default value of the minimum distance is 1. + /// + /// \param distance New minimum distance of the sound + /// + /// \see getMinDistance, setAttenuation + /// + //////////////////////////////////////////////////////////// + void setMinDistance(float distance); + + //////////////////////////////////////////////////////////// + /// \brief Set the attenuation factor of the sound + /// + /// The attenuation is a multiplicative factor which makes + /// the sound more or less loud according to its distance + /// from the listener. An attenuation of 0 will produce a + /// non-attenuated sound, i.e. its volume will always be the same + /// whether it is heard from near or from far. On the other hand, + /// an attenuation value such as 100 will make the sound fade out + /// very quickly as it gets further from the listener. + /// The default value of the attenuation is 1. + /// + /// \param attenuation New attenuation factor of the sound + /// + /// \see getAttenuation, setMinDistance + /// + //////////////////////////////////////////////////////////// + void setAttenuation(float attenuation); + + //////////////////////////////////////////////////////////// + /// \brief Get the pitch of the sound + /// + /// \return Pitch of the sound + /// + /// \see setPitch + /// + //////////////////////////////////////////////////////////// + float getPitch() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the volume of the sound + /// + /// \return Volume of the sound, in the range [0, 100] + /// + /// \see setVolume + /// + //////////////////////////////////////////////////////////// + float getVolume() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the 3D position of the sound in the audio scene + /// + /// \return Position of the sound + /// + /// \see setPosition + /// + //////////////////////////////////////////////////////////// + Vector3f getPosition() const; + + //////////////////////////////////////////////////////////// + /// \brief Tell whether the sound's position is relative to the + /// listener or is absolute + /// + /// \return True if the position is relative, false if it's absolute + /// + /// \see setRelativeToListener + /// + //////////////////////////////////////////////////////////// + bool isRelativeToListener() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the minimum distance of the sound + /// + /// \return Minimum distance of the sound + /// + /// \see setMinDistance, getAttenuation + /// + //////////////////////////////////////////////////////////// + float getMinDistance() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the attenuation factor of the sound + /// + /// \return Attenuation factor of the sound + /// + /// \see setAttenuation, getMinDistance + /// + //////////////////////////////////////////////////////////// + float getAttenuation() const; + +protected : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// This constructor is meant ot be called by derived classes only. + /// + //////////////////////////////////////////////////////////// + SoundSource(); + + //////////////////////////////////////////////////////////// + /// \brief Get the current status of the sound (stopped, paused, playing) + /// + /// \return Current status of the sound + /// + //////////////////////////////////////////////////////////// + Status getStatus() const; + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + unsigned int m_source; ///< OpenAL source identifier +}; + +} // namespace sf + + +#endif // SFML_SOUNDSOURCE_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::SoundSource +/// \ingroup audio +/// +/// sf::SoundSource is not meant to be used directly, it +/// only serves as a common base for all audio objects +/// that can live in the audio environment. +/// +/// It defines several properties for the sound: pitch, +/// volume, position, attenuation, etc. All of them can be +/// changed at any time with no impact on performances. +/// +/// \see sf::Sound, sf::SoundStream +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Audio/SoundStream.hpp b/src/include/SFML/include/SFML/Audio/SoundStream.hpp new file mode 100644 index 0000000..32d3c94 --- /dev/null +++ b/src/include/SFML/include/SFML/Audio/SoundStream.hpp @@ -0,0 +1,377 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SOUNDSTREAM_HPP +#define SFML_SOUNDSTREAM_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Abstract base class for streamed audio sources +/// +//////////////////////////////////////////////////////////// +class SFML_AUDIO_API SoundStream : public SoundSource +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Structure defining a chunk of audio data to stream + /// + //////////////////////////////////////////////////////////// + struct Chunk + { + const Int16* samples; ///< Pointer to the audio samples + std::size_t sampleCount; ///< Number of samples pointed by Samples + }; + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + virtual ~SoundStream(); + + //////////////////////////////////////////////////////////// + /// \brief Start or resume playing the audio stream + /// + /// This function starts the stream if it was stopped, resumes + /// it if it was paused, and restarts it from beginning if it + /// was it already playing. + /// This function uses its own thread so that it doesn't block + /// the rest of the program while the stream is played. + /// + /// \see pause, stop + /// + //////////////////////////////////////////////////////////// + void play(); + + //////////////////////////////////////////////////////////// + /// \brief Pause the audio stream + /// + /// This function pauses the stream if it was playing, + /// otherwise (stream already paused or stopped) it has no effect. + /// + /// \see play, stop + /// + //////////////////////////////////////////////////////////// + void pause(); + + //////////////////////////////////////////////////////////// + /// \brief Stop playing the audio stream + /// + /// This function stops the stream if it was playing or paused, + /// and does nothing if it was already stopped. + /// It also resets the playing position (unlike pause()). + /// + /// \see play, pause + /// + //////////////////////////////////////////////////////////// + void stop(); + + //////////////////////////////////////////////////////////// + /// \brief Return the number of channels of the stream + /// + /// 1 channel means a mono sound, 2 means stereo, etc. + /// + /// \return Number of channels + /// + //////////////////////////////////////////////////////////// + unsigned int getChannelCount() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the stream sample rate of the stream + /// + /// The sample rate is the number of audio samples played per + /// second. The higher, the better the quality. + /// + /// \return Sample rate, in number of samples per second + /// + //////////////////////////////////////////////////////////// + unsigned int getSampleRate() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the current status of the stream (stopped, paused, playing) + /// + /// \return Current status + /// + //////////////////////////////////////////////////////////// + Status getStatus() const; + + //////////////////////////////////////////////////////////// + /// \brief Change the current playing position of the stream + /// + /// The playing position can be changed when the stream is + /// either paused or playing. + /// + /// \param timeOffset New playing position, from the beginning of the stream + /// + /// \see getPlayingOffset + /// + //////////////////////////////////////////////////////////// + void setPlayingOffset(Time timeOffset); + + //////////////////////////////////////////////////////////// + /// \brief Get the current playing position of the stream + /// + /// \return Current playing position, from the beginning of the stream + /// + /// \see setPlayingOffset + /// + //////////////////////////////////////////////////////////// + Time getPlayingOffset() const; + + //////////////////////////////////////////////////////////// + /// \brief Set whether or not the stream should loop after reaching the end + /// + /// If set, the stream will restart from beginning after + /// reaching the end and so on, until it is stopped or + /// setLoop(false) is called. + /// The default looping state for streams is false. + /// + /// \param loop True to play in loop, false to play once + /// + /// \see getLoop + /// + //////////////////////////////////////////////////////////// + void setLoop(bool loop); + + //////////////////////////////////////////////////////////// + /// \brief Tell whether or not the stream is in loop mode + /// + /// \return True if the stream is looping, false otherwise + /// + /// \see setLoop + /// + //////////////////////////////////////////////////////////// + bool getLoop() const; + +protected : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// This constructor is only meant to be called by derived classes. + /// + //////////////////////////////////////////////////////////// + SoundStream(); + + //////////////////////////////////////////////////////////// + /// \brief Define the audio stream parameters + /// + /// This function must be called by derived classes as soon + /// as they know the audio settings of the stream to play. + /// Any attempt to manipulate the stream (play(), ...) before + /// calling this function will fail. + /// It can be called multiple times if the settings of the + /// audio stream change, but only when the stream is stopped. + /// + /// \param channelCount Number of channels of the stream + /// \param sampleRate Sample rate, in samples per second + /// + //////////////////////////////////////////////////////////// + void initialize(unsigned int channelCount, unsigned int sampleRate); + + //////////////////////////////////////////////////////////// + /// \brief Request a new chunk of audio samples from the stream source + /// + /// This function must be overriden by derived classes to provide + /// the audio samples to play. It is called continuously by the + /// streaming loop, in a separate thread. + /// The source can choose to stop the streaming loop at any time, by + /// returning false to the caller. + /// + /// \param data Chunk of data to fill + /// + /// \return True to continue playback, false to stop + /// + //////////////////////////////////////////////////////////// + virtual bool onGetData(Chunk& data) = 0; + + //////////////////////////////////////////////////////////// + /// \brief Change the current playing position in the stream source + /// + /// This function must be overriden by derived classes to + /// allow random seeking into the stream source. + /// + /// \param timeOffset New playing position, relative to the beginning of the stream + /// + //////////////////////////////////////////////////////////// + virtual void onSeek(Time timeOffset) = 0; + +private : + + //////////////////////////////////////////////////////////// + /// \brief Function called as the entry point of the thread + /// + /// This function starts the streaming loop, and returns + /// only when the sound is stopped. + /// + //////////////////////////////////////////////////////////// + void streamData(); + + //////////////////////////////////////////////////////////// + /// \brief Fill a new buffer with audio samples, and append + /// it to the playing queue + /// + /// This function is called as soon as a buffer has been fully + /// consumed; it fills it again and inserts it back into the + /// playing queue. + /// + /// \param buffer Number of the buffer to fill (in [0, BufferCount]) + /// + /// \return True if the stream source has requested to stop, false otherwise + /// + //////////////////////////////////////////////////////////// + bool fillAndPushBuffer(unsigned int bufferNum); + + //////////////////////////////////////////////////////////// + /// \brief Fill the audio buffers and put them all into the playing queue + /// + /// This function is called when playing starts and the + /// playing queue is empty. + /// + /// \return True if the derived class has requested to stop, false otherwise + /// + //////////////////////////////////////////////////////////// + bool fillQueue(); + + //////////////////////////////////////////////////////////// + /// \brief Clear all the audio buffers and empty the playing queue + /// + /// This function is called when the stream is stopped. + /// + //////////////////////////////////////////////////////////// + void clearQueue(); + + enum + { + BufferCount = 3 ///< Number of audio buffers used by the streaming loop + }; + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + Thread m_thread; ///< Thread running the background tasks + bool m_isStreaming; ///< Streaming state (true = playing, false = stopped) + unsigned int m_buffers[BufferCount]; ///< Sound buffers used to store temporary audio data + unsigned int m_channelCount; ///< Number of channels (1 = mono, 2 = stereo, ...) + unsigned int m_sampleRate; ///< Frequency (samples / second) + Uint32 m_format; ///< Format of the internal sound buffers + bool m_loop; ///< Loop flag (true to loop, false to play once) + Uint64 m_samplesProcessed; ///< Number of buffers processed since beginning of the stream + bool m_endBuffers[BufferCount]; ///< Each buffer is marked as "end buffer" or not, for proper duration calculation +}; + +} // namespace sf + + +#endif // SFML_SOUNDSTREAM_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::SoundStream +/// \ingroup audio +/// +/// Unlike audio buffers (see sf::SoundBuffer), audio streams +/// are never completely loaded in memory. Instead, the audio +/// data is acquired continuously while the stream is playing. +/// This behaviour allows to play a sound with no loading delay, +/// and keeps the memory consumption very low. +/// +/// Sound sources that need to be streamed are usually big files +/// (compressed audio musics that would eat hundreds of MB in memory) +/// or files that would take a lot of time to be received +/// (sounds played over the network). +/// +/// sf::SoundStream is a base class that doesn't care about the +/// stream source, which is left to the derived class. SFML provides +/// a built-in specialization for big files (see sf::Music). +/// No network stream source is provided, but you can write your own +/// by combining this class with the network module. +/// +/// A derived class has to override two virtual functions: +/// \li onGetData fills a new chunk of audio data to be played +/// \li onSeek changes the current playing position in the source +/// +/// It is important to note that each SoundStream is played in its +/// own separate thread, so that the streaming loop doesn't block the +/// rest of the program. In particular, the OnGetData and OnSeek +/// virtual functions may sometimes be called from this separate thread. +/// It is important to keep this in mind, because you may have to take +/// care of synchronization issues if you share data between threads. +/// +/// Usage example: +/// \code +/// class CustomStream : public sf::SoundStream +/// { +/// public : +/// +/// bool open(const std::string& location) +/// { +/// // Open the source and get audio settings +/// ... +/// unsigned int channelCount = ...; +/// unsigned int sampleRate = ...; +/// +/// // Initialize the stream -- important! +/// initialize(channelCount, sampleRate); +/// } +/// +/// private : +/// +/// virtual bool onGetData(Chunk& data) +/// { +/// // Fill the chunk with audio data from the stream source +/// data.samples = ...; +/// data.sampleCount = ...; +/// +/// // Return true to continue playing +/// return true; +/// } +/// +/// virtual void onSeek(Uint32 timeOffset) +/// { +/// // Change the current position in the stream source +/// ... +/// } +/// } +/// +/// // Usage +/// CustomStream stream; +/// stream.open("path/to/stream"); +/// stream.play(); +/// \endcode +/// +/// \see sf::Music +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Config.hpp b/src/include/SFML/include/SFML/Config.hpp new file mode 100644 index 0000000..d825a5a --- /dev/null +++ b/src/include/SFML/include/SFML/Config.hpp @@ -0,0 +1,159 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_CONFIG_HPP +#define SFML_CONFIG_HPP + + +//////////////////////////////////////////////////////////// +// Define the SFML version +//////////////////////////////////////////////////////////// +#define SFML_VERSION_MAJOR 2 +#define SFML_VERSION_MINOR 1 + + +//////////////////////////////////////////////////////////// +// Identify the operating system +//////////////////////////////////////////////////////////// +#if defined(_WIN32) || defined(__WIN32__) + + // Windows + #define SFML_SYSTEM_WINDOWS + #ifndef NOMINMAX + #define NOMINMAX + #endif + +#elif defined(linux) || defined(__linux) + + // Linux + #define SFML_SYSTEM_LINUX + +#elif defined(__APPLE__) || defined(MACOSX) || defined(macintosh) || defined(Macintosh) + + // MacOS + #define SFML_SYSTEM_MACOS + +#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + + // FreeBSD + #define SFML_SYSTEM_FREEBSD + +#else + + // Unsupported system + #error This operating system is not supported by SFML library + +#endif + + +//////////////////////////////////////////////////////////// +// Define a portable debug macro +//////////////////////////////////////////////////////////// +#if !defined(NDEBUG) + + #define SFML_DEBUG + +#endif + + +//////////////////////////////////////////////////////////// +// Define helpers to create portable import / export macros for each module +//////////////////////////////////////////////////////////// +#if !defined(SFML_STATIC) + + #if defined(SFML_SYSTEM_WINDOWS) + + // Windows compilers need specific (and different) keywords for export and import + #define SFML_API_EXPORT __declspec(dllexport) + #define SFML_API_IMPORT __declspec(dllimport) + + // For Visual C++ compilers, we also need to turn off this annoying C4251 warning + #ifdef _MSC_VER + + #pragma warning(disable : 4251) + + #endif + + #else // Linux, FreeBSD, Mac OS X + + #if __GNUC__ >= 4 + + // GCC 4 has special keywords for showing/hidding symbols, + // the same keyword is used for both importing and exporting + #define SFML_API_EXPORT __attribute__ ((__visibility__ ("default"))) + #define SFML_API_IMPORT __attribute__ ((__visibility__ ("default"))) + + #else + + // GCC < 4 has no mechanism to explicitely hide symbols, everything's exported + #define SFML_API_EXPORT + #define SFML_API_IMPORT + + #endif + + #endif + +#else + + // Static build doesn't need import/export macros + #define SFML_API_EXPORT + #define SFML_API_IMPORT + +#endif + + +//////////////////////////////////////////////////////////// +// Define portable fixed-size types +//////////////////////////////////////////////////////////// +namespace sf +{ + // All "common" platforms use the same size for char, short and int + // (basically there are 3 types for 3 sizes, so no other match is possible), + // we can use them without doing any kind of check + + // 8 bits integer types + typedef signed char Int8; + typedef unsigned char Uint8; + + // 16 bits integer types + typedef signed short Int16; + typedef unsigned short Uint16; + + // 32 bits integer types + typedef signed int Int32; + typedef unsigned int Uint32; + + // 64 bits integer types + #if defined(_MSC_VER) + typedef signed __int64 Int64; + typedef unsigned __int64 Uint64; + #else + typedef signed long long Int64; + typedef unsigned long long Uint64; + #endif + +} // namespace sf + + +#endif // SFML_CONFIG_HPP diff --git a/src/include/SFML/include/SFML/Graphics.hpp b/src/include/SFML/include/SFML/Graphics.hpp new file mode 100644 index 0000000..4282cd4 --- /dev/null +++ b/src/include/SFML/include/SFML/Graphics.hpp @@ -0,0 +1,62 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_GRAPHICS_HPP +#define SFML_GRAPHICS_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#endif // SFML_GRAPHICS_HPP + +//////////////////////////////////////////////////////////// +/// \defgroup graphics Graphics module +/// +/// 2D graphics module: sprites, text, shapes, ... +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Graphics/BlendMode.hpp b/src/include/SFML/include/SFML/Graphics/BlendMode.hpp new file mode 100644 index 0000000..4b12e11 --- /dev/null +++ b/src/include/SFML/include/SFML/Graphics/BlendMode.hpp @@ -0,0 +1,46 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_BLENDMODE_HPP +#define SFML_BLENDMODE_HPP + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \ingroup graphics +/// \brief Available blending modes for drawing +/// +//////////////////////////////////////////////////////////// +enum BlendMode +{ + BlendAlpha, ///< Pixel = Source * Source.a + Dest * (1 - Source.a) + BlendAdd, ///< Pixel = Source + Dest + BlendMultiply, ///< Pixel = Source * Dest + BlendNone ///< Pixel = Source +}; + +} // namespace sf + + +#endif // SFML_BLENDMODE_HPP diff --git a/src/include/SFML/include/SFML/Graphics/CircleShape.hpp b/src/include/SFML/include/SFML/Graphics/CircleShape.hpp new file mode 100644 index 0000000..b82539e --- /dev/null +++ b/src/include/SFML/include/SFML/Graphics/CircleShape.hpp @@ -0,0 +1,151 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_CIRCLESHAPE_HPP +#define SFML_CIRCLESHAPE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Specialized shape representing a circle +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API CircleShape : public Shape +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// \param radius Radius of the circle + /// \param pointCount Number of points composing the circle + /// + //////////////////////////////////////////////////////////// + explicit CircleShape(float radius = 0, unsigned int pointCount = 30); + + //////////////////////////////////////////////////////////// + /// \brief Set the radius of the circle + /// + /// \param radius New radius of the circle + /// + /// \see getRadius + /// + //////////////////////////////////////////////////////////// + void setRadius(float radius); + + //////////////////////////////////////////////////////////// + /// \brief Get the radius of the circle + /// + /// \return Radius of the circle + /// + /// \see setRadius + /// + //////////////////////////////////////////////////////////// + float getRadius() const; + + //////////////////////////////////////////////////////////// + /// \brief Set the number of points of the circle + /// + /// \param count New number of points of the circle + /// + /// \see getPointCount + /// + //////////////////////////////////////////////////////////// + void setPointCount(unsigned int count); + + //////////////////////////////////////////////////////////// + /// \brief Get the number of points of the shape + /// + /// \return Number of points of the shape + /// + /// \see setPointCount + /// + //////////////////////////////////////////////////////////// + virtual unsigned int getPointCount() const; + + //////////////////////////////////////////////////////////// + /// \brief Get a point of the shape + /// + /// The result is undefined if \a index is out of the valid range. + /// + /// \param index Index of the point to get, in range [0 .. getPointCount() - 1] + /// + /// \return Index-th point of the shape + /// + //////////////////////////////////////////////////////////// + virtual Vector2f getPoint(unsigned int index) const; + +private : + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + float m_radius; ///< Radius of the circle + unsigned int m_pointCount; ///< Number of points composing the circle +}; + +} // namespace sf + + +#endif // SFML_CIRCLESHAPE_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::CircleShape +/// \ingroup graphics +/// +/// This class inherits all the functions of sf::Transformable +/// (position, rotation, scale, bounds, ...) as well as the +/// functions of sf::Shape (outline, color, texture, ...). +/// +/// Usage example: +/// \code +/// sf::CircleShape circle; +/// circle.setRadius(150); +/// circle.setOutlineColor(sf::Color::Red); +/// circle.setOutlineThickness(5); +/// circle.setPosition(10, 20); +/// ... +/// window.draw(circle); +/// \endcode +/// +/// Since the graphics card can't draw perfect circles, we have to +/// fake them with multiple triangles connected to each other. The +/// "points count" property of sf::CircleShape defines how many of these +/// triangles to use, and therefore defines the quality of the circle. +/// +/// The number of points can also be used for another purpose; with +/// small numbers you can create any regular polygon shape: +/// equilateral triangle, square, pentagon, hexagon, ... +/// +/// \see sf::Shape, sf::RectangleShape, sf::ConvexShape +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Graphics/Color.hpp b/src/include/SFML/include/SFML/Graphics/Color.hpp new file mode 100644 index 0000000..1b7f466 --- /dev/null +++ b/src/include/SFML/include/SFML/Graphics/Color.hpp @@ -0,0 +1,228 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_COLOR_HPP +#define SFML_COLOR_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Utility class for manpulating RGBA colors +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API Color +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Constructs an opaque black color. It is equivalent to + /// sf::Color(0, 0, 0, 255). + /// + //////////////////////////////////////////////////////////// + Color(); + + //////////////////////////////////////////////////////////// + /// \brief Construct the color from its 4 RGBA components + /// + /// \param red Red component (in the range [0, 255]) + /// \param green Green component (in the range [0, 255]) + /// \param blue Blue component (in the range [0, 255]) + /// \param alpha Alpha (opacity) component (in the range [0, 255]) + /// + //////////////////////////////////////////////////////////// + Color(Uint8 red, Uint8 green, Uint8 blue, Uint8 alpha = 255); + + //////////////////////////////////////////////////////////// + // Static member data + //////////////////////////////////////////////////////////// + static const Color Black; ///< Black predefined color + static const Color White; ///< White predefined color + static const Color Red; ///< Red predefined color + static const Color Green; ///< Green predefined color + static const Color Blue; ///< Blue predefined color + static const Color Yellow; ///< Yellow predefined color + static const Color Magenta; ///< Magenta predefined color + static const Color Cyan; ///< Cyan predefined color + static const Color Transparent; ///< Transparent (black) predefined color + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + Uint8 r; ///< Red component + Uint8 g; ///< Green component + Uint8 b; ///< Blue component + Uint8 a; ///< Alpha (opacity) component +}; + +//////////////////////////////////////////////////////////// +/// \relates Color +/// \brief Overload of the == operator +/// +/// This operator compares two colors and check if they are equal. +/// +/// \param left Left operand +/// \param right Right operand +/// +/// \return True if colors are equal, false if they are different +/// +//////////////////////////////////////////////////////////// +SFML_GRAPHICS_API bool operator ==(const Color& left, const Color& right); + +//////////////////////////////////////////////////////////// +/// \relates Color +/// \brief Overload of the != operator +/// +/// This operator compares two colors and check if they are different. +/// +/// \param left Left operand +/// \param right Right operand +/// +/// \return True if colors are different, false if they are equal +/// +//////////////////////////////////////////////////////////// +SFML_GRAPHICS_API bool operator !=(const Color& left, const Color& right); + +//////////////////////////////////////////////////////////// +/// \relates Color +/// \brief Overload of the binary + operator +/// +/// This operator returns the component-wise sum of two colors. +/// Components that exceed 255 are clamped to 255. +/// +/// \param left Left operand +/// \param right Right operand +/// +/// \return Result of \a left + \a right +/// +//////////////////////////////////////////////////////////// +SFML_GRAPHICS_API Color operator +(const Color& left, const Color& right); + +//////////////////////////////////////////////////////////// +/// \relates Color +/// \brief Overload of the binary * operator +/// +/// This operator returns the component-wise multiplication +/// (also called "modulation") of two colors. +/// Components are then divided by 255 so that the result is +/// still in the range [0, 255]. +/// +/// \param left Left operand +/// \param right Right operand +/// +/// \return Result of \a left * \a right +/// +//////////////////////////////////////////////////////////// +SFML_GRAPHICS_API Color operator *(const Color& left, const Color& right); + +//////////////////////////////////////////////////////////// +/// \relates Color +/// \brief Overload of the binary += operator +/// +/// This operator computes the component-wise sum of two colors, +/// and assigns the result to the left operand. +/// Components that exceed 255 are clamped to 255. +/// +/// \param left Left operand +/// \param right Right operand +/// +/// \return Reference to \a left +/// +//////////////////////////////////////////////////////////// +SFML_GRAPHICS_API Color& operator +=(Color& left, const Color& right); + +//////////////////////////////////////////////////////////// +/// \relates Color +/// \brief Overload of the binary *= operator +/// +/// This operator returns the component-wise multiplication +/// (also called "modulation") of two colors, and assigns +/// the result to the left operand. +/// Components are then divided by 255 so that the result is +/// still in the range [0, 255]. +/// +/// \param left Left operand +/// \param right Right operand +/// +/// \return Reference to \a left +/// +//////////////////////////////////////////////////////////// +SFML_GRAPHICS_API Color& operator *=(Color& left, const Color& right); + +} // namespace sf + + +#endif // SFML_COLOR_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Color +/// \ingroup graphics +/// +/// sf::Color is a simple color class composed of 4 components: +/// \li Red +/// \li Green +/// \li Blue +/// \li Alpha (opacity) +/// +/// Each component is a public member, an unsigned integer in +/// the range [0, 255]. Thus, colors can be constructed and +/// manipulated very easily: +/// +/// \code +/// sf::Color color(255, 0, 0); // red +/// color.r = 0; // make it black +/// color.b = 128; // make it dark blue +/// \endcode +/// +/// The fourth component of colors, named "alpha", represents +/// the opacity of the color. A color with an alpha value of +/// 255 will be fully opaque, while an alpha value of 0 will +/// make a color fully transparent, whatever the value of the +/// other components is. +/// +/// The most common colors are already defined as static variables: +/// \code +/// sf::Color black = sf::Color::Black; +/// sf::Color white = sf::Color::White; +/// sf::Color red = sf::Color::Red; +/// sf::Color green = sf::Color::Green; +/// sf::Color blue = sf::Color::Blue; +/// sf::Color yellow = sf::Color::Yellow; +/// sf::Color magenta = sf::Color::Magenta; +/// sf::Color cyan = sf::Color::Cyan; +/// sf::Color transparent = sf::Color::Transparent; +/// \endcode +/// +/// Colors can also be added and modulated (multiplied) using the +/// overloaded operators + and *. +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Graphics/ConvexShape.hpp b/src/include/SFML/include/SFML/Graphics/ConvexShape.hpp new file mode 100644 index 0000000..03af57f --- /dev/null +++ b/src/include/SFML/include/SFML/Graphics/ConvexShape.hpp @@ -0,0 +1,150 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_CONVEXSHAPE_HPP +#define SFML_CONVEXSHAPE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Specialized shape representing a convex polygon +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API ConvexShape : public Shape +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// \param pointCount Number of points of the polygon + /// + //////////////////////////////////////////////////////////// + explicit ConvexShape(unsigned int pointCount = 0); + + //////////////////////////////////////////////////////////// + /// \brief Set the number of points of the polygon + /// + /// \a count must be greater than 2 to define a valid shape. + /// + /// \param count New number of points of the polygon + /// + /// \see getPointCount + /// + //////////////////////////////////////////////////////////// + void setPointCount(unsigned int count); + + //////////////////////////////////////////////////////////// + /// \brief Get the number of points of the polygon + /// + /// \return Number of points of the polygon + /// + /// \see setPointCount + /// + //////////////////////////////////////////////////////////// + virtual unsigned int getPointCount() const; + + //////////////////////////////////////////////////////////// + /// \brief Set the position of a point + /// + /// Don't forget that the polygon must remain convex, and + /// the points need to stay ordered! + /// setPointCount must be called first in order to set the total + /// number of points. The result is undefined if \a index is out + /// of the valid range. + /// + /// \param index Index of the point to change, in range [0 .. getPointCount() - 1] + /// \param point New position of the point + /// + /// \see getPoint + /// + //////////////////////////////////////////////////////////// + void setPoint(unsigned int index, const Vector2f& point); + + //////////////////////////////////////////////////////////// + /// \brief Get the position of a point + /// + /// The result is undefined if \a index is out of the valid range. + /// + /// \param index Index of the point to get, in range [0 .. getPointCount() - 1] + /// + /// \return Position of the index-th point of the polygon + /// + /// \see setPoint + /// + //////////////////////////////////////////////////////////// + virtual Vector2f getPoint(unsigned int index) const; + +private : + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + std::vector m_points; ///< Points composing the convex polygon +}; + +} // namespace sf + + +#endif // SFML_CONVEXSHAPE_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::ConvexShape +/// \ingroup graphics +/// +/// This class inherits all the functions of sf::Transformable +/// (position, rotation, scale, bounds, ...) as well as the +/// functions of sf::Shape (outline, color, texture, ...). +/// +/// It is important to keep in mind that a convex shape must +/// always be... convex, otherwise it may not be drawn correctly. +/// Moreover, the points must be defined in order; using a random +/// order would result in an incorrect shape. +/// +/// Usage example: +/// \code +/// sf::ConvexShape polygon; +/// polygon.setPointCount(3); +/// polygon.setPoint(0, sf::Vector2f(0, 0)); +/// polygon.setPoint(1, sf::Vector2f(0, 10)); +/// polygon.setPoint(2, sf::Vector2f(25, 5)); +/// polygon.setOutlineColor(sf::Color::Red); +/// polygon.setOutlineThickness(5); +/// polygon.setPosition(10, 20); +/// ... +/// window.draw(polygon); +/// \endcode +/// +/// \see sf::Shape, sf::RectangleShape, sf::CircleShape +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Graphics/Drawable.hpp b/src/include/SFML/include/SFML/Graphics/Drawable.hpp new file mode 100644 index 0000000..6e10afe --- /dev/null +++ b/src/include/SFML/include/SFML/Graphics/Drawable.hpp @@ -0,0 +1,126 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_DRAWABLE_HPP +#define SFML_DRAWABLE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +class RenderTarget; + +//////////////////////////////////////////////////////////// +/// \brief Abstract base class for objects that can be drawn +/// to a render target +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API Drawable +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Virtual destructor + /// + //////////////////////////////////////////////////////////// + virtual ~Drawable() {} + +protected : + + friend class RenderTarget; + + //////////////////////////////////////////////////////////// + /// \brief Draw the object to a render target + /// + /// This is a pure virtual function that has to be implemented + /// by the derived class to define how the drawable should be + /// drawn. + /// + /// \param target Render target to draw to + /// \param states Current render states + /// + //////////////////////////////////////////////////////////// + virtual void draw(RenderTarget& target, RenderStates states) const = 0; +}; + +} // namespace sf + + +#endif // SFML_DRAWABLE_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Drawable +/// \ingroup graphics +/// +/// sf::Drawable is a very simple base class that allows objects +/// of derived classes to be drawn to a sf::RenderTarget. +/// +/// All you have to do in your derived class is to override the +/// draw virtual function. +/// +/// Note that inheriting from sf::Drawable is not mandatory, +/// but it allows this nice syntax "window.draw(object)" rather +/// than "object.draw(window)", which is more consistent with other +/// SFML classes. +/// +/// Example: +/// \code +/// class MyDrawable : public sf::Drawable +/// { +/// public : +/// +/// ... +/// +/// private : +/// +/// virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const +/// { +/// // You can draw other high-level objects +/// target.draw(m_sprite, states); +/// +/// // ... or use the low-level API +/// states.texture = &m_texture; +/// target.draw(m_vertices, states); +/// +/// // ... or draw with OpenGL directly +/// glBegin(GL_QUADS); +/// ... +/// glEnd(); +/// } +/// +/// sf::Sprite m_sprite; +/// sf::Texture m_texture; +/// sf::VertexArray m_vertices; +/// }; +/// \endcode +/// +/// \see sf::RenderTarget +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Graphics/Export.hpp b/src/include/SFML/include/SFML/Graphics/Export.hpp new file mode 100644 index 0000000..eb76ae8 --- /dev/null +++ b/src/include/SFML/include/SFML/Graphics/Export.hpp @@ -0,0 +1,48 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_GRAPHICS_EXPORT_HPP +#define SFML_GRAPHICS_EXPORT_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +//////////////////////////////////////////////////////////// +// Define portable import / export macros +//////////////////////////////////////////////////////////// +#if defined(SFML_GRAPHICS_EXPORTS) + + #define SFML_GRAPHICS_API SFML_API_EXPORT + +#else + + #define SFML_GRAPHICS_API SFML_API_IMPORT + +#endif + + +#endif // SFML_GRAPHICS_EXPORT_HPP diff --git a/src/include/SFML/include/SFML/Graphics/Font.hpp b/src/include/SFML/include/SFML/Graphics/Font.hpp new file mode 100644 index 0000000..dc3cd48 --- /dev/null +++ b/src/include/SFML/include/SFML/Graphics/Font.hpp @@ -0,0 +1,361 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_FONT_HPP +#define SFML_FONT_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace sf +{ +class InputStream; + +//////////////////////////////////////////////////////////// +/// \brief Class for loading and manipulating character fonts +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API Font +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// This constructor defines an empty font + /// + //////////////////////////////////////////////////////////// + Font(); + + //////////////////////////////////////////////////////////// + /// \brief Copy constructor + /// + /// \param copy Instance to copy + /// + //////////////////////////////////////////////////////////// + Font(const Font& copy); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + /// Cleans up all the internal resources used by the font + /// + //////////////////////////////////////////////////////////// + ~Font(); + + //////////////////////////////////////////////////////////// + /// \brief Load the font from a file + /// + /// The supported font formats are: TrueType, Type 1, CFF, + /// OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42. + /// Note that this function know nothing about the standard + /// fonts installed on the user's system, thus you can't + /// load them directly. + /// + /// \param filename Path of the font file to load + /// + /// \return True if loading succeeded, false if it failed + /// + /// \see loadFromMemory, loadFromStream + /// + //////////////////////////////////////////////////////////// + bool loadFromFile(const std::string& filename); + + //////////////////////////////////////////////////////////// + /// \brief Load the font from a file in memory + /// + /// The supported font formats are: TrueType, Type 1, CFF, + /// OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42. + /// Warning: SFML cannot preload all the font data in this + /// function, so the buffer pointed by \a data has to remain + /// valid as long as the font is used. + /// + /// \param data Pointer to the file data in memory + /// \param sizeInBytes Size of the data to load, in bytes + /// + /// \return True if loading succeeded, false if it failed + /// + /// \see loadFromFile, loadFromStream + /// + //////////////////////////////////////////////////////////// + bool loadFromMemory(const void* data, std::size_t sizeInBytes); + + //////////////////////////////////////////////////////////// + /// \brief Load the font from a custom stream + /// + /// The supported font formats are: TrueType, Type 1, CFF, + /// OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42. + /// Warning: SFML cannot preload all the font data in this + /// function, so the contents of \a stream have to remain + /// valid as long as the font is used. + /// + /// \param stream Source stream to read from + /// + /// \return True if loading succeeded, false if it failed + /// + /// \see loadFromFile, loadFromMemory + /// + //////////////////////////////////////////////////////////// + bool loadFromStream(InputStream& stream); + + //////////////////////////////////////////////////////////// + /// \brief Retrieve a glyph of the font + /// + /// \param codePoint Unicode code point of the character to get + /// \param characterSize Reference character size + /// \param bold Retrieve the bold version or the regular one? + /// + /// \return The glyph corresponding to \a codePoint and \a characterSize + /// + //////////////////////////////////////////////////////////// + const Glyph& getGlyph(Uint32 codePoint, unsigned int characterSize, bool bold) const; + + //////////////////////////////////////////////////////////// + /// \brief Get the kerning offset of two glyphs + /// + /// The kerning is an extra offset (negative) to apply between two + /// glyphs when rendering them, to make the pair look more "natural". + /// For example, the pair "AV" have a special kerning to make them + /// closer than other characters. Most of the glyphs pairs have a + /// kerning offset of zero, though. + /// + /// \param first Unicode code point of the first character + /// \param second Unicode code point of the second character + /// \param characterSize Reference character size + /// + /// \return Kerning value for \a first and \a second, in pixels + /// + //////////////////////////////////////////////////////////// + int getKerning(Uint32 first, Uint32 second, unsigned int characterSize) const; + + //////////////////////////////////////////////////////////// + /// \brief Get the line spacing + /// + /// Line spacing is the vertical offset to apply between two + /// consecutive lines of text. + /// + /// \param characterSize Reference character size + /// + /// \return Line spacing, in pixels + /// + //////////////////////////////////////////////////////////// + int getLineSpacing(unsigned int characterSize) const; + + //////////////////////////////////////////////////////////// + /// \brief Retrieve the texture containing the loaded glyphs of a certain size + /// + /// The contents of the returned texture changes as more glyphs + /// are requested, thus it is not very relevant. It is mainly + /// used internally by sf::Text. + /// + /// \param characterSize Reference character size + /// + /// \return Texture containing the glyphs of the requested size + /// + //////////////////////////////////////////////////////////// + const Texture& getTexture(unsigned int characterSize) const; + + //////////////////////////////////////////////////////////// + /// \brief Overload of assignment operator + /// + /// \param right Instance to assign + /// + /// \return Reference to self + /// + //////////////////////////////////////////////////////////// + Font& operator =(const Font& right); + +private : + + //////////////////////////////////////////////////////////// + /// \brief Structure defining a row of glyphs + /// + //////////////////////////////////////////////////////////// + struct Row + { + Row(unsigned int rowTop, unsigned int rowHeight) : width(0), top(rowTop), height(rowHeight) {} + + unsigned int width; ///< Current width of the row + unsigned int top; ///< Y position of the row into the texture + unsigned int height; ///< Height of the row + }; + + //////////////////////////////////////////////////////////// + // Types + //////////////////////////////////////////////////////////// + typedef std::map GlyphTable; ///< Table mapping a codepoint to its glyph + + //////////////////////////////////////////////////////////// + /// \brief Structure defining a page of glyphs + /// + //////////////////////////////////////////////////////////// + struct Page + { + Page(); + + GlyphTable glyphs; ///< Table mapping code points to their corresponding glyph + sf::Texture texture; ///< Texture containing the pixels of the glyphs + unsigned int nextRow; ///< Y position of the next new row in the texture + std::vector rows; ///< List containing the position of all the existing rows + }; + + //////////////////////////////////////////////////////////// + /// \brief Free all the internal resources + /// + //////////////////////////////////////////////////////////// + void cleanup(); + + //////////////////////////////////////////////////////////// + /// \brief Load a new glyph and store it in the cache + /// + /// \param codePoint Unicode code point of the character to load + /// \param characterSize Reference character size + /// \param bold Retrieve the bold version or the regular one? + /// + /// \return The glyph corresponding to \a codePoint and \a characterSize + /// + //////////////////////////////////////////////////////////// + Glyph loadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold) const; + + //////////////////////////////////////////////////////////// + /// \brief Find a suitable rectangle within the texture for a glyph + /// + /// \param page Page of glyphs to search in + /// \param width Width of the rectangle + /// \param height Height of the rectangle + /// + /// \return Found rectangle within the texture + /// + //////////////////////////////////////////////////////////// + IntRect findGlyphRect(Page& page, unsigned int width, unsigned int height) const; + + //////////////////////////////////////////////////////////// + /// \brief Make sure that the given size is the current one + /// + /// \param characterSize Reference character size + /// + /// \return True on success, false if any error happened + /// + //////////////////////////////////////////////////////////// + bool setCurrentSize(unsigned int characterSize) const; + + //////////////////////////////////////////////////////////// + // Types + //////////////////////////////////////////////////////////// + typedef std::map PageTable; ///< Table mapping a character size to its page (texture) + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + void* m_library; ///< Pointer to the internal library interface (it is typeless to avoid exposing implementation details) + void* m_face; ///< Pointer to the internal font face (it is typeless to avoid exposing implementation details) + void* m_streamRec; ///< Pointer to the stream rec instance (it is typeless to avoid exposing implementation details) + int* m_refCount; ///< Reference counter used by implicit sharing + mutable PageTable m_pages; ///< Table containing the glyphs pages by character size + mutable std::vector m_pixelBuffer; ///< Pixel buffer holding a glyph's pixels before being written to the texture +}; + +} // namespace sf + + +#endif // SFML_FONT_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Font +/// \ingroup graphics +/// +/// Fonts can be loaded from a file, from memory or from a custom +/// stream, and supports the most common types of fonts. See +/// the loadFromFile function for the complete list of supported formats. +/// +/// Once it is loaded, a sf::Font instance provides three +/// types of information about the font: +/// \li Global metrics, such as the line spacing +/// \li Per-glyph metrics, such as bounding box or kerning +/// \li Pixel representation of glyphs +/// +/// Fonts alone are not very useful: they hold the font data +/// but cannot make anything useful of it. To do so you need to +/// use the sf::Text class, which is able to properly output text +/// with several options such as character size, style, color, +/// position, rotation, etc. +/// This separation allows more flexibility and better performances: +/// indeed a sf::Font is a heavy resource, and any operation on it +/// is slow (often too slow for real-time applications). On the other +/// side, a sf::Text is a lightweight object which can combine the +/// glyphs data and metrics of a sf::Font to display any text on a +/// render target. +/// Note that it is also possible to bind several sf::Text instances +/// to the same sf::Font. +/// +/// It is important to note that the sf::Text instance doesn't +/// copy the font that it uses, it only keeps a reference to it. +/// Thus, a sf::Font must not be destructed while it is +/// used by a sf::Text (i.e. never write a function that +/// uses a local sf::Font instance for creating a text). +/// +/// Usage example: +/// \code +/// // Declare a new font +/// sf::Font font; +/// +/// // Load it from a file +/// if (!font.loadFromFile("arial.ttf")) +/// { +/// // error... +/// } +/// +/// // Create a text which uses our font +/// sf::Text text1; +/// text1.setFont(font); +/// text1.setCharacterSize(30); +/// text1.setStyle(sf::Text::Regular); +/// +/// // Create another text using the same font, but with different parameters +/// sf::Text text2; +/// text2.setFont(font); +/// text2.setCharacterSize(50); +/// text1.setStyle(sf::Text::Italic); +/// \endcode +/// +/// Apart from loading font files, and passing them to instances +/// of sf::Text, you should normally not have to deal directly +/// with this class. However, it may be useful to access the +/// font metrics or rasterized glyphs for advanced usage. +/// +/// \see sf::Text +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Graphics/Glyph.hpp b/src/include/SFML/include/SFML/Graphics/Glyph.hpp new file mode 100644 index 0000000..935a15e --- /dev/null +++ b/src/include/SFML/include/SFML/Graphics/Glyph.hpp @@ -0,0 +1,79 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_GLYPH_HPP +#define SFML_GLYPH_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Structure describing a glyph +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API Glyph +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + Glyph() : advance(0) {} + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + int advance; ///< Offset to move horizontically to the next character + IntRect bounds; ///< Bounding rectangle of the glyph, in coordinates relative to the baseline + IntRect textureRect; ///< Texture coordinates of the glyph inside the font's texture +}; + +} // namespace sf + + +#endif // SFML_GLYPH_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Glyph +/// \ingroup graphics +/// +/// A glyph is the visual representation of a character. +/// +/// The sf::Glyph structure provides the information needed +/// to handle the glyph: +/// \li its coordinates in the font's texture +/// \li its bounding rectangle +/// \li the offset to apply to get the starting position of the next glyph +/// +/// \see sf::Font +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Graphics/Image.hpp b/src/include/SFML/include/SFML/Graphics/Image.hpp new file mode 100644 index 0000000..dd1c59a --- /dev/null +++ b/src/include/SFML/include/SFML/Graphics/Image.hpp @@ -0,0 +1,318 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_IMAGE_HPP +#define SFML_IMAGE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include + + +namespace sf +{ +class InputStream; + +//////////////////////////////////////////////////////////// +/// \brief Class for loading, manipulating and saving images +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API Image +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Creates an empty image. + /// + //////////////////////////////////////////////////////////// + Image(); + + //////////////////////////////////////////////////////////// + /// \brief Create the image and fill it with a unique color + /// + /// \param width Width of the image + /// \param height Height of the image + /// \param color Fill color + /// + //////////////////////////////////////////////////////////// + void create(unsigned int width, unsigned int height, const Color& color = Color(0, 0, 0)); + + //////////////////////////////////////////////////////////// + /// \brief Create the image from an array of pixels + /// + /// The \a pixel array is assumed to contain 32-bits RGBA pixels, + /// and have the given \a width and \a height. If not, this is + /// an undefined behaviour. + /// If \a pixels is null, an empty image is created. + /// + /// \param width Width of the image + /// \param height Height of the image + /// \param pixels Array of pixels to copy to the image + /// + //////////////////////////////////////////////////////////// + void create(unsigned int width, unsigned int height, const Uint8* pixels); + + //////////////////////////////////////////////////////////// + /// \brief Load the image from a file on disk + /// + /// The supported image formats are bmp, png, tga, jpg, gif, + /// psd, hdr and pic. Some format options are not supported, + /// like progressive jpeg. + /// If this function fails, the image is left unchanged. + /// + /// \param filename Path of the image file to load + /// + /// \return True if loading was successful + /// + /// \see loadFromMemory, loadFromStream, saveToFile + /// + //////////////////////////////////////////////////////////// + bool loadFromFile(const std::string& filename); + + //////////////////////////////////////////////////////////// + /// \brief Load the image from a file in memory + /// + /// The supported image formats are bmp, png, tga, jpg, gif, + /// psd, hdr and pic. Some format options are not supported, + /// like progressive jpeg. + /// If this function fails, the image is left unchanged. + /// + /// \param data Pointer to the file data in memory + /// \param size Size of the data to load, in bytes + /// + /// \return True if loading was successful + /// + /// \see loadFromFile, loadFromStream + /// + //////////////////////////////////////////////////////////// + bool loadFromMemory(const void* data, std::size_t size); + + //////////////////////////////////////////////////////////// + /// \brief Load the image from a custom stream + /// + /// The supported image formats are bmp, png, tga, jpg, gif, + /// psd, hdr and pic. Some format options are not supported, + /// like progressive jpeg. + /// If this function fails, the image is left unchanged. + /// + /// \param stream Source stream to read from + /// + /// \return True if loading was successful + /// + /// \see loadFromFile, loadFromMemory + /// + //////////////////////////////////////////////////////////// + bool loadFromStream(InputStream& stream); + + //////////////////////////////////////////////////////////// + /// \brief Save the image to a file on disk + /// + /// The format of the image is automatically deduced from + /// the extension. The supported image formats are bmp, png, + /// tga and jpg. The destination file is overwritten + /// if it already exists. This function fails if the image is empty. + /// + /// \param filename Path of the file to save + /// + /// \return True if saving was successful + /// + /// \see create, loadFromFile, loadFromMemory + /// + //////////////////////////////////////////////////////////// + bool saveToFile(const std::string& filename) const; + + //////////////////////////////////////////////////////////// + /// \brief Return the size (width and height) of the image + /// + /// \return Size of the image, in pixels + /// + //////////////////////////////////////////////////////////// + Vector2u getSize() const; + + //////////////////////////////////////////////////////////// + /// \brief Create a transparency mask from a specified color-key + /// + /// This function sets the alpha value of every pixel matching + /// the given color to \a alpha (0 by default), so that they + /// become transparent. + /// + /// \param color Color to make transparent + /// \param alpha Alpha value to assign to transparent pixels + /// + //////////////////////////////////////////////////////////// + void createMaskFromColor(const Color& color, Uint8 alpha = 0); + + //////////////////////////////////////////////////////////// + /// \brief Copy pixels from another image onto this one + /// + /// This function does a slow pixel copy and should not be + /// used intensively. It can be used to prepare a complex + /// static image from several others, but if you need this + /// kind of feature in real-time you'd better use sf::RenderTexture. + /// + /// If \a sourceRect is empty, the whole image is copied. + /// If \a applyAlpha is set to true, the transparency of + /// source pixels is applied. If it is false, the pixels are + /// copied unchanged with their alpha value. + /// + /// \param source Source image to copy + /// \param destX X coordinate of the destination position + /// \param destY Y coordinate of the destination position + /// \param sourceRect Sub-rectangle of the source image to copy + /// \param applyAlpha Should the copy take in account the source transparency? + /// + //////////////////////////////////////////////////////////// + void copy(const Image& source, unsigned int destX, unsigned int destY, const IntRect& sourceRect = IntRect(0, 0, 0, 0), bool applyAlpha = false); + + //////////////////////////////////////////////////////////// + /// \brief Change the color of a pixel + /// + /// This function doesn't check the validity of the pixel + /// coordinates, using out-of-range values will result in + /// an undefined behaviour. + /// + /// \param x X coordinate of pixel to change + /// \param y Y coordinate of pixel to change + /// \param color New color of the pixel + /// + /// \see getPixel + /// + //////////////////////////////////////////////////////////// + void setPixel(unsigned int x, unsigned int y, const Color& color); + + //////////////////////////////////////////////////////////// + /// \brief Get the color of a pixel + /// + /// This function doesn't check the validity of the pixel + /// coordinates, using out-of-range values will result in + /// an undefined behaviour. + /// + /// \param x X coordinate of pixel to get + /// \param y Y coordinate of pixel to get + /// + /// \return Color of the pixel at coordinates (x, y) + /// + /// \see setPixel + /// + //////////////////////////////////////////////////////////// + Color getPixel(unsigned int x, unsigned int y) const; + + //////////////////////////////////////////////////////////// + /// \brief Get a read-only pointer to the array of pixels + /// + /// The returned value points to an array of RGBA pixels made of + /// 8 bits integers components. The size of the array is + /// width * height * 4 (getSize().x * getSize().y * 4). + /// Warning: the returned pointer may become invalid if you + /// modify the image, so you should never store it for too long. + /// If the image is empty, a null pointer is returned. + /// + /// \return Read-only pointer to the array of pixels + /// + //////////////////////////////////////////////////////////// + const Uint8* getPixelsPtr() const; + + //////////////////////////////////////////////////////////// + /// \brief Flip the image horizontally (left <-> right) + /// + //////////////////////////////////////////////////////////// + void flipHorizontally(); + + //////////////////////////////////////////////////////////// + /// \brief Flip the image vertically (top <-> bottom) + /// + //////////////////////////////////////////////////////////// + void flipVertically(); + +private : + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + Vector2u m_size; ///< Image size + std::vector m_pixels; ///< Pixels of the image +}; + +} // namespace sf + + +#endif // SFML_IMAGE_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Image +/// \ingroup graphics +/// +/// sf::Image is an abstraction to manipulate images +/// as bidimensional arrays of pixels. The class provides +/// functions to load, read, write and save pixels, as well +/// as many other useful functions. +/// +/// sf::Image can handle a unique internal representation of +/// pixels, which is RGBA 32 bits. This means that a pixel +/// must be composed of 8 bits red, green, blue and alpha +/// channels -- just like a sf::Color. +/// All the functions that return an array of pixels follow +/// this rule, and all parameters that you pass to sf::Image +/// functions (such as loadFromPixels) must use this +/// representation as well. +/// +/// A sf::Image can be copied, but it is a heavy resource and +/// if possible you should always use [const] references to +/// pass or return them to avoid useless copies. +/// +/// Usage example: +/// \code +/// // Load an image file from a file +/// sf::Image background; +/// if (!background.loadFromFile("background.jpg")) +/// return -1; +/// +/// // Create a 20x20 image filled with black color +/// sf::Image image; +/// image.create(20, 20, sf::Color::Black); +/// +/// // Copy image1 on image2 at position (10, 10) +/// image.copy(background, 10, 10); +/// +/// // Make the top-left pixel transparent +/// sf::Color color = image.getPixel(0, 0); +/// color.a = 0; +/// image.setPixel(0, 0, color); +/// +/// // Save the image to a file +/// if (!image.saveToFile("result.png")) +/// return -1; +/// \endcode +/// +/// \see sf::Texture +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Graphics/PrimitiveType.hpp b/src/include/SFML/include/SFML/Graphics/PrimitiveType.hpp new file mode 100644 index 0000000..8f3cfb2 --- /dev/null +++ b/src/include/SFML/include/SFML/Graphics/PrimitiveType.hpp @@ -0,0 +1,53 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_PRIMITIVETYPE_HPP +#define SFML_PRIMITIVETYPE_HPP + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \ingroup graphics +/// \brief Types of primitives that a sf::VertexArray can render +/// +/// Points and lines have no area, therefore their thickness +/// will always be 1 pixel, regarldess the current transform +/// and view. +/// +//////////////////////////////////////////////////////////// +enum PrimitiveType +{ + Points, ///< List of individual points + Lines, ///< List of individual lines + LinesStrip, ///< List of connected lines, a point uses the previous point to form a line + Triangles, ///< List of individual triangles + TrianglesStrip, ///< List of connected triangles, a point uses the two previous points to form a triangle + TrianglesFan, ///< List of connected triangles, a point uses the common center and the previous point to form a triangle + Quads ///< List of individual quads +}; + +} // namespace sf + + +#endif // SFML_PRIMITIVETYPE_HPP diff --git a/src/include/SFML/include/SFML/Graphics/Rect.hpp b/src/include/SFML/include/SFML/Graphics/Rect.hpp new file mode 100644 index 0000000..09d4c87 --- /dev/null +++ b/src/include/SFML/include/SFML/Graphics/Rect.hpp @@ -0,0 +1,248 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_RECT_HPP +#define SFML_RECT_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Utility class for manipulating 2D axis aligned rectangles +/// +//////////////////////////////////////////////////////////// +template +class Rect +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Creates an empty rectangle (it is equivalent to calling + /// Rect(0, 0, 0, 0)). + /// + //////////////////////////////////////////////////////////// + Rect(); + + //////////////////////////////////////////////////////////// + /// \brief Construct the rectangle from its coordinates + /// + /// Be careful, the last two parameters are the width + /// and height, not the right and bottom coordinates! + /// + /// \param rectLeft Left coordinate of the rectangle + /// \param rectTop Top coordinate of the rectangle + /// \param rectWidth Width of the rectangle + /// \param rectHeight Height of the rectangle + /// + //////////////////////////////////////////////////////////// + Rect(T rectLeft, T rectTop, T rectWidth, T rectHeight); + + //////////////////////////////////////////////////////////// + /// \brief Construct the rectangle from position and size + /// + /// Be careful, the last parameter is the size, + /// not the bottom-right corner! + /// + /// \param position Position of the top-left corner of the rectangle + /// \param size Size of the rectangle + /// + //////////////////////////////////////////////////////////// + Rect(const Vector2& position, const Vector2& size); + + //////////////////////////////////////////////////////////// + /// \brief Construct the rectangle from another type of rectangle + /// + /// This constructor doesn't replace the copy constructor, + /// it's called only when U != T. + /// A call to this constructor will fail to compile if U + /// is not convertible to T. + /// + /// \param rectangle Rectangle to convert + /// + //////////////////////////////////////////////////////////// + template + explicit Rect(const Rect& rectangle); + + //////////////////////////////////////////////////////////// + /// \brief Check if a point is inside the rectangle's area + /// + /// \param x X coordinate of the point to test + /// \param y Y coordinate of the point to test + /// + /// \return True if the point is inside, false otherwise + /// + /// \see intersects + /// + //////////////////////////////////////////////////////////// + bool contains(T x, T y) const; + + //////////////////////////////////////////////////////////// + /// \brief Check if a point is inside the rectangle's area + /// + /// \param point Point to test + /// + /// \return True if the point is inside, false otherwise + /// + /// \see intersects + /// + //////////////////////////////////////////////////////////// + bool contains(const Vector2& point) const; + + //////////////////////////////////////////////////////////// + /// \brief Check the intersection between two rectangles + /// + /// \param rectangle Rectangle to test + /// + /// \return True if rectangles overlap, false otherwise + /// + /// \see contains + /// + //////////////////////////////////////////////////////////// + bool intersects(const Rect& rectangle) const; + + //////////////////////////////////////////////////////////// + /// \brief Check the intersection between two rectangles + /// + /// This overload returns the overlapped rectangle in the + /// \a intersection parameter. + /// + /// \param rectangle Rectangle to test + /// \param intersection Rectangle to be filled with the intersection + /// + /// \return True if rectangles overlap, false otherwise + /// + /// \see contains + /// + //////////////////////////////////////////////////////////// + bool intersects(const Rect& rectangle, Rect& intersection) const; + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + T left; ///< Left coordinate of the rectangle + T top; ///< Top coordinate of the rectangle + T width; ///< Width of the rectangle + T height; ///< Height of the rectangle +}; + +//////////////////////////////////////////////////////////// +/// \relates Rect +/// \brief Overload of binary operator == +/// +/// This operator compares strict equality between two rectangles. +/// +/// \param left Left operand (a rectangle) +/// \param right Right operand (a rectangle) +/// +/// \return True if \a left is equal to \a right +/// +//////////////////////////////////////////////////////////// +template +bool operator ==(const Rect& left, const Rect& right); + +//////////////////////////////////////////////////////////// +/// \relates Rect +/// \brief Overload of binary operator != +/// +/// This operator compares strict difference between two rectangles. +/// +/// \param left Left operand (a rectangle) +/// \param right Right operand (a rectangle) +/// +/// \return True if \a left is not equal to \a right +/// +//////////////////////////////////////////////////////////// +template +bool operator !=(const Rect& left, const Rect& right); + +#include + +// Create typedefs for the most common types +typedef Rect IntRect; +typedef Rect FloatRect; + +} // namespace sf + + +#endif // SFML_RECT_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Rect +/// \ingroup graphics +/// +/// A rectangle is defined by its top-left corner and its size. +/// It is a very simple class defined for convenience, so +/// its member variables (left, top, width and height) are public +/// and can be accessed directly, just like the vector classes +/// (Vector2 and Vector3). +/// +/// To keep things simple, sf::Rect doesn't define +/// functions to emulate the properties that are not directly +/// members (such as right, bottom, center, etc.), it rather +/// only provides intersection functions. +/// +/// sf::Rect uses the usual rules for its boundaries: +/// \li The left and top edges are included in the rectangle's area +/// \li The right (left + width) and bottom (top + height) edges are excluded from the rectangle's area +/// +/// This means that sf::IntRect(0, 0, 1, 1) and sf::IntRect(1, 1, 1, 1) +/// don't intersect. +/// +/// sf::Rect is a template and may be used with any numeric type, but +/// for simplicity the instanciations used by SFML are typedefed: +/// \li sf::Rect is sf::IntRect +/// \li sf::Rect is sf::FloatRect +/// +/// So that you don't have to care about the template syntax. +/// +/// Usage example: +/// \code +/// // Define a rectangle, located at (0, 0) with a size of 20x5 +/// sf::IntRect r1(0, 0, 20, 5); +/// +/// // Define another rectangle, located at (4, 2) with a size of 18x10 +/// sf::Vector2i position(4, 2); +/// sf::Vector2i size(18, 10); +/// sf::IntRect r2(position, size); +/// +/// // Test intersections with the point (3, 1) +/// bool b1 = r1.contains(3, 1); // true +/// bool b2 = r2.contains(3, 1); // false +/// +/// // Test the intersection between r1 and r2 +/// sf::IntRect result; +/// bool b3 = r1.intersects(r2, result); // true +/// // result == (4, 2, 16, 3) +/// \endcode +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Graphics/Rect.inl b/src/include/SFML/include/SFML/Graphics/Rect.inl new file mode 100644 index 0000000..2b99124 --- /dev/null +++ b/src/include/SFML/include/SFML/Graphics/Rect.inl @@ -0,0 +1,159 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2012 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////// +template +Rect::Rect() : +left (0), +top (0), +width (0), +height(0) +{ + +} + + +//////////////////////////////////////////////////////////// +template +Rect::Rect(T rectLeft, T rectTop, T rectWidth, T rectHeight) : +left (rectLeft), +top (rectTop), +width (rectWidth), +height(rectHeight) +{ + +} + + +//////////////////////////////////////////////////////////// +template +Rect::Rect(const Vector2& position, const Vector2& size) : +left (position.x), +top (position.y), +width (size.x), +height(size.y) +{ + +} + + +//////////////////////////////////////////////////////////// +template +template +Rect::Rect(const Rect& rectangle) : +left (static_cast(rectangle.left)), +top (static_cast(rectangle.top)), +width (static_cast(rectangle.width)), +height(static_cast(rectangle.height)) +{ +} + + +//////////////////////////////////////////////////////////// +template +bool Rect::contains(T x, T y) const +{ + // Rectangles with negative dimensions are allowed, so we must handle them correctly + + // Compute the real min and max of the rectangle on both axes + T minX = std::min(left, left + width); + T maxX = std::max(left, left + width); + T minY = std::min(top, top + height); + T maxY = std::max(top, top + height); + + return (x >= minX) && (x < maxX) && (y >= minY) && (y < maxY); +} + + +//////////////////////////////////////////////////////////// +template +bool Rect::contains(const Vector2& point) const +{ + return contains(point.x, point.y); +} + + +//////////////////////////////////////////////////////////// +template +bool Rect::intersects(const Rect& rectangle) const +{ + Rect intersection; + return intersects(rectangle, intersection); +} + + +//////////////////////////////////////////////////////////// +template +bool Rect::intersects(const Rect& rectangle, Rect& intersection) const +{ + // Rectangles with negative dimensions are allowed, so we must handle them correctly + + // Compute the min and max of the first rectangle on both axes + T r1MinX = std::min(left, left + width); + T r1MaxX = std::max(left, left + width); + T r1MinY = std::min(top, top + height); + T r1MaxY = std::max(top, top + height); + + // Compute the min and max of the second rectangle on both axes + T r2MinX = std::min(rectangle.left, rectangle.left + rectangle.width); + T r2MaxX = std::max(rectangle.left, rectangle.left + rectangle.width); + T r2MinY = std::min(rectangle.top, rectangle.top + rectangle.height); + T r2MaxY = std::max(rectangle.top, rectangle.top + rectangle.height); + + // Compute the intersection boundaries + T interLeft = std::max(r1MinX, r2MinX); + T interTop = std::max(r1MinY, r2MinY); + T interRight = std::min(r1MaxX, r2MaxX); + T interBottom = std::min(r1MaxY, r2MaxY); + + // If the intersection is valid (positive non zero area), then there is an intersection + if ((interLeft < interRight) && (interTop < interBottom)) + { + intersection = Rect(interLeft, interTop, interRight - interLeft, interBottom - interTop); + return true; + } + else + { + intersection = Rect(0, 0, 0, 0); + return false; + } +} + + +//////////////////////////////////////////////////////////// +template +inline bool operator ==(const Rect& left, const Rect& right) +{ + return (left.left == right.left) && (left.width == right.width) && + (left.top == right.top) && (left.height == right.height); +} + + +//////////////////////////////////////////////////////////// +template +inline bool operator !=(const Rect& left, const Rect& right) +{ + return !(left == right); +} diff --git a/src/include/SFML/include/SFML/Graphics/RectangleShape.hpp b/src/include/SFML/include/SFML/Graphics/RectangleShape.hpp new file mode 100644 index 0000000..2140e91 --- /dev/null +++ b/src/include/SFML/include/SFML/Graphics/RectangleShape.hpp @@ -0,0 +1,128 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_RECTANGLESHAPE_HPP +#define SFML_RECTANGLESHAPE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Specialized shape representing a rectangle +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API RectangleShape : public Shape +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// \param size Size of the rectangle + /// + //////////////////////////////////////////////////////////// + explicit RectangleShape(const Vector2f& size = Vector2f(0, 0)); + + //////////////////////////////////////////////////////////// + /// \brief Set the size of the rectangle + /// + /// \param size New size of the rectangle + /// + /// \see getSize + /// + //////////////////////////////////////////////////////////// + void setSize(const Vector2f& size); + + //////////////////////////////////////////////////////////// + /// \brief Get the size of the rectangle + /// + /// \return Size of the rectangle + /// + /// \see setSize + /// + //////////////////////////////////////////////////////////// + const Vector2f& getSize() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the number of points defining the shape + /// + /// \return Number of points of the shape + /// + //////////////////////////////////////////////////////////// + virtual unsigned int getPointCount() const; + + //////////////////////////////////////////////////////////// + /// \brief Get a point of the shape + /// + /// The result is undefined if \a index is out of the valid range. + /// + /// \param index Index of the point to get, in range [0 .. getPointCount() - 1] + /// + /// \return Index-th point of the shape + /// + //////////////////////////////////////////////////////////// + virtual Vector2f getPoint(unsigned int index) const; + +private : + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + Vector2f m_size; ///< Size of the rectangle +}; + +} // namespace sf + + +#endif // SFML_RECTANGLESHAPE_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::RectangleShape +/// \ingroup graphics +/// +/// This class inherits all the functions of sf::Transformable +/// (position, rotation, scale, bounds, ...) as well as the +/// functions of sf::Shape (outline, color, texture, ...). +/// +/// Usage example: +/// \code +/// sf::RectangleShape rectangle; +/// rectangle.setSize(sf::Vector2f(100, 50)); +/// rectangle.setOutlineColor(sf::Color::Red); +/// rectangle.setOutlineThickness(5); +/// rectangle.setPosition(10, 20); +/// ... +/// window.draw(rectangle); +/// \endcode +/// +/// \see sf::Shape, sf::CircleShape, sf::ConvexShape +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Graphics/RenderStates.hpp b/src/include/SFML/include/SFML/Graphics/RenderStates.hpp new file mode 100644 index 0000000..bf4183c --- /dev/null +++ b/src/include/SFML/include/SFML/Graphics/RenderStates.hpp @@ -0,0 +1,174 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_RENDERSTATES_HPP +#define SFML_RENDERSTATES_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +class Shader; +class Texture; + +//////////////////////////////////////////////////////////// +/// \brief Define the states used for drawing to a RenderTarget +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API RenderStates +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Constructing a default set of render states is equivalent + /// to using sf::RenderStates::Default. + /// The default set defines: + /// \li the BlendAlpha blend mode + /// \li the identity transform + /// \li a null texture + /// \li a null shader + /// + //////////////////////////////////////////////////////////// + RenderStates(); + + //////////////////////////////////////////////////////////// + /// \brief Construct a default set of render states with a custom blend mode + /// + /// \param theBlendMode Blend mode to use + /// + //////////////////////////////////////////////////////////// + RenderStates(BlendMode theBlendMode); + + //////////////////////////////////////////////////////////// + /// \brief Construct a default set of render states with a custom transform + /// + /// \param theTransform Transform to use + /// + //////////////////////////////////////////////////////////// + RenderStates(const Transform& theTransform); + + //////////////////////////////////////////////////////////// + /// \brief Construct a default set of render states with a custom texture + /// + /// \param theTexture Texture to use + /// + //////////////////////////////////////////////////////////// + RenderStates(const Texture* theTexture); + + //////////////////////////////////////////////////////////// + /// \brief Construct a default set of render states with a custom shader + /// + /// \param theShader Shader to use + /// + //////////////////////////////////////////////////////////// + RenderStates(const Shader* theShader); + + //////////////////////////////////////////////////////////// + /// \brief Construct a set of render states with all its attributes + /// + /// \param theBlendMode Blend mode to use + /// \param theTransform Transform to use + /// \param theTexture Texture to use + /// \param theShader Shader to use + /// + //////////////////////////////////////////////////////////// + RenderStates(BlendMode theBlendMode, const Transform& theTransform, + const Texture* theTexture, const Shader* theShader); + + //////////////////////////////////////////////////////////// + // Static member data + //////////////////////////////////////////////////////////// + static const RenderStates Default; ///< Special instance holding the default render states + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + BlendMode blendMode; ///< Blending mode + Transform transform; ///< Transform + const Texture* texture; ///< Texture + const Shader* shader; ///< Shader +}; + +} // namespace sf + + +#endif // SFML_RENDERSTATES_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::RenderStates +/// \ingroup graphics +/// +/// There are four global states that can be applied to +/// the drawn objects: +/// \li the blend mode: how pixels of the object are blended with the background +/// \li the transform: how the object is positioned/rotated/scaled +/// \li the texture: what image is mapped to the object +/// \li the shader: what custom effect is applied to the object +/// +/// High-level objects such as sprites or text force some of +/// these states when they are drawn. For example, a sprite +/// will set its own texture, so that you don't have to care +/// about it when drawing the sprite. +/// +/// The transform is a special case: sprites, texts and shapes +/// (and it's a good idea to do it with your own drawable classes +/// too) combine their transform with the one that is passed in the +/// RenderStates structure. So that you can use a "global" transform +/// on top of each object's transform. +/// +/// Most objects, especially high-level drawables, can be drawn +/// directly without defining render states explicitely -- the +/// default set of states is ok in most cases. +/// \code +/// window.Draw(sprite); +/// \endcode +/// +/// If you want to use a single specific render state, +/// for example a shader, you can pass it directly to the Draw +/// function: sf::RenderStates has an implicit one-argument +/// constructor for each state. +/// \code +/// window.draw(sprite, shader); +/// \endcode +/// +/// When you're inside the Draw function of a drawable +/// object (inherited from sf::Drawable), you can +/// either pass the render states unmodified, or change +/// some of them. +/// For example, a transformable object will combine the +/// current transform with its own transform. A sprite will +/// set its texture. Etc. +/// +/// \see sf::RenderTarget, sf::Drawable +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Graphics/RenderTarget.hpp b/src/include/SFML/include/SFML/Graphics/RenderTarget.hpp new file mode 100644 index 0000000..a9d5cea --- /dev/null +++ b/src/include/SFML/include/SFML/Graphics/RenderTarget.hpp @@ -0,0 +1,451 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_RENDERTARGET_HPP +#define SFML_RENDERTARGET_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace sf +{ +class Drawable; + +//////////////////////////////////////////////////////////// +/// \brief Base class for all render targets (window, texture, ...) +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API RenderTarget : NonCopyable +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + virtual ~RenderTarget(); + + //////////////////////////////////////////////////////////// + /// \brief Clear the entire target with a single color + /// + /// This function is usually called once every frame, + /// to clear the previous contents of the target. + /// + /// \param color Fill color to use to clear the render target + /// + //////////////////////////////////////////////////////////// + void clear(const Color& color = Color(0, 0, 0, 255)); + + //////////////////////////////////////////////////////////// + /// \brief Change the current active view + /// + /// The view is like a 2D camera, it controls which part of + /// the 2D scene is visible, and how it is viewed in the + /// render-target. + /// The new view will affect everything that is drawn, until + /// another view is set. + /// The render target keeps its own copy of the view object, + /// so it is not necessary to keep the original one alive + /// after calling this function. + /// To restore the original view of the target, you can pass + /// the result of getDefaultView() to this function. + /// + /// \param view New view to use + /// + /// \see getView, getDefaultView + /// + //////////////////////////////////////////////////////////// + void setView(const View& view); + + //////////////////////////////////////////////////////////// + /// \brief Get the view currently in use in the render target + /// + /// \return The view object that is currently used + /// + /// \see setView, getDefaultView + /// + //////////////////////////////////////////////////////////// + const View& getView() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the default view of the render target + /// + /// The default view has the initial size of the render target, + /// and never changes after the target has been created. + /// + /// \return The default view of the render target + /// + /// \see setView, getView + /// + //////////////////////////////////////////////////////////// + const View& getDefaultView() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the viewport of a view, applied to this render target + /// + /// The viewport is defined in the view as a ratio, this function + /// simply applies this ratio to the current dimensions of the + /// render target to calculate the pixels rectangle that the viewport + /// actually covers in the target. + /// + /// \param view The view for which we want to compute the viewport + /// + /// \return Viewport rectangle, expressed in pixels + /// + //////////////////////////////////////////////////////////// + IntRect getViewport(const View& view) const; + + //////////////////////////////////////////////////////////// + /// \brief Convert a point from target coordinates to world + /// coordinates, using the current view + /// + /// This function is an overload of the mapPixelToCoords + /// function that implicitely uses the current view. + /// It is equivalent to: + /// \code + /// target.mapPixelToCoords(point, target.getView()); + /// \endcode + /// + /// \param point Pixel to convert + /// + /// \return The converted point, in "world" coordinates + /// + /// \see mapCoordsToPixel + /// + //////////////////////////////////////////////////////////// + Vector2f mapPixelToCoords(const Vector2i& point) const; + + //////////////////////////////////////////////////////////// + /// \brief Convert a point from target coordinates to world coordinates + /// + /// This function finds the 2D position that matches the + /// given pixel of the render-target. In other words, it does + /// the inverse of what the graphics card does, to find the + /// initial position of a rendered pixel. + /// + /// Initially, both coordinate systems (world units and target pixels) + /// match perfectly. But if you define a custom view or resize your + /// render-target, this assertion is not true anymore, ie. a point + /// located at (10, 50) in your render-target may map to the point + /// (150, 75) in your 2D world -- if the view is translated by (140, 25). + /// + /// For render-windows, this function is typically used to find + /// which point (or object) is located below the mouse cursor. + /// + /// This version uses a custom view for calculations, see the other + /// overload of the function if you want to use the current view of the + /// render-target. + /// + /// \param point Pixel to convert + /// \param view The view to use for converting the point + /// + /// \return The converted point, in "world" units + /// + /// \see mapCoordsToPixel + /// + //////////////////////////////////////////////////////////// + Vector2f mapPixelToCoords(const Vector2i& point, const View& view) const; + + //////////////////////////////////////////////////////////// + /// \brief Convert a point from world coordinates to target + /// coordinates, using the current view + /// + /// This function is an overload of the mapCoordsToPixel + /// function that implicitely uses the current view. + /// It is equivalent to: + /// \code + /// target.mapCoordsToPixel(point, target.getView()); + /// \endcode + /// + /// \param point Point to convert + /// + /// \return The converted point, in target coordinates (pixels) + /// + /// \see mapPixelToCoords + /// + //////////////////////////////////////////////////////////// + Vector2i mapCoordsToPixel(const Vector2f& point) const; + + //////////////////////////////////////////////////////////// + /// \brief Convert a point from world coordinates to target coordinates + /// + /// This function finds the pixel of the render-target that matches + /// the given 2D point. In other words, it goes through the same process + /// as the graphics card, to compute the final position of a rendered point. + /// + /// Initially, both coordinate systems (world units and target pixels) + /// match perfectly. But if you define a custom view or resize your + /// render-target, this assertion is not true anymore, ie. a point + /// located at (150, 75) in your 2D world may map to the pixel + /// (10, 50) of your render-target -- if the view is translated by (140, 25). + /// + /// This version uses a custom view for calculations, see the other + /// overload of the function if you want to use the current view of the + /// render-target. + /// + /// \param point Point to convert + /// \param view The view to use for converting the point + /// + /// \return The converted point, in target coordinates (pixels) + /// + /// \see mapPixelToCoords + /// + //////////////////////////////////////////////////////////// + Vector2i mapCoordsToPixel(const Vector2f& point, const View& view) const; + + //////////////////////////////////////////////////////////// + /// \brief Draw a drawable object to the render-target + /// + /// \param drawable Object to draw + /// \param states Render states to use for drawing + /// + //////////////////////////////////////////////////////////// + void draw(const Drawable& drawable, const RenderStates& states = RenderStates::Default); + + //////////////////////////////////////////////////////////// + /// \brief Draw primitives defined by an array of vertices + /// + /// \param vertices Pointer to the vertices + /// \param vertexCount Number of vertices in the array + /// \param type Type of primitives to draw + /// \param states Render states to use for drawing + /// + //////////////////////////////////////////////////////////// + void draw(const Vertex* vertices, unsigned int vertexCount, + PrimitiveType type, const RenderStates& states = RenderStates::Default); + + //////////////////////////////////////////////////////////// + /// \brief Return the size of the rendering region of the target + /// + /// \return Size in pixels + /// + //////////////////////////////////////////////////////////// + virtual Vector2u getSize() const = 0; + + //////////////////////////////////////////////////////////// + /// \brief Save the current OpenGL render states and matrices + /// + /// This function can be used when you mix SFML drawing + /// and direct OpenGL rendering. Combined with PopGLStates, + /// it ensures that: + /// \li SFML's internal states are not messed up by your OpenGL code + /// \li your OpenGL states are not modified by a call to a SFML function + /// + /// More specifically, it must be used around code that + /// calls Draw functions. Example: + /// \code + /// // OpenGL code here... + /// window.pushGLStates(); + /// window.draw(...); + /// window.draw(...); + /// window.popGLStates(); + /// // OpenGL code here... + /// \endcode + /// + /// Note that this function is quite expensive: it saves all the + /// possible OpenGL states and matrices, even the ones you + /// don't care about. Therefore it should be used wisely. + /// It is provided for convenience, but the best results will + /// be achieved if you handle OpenGL states yourself (because + /// you know which states have really changed, and need to be + /// saved and restored). Take a look at the ResetGLStates + /// function if you do so. + /// + /// \see popGLStates + /// + //////////////////////////////////////////////////////////// + void pushGLStates(); + + //////////////////////////////////////////////////////////// + /// \brief Restore the previously saved OpenGL render states and matrices + /// + /// See the description of pushGLStates to get a detailed + /// description of these functions. + /// + /// \see pushGLStates + /// + //////////////////////////////////////////////////////////// + void popGLStates(); + + //////////////////////////////////////////////////////////// + /// \brief Reset the internal OpenGL states so that the target is ready for drawing + /// + /// This function can be used when you mix SFML drawing + /// and direct OpenGL rendering, if you choose not to use + /// pushGLStates/popGLStates. It makes sure that all OpenGL + /// states needed by SFML are set, so that subsequent draw() + /// calls will work as expected. + /// + /// Example: + /// \code + /// // OpenGL code here... + /// glPushAttrib(...); + /// window.resetGLStates(); + /// window.draw(...); + /// window.draw(...); + /// glPopAttrib(...); + /// // OpenGL code here... + /// \endcode + /// + //////////////////////////////////////////////////////////// + void resetGLStates(); + +protected : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + RenderTarget(); + + //////////////////////////////////////////////////////////// + /// \brief Performs the common initialization step after creation + /// + /// The derived classes must call this function after the + /// target is created and ready for drawing. + /// + //////////////////////////////////////////////////////////// + void initialize(); + +private: + + //////////////////////////////////////////////////////////// + /// \brief Apply the current view + /// + //////////////////////////////////////////////////////////// + void applyCurrentView(); + + //////////////////////////////////////////////////////////// + /// \brief Apply a new blending mode + /// + /// \param mode Blending mode to apply + /// + //////////////////////////////////////////////////////////// + void applyBlendMode(BlendMode mode); + + //////////////////////////////////////////////////////////// + /// \brief Apply a new transform + /// + /// \param transform Transform to apply + /// + //////////////////////////////////////////////////////////// + void applyTransform(const Transform& transform); + + //////////////////////////////////////////////////////////// + /// \brief Apply a new texture + /// + /// \param texture Texture to apply + /// + //////////////////////////////////////////////////////////// + void applyTexture(const Texture* texture); + + //////////////////////////////////////////////////////////// + /// \brief Apply a new shader + /// + /// \param shader Shader to apply + /// + //////////////////////////////////////////////////////////// + void applyShader(const Shader* shader); + + //////////////////////////////////////////////////////////// + /// \brief Activate the target for rendering + /// + /// This function must be implemented by derived classes to make + /// their OpenGL context current; it is called by the base class + /// everytime it's going to use OpenGL calls. + /// + /// \param active True to make the target active, false to deactivate it + /// + /// \return True if the function succeeded + /// + //////////////////////////////////////////////////////////// + virtual bool activate(bool active) = 0; + + //////////////////////////////////////////////////////////// + /// \brief Render states cache + /// + //////////////////////////////////////////////////////////// + struct StatesCache + { + enum {VertexCacheSize = 4}; + + bool glStatesSet; ///< Are our internal GL states set yet? + bool viewChanged; ///< Has the current view changed since last draw? + BlendMode lastBlendMode; ///< Cached blending mode + Uint64 lastTextureId; ///< Cached texture + bool useVertexCache; ///< Did we previously use the vertex cache? + Vertex vertexCache[VertexCacheSize]; ///< Pre-transformed vertices cache + }; + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + View m_defaultView; ///< Default view + View m_view; ///< Current view + StatesCache m_cache; ///< Render states cache +}; + +} // namespace sf + + +#endif // SFML_RENDERTARGET_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::RenderTarget +/// \ingroup graphics +/// +/// sf::RenderTarget defines the common behaviour of all the +/// 2D render targets usable in the graphics module. It makes +/// it possible to draw 2D entities like sprites, shapes, text +/// without using any OpenGL command directly. +/// +/// A sf::RenderTarget is also able to use views (sf::View), +/// which are a kind of 2D cameras. With views you can globally +/// scroll, rotate or zoom everything that is drawn, +/// without having to transform every single entity. See the +/// documentation of sf::View for more details and sample pieces of +/// code about this class. +/// +/// On top of that, render targets are still able to render direct +/// OpenGL stuff. It is even possible to mix together OpenGL calls +/// and regular SFML drawing commands. When doing so, make sure that +/// OpenGL states are not messed up by calling the +/// pushGLStates/popGLStates functions. +/// +/// \see sf::RenderWindow, sf::RenderTexture, sf::View +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Graphics/RenderTexture.hpp b/src/include/SFML/include/SFML/Graphics/RenderTexture.hpp new file mode 100644 index 0000000..a0c5640 --- /dev/null +++ b/src/include/SFML/include/SFML/Graphics/RenderTexture.hpp @@ -0,0 +1,280 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_RENDERTEXTURE_HPP +#define SFML_RENDERTEXTURE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +namespace priv +{ + class RenderTextureImpl; +} + +//////////////////////////////////////////////////////////// +/// \brief Target for off-screen 2D rendering into a texture +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API RenderTexture : public RenderTarget +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Constructs an empty, invalid render-texture. You must + /// call create to have a valid render-texture. + /// + /// \see create + /// + //////////////////////////////////////////////////////////// + RenderTexture(); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + virtual ~RenderTexture(); + + //////////////////////////////////////////////////////////// + /// \brief Create the render-texture + /// + /// Before calling this function, the render-texture is in + /// an invalid state, thus it is mandatory to call it before + /// doing anything with the render-texture. + /// The last parameter, \a depthBuffer, is useful if you want + /// to use the render-texture for 3D OpenGL rendering that requires + /// a depth-buffer. Otherwise it is unnecessary, and you should + /// leave this parameter to false (which is its default value). + /// + /// \param width Width of the render-texture + /// \param height Height of the render-texture + /// \param depthBuffer Do you want this render-texture to have a depth buffer? + /// + /// \return True if creation has been successful + /// + //////////////////////////////////////////////////////////// + bool create(unsigned int width, unsigned int height, bool depthBuffer = false); + + //////////////////////////////////////////////////////////// + /// \brief Enable or disable texture smoothing + /// + /// This function is similar to Texture::setSmooth. + /// This parameter is disabled by default. + /// + /// \param smooth True to enable smoothing, false to disable it + /// + /// \see isSmooth + /// + //////////////////////////////////////////////////////////// + void setSmooth(bool smooth); + + //////////////////////////////////////////////////////////// + /// \brief Tell whether the smooth filtering is enabled or not + /// + /// \return True if texture smoothing is enabled + /// + /// \see setSmooth + /// + //////////////////////////////////////////////////////////// + bool isSmooth() const; + + //////////////////////////////////////////////////////////// + /// \brief Enable or disable texture repeating + /// + /// This function is similar to Texture::setRepeated. + /// This parameter is disabled by default. + /// + /// \param repeated True to enable repeating, false to disable it + /// + /// \see isRepeated + /// + //////////////////////////////////////////////////////////// + void setRepeated(bool repeated); + + //////////////////////////////////////////////////////////// + /// \brief Tell whether the texture is repeated or not + /// + /// \return True if texture is repeated + /// + /// \see setRepeated + /// + //////////////////////////////////////////////////////////// + bool isRepeated() const; + + //////////////////////////////////////////////////////////// + /// \brief Activate of deactivate the render-texture for rendering + /// + /// This function makes the render-texture's context current for + /// future OpenGL rendering operations (so you shouldn't care + /// about it if you're not doing direct OpenGL stuff). + /// Only one context can be current in a thread, so if you + /// want to draw OpenGL geometry to another render target + /// (like a RenderWindow) don't forget to activate it again. + /// + /// \param active True to activate, false to deactivate + /// + /// \return True if operation was successful, false otherwise + /// + //////////////////////////////////////////////////////////// + bool setActive(bool active = true); + + //////////////////////////////////////////////////////////// + /// \brief Update the contents of the target texture + /// + /// This function updates the target texture with what + /// has been drawn so far. Like for windows, calling this + /// function is mandatory at the end of rendering. Not calling + /// it may leave the texture in an undefined state. + /// + //////////////////////////////////////////////////////////// + void display(); + + //////////////////////////////////////////////////////////// + /// \brief Return the size of the rendering region of the texture + /// + /// The returned value is the size that you passed to + /// the create function. + /// + /// \return Size in pixels + /// + //////////////////////////////////////////////////////////// + virtual Vector2u getSize() const; + + //////////////////////////////////////////////////////////// + /// \brief Get a read-only reference to the target texture + /// + /// After drawing to the render-texture and calling Display, + /// you can retrieve the updated texture using this function, + /// and draw it using a sprite (for example). + /// The internal sf::Texture of a render-texture is always the + /// same instance, so that it is possible to call this function + /// once and keep a reference to the texture even after it is + /// modified. + /// + /// \return Const reference to the texture + /// + //////////////////////////////////////////////////////////// + const Texture& getTexture() const; + +private : + + //////////////////////////////////////////////////////////// + /// \brief Activate the target for rendering + /// + /// This function is called by the base class + /// everytime it's going to use OpenGL calls. + /// + /// \param active True to make the target active, false to deactivate it + /// + /// \return True if the function succeeded + /// + //////////////////////////////////////////////////////////// + virtual bool activate(bool active); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + priv::RenderTextureImpl* m_impl; ///< Platform/hardware specific implementation + Texture m_texture; ///< Target texture to draw on +}; + +} // namespace sf + + +#endif // SFML_RENDERTEXTURE_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::RenderTexture +/// \ingroup graphics +/// +/// sf::RenderTexture is the little brother of sf::RenderWindow. +/// It implements the same 2D drawing and OpenGL-related functions +/// (see their base class sf::RenderTarget for more details), +/// the difference is that the result is stored in an off-screen +/// texture rather than being show in a window. +/// +/// Rendering to a texture can be useful in a variety of situations: +/// \li precomputing a complex static texture (like a level's background from multiple tiles) +/// \li applying post-effects to the whole scene with shaders +/// \li creating a sprite from a 3D object rendered with OpenGL +/// \li etc. +/// +/// Usage example: +/// +/// \code +/// // Create a new render-window +/// sf::RenderWindow window(sf::VideoMode(800, 600), "SFML window"); +/// +/// // Create a new render-texture +/// sf::RenderTexture texture; +/// if (!texture.create(500, 500)) +/// return -1; +/// +/// // The main loop +/// while (window.isOpen()) +/// { +/// // Event processing +/// // ... +/// +/// // Clear the whole texture with red color +/// texture.clear(sf::Color::Red); +/// +/// // Draw stuff to the texture +/// texture.draw(sprite); // sprite is a sf::Sprite +/// texture.draw(shape); // shape is a sf::Shape +/// texture.draw(text); // text is a sf::Text +/// +/// // We're done drawing to the texture +/// texture.display(); +/// +/// // Now we start rendering to the window, clear it first +/// window.clear(); +/// +/// // Draw the texture +/// sf::Sprite sprite(texture.getTexture()); +/// window.draw(sprite); +/// +/// // End the current frame and display its contents on screen +/// window.display(); +/// } +/// \endcode +/// +/// Like sf::RenderWindow, sf::RenderTexture is still able to render direct +/// OpenGL stuff. It is even possible to mix together OpenGL calls +/// and regular SFML drawing commands. If you need a depth buffer for +/// 3D rendering, don't forget to request it when calling RenderTexture::create. +/// +/// \see sf::RenderTarget, sf::RenderWindow, sf::View, sf::Texture +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Graphics/RenderWindow.hpp b/src/include/SFML/include/SFML/Graphics/RenderWindow.hpp new file mode 100644 index 0000000..64d1bad --- /dev/null +++ b/src/include/SFML/include/SFML/Graphics/RenderWindow.hpp @@ -0,0 +1,266 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_RENDERWINDOW_HPP +#define SFML_RENDERWINDOW_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Window that can serve as a target for 2D drawing +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API RenderWindow : public Window, public RenderTarget +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// This constructor doesn't actually create the window, + /// use the other constructors or call "create" to do so. + /// + //////////////////////////////////////////////////////////// + RenderWindow(); + + //////////////////////////////////////////////////////////// + /// \brief Construct a new window + /// + /// This constructor creates the window with the size and pixel + /// depth defined in \a mode. An optional style can be passed to + /// customize the look and behaviour of the window (borders, + /// title bar, resizable, closable, ...). + /// + /// The fourth parameter is an optional structure specifying + /// advanced OpenGL context settings such as antialiasing, + /// depth-buffer bits, etc. You shouldn't care about these + /// parameters for a regular usage of the graphics module. + /// + /// \param mode Video mode to use (defines the width, height and depth of the rendering area of the window) + /// \param title Title of the window + /// \param style Window style + /// \param settings Additional settings for the underlying OpenGL context + /// + //////////////////////////////////////////////////////////// + RenderWindow(VideoMode mode, const String& title, Uint32 style = Style::Default, const ContextSettings& settings = ContextSettings()); + + //////////////////////////////////////////////////////////// + /// \brief Construct the window from an existing control + /// + /// Use this constructor if you want to create an SFML + /// rendering area into an already existing control. + /// + /// The fourth parameter is an optional structure specifying + /// advanced OpenGL context settings such as antialiasing, + /// depth-buffer bits, etc. You shouldn't care about these + /// parameters for a regular usage of the graphics module. + /// + /// \param handle Platform-specific handle of the control + /// \param settings Additional settings for the underlying OpenGL context + /// + //////////////////////////////////////////////////////////// + explicit RenderWindow(WindowHandle handle, const ContextSettings& settings = ContextSettings()); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + /// Closes the window and free all the resources attached to it. + /// + //////////////////////////////////////////////////////////// + virtual ~RenderWindow(); + + //////////////////////////////////////////////////////////// + /// \brief Get the size of the rendering region of the window + /// + /// The size doesn't include the titlebar and borders + /// of the window. + /// + /// \return Size in pixels + /// + //////////////////////////////////////////////////////////// + virtual Vector2u getSize() const; + + //////////////////////////////////////////////////////////// + /// \brief Copy the current contents of the window to an image + /// + /// This is a slow operation, whose main purpose is to make + /// screenshots of the application. If you want to update an + /// image with the contents of the window and then use it for + /// drawing, you should rather use a sf::Texture and its + /// update(Window&) function. + /// You can also draw things directly to a texture with the + /// sf::RenderTexture class. + /// + /// \return Image containing the captured contents + /// + //////////////////////////////////////////////////////////// + Image capture() const; + +protected: + + //////////////////////////////////////////////////////////// + /// \brief Function called after the window has been created + /// + /// This function is called so that derived classes can + /// perform their own specific initialization as soon as + /// the window is created. + /// + //////////////////////////////////////////////////////////// + virtual void onCreate(); + + //////////////////////////////////////////////////////////// + /// \brief Function called after the window has been resized + /// + /// This function is called so that derived classes can + /// perform custom actions when the size of the window changes. + /// + //////////////////////////////////////////////////////////// + virtual void onResize(); + +private : + + //////////////////////////////////////////////////////////// + /// \brief Activate the target for rendering + /// + /// \param active True to make the target active, false to deactivate it + /// + /// \return True if the function succeeded + /// + //////////////////////////////////////////////////////////// + virtual bool activate(bool active); +}; + +} // namespace sf + + +#endif // SFML_RENDERWINDOW_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::RenderWindow +/// \ingroup graphics +/// +/// sf::RenderWindow is the main class of the Graphics module. +/// It defines an OS window that can be painted using the other +/// classes of the graphics module. +/// +/// sf::RenderWindow is derived from sf::Window, thus it inherits +/// all its features: events, window management, OpenGL rendering, +/// etc. See the documentation of sf::Window for a more complete +/// description of all these features, as well as code examples. +/// +/// On top of that, sf::RenderWindow adds more features related to +/// 2D drawing with the graphics module (see its base class +/// sf::RenderTarget for more details). +/// Here is a typical rendering and event loop with a sf::RenderWindow: +/// +/// \code +/// // Declare and create a new render-window +/// sf::RenderWindow window(sf::VideoMode(800, 600), "SFML window"); +/// +/// // Limit the framerate to 60 frames per second (this step is optional) +/// window.setFramerateLimit(60); +/// +/// // The main loop - ends as soon as the window is closed +/// while (window.isOpen()) +/// { +/// // Event processing +/// sf::Event event; +/// while (window.pollEvent(event)) +/// { +/// // Request for closing the window +/// if (event.type == sf::Event::Closed) +/// window.close(); +/// } +/// +/// // Clear the whole window before rendering a new frame +/// window.clear(); +/// +/// // Draw some graphical entities +/// window.draw(sprite); +/// window.draw(circle); +/// window.draw(text); +/// +/// // End the current frame and display its contents on screen +/// window.display(); +/// } +/// \endcode +/// +/// Like sf::Window, sf::RenderWindow is still able to render direct +/// OpenGL stuff. It is even possible to mix together OpenGL calls +/// and regular SFML drawing commands. +/// +/// \code +/// // Create the render window +/// sf::RenderWindow window(sf::VideoMode(800, 600), "SFML OpenGL"); +/// +/// // Create a sprite and a text to display +/// sf::Sprite sprite; +/// sf::Text text; +/// ... +/// +/// // Perform OpenGL initializations +/// glMatrixMode(GL_PROJECTION); +/// ... +/// +/// // Start the rendering loop +/// while (window.isOpen()) +/// { +/// // Process events +/// ... +/// +/// // Draw a background sprite +/// window.pushGLStates(); +/// window.draw(sprite); +/// window.popGLStates(); +/// +/// // Draw a 3D object using OpenGL +/// glBegin(GL_QUADS); +/// glVertex3f(...); +/// ... +/// glEnd(); +/// +/// // Draw text on top of the 3D object +/// window.pushGLStates(); +/// window.draw(text); +/// window.popGLStates(); +/// +/// // Finally, display the rendered frame on screen +/// window.display(); +/// } +/// \endcode +/// +/// \see sf::Window, sf::RenderTarget, sf::RenderTexture, sf::View +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Graphics/Shader.hpp b/src/include/SFML/include/SFML/Graphics/Shader.hpp new file mode 100644 index 0000000..17801ba --- /dev/null +++ b/src/include/SFML/include/SFML/Graphics/Shader.hpp @@ -0,0 +1,635 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SHADER_HPP +#define SFML_SHADER_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace sf +{ +class InputStream; +class Texture; + +//////////////////////////////////////////////////////////// +/// \brief Shader class (vertex and fragment) +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API Shader : GlResource, NonCopyable +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Types of shaders + /// + //////////////////////////////////////////////////////////// + enum Type + { + Vertex, ///< Vertex shader + Fragment ///< Fragment (pixel) shader + }; + + //////////////////////////////////////////////////////////// + /// \brief Special type/value that can be passed to setParameter, + /// and that represents the texture of the object being drawn + /// + //////////////////////////////////////////////////////////// + struct CurrentTextureType {}; + static CurrentTextureType CurrentTexture; + +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// This constructor creates an invalid shader. + /// + //////////////////////////////////////////////////////////// + Shader(); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~Shader(); + + //////////////////////////////////////////////////////////// + /// \brief Load either the vertex or fragment shader from a file + /// + /// This function loads a single shader, either vertex or + /// fragment, identified by the second argument. + /// The source must be a text file containing a valid + /// shader in GLSL language. GLSL is a C-like language + /// dedicated to OpenGL shaders; you'll probably need to + /// read a good documentation for it before writing your + /// own shaders. + /// + /// \param filename Path of the vertex or fragment shader file to load + /// \param type Type of shader (vertex or fragment) + /// + /// \return True if loading succeeded, false if it failed + /// + /// \see loadFromMemory, loadFromStream + /// + //////////////////////////////////////////////////////////// + bool loadFromFile(const std::string& filename, Type type); + + //////////////////////////////////////////////////////////// + /// \brief Load both the vertex and fragment shaders from files + /// + /// This function loads both the vertex and the fragment + /// shaders. If one of them fails to load, the shader is left + /// empty (the valid shader is unloaded). + /// The sources must be text files containing valid shaders + /// in GLSL language. GLSL is a C-like language dedicated to + /// OpenGL shaders; you'll probably need to read a good documentation + /// for it before writing your own shaders. + /// + /// \param vertexShaderFilename Path of the vertex shader file to load + /// \param fragmentShaderFilename Path of the fragment shader file to load + /// + /// \return True if loading succeeded, false if it failed + /// + /// \see loadFromMemory, loadFromStream + /// + //////////////////////////////////////////////////////////// + bool loadFromFile(const std::string& vertexShaderFilename, const std::string& fragmentShaderFilename); + + //////////////////////////////////////////////////////////// + /// \brief Load either the vertex or fragment shader from a source code in memory + /// + /// This function loads a single shader, either vertex or + /// fragment, identified by the second argument. + /// The source code must be a valid shader in GLSL language. + /// GLSL is a C-like language dedicated to OpenGL shaders; + /// you'll probably need to read a good documentation for + /// it before writing your own shaders. + /// + /// \param shader String containing the source code of the shader + /// \param type Type of shader (vertex or fragment) + /// + /// \return True if loading succeeded, false if it failed + /// + /// \see loadFromFile, loadFromStream + /// + //////////////////////////////////////////////////////////// + bool loadFromMemory(const std::string& shader, Type type); + + //////////////////////////////////////////////////////////// + /// \brief Load both the vertex and fragment shaders from source codes in memory + /// + /// This function loads both the vertex and the fragment + /// shaders. If one of them fails to load, the shader is left + /// empty (the valid shader is unloaded). + /// The sources must be valid shaders in GLSL language. GLSL is + /// a C-like language dedicated to OpenGL shaders; you'll + /// probably need to read a good documentation for it before + /// writing your own shaders. + /// + /// \param vertexShader String containing the source code of the vertex shader + /// \param fragmentShader String containing the source code of the fragment shader + /// + /// \return True if loading succeeded, false if it failed + /// + /// \see loadFromFile, loadFromStream + /// + //////////////////////////////////////////////////////////// + bool loadFromMemory(const std::string& vertexShader, const std::string& fragmentShader); + + //////////////////////////////////////////////////////////// + /// \brief Load either the vertex or fragment shader from a custom stream + /// + /// This function loads a single shader, either vertex or + /// fragment, identified by the second argument. + /// The source code must be a valid shader in GLSL language. + /// GLSL is a C-like language dedicated to OpenGL shaders; + /// you'll probably need to read a good documentation for it + /// before writing your own shaders. + /// + /// \param stream Source stream to read from + /// \param type Type of shader (vertex or fragment) + /// + /// \return True if loading succeeded, false if it failed + /// + /// \see loadFromFile, loadFromMemory + /// + //////////////////////////////////////////////////////////// + bool loadFromStream(InputStream& stream, Type type); + + //////////////////////////////////////////////////////////// + /// \brief Load both the vertex and fragment shaders from custom streams + /// + /// This function loads both the vertex and the fragment + /// shaders. If one of them fails to load, the shader is left + /// empty (the valid shader is unloaded). + /// The source codes must be valid shaders in GLSL language. + /// GLSL is a C-like language dedicated to OpenGL shaders; + /// you'll probably need to read a good documentation for + /// it before writing your own shaders. + /// + /// \param vertexShaderStream Source stream to read the vertex shader from + /// \param fragmentShaderStream Source stream to read the fragment shader from + /// + /// \return True if loading succeeded, false if it failed + /// + /// \see loadFromFile, loadFromMemory + /// + //////////////////////////////////////////////////////////// + bool loadFromStream(InputStream& vertexShaderStream, InputStream& fragmentShaderStream); + + //////////////////////////////////////////////////////////// + /// \brief Change a float parameter of the shader + /// + /// \a name is the name of the variable to change in the shader. + /// The corresponding parameter in the shader must be a float + /// (float GLSL type). + /// + /// Example: + /// \code + /// uniform float myparam; // this is the variable in the shader + /// \endcode + /// \code + /// shader.setParameter("myparam", 5.2f); + /// \endcode + /// + /// \param name Name of the parameter in the shader + /// \param x Value to assign + /// + //////////////////////////////////////////////////////////// + void setParameter(const std::string& name, float x); + + //////////////////////////////////////////////////////////// + /// \brief Change a 2-components vector parameter of the shader + /// + /// \a name is the name of the variable to change in the shader. + /// The corresponding parameter in the shader must be a 2x1 vector + /// (vec2 GLSL type). + /// + /// Example: + /// \code + /// uniform vec2 myparam; // this is the variable in the shader + /// \endcode + /// \code + /// shader.setParameter("myparam", 5.2f, 6.0f); + /// \endcode + /// + /// \param name Name of the parameter in the shader + /// \param x First component of the value to assign + /// \param y Second component of the value to assign + /// + //////////////////////////////////////////////////////////// + void setParameter(const std::string& name, float x, float y); + + //////////////////////////////////////////////////////////// + /// \brief Change a 3-components vector parameter of the shader + /// + /// \a name is the name of the variable to change in the shader. + /// The corresponding parameter in the shader must be a 3x1 vector + /// (vec3 GLSL type). + /// + /// Example: + /// \code + /// uniform vec3 myparam; // this is the variable in the shader + /// \endcode + /// \code + /// shader.setParameter("myparam", 5.2f, 6.0f, -8.1f); + /// \endcode + /// + /// \param name Name of the parameter in the shader + /// \param x First component of the value to assign + /// \param y Second component of the value to assign + /// \param z Third component of the value to assign + /// + //////////////////////////////////////////////////////////// + void setParameter(const std::string& name, float x, float y, float z); + + //////////////////////////////////////////////////////////// + /// \brief Change a 4-components vector parameter of the shader + /// + /// \a name is the name of the variable to change in the shader. + /// The corresponding parameter in the shader must be a 4x1 vector + /// (vec4 GLSL type). + /// + /// Example: + /// \code + /// uniform vec4 myparam; // this is the variable in the shader + /// \endcode + /// \code + /// shader.setParameter("myparam", 5.2f, 6.0f, -8.1f, 0.4f); + /// \endcode + /// + /// \param name Name of the parameter in the shader + /// \param x First component of the value to assign + /// \param y Second component of the value to assign + /// \param z Third component of the value to assign + /// \param w Fourth component of the value to assign + /// + //////////////////////////////////////////////////////////// + void setParameter(const std::string& name, float x, float y, float z, float w); + + //////////////////////////////////////////////////////////// + /// \brief Change a 2-components vector parameter of the shader + /// + /// \a name is the name of the variable to change in the shader. + /// The corresponding parameter in the shader must be a 2x1 vector + /// (vec2 GLSL type). + /// + /// Example: + /// \code + /// uniform vec2 myparam; // this is the variable in the shader + /// \endcode + /// \code + /// shader.setParameter("myparam", sf::Vector2f(5.2f, 6.0f)); + /// \endcode + /// + /// \param name Name of the parameter in the shader + /// \param vector Vector to assign + /// + //////////////////////////////////////////////////////////// + void setParameter(const std::string& name, const Vector2f& vector); + + //////////////////////////////////////////////////////////// + /// \brief Change a 3-components vector parameter of the shader + /// + /// \a name is the name of the variable to change in the shader. + /// The corresponding parameter in the shader must be a 3x1 vector + /// (vec3 GLSL type). + /// + /// Example: + /// \code + /// uniform vec3 myparam; // this is the variable in the shader + /// \endcode + /// \code + /// shader.setParameter("myparam", sf::Vector3f(5.2f, 6.0f, -8.1f)); + /// \endcode + /// + /// \param name Name of the parameter in the shader + /// \param vector Vector to assign + /// + //////////////////////////////////////////////////////////// + void setParameter(const std::string& name, const Vector3f& vector); + + //////////////////////////////////////////////////////////// + /// \brief Change a color parameter of the shader + /// + /// \a name is the name of the variable to change in the shader. + /// The corresponding parameter in the shader must be a 4x1 vector + /// (vec4 GLSL type). + /// + /// It is important to note that the components of the color are + /// normalized before being passed to the shader. Therefore, + /// they are converted from range [0 .. 255] to range [0 .. 1]. + /// For example, a sf::Color(255, 125, 0, 255) will be transformed + /// to a vec4(1.0, 0.5, 0.0, 1.0) in the shader. + /// + /// Example: + /// \code + /// uniform vec4 color; // this is the variable in the shader + /// \endcode + /// \code + /// shader.setParameter("color", sf::Color(255, 128, 0, 255)); + /// \endcode + /// + /// \param name Name of the parameter in the shader + /// \param color Color to assign + /// + //////////////////////////////////////////////////////////// + void setParameter(const std::string& name, const Color& color); + + //////////////////////////////////////////////////////////// + /// \brief Change a matrix parameter of the shader + /// + /// \a name is the name of the variable to change in the shader. + /// The corresponding parameter in the shader must be a 4x4 matrix + /// (mat4 GLSL type). + /// + /// Example: + /// \code + /// uniform mat4 matrix; // this is the variable in the shader + /// \endcode + /// \code + /// sf::Transform transform; + /// transform.translate(5, 10); + /// shader.setParameter("matrix", transform); + /// \endcode + /// + /// \param name Name of the parameter in the shader + /// \param transform Transform to assign + /// + //////////////////////////////////////////////////////////// + void setParameter(const std::string& name, const sf::Transform& transform); + + //////////////////////////////////////////////////////////// + /// \brief Change a texture parameter of the shader + /// + /// \a name is the name of the variable to change in the shader. + /// The corresponding parameter in the shader must be a 2D texture + /// (sampler2D GLSL type). + /// + /// Example: + /// \code + /// uniform sampler2D the_texture; // this is the variable in the shader + /// \endcode + /// \code + /// sf::Texture texture; + /// ... + /// shader.setParameter("the_texture", texture); + /// \endcode + /// It is important to note that \a texture must remain alive as long + /// as the shader uses it, no copy is made internally. + /// + /// To use the texture of the object being draw, which cannot be + /// known in advance, you can pass the special value + /// sf::Shader::CurrentTexture: + /// \code + /// shader.setParameter("the_texture", sf::Shader::CurrentTexture). + /// \endcode + /// + /// \param name Name of the texture in the shader + /// \param texture Texture to assign + /// + //////////////////////////////////////////////////////////// + void setParameter(const std::string& name, const Texture& texture); + + //////////////////////////////////////////////////////////// + /// \brief Change a texture parameter of the shader + /// + /// This overload maps a shader texture variable to the + /// texture of the object being drawn, which cannot be + /// known in advance. The second argument must be + /// sf::Shader::CurrentTexture. + /// The corresponding parameter in the shader must be a 2D texture + /// (sampler2D GLSL type). + /// + /// Example: + /// \code + /// uniform sampler2D current; // this is the variable in the shader + /// \endcode + /// \code + /// shader.setParameter("current", sf::Shader::CurrentTexture); + /// \endcode + /// + /// \param name Name of the texture in the shader + /// + //////////////////////////////////////////////////////////// + void setParameter(const std::string& name, CurrentTextureType); + + //////////////////////////////////////////////////////////// + /// \brief Bind a shader for rendering + /// + /// This function is not part of the graphics API, it mustn't be + /// used when drawing SFML entities. It must be used only if you + /// mix sf::Shader with OpenGL code. + /// + /// \code + /// sf::Shader s1, s2; + /// ... + /// sf::Shader::bind(&s1); + /// // draw OpenGL stuff that use s1... + /// sf::Shader::bind(&s2); + /// // draw OpenGL stuff that use s2... + /// sf::Shader::bind(NULL); + /// // draw OpenGL stuff that use no shader... + /// \endcode + /// + /// \param shader Shader to bind, can be null to use no shader + /// + //////////////////////////////////////////////////////////// + static void bind(const Shader* shader); + + //////////////////////////////////////////////////////////// + /// \brief Tell whether or not the system supports shaders + /// + /// This function should always be called before using + /// the shader features. If it returns false, then + /// any attempt to use sf::Shader will fail. + /// + /// \return True if shaders are supported, false otherwise + /// + //////////////////////////////////////////////////////////// + static bool isAvailable(); + +private : + + //////////////////////////////////////////////////////////// + /// \brief Compile the shader(s) and create the program + /// + /// If one of the arguments is NULL, the corresponding shader + /// is not created. + /// + /// \param vertexShaderCode Source code of the vertex shader + /// \param fragmentShaderCode Source code of the fragment shader + /// + /// \return True on success, false if any error happened + /// + //////////////////////////////////////////////////////////// + bool compile(const char* vertexShaderCode, const char* fragmentShaderCode); + + //////////////////////////////////////////////////////////// + /// \brief Bind all the textures used by the shader + /// + /// This function each texture to a different unit, and + /// updates the corresponding variables in the shader accordingly. + /// + //////////////////////////////////////////////////////////// + void bindTextures() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the location ID of a shader parameter + /// + /// \param name Name of the parameter to search + /// + /// \return Location ID of the parameter, or -1 if not found + /// + //////////////////////////////////////////////////////////// + int getParamLocation(const std::string& name); + + //////////////////////////////////////////////////////////// + // Types + //////////////////////////////////////////////////////////// + typedef std::map TextureTable; + typedef std::map ParamTable; + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + unsigned int m_shaderProgram; ///< OpenGL identifier for the program + int m_currentTexture; ///< Location of the current texture in the shader + TextureTable m_textures; ///< Texture variables in the shader, mapped to their location + ParamTable m_params; ///< Parameters location cache +}; + +} // namespace sf + + +#endif // SFML_SHADER_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Shader +/// \ingroup graphics +/// +/// Shaders are programs written using a specific language, +/// executed directly by the graphics card and allowing +/// to apply real-time operations to the rendered entities. +/// +/// There are two kinds of shaders: +/// \li Vertex shaders, that process vertices +/// \li Fragment (pixel) shaders, that process pixels +/// +/// A sf::Shader can be composed of either a vertex shader +/// alone, a fragment shader alone, or both combined +/// (see the variants of the load functions). +/// +/// Shaders are written in GLSL, which is a C-like +/// language dedicated to OpenGL shaders. You'll probably +/// need to learn its basics before writing your own shaders +/// for SFML. +/// +/// Like any C/C++ program, a shader has its own variables +/// that you can set from your C++ application. sf::Shader +/// handles 5 different types of variables: +/// \li floats +/// \li vectors (2, 3 or 4 components) +/// \li colors +/// \li textures +/// \li transforms (matrices) +/// +/// The value of the variables can be changed at any time +/// with the various overloads of the setParameter function: +/// \code +/// shader.setParameter("offset", 2.f); +/// shader.setParameter("point", 0.5f, 0.8f, 0.3f); +/// shader.setParameter("color", sf::Color(128, 50, 255)); +/// shader.setParameter("matrix", transform); // transform is a sf::Transform +/// shader.setParameter("overlay", texture); // texture is a sf::Texture +/// shader.setParameter("texture", sf::Shader::CurrentTexture); +/// \endcode +/// +/// The special Shader::CurrentTexture argument maps the +/// given texture variable to the current texture of the +/// object being drawn (which cannot be known in advance). +/// +/// To apply a shader to a drawable, you must pass it as an +/// additional parameter to the Draw function: +/// \code +/// window.draw(sprite, &shader); +/// \endcode +/// +/// ... which is in fact just a shortcut for this: +/// \code +/// sf::RenderStates states; +/// states.shader = &shader; +/// window.draw(sprite, states); +/// \endcode +/// +/// In the code above we pass a pointer to the shader, because it may +/// be null (which means "no shader"). +/// +/// Shaders can be used on any drawable, but some combinations are +/// not interesting. For example, using a vertex shader on a sf::Sprite +/// is limited because there are only 4 vertices, the sprite would +/// have to be subdivided in order to apply wave effects. +/// Another bad example is a fragment shader with sf::Text: the texture +/// of the text is not the actual text that you see on screen, it is +/// a big texture containing all the characters of the font in an +/// arbitrary order; thus, texture lookups on pixels other than the +/// current one may not give you the expected result. +/// +/// Shaders can also be used to apply global post-effects to the +/// current contents of the target (like the old sf::PostFx class +/// in SFML 1). This can be done in two different ways: +/// \li draw everything to a sf::RenderTexture, then draw it to +/// the main target using the shader +/// \li draw everything directly to the main target, then use +/// sf::Texture::update(Window&) to copy its contents to a texture +/// and draw it to the main target using the shader +/// +/// The first technique is more optimized because it doesn't involve +/// retrieving the target's pixels to system memory, but the +/// second one doesn't impact the rendering process and can be +/// easily inserted anywhere without impacting all the code. +/// +/// Like sf::Texture that can be used as a raw OpenGL texture, +/// sf::Shader can also be used directly as a raw shader for +/// custom OpenGL geometry. +/// \code +/// sf::Shader::bind(&shader); +/// ... render OpenGL geometry ... +/// sf::Shader::bind(NULL); +/// \endcode +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Graphics/Shape.hpp b/src/include/SFML/include/SFML/Graphics/Shape.hpp new file mode 100644 index 0000000..e8d5677 --- /dev/null +++ b/src/include/SFML/include/SFML/Graphics/Shape.hpp @@ -0,0 +1,345 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SHAPE_HPP +#define SFML_SHAPE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Base class for textured shapes with outline +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API Shape : public Drawable, public Transformable +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Virtual destructor + /// + //////////////////////////////////////////////////////////// + virtual ~Shape(); + + //////////////////////////////////////////////////////////// + /// \brief Change the source texture of the shape + /// + /// The \a texture argument refers to a texture that must + /// exist as long as the shape uses it. Indeed, the shape + /// doesn't store its own copy of the texture, but rather keeps + /// a pointer to the one that you passed to this function. + /// If the source texture is destroyed and the shape tries to + /// use it, the behaviour is undefined. + /// \a texture can be NULL to disable texturing. + /// If \a resetRect is true, the TextureRect property of + /// the shape is automatically adjusted to the size of the new + /// texture. If it is false, the texture rect is left unchanged. + /// + /// \param texture New texture + /// \param resetRect Should the texture rect be reset to the size of the new texture? + /// + /// \see getTexture, setTextureRect + /// + //////////////////////////////////////////////////////////// + void setTexture(const Texture* texture, bool resetRect = false); + + //////////////////////////////////////////////////////////// + /// \brief Set the sub-rectangle of the texture that the shape will display + /// + /// The texture rect is useful when you don't want to display + /// the whole texture, but rather a part of it. + /// By default, the texture rect covers the entire texture. + /// + /// \param rect Rectangle defining the region of the texture to display + /// + /// \see getTextureRect, setTexture + /// + //////////////////////////////////////////////////////////// + void setTextureRect(const IntRect& rect); + + //////////////////////////////////////////////////////////// + /// \brief Set the fill color of the shape + /// + /// This color is modulated (multiplied) with the shape's + /// texture if any. It can be used to colorize the shape, + /// or change its global opacity. + /// You can use sf::Color::Transparent to make the inside of + /// the shape transparent, and have the outline alone. + /// By default, the shape's fill color is opaque white. + /// + /// \param color New color of the shape + /// + /// \see getFillColor, setOutlineColor + /// + //////////////////////////////////////////////////////////// + void setFillColor(const Color& color); + + //////////////////////////////////////////////////////////// + /// \brief Set the outline color of the shape + /// + /// By default, the shape's outline color is opaque white. + /// + /// \param color New outline color of the shape + /// + /// \see getOutlineColor, setFillColor + /// + //////////////////////////////////////////////////////////// + void setOutlineColor(const Color& color); + + //////////////////////////////////////////////////////////// + /// \brief Set the thickness of the shape's outline + /// + /// Note that negative values are allowed (so that the outline + /// expands towards the center of the shape), and using zero + /// disables the outline. + /// By default, the outline thickness is 0. + /// + /// \param thickness New outline thickness + /// + /// \see getOutlineThickness + /// + //////////////////////////////////////////////////////////// + void setOutlineThickness(float thickness); + + //////////////////////////////////////////////////////////// + /// \brief Get the source texture of the shape + /// + /// If the shape has no source texture, a NULL pointer is returned. + /// The returned pointer is const, which means that you can't + /// modify the texture when you retrieve it with this function. + /// + /// \return Pointer to the shape's texture + /// + /// \see setTexture + /// + //////////////////////////////////////////////////////////// + const Texture* getTexture() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the sub-rectangle of the texture displayed by the shape + /// + /// \return Texture rectangle of the shape + /// + /// \see setTextureRect + /// + //////////////////////////////////////////////////////////// + const IntRect& getTextureRect() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the fill color of the shape + /// + /// \return Fill color of the shape + /// + /// \see setFillColor + /// + //////////////////////////////////////////////////////////// + const Color& getFillColor() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the outline color of the shape + /// + /// \return Outline color of the shape + /// + /// \see setOutlineColor + /// + //////////////////////////////////////////////////////////// + const Color& getOutlineColor() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the outline thickness of the shape + /// + /// \return Outline thickness of the shape + /// + /// \see setOutlineThickness + /// + //////////////////////////////////////////////////////////// + float getOutlineThickness() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the total number of points of the shape + /// + /// \return Number of points of the shape + /// + /// \see getPoint + /// + //////////////////////////////////////////////////////////// + virtual unsigned int getPointCount() const = 0; + + //////////////////////////////////////////////////////////// + /// \brief Get a point of the shape + /// + /// The result is undefined if \a index is out of the valid range. + /// + /// \param index Index of the point to get, in range [0 .. getPointCount() - 1] + /// + /// \return Index-th point of the shape + /// + /// \see getPointCount + /// + //////////////////////////////////////////////////////////// + virtual Vector2f getPoint(unsigned int index) const = 0; + + //////////////////////////////////////////////////////////// + /// \brief Get the local bounding rectangle of the entity + /// + /// The returned rectangle is in local coordinates, which means + /// that it ignores the transformations (translation, rotation, + /// scale, ...) that are applied to the entity. + /// In other words, this function returns the bounds of the + /// entity in the entity's coordinate system. + /// + /// \return Local bounding rectangle of the entity + /// + //////////////////////////////////////////////////////////// + FloatRect getLocalBounds() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the global bounding rectangle of the entity + /// + /// The returned rectangle is in global coordinates, which means + /// that it takes in account the transformations (translation, + /// rotation, scale, ...) that are applied to the entity. + /// In other words, this function returns the bounds of the + /// sprite in the global 2D world's coordinate system. + /// + /// \return Global bounding rectangle of the entity + /// + //////////////////////////////////////////////////////////// + FloatRect getGlobalBounds() const; + +protected : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + Shape(); + + //////////////////////////////////////////////////////////// + /// \brief Recompute the internal geometry of the shape + /// + /// This function must be called by the derived class everytime + /// the shape's points change (ie. the result of either + /// getPointCount or getPoint is different). + /// + //////////////////////////////////////////////////////////// + void update(); + +private : + + //////////////////////////////////////////////////////////// + /// \brief Draw the shape to a render target + /// + /// \param target Render target to draw to + /// \param states Current render states + /// + //////////////////////////////////////////////////////////// + virtual void draw(RenderTarget& target, RenderStates states) const; + + //////////////////////////////////////////////////////////// + /// \brief Update the fill vertices' color + /// + //////////////////////////////////////////////////////////// + void updateFillColors(); + + //////////////////////////////////////////////////////////// + /// \brief Update the fill vertices' texture coordinates + /// + //////////////////////////////////////////////////////////// + void updateTexCoords(); + + //////////////////////////////////////////////////////////// + /// \brief Update the outline vertices' position + /// + //////////////////////////////////////////////////////////// + void updateOutline(); + + //////////////////////////////////////////////////////////// + /// \brief Update the outline vertices' color + /// + //////////////////////////////////////////////////////////// + void updateOutlineColors(); + +private : + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + const Texture* m_texture; ///< Texture of the shape + IntRect m_textureRect; ///< Rectangle defining the area of the source texture to display + Color m_fillColor; ///< Fill color + Color m_outlineColor; ///< Outline color + float m_outlineThickness; ///< Thickness of the shape's outline + VertexArray m_vertices; ///< Vertex array containing the fill geometry + VertexArray m_outlineVertices; ///< Vertex array containing the outline geometry + FloatRect m_insideBounds; ///< Bounding rectangle of the inside (fill) + FloatRect m_bounds; ///< Bounding rectangle of the whole shape (outline + fill) +}; + +} // namespace sf + + +#endif // SFML_SHAPE_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Shape +/// \ingroup graphics +/// +/// sf::Shape is a drawable class that allows to define and +/// display a custom convex shape on a render target. +/// It's only an abstract base, it needs to be specialized for +/// concrete types of shapes (circle, rectangle, convex polygon, +/// star, ...). +/// +/// In addition to the attributes provided by the specialized +/// shape classes, a shape always has the following attributes: +/// \li a texture +/// \li a texture rectangle +/// \li a fill color +/// \li an outline color +/// \li an outline thickness +/// +/// Each feature is optional, and can be disabled easily: +/// \li the texture can be null +/// \li the fill/outline colors can be sf::Color::Transparent +/// \li the outline thickness can be zero +/// +/// You can write your own derived shape class, there are only +/// two virtual functions to override: +/// \li getPointCount must return the number of points of the shape +/// \li getPoint must return the points of the shape +/// +/// \see sf::RectangleShape, sf::CircleShape, sf::ConvexShape, sf::Transformable +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Graphics/Sprite.hpp b/src/include/SFML/include/SFML/Graphics/Sprite.hpp new file mode 100644 index 0000000..5d286f4 --- /dev/null +++ b/src/include/SFML/include/SFML/Graphics/Sprite.hpp @@ -0,0 +1,277 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SPRITE_HPP +#define SFML_SPRITE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include + + +namespace sf +{ +class Texture; + +//////////////////////////////////////////////////////////// +/// \brief Drawable representation of a texture, with its +/// own transformations, color, etc. +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API Sprite : public Drawable, public Transformable +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Creates an empty sprite with no source texture. + /// + //////////////////////////////////////////////////////////// + Sprite(); + + //////////////////////////////////////////////////////////// + /// \brief Construct the sprite from a source texture + /// + /// \param texture Source texture + /// + /// \see setTexture + /// + //////////////////////////////////////////////////////////// + explicit Sprite(const Texture& texture); + + //////////////////////////////////////////////////////////// + /// \brief Construct the sprite from a sub-rectangle of a source texture + /// + /// \param texture Source texture + /// \param rectangle Sub-rectangle of the texture to assign to the sprite + /// + /// \see setTexture, setTextureRect + /// + //////////////////////////////////////////////////////////// + Sprite(const Texture& texture, const IntRect& rectangle); + + //////////////////////////////////////////////////////////// + /// \brief Change the source texture of the sprite + /// + /// The \a texture argument refers to a texture that must + /// exist as long as the sprite uses it. Indeed, the sprite + /// doesn't store its own copy of the texture, but rather keeps + /// a pointer to the one that you passed to this function. + /// If the source texture is destroyed and the sprite tries to + /// use it, the behaviour is undefined. + /// If \a resetRect is true, the TextureRect property of + /// the sprite is automatically adjusted to the size of the new + /// texture. If it is false, the texture rect is left unchanged. + /// + /// \param texture New texture + /// \param resetRect Should the texture rect be reset to the size of the new texture? + /// + /// \see getTexture, setTextureRect + /// + //////////////////////////////////////////////////////////// + void setTexture(const Texture& texture, bool resetRect = false); + + //////////////////////////////////////////////////////////// + /// \brief Set the sub-rectangle of the texture that the sprite will display + /// + /// The texture rect is useful when you don't want to display + /// the whole texture, but rather a part of it. + /// By default, the texture rect covers the entire texture. + /// + /// \param rectangle Rectangle defining the region of the texture to display + /// + /// \see getTextureRect, setTexture + /// + //////////////////////////////////////////////////////////// + void setTextureRect(const IntRect& rectangle); + + //////////////////////////////////////////////////////////// + /// \brief Set the global color of the sprite + /// + /// This color is modulated (multiplied) with the sprite's + /// texture. It can be used to colorize the sprite, or change + /// its global opacity. + /// By default, the sprite's color is opaque white. + /// + /// \param color New color of the sprite + /// + /// \see getColor + /// + //////////////////////////////////////////////////////////// + void setColor(const Color& color); + + //////////////////////////////////////////////////////////// + /// \brief Get the source texture of the sprite + /// + /// If the sprite has no source texture, a NULL pointer is returned. + /// The returned pointer is const, which means that you can't + /// modify the texture when you retrieve it with this function. + /// + /// \return Pointer to the sprite's texture + /// + /// \see setTexture + /// + //////////////////////////////////////////////////////////// + const Texture* getTexture() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the sub-rectangle of the texture displayed by the sprite + /// + /// \return Texture rectangle of the sprite + /// + /// \see setTextureRect + /// + //////////////////////////////////////////////////////////// + const IntRect& getTextureRect() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the global color of the sprite + /// + /// \return Global color of the sprite + /// + /// \see setColor + /// + //////////////////////////////////////////////////////////// + const Color& getColor() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the local bounding rectangle of the entity + /// + /// The returned rectangle is in local coordinates, which means + /// that it ignores the transformations (translation, rotation, + /// scale, ...) that are applied to the entity. + /// In other words, this function returns the bounds of the + /// entity in the entity's coordinate system. + /// + /// \return Local bounding rectangle of the entity + /// + //////////////////////////////////////////////////////////// + FloatRect getLocalBounds() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the global bounding rectangle of the entity + /// + /// The returned rectangle is in global coordinates, which means + /// that it takes in account the transformations (translation, + /// rotation, scale, ...) that are applied to the entity. + /// In other words, this function returns the bounds of the + /// sprite in the global 2D world's coordinate system. + /// + /// \return Global bounding rectangle of the entity + /// + //////////////////////////////////////////////////////////// + FloatRect getGlobalBounds() const; + +private : + + //////////////////////////////////////////////////////////// + /// \brief Draw the sprite to a render target + /// + /// \param target Render target to draw to + /// \param states Current render states + /// + //////////////////////////////////////////////////////////// + virtual void draw(RenderTarget& target, RenderStates states) const; + + //////////////////////////////////////////////////////////// + /// \brief Update the vertices' positions + /// + //////////////////////////////////////////////////////////// + void updatePositions(); + + //////////////////////////////////////////////////////////// + /// \brief Update the vertices' texture coordinates + /// + //////////////////////////////////////////////////////////// + void updateTexCoords(); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + Vertex m_vertices[4]; ///< Vertices defining the sprite's geometry + const Texture* m_texture; ///< Texture of the sprite + IntRect m_textureRect; ///< Rectangle defining the area of the source texture to display +}; + +} // namespace sf + + +#endif // SFML_SPRITE_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Sprite +/// \ingroup graphics +/// +/// sf::Sprite is a drawable class that allows to easily display +/// a texture (or a part of it) on a render target. +/// +/// It inherits all the functions from sf::Transformable: +/// position, rotation, scale, origin. It also adds sprite-specific +/// properties such as the texture to use, the part of it to display, +/// and some convenience functions to change the overall color of the +/// sprite, or to get its bounding rectangle. +/// +/// sf::Sprite works in combination with the sf::Texture class, which +/// loads and provides the pixel data of a given texture. +/// +/// The separation of sf::Sprite and sf::Texture allows more flexibility +/// and better performances: indeed a sf::Texture is a heavy resource, +/// and any operation on it is slow (often too slow for real-time +/// applications). On the other side, a sf::Sprite is a lightweight +/// object which can use the pixel data of a sf::Texture and draw +/// it with its own transformation/color/blending attributes. +/// +/// It is important to note that the sf::Sprite instance doesn't +/// copy the texture that it uses, it only keeps a reference to it. +/// Thus, a sf::Texture must not be destroyed while it is +/// used by a sf::Sprite (i.e. never write a function that +/// uses a local sf::Texture instance for creating a sprite). +/// +/// Usage example: +/// \code +/// // Declare and load a texture +/// sf::Texture texture; +/// texture.loadFromFile("texture.png"); +/// +/// // Create a sprite +/// sf::Sprite sprite; +/// sprite.setTexture(texture); +/// sprite.setTextureRect(sf::IntRect(10, 10, 50, 30)); +/// sprite.setColor(sf::Color(255, 255, 255, 200)); +/// sprite.setPosition(100, 25); +/// +/// // Draw it +/// window.draw(sprite); +/// \endcode +/// +/// \see sf::Texture, sf::Transformable +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Graphics/Text.hpp b/src/include/SFML/include/SFML/Graphics/Text.hpp new file mode 100644 index 0000000..6301f84 --- /dev/null +++ b/src/include/SFML/include/SFML/Graphics/Text.hpp @@ -0,0 +1,351 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_TEXT_HPP +#define SFML_TEXT_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Graphical text that can be drawn to a render target +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API Text : public Drawable, public Transformable +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Enumeration of the string drawing styles + /// + //////////////////////////////////////////////////////////// + enum Style + { + Regular = 0, ///< Regular characters, no style + Bold = 1 << 0, ///< Bold characters + Italic = 1 << 1, ///< Italic characters + Underlined = 1 << 2 ///< Underlined characters + }; + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Creates an empty text. + /// + //////////////////////////////////////////////////////////// + Text(); + + //////////////////////////////////////////////////////////// + /// \brief Construct the text from a string, font and size + /// + /// \param string Text assigned to the string + /// \param font Font used to draw the string + /// \param characterSize Base size of characters, in pixels + /// + //////////////////////////////////////////////////////////// + Text(const String& string, const Font& font, unsigned int characterSize = 30); + + //////////////////////////////////////////////////////////// + /// \brief Set the text's string + /// + /// The \a string argument is a sf::String, which can + /// automatically be constructed from standard string types. + /// So, the following calls are all valid: + /// \code + /// text.setString("hello"); + /// text.setString(L"hello"); + /// text.setString(std::string("hello")); + /// text.setString(std::wstring(L"hello")); + /// \endcode + /// A text's string is empty by default. + /// + /// \param string New string + /// + /// \see getString + /// + //////////////////////////////////////////////////////////// + void setString(const String& string); + + //////////////////////////////////////////////////////////// + /// \brief Set the text's font + /// + /// The \a font argument refers to a font that must + /// exist as long as the text uses it. Indeed, the text + /// doesn't store its own copy of the font, but rather keeps + /// a pointer to the one that you passed to this function. + /// If the font is destroyed and the text tries to + /// use it, the behaviour is undefined. + /// + /// \param font New font + /// + /// \see getFont + /// + //////////////////////////////////////////////////////////// + void setFont(const Font& font); + + //////////////////////////////////////////////////////////// + /// \brief Set the character size + /// + /// The default size is 30. + /// + /// \param size New character size, in pixels + /// + /// \see getCharacterSize + /// + //////////////////////////////////////////////////////////// + void setCharacterSize(unsigned int size); + + //////////////////////////////////////////////////////////// + /// \brief Set the text's style + /// + /// You can pass a combination of one or more styles, for + /// example sf::Text::Bold | sf::Text::Italic. + /// The default style is sf::Text::Regular. + /// + /// \param style New style + /// + /// \see getStyle + /// + //////////////////////////////////////////////////////////// + void setStyle(Uint32 style); + + //////////////////////////////////////////////////////////// + /// \brief Set the global color of the text + /// + /// By default, the text's color is opaque white. + /// + /// \param color New color of the text + /// + /// \see getColor + /// + //////////////////////////////////////////////////////////// + void setColor(const Color& color); + + //////////////////////////////////////////////////////////// + /// \brief Get the text's string + /// + /// The returned string is a sf::String, which can automatically + /// be converted to standard string types. So, the following + /// lines of code are all valid: + /// \code + /// sf::String s1 = text.getString(); + /// std::string s2 = text.getString(); + /// std::wstring s3 = text.getString(); + /// \endcode + /// + /// \return Text's string + /// + /// \see setString + /// + //////////////////////////////////////////////////////////// + const String& getString() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the text's font + /// + /// If the text has no font attached, a NULL pointer is returned. + /// The returned reference is const, which means that you + /// cannot modify the font when you get it from this function. + /// + /// \return Pointer to the text's font + /// + /// \see setFont + /// + //////////////////////////////////////////////////////////// + const Font* getFont() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the character size + /// + /// \return Size of the characters, in pixels + /// + /// \see setCharacterSize + /// + //////////////////////////////////////////////////////////// + unsigned int getCharacterSize() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the text's style + /// + /// \return Text's style + /// + /// \see setStyle + /// + //////////////////////////////////////////////////////////// + Uint32 getStyle() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the global color of the text + /// + /// \return Global color of the text + /// + /// \see setColor + /// + //////////////////////////////////////////////////////////// + const Color& getColor() const; + + //////////////////////////////////////////////////////////// + /// \brief Return the position of the \a index-th character + /// + /// This function computes the visual position of a character + /// from its index in the string. The returned position is + /// in global coordinates (translation, rotation, scale and + /// origin are applied). + /// If \a index is out of range, the position of the end of + /// the string is returned. + /// + /// \param index Index of the character + /// + /// \return Position of the character + /// + //////////////////////////////////////////////////////////// + Vector2f findCharacterPos(std::size_t index) const; + + //////////////////////////////////////////////////////////// + /// \brief Get the local bounding rectangle of the entity + /// + /// The returned rectangle is in local coordinates, which means + /// that it ignores the transformations (translation, rotation, + /// scale, ...) that are applied to the entity. + /// In other words, this function returns the bounds of the + /// entity in the entity's coordinate system. + /// + /// \return Local bounding rectangle of the entity + /// + //////////////////////////////////////////////////////////// + FloatRect getLocalBounds() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the global bounding rectangle of the entity + /// + /// The returned rectangle is in global coordinates, which means + /// that it takes in account the transformations (translation, + /// rotation, scale, ...) that are applied to the entity. + /// In other words, this function returns the bounds of the + /// sprite in the global 2D world's coordinate system. + /// + /// \return Global bounding rectangle of the entity + /// + //////////////////////////////////////////////////////////// + FloatRect getGlobalBounds() const; + +private : + + //////////////////////////////////////////////////////////// + /// \brief Draw the text to a render target + /// + /// \param target Render target to draw to + /// \param states Current render states + /// + //////////////////////////////////////////////////////////// + virtual void draw(RenderTarget& target, RenderStates states) const; + + //////////////////////////////////////////////////////////// + /// \brief Update the text's geometry + /// + //////////////////////////////////////////////////////////// + void updateGeometry(); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + String m_string; ///< String to display + const Font* m_font; ///< Font used to display the string + unsigned int m_characterSize; ///< Base size of characters, in pixels + Uint32 m_style; ///< Text style (see Style enum) + Color m_color; ///< Text color + VertexArray m_vertices; ///< Vertex array containing the text's geometry + FloatRect m_bounds; ///< Bounding rectangle of the text (in local coordinates) +}; + +} // namespace sf + + +#endif // SFML_TEXT_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Text +/// \ingroup graphics +/// +/// sf::Text is a drawable class that allows to easily display +/// some text with custom style and color on a render target. +/// +/// It inherits all the functions from sf::Transformable: +/// position, rotation, scale, origin. It also adds text-specific +/// properties such as the font to use, the character size, +/// the font style (bold, italic, underlined), the global color +/// and the text to display of course. +/// It also provides convenience functions to calculate the +/// graphical size of the text, or to get the global position +/// of a given character. +/// +/// sf::Text works in combination with the sf::Font class, which +/// loads and provides the glyphs (visual characters) of a given font. +/// +/// The separation of sf::Font and sf::Text allows more flexibility +/// and better performances: indeed a sf::Font is a heavy resource, +/// and any operation on it is slow (often too slow for real-time +/// applications). On the other side, a sf::Text is a lightweight +/// object which can combine the glyphs data and metrics of a sf::Font +/// to display any text on a render target. +/// +/// It is important to note that the sf::Text instance doesn't +/// copy the font that it uses, it only keeps a reference to it. +/// Thus, a sf::Font must not be destructed while it is +/// used by a sf::Text (i.e. never write a function that +/// uses a local sf::Font instance for creating a text). +/// +/// Usage example: +/// \code +/// // Declare and load a font +/// sf::Font font; +/// font.loadFromFile("arial.ttf"); +/// +/// // Create a text +/// sf::Text text("hello", font); +/// text.setCharacterSize(30); +/// text.setStyle(sf::Text::Bold); +/// text.setColor(sf::Color::Red); +/// +/// // Draw it +/// window.draw(text); +/// \endcode +/// +/// \see sf::Font, sf::Transformable +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Graphics/Texture.hpp b/src/include/SFML/include/SFML/Graphics/Texture.hpp new file mode 100644 index 0000000..ba61f54 --- /dev/null +++ b/src/include/SFML/include/SFML/Graphics/Texture.hpp @@ -0,0 +1,602 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_TEXTURE_HPP +#define SFML_TEXTURE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +class Window; +class RenderTarget; +class RenderTexture; +class InputStream; + +//////////////////////////////////////////////////////////// +/// \brief Image living on the graphics card that can be used for drawing +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API Texture : GlResource +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Types of texture coordinates that can be used for rendering + /// + //////////////////////////////////////////////////////////// + enum CoordinateType + { + Normalized, ///< Texture coordinates in range [0 .. 1] + Pixels ///< Texture coordinates in range [0 .. size] + }; + +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Creates an empty texture. + /// + //////////////////////////////////////////////////////////// + Texture(); + + //////////////////////////////////////////////////////////// + /// \brief Copy constructor + /// + /// \param copy instance to copy + /// + //////////////////////////////////////////////////////////// + Texture(const Texture& copy); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~Texture(); + + //////////////////////////////////////////////////////////// + /// \brief Create the texture + /// + /// If this function fails, the texture is left unchanged. + /// + /// \param width Width of the texture + /// \param height Height of the texture + /// + /// \return True if creation was successful + /// + //////////////////////////////////////////////////////////// + bool create(unsigned int width, unsigned int height); + + //////////////////////////////////////////////////////////// + /// \brief Load the texture from a file on disk + /// + /// This function is a shortcut for the following code: + /// \code + /// sf::Image image; + /// image.loadFromFile(filename); + /// texture.loadFromImage(image, area); + /// \endcode + /// + /// The \a area argument can be used to load only a sub-rectangle + /// of the whole image. If you want the entire image then leave + /// the default value (which is an empty IntRect). + /// If the \a area rectangle crosses the bounds of the image, it + /// is adjusted to fit the image size. + /// + /// The maximum size for a texture depends on the graphics + /// driver and can be retrieved with the getMaximumSize function. + /// + /// If this function fails, the texture is left unchanged. + /// + /// \param filename Path of the image file to load + /// \param area Area of the image to load + /// + /// \return True if loading was successful + /// + /// \see loadFromMemory, loadFromStream, loadFromImage + /// + //////////////////////////////////////////////////////////// + bool loadFromFile(const std::string& filename, const IntRect& area = IntRect()); + + //////////////////////////////////////////////////////////// + /// \brief Load the texture from a file in memory + /// + /// This function is a shortcut for the following code: + /// \code + /// sf::Image image; + /// image.loadFromMemory(data, size); + /// texture.loadFromImage(image, area); + /// \endcode + /// + /// The \a area argument can be used to load only a sub-rectangle + /// of the whole image. If you want the entire image then leave + /// the default value (which is an empty IntRect). + /// If the \a area rectangle crosses the bounds of the image, it + /// is adjusted to fit the image size. + /// + /// The maximum size for a texture depends on the graphics + /// driver and can be retrieved with the getMaximumSize function. + /// + /// If this function fails, the texture is left unchanged. + /// + /// \param data Pointer to the file data in memory + /// \param size Size of the data to load, in bytes + /// \param area Area of the image to load + /// + /// \return True if loading was successful + /// + /// \see loadFromFile, loadFromStream, loadFromImage + /// + //////////////////////////////////////////////////////////// + bool loadFromMemory(const void* data, std::size_t size, const IntRect& area = IntRect()); + + //////////////////////////////////////////////////////////// + /// \brief Load the texture from a custom stream + /// + /// This function is a shortcut for the following code: + /// \code + /// sf::Image image; + /// image.loadFromStream(stream); + /// texture.loadFromImage(image, area); + /// \endcode + /// + /// The \a area argument can be used to load only a sub-rectangle + /// of the whole image. If you want the entire image then leave + /// the default value (which is an empty IntRect). + /// If the \a area rectangle crosses the bounds of the image, it + /// is adjusted to fit the image size. + /// + /// The maximum size for a texture depends on the graphics + /// driver and can be retrieved with the getMaximumSize function. + /// + /// If this function fails, the texture is left unchanged. + /// + /// \param stream Source stream to read from + /// \param area Area of the image to load + /// + /// \return True if loading was successful + /// + /// \see loadFromFile, loadFromMemory, loadFromImage + /// + //////////////////////////////////////////////////////////// + bool loadFromStream(sf::InputStream& stream, const IntRect& area = IntRect()); + + //////////////////////////////////////////////////////////// + /// \brief Load the texture from an image + /// + /// The \a area argument can be used to load only a sub-rectangle + /// of the whole image. If you want the entire image then leave + /// the default value (which is an empty IntRect). + /// If the \a area rectangle crosses the bounds of the image, it + /// is adjusted to fit the image size. + /// + /// The maximum size for a texture depends on the graphics + /// driver and can be retrieved with the getMaximumSize function. + /// + /// If this function fails, the texture is left unchanged. + /// + /// \param image Image to load into the texture + /// \param area Area of the image to load + /// + /// \return True if loading was successful + /// + /// \see loadFromFile, loadFromMemory + /// + //////////////////////////////////////////////////////////// + bool loadFromImage(const Image& image, const IntRect& area = IntRect()); + + //////////////////////////////////////////////////////////// + /// \brief Return the size of the texture + /// + /// \return Size in pixels + /// + //////////////////////////////////////////////////////////// + Vector2u getSize() const; + + //////////////////////////////////////////////////////////// + /// \brief Copy the texture pixels to an image + /// + /// This function performs a slow operation that downloads + /// the texture's pixels from the graphics card and copies + /// them to a new image, potentially applying transformations + /// to pixels if necessary (texture may be padded or flipped). + /// + /// \return Image containing the texture's pixels + /// + /// \see loadFromImage + /// + //////////////////////////////////////////////////////////// + Image copyToImage() const; + + //////////////////////////////////////////////////////////// + /// \brief Update the whole texture from an array of pixels + /// + /// The \a pixel array is assumed to have the same size as + /// the \a area rectangle, and to contain 32-bits RGBA pixels. + /// + /// No additional check is performed on the size of the pixel + /// array, passing invalid arguments will lead to an undefined + /// behaviour. + /// + /// This function does nothing if \a pixels is null or if the + /// texture was not previously created. + /// + /// \param pixels Array of pixels to copy to the texture + /// + //////////////////////////////////////////////////////////// + void update(const Uint8* pixels); + + //////////////////////////////////////////////////////////// + /// \brief Update a part of the texture from an array of pixels + /// + /// The size of the \a pixel array must match the \a width and + /// \a height arguments, and it must contain 32-bits RGBA pixels. + /// + /// No additional check is performed on the size of the pixel + /// array or the bounds of the area to update, passing invalid + /// arguments will lead to an undefined behaviour. + /// + /// This function does nothing if \a pixels is null or if the + /// texture was not previously created. + /// + /// \param pixels Array of pixels to copy to the texture + /// \param width Width of the pixel region contained in \a pixels + /// \param height Height of the pixel region contained in \a pixels + /// \param x X offset in the texture where to copy the source pixels + /// \param y Y offset in the texture where to copy the source pixels + /// + //////////////////////////////////////////////////////////// + void update(const Uint8* pixels, unsigned int width, unsigned int height, unsigned int x, unsigned int y); + + //////////////////////////////////////////////////////////// + /// \brief Update the texture from an image + /// + /// Although the source image can be smaller than the texture, + /// this function is usually used for updating the whole texture. + /// The other overload, which has (x, y) additional arguments, + /// is more convenient for updating a sub-area of the texture. + /// + /// No additional check is performed on the size of the image, + /// passing an image bigger than the texture will lead to an + /// undefined behaviour. + /// + /// This function does nothing if the texture was not + /// previously created. + /// + /// \param image Image to copy to the texture + /// + //////////////////////////////////////////////////////////// + void update(const Image& image); + + //////////////////////////////////////////////////////////// + /// \brief Update a part of the texture from an image + /// + /// No additional check is performed on the size of the image, + /// passing an invalid combination of image size and offset + /// will lead to an undefined behaviour. + /// + /// This function does nothing if the texture was not + /// previously created. + /// + /// \param image Image to copy to the texture + /// \param x X offset in the texture where to copy the source image + /// \param y Y offset in the texture where to copy the source image + /// + //////////////////////////////////////////////////////////// + void update(const Image& image, unsigned int x, unsigned int y); + + //////////////////////////////////////////////////////////// + /// \brief Update the texture from the contents of a window + /// + /// Although the source window can be smaller than the texture, + /// this function is usually used for updating the whole texture. + /// The other overload, which has (x, y) additional arguments, + /// is more convenient for updating a sub-area of the texture. + /// + /// No additional check is performed on the size of the window, + /// passing a window bigger than the texture will lead to an + /// undefined behaviour. + /// + /// This function does nothing if either the texture or the window + /// was not previously created. + /// + /// \param window Window to copy to the texture + /// + //////////////////////////////////////////////////////////// + void update(const Window& window); + + //////////////////////////////////////////////////////////// + /// \brief Update a part of the texture from the contents of a window + /// + /// No additional check is performed on the size of the window, + /// passing an invalid combination of window size and offset + /// will lead to an undefined behaviour. + /// + /// This function does nothing if either the texture or the window + /// was not previously created. + /// + /// \param window Window to copy to the texture + /// \param x X offset in the texture where to copy the source window + /// \param y Y offset in the texture where to copy the source window + /// + //////////////////////////////////////////////////////////// + void update(const Window& window, unsigned int x, unsigned int y); + + //////////////////////////////////////////////////////////// + /// \brief Enable or disable the smooth filter + /// + /// When the filter is activated, the texture appears smoother + /// so that pixels are less noticeable. However if you want + /// the texture to look exactly the same as its source file, + /// you should leave it disabled. + /// The smooth filter is disabled by default. + /// + /// \param smooth True to enable smoothing, false to disable it + /// + /// \see isSmooth + /// + //////////////////////////////////////////////////////////// + void setSmooth(bool smooth); + + //////////////////////////////////////////////////////////// + /// \brief Tell whether the smooth filter is enabled or not + /// + /// \return True if smoothing is enabled, false if it is disabled + /// + /// \see setSmooth + /// + //////////////////////////////////////////////////////////// + bool isSmooth() const; + + //////////////////////////////////////////////////////////// + /// \brief Enable or disable repeating + /// + /// Repeating is involved when using texture coordinates + /// outside the texture rectangle [0, 0, width, height]. + /// In this case, if repeat mode is enabled, the whole texture + /// will be repeated as many times as needed to reach the + /// coordinate (for example, if the X texture coordinate is + /// 3 * width, the texture will be repeated 3 times). + /// If repeat mode is disabled, the "extra space" will instead + /// be filled with border pixels. + /// Warning: on very old graphics cards, white pixels may appear + /// when the texture is repeated. With such cards, repeat mode + /// can be used reliably only if the texture has power-of-two + /// dimensions (such as 256x128). + /// Repeating is disabled by default. + /// + /// \param repeated True to repeat the texture, false to disable repeating + /// + /// \see isRepeated + /// + //////////////////////////////////////////////////////////// + void setRepeated(bool repeated); + + //////////////////////////////////////////////////////////// + /// \brief Tell whether the texture is repeated or not + /// + /// \return True if repeat mode is enabled, false if it is disabled + /// + /// \see setRepeated + /// + //////////////////////////////////////////////////////////// + bool isRepeated() const; + + //////////////////////////////////////////////////////////// + /// \brief Overload of assignment operator + /// + /// \param right Instance to assign + /// + /// \return Reference to self + /// + //////////////////////////////////////////////////////////// + Texture& operator =(const Texture& right); + + //////////////////////////////////////////////////////////// + /// \brief Bind a texture for rendering + /// + /// This function is not part of the graphics API, it mustn't be + /// used when drawing SFML entities. It must be used only if you + /// mix sf::Texture with OpenGL code. + /// + /// \code + /// sf::Texture t1, t2; + /// ... + /// sf::Texture::bind(&t1); + /// // draw OpenGL stuff that use t1... + /// sf::Texture::bind(&t2); + /// // draw OpenGL stuff that use t2... + /// sf::Texture::bind(NULL); + /// // draw OpenGL stuff that use no texture... + /// \endcode + /// + /// The \a coordinateType argument controls how texture + /// coordinates will be interpreted. If Normalized (the default), they + /// must be in range [0 .. 1], which is the default way of handling + /// texture coordinates with OpenGL. If Pixels, they must be given + /// in pixels (range [0 .. size]). This mode is used internally by + /// the graphics classes of SFML, it makes the definition of texture + /// coordinates more intuitive for the high-level API, users don't need + /// to compute normalized values. + /// + /// \param texture Pointer to the texture to bind, can be null to use no texture + /// \param coordinateType Type of texture coordinates to use + /// + //////////////////////////////////////////////////////////// + static void bind(const Texture* texture, CoordinateType coordinateType = Normalized); + + //////////////////////////////////////////////////////////// + /// \brief Get the maximum texture size allowed + /// + /// This maximum size is defined by the graphics driver. + /// You can expect a value of 512 pixels for low-end graphics + /// card, and up to 8192 pixels or more for newer hardware. + /// + /// \return Maximum size allowed for textures, in pixels + /// + //////////////////////////////////////////////////////////// + static unsigned int getMaximumSize(); + +private : + + friend class RenderTexture; + friend class RenderTarget; + + //////////////////////////////////////////////////////////// + /// \brief Get a valid image size according to hardware support + /// + /// This function checks whether the graphics driver supports + /// non power of two sizes or not, and adjusts the size + /// accordingly. + /// The returned size is greater than or equal to the original size. + /// + /// \param Size size to convert + /// + /// \return Valid nearest size (greater than or equal to specified size) + /// + //////////////////////////////////////////////////////////// + static unsigned int getValidSize(unsigned int size); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + Vector2u m_size; ///< Public texture size + Vector2u m_actualSize; ///< Actual texture size (can be greater than public size because of padding) + unsigned int m_texture; ///< Internal texture identifier + bool m_isSmooth; ///< Status of the smooth filter + bool m_isRepeated; ///< Is the texture in repeat mode? + mutable bool m_pixelsFlipped; ///< To work around the inconsistency in Y orientation + Uint64 m_cacheId; ///< Unique number that identifies the texture to the render target's cache +}; + +} // namespace sf + + +#endif // SFML_TEXTURE_HPP + +//////////////////////////////////////////////////////////// +/// \class sf::Texture +/// \ingroup graphics +/// +/// sf::Texture stores pixels that can be drawn, with a sprite +/// for example. A texture lives in the graphics card memory, +/// therefore it is very fast to draw a texture to a render target, +/// or copy a render target to a texture (the graphics card can +/// access both directly). +/// +/// Being stored in the graphics card memory has some drawbacks. +/// A texture cannot be manipulated as freely as a sf::Image, +/// you need to prepare the pixels first and then upload them +/// to the texture in a single operation (see Texture::update). +/// +/// sf::Texture makes it easy to convert from/to sf::Image, but +/// keep in mind that these calls require transfers between +/// the graphics card and the central memory, therefore they are +/// slow operations. +/// +/// A texture can be loaded from an image, but also directly +/// from a file/memory/stream. The necessary shortcuts are defined +/// so that you don't need an image first for the most common cases. +/// However, if you want to perform some modifications on the pixels +/// before creating the final texture, you can load your file to a +/// sf::Image, do whatever you need with the pixels, and then call +/// Texture::loadFromImage. +/// +/// Since they live in the graphics card memory, the pixels of a texture +/// cannot be accessed without a slow copy first. And they cannot be +/// accessed individually. Therefore, if you need to read the texture's +/// pixels (like for pixel-perfect collisions), it is recommended to +/// store the collision information separately, for example in an array +/// of booleans. +/// +/// Like sf::Image, sf::Texture can handle a unique internal +/// representation of pixels, which is RGBA 32 bits. This means +/// that a pixel must be composed of 8 bits red, green, blue and +/// alpha channels -- just like a sf::Color. +/// +/// Usage example: +/// \code +/// // This example shows the most common use of sf::Texture: +/// // drawing a sprite +/// +/// // Load a texture from a file +/// sf::Texture texture; +/// if (!texture.loadFromFile("texture.png")) +/// return -1; +/// +/// // Assign it to a sprite +/// sf::Sprite sprite; +/// sprite.setTexture(texture); +/// +/// // Draw the textured sprite +/// window.draw(sprite); +/// \endcode +/// +/// \code +/// // This example shows another common use of sf::Texture: +/// // streaming real-time data, like video frames +/// +/// // Create an empty texture +/// sf::Texture texture; +/// if (!texture.create(640, 480)) +/// return -1; +/// +/// // Create a sprite that will display the texture +/// sf::Sprite sprite(texture); +/// +/// while (...) // the main loop +/// { +/// ... +/// +/// // update the texture +/// sf::Uint8* pixels = ...; // get a fresh chunk of pixels (the next frame of a movie, for example) +/// texture.update(pixels); +/// +/// // draw it +/// window.draw(sprite); +/// +/// ... +/// } +/// +/// \endcode +/// +/// Like sf::Shader that can be used as a raw OpenGL shader, +/// sf::Texture can also be used directly as a raw texture for +/// custom OpenGL geometry. +/// \code +/// sf::Texture::bind(&texture); +/// ... render OpenGL geometry ... +/// sf::Texture::bind(NULL); +/// \endcode +/// +/// \see sf::Sprite, sf::Image, sf::RenderTexture +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Graphics/Transform.hpp b/src/include/SFML/include/SFML/Graphics/Transform.hpp new file mode 100644 index 0000000..3b91a8a --- /dev/null +++ b/src/include/SFML/include/SFML/Graphics/Transform.hpp @@ -0,0 +1,450 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_TRANSFORM_HPP +#define SFML_TRANSFORM_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Define a 3x3 transform matrix +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API Transform +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Creates an identity transform (a transform that does nothing). + /// + //////////////////////////////////////////////////////////// + Transform(); + + //////////////////////////////////////////////////////////// + /// \brief Construct a transform from a 3x3 matrix + /// + /// \param a00 Element (0, 0) of the matrix + /// \param a01 Element (0, 1) of the matrix + /// \param a02 Element (0, 2) of the matrix + /// \param a10 Element (1, 0) of the matrix + /// \param a11 Element (1, 1) of the matrix + /// \param a12 Element (1, 2) of the matrix + /// \param a20 Element (2, 0) of the matrix + /// \param a21 Element (2, 1) of the matrix + /// \param a22 Element (2, 2) of the matrix + /// + //////////////////////////////////////////////////////////// + Transform(float a00, float a01, float a02, + float a10, float a11, float a12, + float a20, float a21, float a22); + + //////////////////////////////////////////////////////////// + /// \brief Return the transform as a 4x4 matrix + /// + /// This function returns a pointer to an array of 16 floats + /// containing the transform elements as a 4x4 matrix, which + /// is directly compatible with OpenGL functions. + /// + /// \code + /// sf::Transform transform = ...; + /// glLoadMatrixf(transform.getMatrix()); + /// \endcode + /// + /// \return Pointer to a 4x4 matrix + /// + //////////////////////////////////////////////////////////// + const float* getMatrix() const; + + //////////////////////////////////////////////////////////// + /// \brief Return the inverse of the transform + /// + /// If the inverse cannot be computed, an identity transform + /// is returned. + /// + /// \return A new transform which is the inverse of self + /// + //////////////////////////////////////////////////////////// + Transform getInverse() const; + + //////////////////////////////////////////////////////////// + /// \brief Transform a 2D point + /// + /// \param x X coordinate of the point to transform + /// \param y Y coordinate of the point to transform + /// + /// \return Transformed point + /// + //////////////////////////////////////////////////////////// + Vector2f transformPoint(float x, float y) const; + + //////////////////////////////////////////////////////////// + /// \brief Transform a 2D point + /// + /// \param point Point to transform + /// + /// \return Transformed point + /// + //////////////////////////////////////////////////////////// + Vector2f transformPoint(const Vector2f& point) const; + + //////////////////////////////////////////////////////////// + /// \brief Transform a rectangle + /// + /// Since SFML doesn't provide support for oriented rectangles, + /// the result of this function is always an axis-aligned + /// rectangle. Which means that if the transform contains a + /// rotation, the bounding rectangle of the transformed rectangle + /// is returned. + /// + /// \param rectangle Rectangle to transform + /// + /// \return Transformed rectangle + /// + //////////////////////////////////////////////////////////// + FloatRect transformRect(const FloatRect& rectangle) const; + + //////////////////////////////////////////////////////////// + /// \brief Combine the current transform with another one + /// + /// The result is a transform that is equivalent to applying + /// *this followed by \a transform. Mathematically, it is + /// equivalent to a matrix multiplication. + /// + /// \param transform Transform to combine with this transform + /// + /// \return Reference to *this + /// + //////////////////////////////////////////////////////////// + Transform& combine(const Transform& transform); + + //////////////////////////////////////////////////////////// + /// \brief Combine the current transform with a translation + /// + /// This function returns a reference to *this, so that calls + /// can be chained. + /// \code + /// sf::Transform transform; + /// transform.translate(100, 200).rotate(45); + /// \endcode + /// + /// \param x Offset to apply on X axis + /// \param y Offset to apply on Y axis + /// + /// \return Reference to *this + /// + /// \see rotate, scale + /// + //////////////////////////////////////////////////////////// + Transform& translate(float x, float y); + + //////////////////////////////////////////////////////////// + /// \brief Combine the current transform with a translation + /// + /// This function returns a reference to *this, so that calls + /// can be chained. + /// \code + /// sf::Transform transform; + /// transform.translate(sf::Vector2f(100, 200)).rotate(45); + /// \endcode + /// + /// \param offset Translation offset to apply + /// + /// \return Reference to *this + /// + /// \see rotate, scale + /// + //////////////////////////////////////////////////////////// + Transform& translate(const Vector2f& offset); + + //////////////////////////////////////////////////////////// + /// \brief Combine the current transform with a rotation + /// + /// This function returns a reference to *this, so that calls + /// can be chained. + /// \code + /// sf::Transform transform; + /// transform.rotate(90).translate(50, 20); + /// \endcode + /// + /// \param angle Rotation angle, in degrees + /// + /// \return Reference to *this + /// + /// \see translate, scale + /// + //////////////////////////////////////////////////////////// + Transform& rotate(float angle); + + //////////////////////////////////////////////////////////// + /// \brief Combine the current transform with a rotation + /// + /// The center of rotation is provided for convenience as a second + /// argument, so that you can build rotations around arbitrary points + /// more easily (and efficiently) than the usual + /// translate(-center).rotate(angle).translate(center). + /// + /// This function returns a reference to *this, so that calls + /// can be chained. + /// \code + /// sf::Transform transform; + /// transform.rotate(90, 8, 3).translate(50, 20); + /// \endcode + /// + /// \param angle Rotation angle, in degrees + /// \param centerX X coordinate of the center of rotation + /// \param centerY Y coordinate of the center of rotation + /// + /// \return Reference to *this + /// + /// \see translate, scale + /// + //////////////////////////////////////////////////////////// + Transform& rotate(float angle, float centerX, float centerY); + + //////////////////////////////////////////////////////////// + /// \brief Combine the current transform with a rotation + /// + /// The center of rotation is provided for convenience as a second + /// argument, so that you can build rotations around arbitrary points + /// more easily (and efficiently) than the usual + /// translate(-center).rotate(angle).translate(center). + /// + /// This function returns a reference to *this, so that calls + /// can be chained. + /// \code + /// sf::Transform transform; + /// transform.rotate(90, sf::Vector2f(8, 3)).translate(sf::Vector2f(50, 20)); + /// \endcode + /// + /// \param angle Rotation angle, in degrees + /// \param center Center of rotation + /// + /// \return Reference to *this + /// + /// \see translate, scale + /// + //////////////////////////////////////////////////////////// + Transform& rotate(float angle, const Vector2f& center); + + //////////////////////////////////////////////////////////// + /// \brief Combine the current transform with a scaling + /// + /// This function returns a reference to *this, so that calls + /// can be chained. + /// \code + /// sf::Transform transform; + /// transform.scale(2, 1).rotate(45); + /// \endcode + /// + /// \param scaleX Scaling factor on the X axis + /// \param scaleY Scaling factor on the Y axis + /// + /// \return Reference to *this + /// + /// \see translate, rotate + /// + //////////////////////////////////////////////////////////// + Transform& scale(float scaleX, float scaleY); + + //////////////////////////////////////////////////////////// + /// \brief Combine the current transform with a scaling + /// + /// The center of scaling is provided for convenience as a second + /// argument, so that you can build scaling around arbitrary points + /// more easily (and efficiently) than the usual + /// translate(-center).scale(factors).translate(center). + /// + /// This function returns a reference to *this, so that calls + /// can be chained. + /// \code + /// sf::Transform transform; + /// transform.scale(2, 1, 8, 3).rotate(45); + /// \endcode + /// + /// \param scaleX Scaling factor on X axis + /// \param scaleY Scaling factor on Y axis + /// \param centerX X coordinate of the center of scaling + /// \param centerY Y coordinate of the center of scaling + /// + /// \return Reference to *this + /// + /// \see translate, rotate + /// + //////////////////////////////////////////////////////////// + Transform& scale(float scaleX, float scaleY, float centerX, float centerY); + + //////////////////////////////////////////////////////////// + /// \brief Combine the current transform with a scaling + /// + /// This function returns a reference to *this, so that calls + /// can be chained. + /// \code + /// sf::Transform transform; + /// transform.scale(sf::Vector2f(2, 1)).rotate(45); + /// \endcode + /// + /// \param factors Scaling factors + /// + /// \return Reference to *this + /// + /// \see translate, rotate + /// + //////////////////////////////////////////////////////////// + Transform& scale(const Vector2f& factors); + + //////////////////////////////////////////////////////////// + /// \brief Combine the current transform with a scaling + /// + /// The center of scaling is provided for convenience as a second + /// argument, so that you can build scaling around arbitrary points + /// more easily (and efficiently) than the usual + /// translate(-center).scale(factors).translate(center). + /// + /// This function returns a reference to *this, so that calls + /// can be chained. + /// \code + /// sf::Transform transform; + /// transform.scale(sf::Vector2f(2, 1), sf::Vector2f(8, 3)).rotate(45); + /// \endcode + /// + /// \param factors Scaling factors + /// \param center Center of scaling + /// + /// \return Reference to *this + /// + /// \see translate, rotate + /// + //////////////////////////////////////////////////////////// + Transform& scale(const Vector2f& factors, const Vector2f& center); + + //////////////////////////////////////////////////////////// + // Static member data + //////////////////////////////////////////////////////////// + static const Transform Identity; ///< The identity transform (does nothing) + +private: + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + float m_matrix[16]; ///< 4x4 matrix defining the transformation +}; + +//////////////////////////////////////////////////////////// +/// \relates sf::Transform +/// \brief Overload of binary operator * to combine two transforms +/// +/// This call is equivalent to calling Transform(left).combine(right). +/// +/// \param left Left operand (the first transform) +/// \param right Right operand (the second transform) +/// +/// \return New combined transform +/// +//////////////////////////////////////////////////////////// +SFML_GRAPHICS_API Transform operator *(const Transform& left, const Transform& right); + +//////////////////////////////////////////////////////////// +/// \relates sf::Transform +/// \brief Overload of binary operator *= to combine two transforms +/// +/// This call is equivalent to calling left.combine(right). +/// +/// \param left Left operand (the first transform) +/// \param right Right operand (the second transform) +/// +/// \return The combined transform +/// +//////////////////////////////////////////////////////////// +SFML_GRAPHICS_API Transform& operator *=(Transform& left, const Transform& right); + +//////////////////////////////////////////////////////////// +/// \relates sf::Transform +/// \brief Overload of binary operator * to transform a point +/// +/// This call is equivalent to calling left.transformPoint(right). +/// +/// \param left Left operand (the transform) +/// \param right Right operand (the point to transform) +/// +/// \return New transformed point +/// +//////////////////////////////////////////////////////////// +SFML_GRAPHICS_API Vector2f operator *(const Transform& left, const Vector2f& right); + +} // namespace sf + + +#endif // SFML_TRANSFORM_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Transform +/// \ingroup graphics +/// +/// A sf::Transform specifies how to translate, rotate, scale, +/// shear, project, whatever things. In mathematical terms, it defines +/// how to transform a coordinate system into another. +/// +/// For example, if you apply a rotation transform to a sprite, the +/// result will be a rotated sprite. And anything that is transformed +/// by this rotation transform will be rotated the same way, according +/// to its initial position. +/// +/// Transforms are typically used for drawing. But they can also be +/// used for any computation that requires to transform points between +/// the local and global coordinate systems of an entity (like collision +/// detection). +/// +/// Example: +/// \code +/// // define a translation transform +/// sf::Transform translation; +/// translation.translate(20, 50); +/// +/// // define a rotation transform +/// sf::Transform rotation; +/// rotation.rotate(45); +/// +/// // combine them +/// sf::Transform transform = translation * rotation; +/// +/// // use the result to transform stuff... +/// sf::Vector2f point = transform.transformPoint(10, 20); +/// sf::FloatRect rect = transform.transformRect(sf::FloatRect(0, 0, 10, 100)); +/// \endcode +/// +/// \see sf::Transformable, sf::RenderStates +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Graphics/Transformable.hpp b/src/include/SFML/include/SFML/Graphics/Transformable.hpp new file mode 100644 index 0000000..28fb386 --- /dev/null +++ b/src/include/SFML/include/SFML/Graphics/Transformable.hpp @@ -0,0 +1,417 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_TRANSFORMABLE_HPP +#define SFML_TRANSFORMABLE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Decomposed transform defined by a position, a rotation and a scale +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API Transformable +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + Transformable(); + + //////////////////////////////////////////////////////////// + /// \brief Virtual destructor + /// + //////////////////////////////////////////////////////////// + virtual ~Transformable(); + + //////////////////////////////////////////////////////////// + /// \brief set the position of the object + /// + /// This function completely overwrites the previous position. + /// See the move function to apply an offset based on the previous position instead. + /// The default position of a transformable object is (0, 0). + /// + /// \param x X coordinate of the new position + /// \param y Y coordinate of the new position + /// + /// \see move, getPosition + /// + //////////////////////////////////////////////////////////// + void setPosition(float x, float y); + + //////////////////////////////////////////////////////////// + /// \brief set the position of the object + /// + /// This function completely overwrites the previous position. + /// See the move function to apply an offset based on the previous position instead. + /// The default position of a transformable object is (0, 0). + /// + /// \param position New position + /// + /// \see move, getPosition + /// + //////////////////////////////////////////////////////////// + void setPosition(const Vector2f& position); + + //////////////////////////////////////////////////////////// + /// \brief set the orientation of the object + /// + /// This function completely overwrites the previous rotation. + /// See the rotate function to add an angle based on the previous rotation instead. + /// The default rotation of a transformable object is 0. + /// + /// \param angle New rotation, in degrees + /// + /// \see rotate, getRotation + /// + //////////////////////////////////////////////////////////// + void setRotation(float angle); + + //////////////////////////////////////////////////////////// + /// \brief set the scale factors of the object + /// + /// This function completely overwrites the previous scale. + /// See the scale function to add a factor based on the previous scale instead. + /// The default scale of a transformable object is (1, 1). + /// + /// \param factorX New horizontal scale factor + /// \param factorY New vertical scale factor + /// + /// \see scale, getScale + /// + //////////////////////////////////////////////////////////// + void setScale(float factorX, float factorY); + + //////////////////////////////////////////////////////////// + /// \brief set the scale factors of the object + /// + /// This function completely overwrites the previous scale. + /// See the scale function to add a factor based on the previous scale instead. + /// The default scale of a transformable object is (1, 1). + /// + /// \param factors New scale factors + /// + /// \see scale, getScale + /// + //////////////////////////////////////////////////////////// + void setScale(const Vector2f& factors); + + //////////////////////////////////////////////////////////// + /// \brief set the local origin of the object + /// + /// The origin of an object defines the center point for + /// all transformations (position, scale, rotation). + /// The coordinates of this point must be relative to the + /// top-left corner of the object, and ignore all + /// transformations (position, scale, rotation). + /// The default origin of a transformable object is (0, 0). + /// + /// \param x X coordinate of the new origin + /// \param y Y coordinate of the new origin + /// + /// \see getOrigin + /// + //////////////////////////////////////////////////////////// + void setOrigin(float x, float y); + + //////////////////////////////////////////////////////////// + /// \brief set the local origin of the object + /// + /// The origin of an object defines the center point for + /// all transformations (position, scale, rotation). + /// The coordinates of this point must be relative to the + /// top-left corner of the object, and ignore all + /// transformations (position, scale, rotation). + /// The default origin of a transformable object is (0, 0). + /// + /// \param origin New origin + /// + /// \see getOrigin + /// + //////////////////////////////////////////////////////////// + void setOrigin(const Vector2f& origin); + + //////////////////////////////////////////////////////////// + /// \brief get the position of the object + /// + /// \return Current position + /// + /// \see setPosition + /// + //////////////////////////////////////////////////////////// + const Vector2f& getPosition() const; + + //////////////////////////////////////////////////////////// + /// \brief get the orientation of the object + /// + /// The rotation is always in the range [0, 360]. + /// + /// \return Current rotation, in degrees + /// + /// \see setRotation + /// + //////////////////////////////////////////////////////////// + float getRotation() const; + + //////////////////////////////////////////////////////////// + /// \brief get the current scale of the object + /// + /// \return Current scale factors + /// + /// \see setScale + /// + //////////////////////////////////////////////////////////// + const Vector2f& getScale() const; + + //////////////////////////////////////////////////////////// + /// \brief get the local origin of the object + /// + /// \return Current origin + /// + /// \see setOrigin + /// + //////////////////////////////////////////////////////////// + const Vector2f& getOrigin() const; + + //////////////////////////////////////////////////////////// + /// \brief Move the object by a given offset + /// + /// This function adds to the current position of the object, + /// unlike setPosition which overwrites it. + /// Thus, it is equivalent to the following code: + /// \code + /// sf::Vector2f pos = object.getPosition(); + /// object.setPosition(pos.x + offsetX, pos.y + offsetY); + /// \endcode + /// + /// \param offsetX X offset + /// \param offsetY Y offset + /// + /// \see setPosition + /// + //////////////////////////////////////////////////////////// + void move(float offsetX, float offsetY); + + //////////////////////////////////////////////////////////// + /// \brief Move the object by a given offset + /// + /// This function adds to the current position of the object, + /// unlike setPosition which overwrites it. + /// Thus, it is equivalent to the following code: + /// \code + /// object.setPosition(object.getPosition() + offset); + /// \endcode + /// + /// \param offset Offset + /// + /// \see setPosition + /// + //////////////////////////////////////////////////////////// + void move(const Vector2f& offset); + + //////////////////////////////////////////////////////////// + /// \brief Rotate the object + /// + /// This function adds to the current rotation of the object, + /// unlike setRotation which overwrites it. + /// Thus, it is equivalent to the following code: + /// \code + /// object.setRotation(object.getRotation() + angle); + /// \endcode + /// + /// \param angle Angle of rotation, in degrees + /// + //////////////////////////////////////////////////////////// + void rotate(float angle); + + //////////////////////////////////////////////////////////// + /// \brief Scale the object + /// + /// This function multiplies the current scale of the object, + /// unlike setScale which overwrites it. + /// Thus, it is equivalent to the following code: + /// \code + /// sf::Vector2f scale = object.getScale(); + /// object.setScale(scale.x * factorX, scale.y * factorY); + /// \endcode + /// + /// \param factorX Horizontal scale factor + /// \param factorY Vertical scale factor + /// + /// \see setScale + /// + //////////////////////////////////////////////////////////// + void scale(float factorX, float factorY); + + //////////////////////////////////////////////////////////// + /// \brief Scale the object + /// + /// This function multiplies the current scale of the object, + /// unlike setScale which overwrites it. + /// Thus, it is equivalent to the following code: + /// \code + /// sf::Vector2f scale = object.getScale(); + /// object.setScale(scale.x * factor.x, scale.y * factor.y); + /// \endcode + /// + /// \param factor Scale factors + /// + /// \see setScale + /// + //////////////////////////////////////////////////////////// + void scale(const Vector2f& factor); + + //////////////////////////////////////////////////////////// + /// \brief get the combined transform of the object + /// + /// \return Transform combining the position/rotation/scale/origin of the object + /// + /// \see getInverseTransform + /// + //////////////////////////////////////////////////////////// + const Transform& getTransform() const; + + //////////////////////////////////////////////////////////// + /// \brief get the inverse of the combined transform of the object + /// + /// \return Inverse of the combined transformations applied to the object + /// + /// \see getTransform + /// + //////////////////////////////////////////////////////////// + const Transform& getInverseTransform() const; + +private : + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + Vector2f m_origin; ///< Origin of translation/rotation/scaling of the object + Vector2f m_position; ///< Position of the object in the 2D world + float m_rotation; ///< Orientation of the object, in degrees + Vector2f m_scale; ///< Scale of the object + mutable Transform m_transform; ///< Combined transformation of the object + mutable bool m_transformNeedUpdate; ///< Does the transform need to be recomputed? + mutable Transform m_inverseTransform; ///< Combined transformation of the object + mutable bool m_inverseTransformNeedUpdate; ///< Does the transform need to be recomputed? +}; + +} // namespace sf + + +#endif // SFML_TRANSFORMABLE_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Transformable +/// \ingroup graphics +/// +/// This class is provided for convenience, on top of sf::Transform. +/// +/// sf::Transform, as a low-level class, offers a great level of +/// flexibility but it is not always convenient to manage. Indeed, +/// one can easily combine any kind of operation, such as a translation +/// followed by a rotation followed by a scaling, but once the result +/// transform is built, there's no way to go backward and, let's say, +/// change only the rotation without modifying the translation and scaling. +/// The entire transform must be recomputed, which means that you +/// need to retrieve the initial translation and scale factors as +/// well, and combine them the same way you did before updating the +/// rotation. This is a tedious operation, and it requires to store +/// all the individual components of the final transform. +/// +/// That's exactly what sf::Transformable was written for: it hides +/// these variables and the composed transform behind an easy to use +/// interface. You can set or get any of the individual components +/// without worrying about the others. It also provides the composed +/// transform (as a sf::Transform), and keeps it up-to-date. +/// +/// In addition to the position, rotation and scale, sf::Transformable +/// provides an "origin" component, which represents the local origin +/// of the three other components. Let's take an example with a 10x10 +/// pixels sprite. By default, the sprite is positioned/rotated/scaled +/// relatively to its top-left corner, because it is the local point +/// (0, 0). But if we change the origin to be (5, 5), the sprite will +/// be positioned/rotated/scaled around its center instead. And if +/// we set the origin to (10, 10), it will be transformed around its +/// bottom-right corner. +/// +/// To keep the sf::Transformable class simple, there's only one +/// origin for all the components. You cannot position the sprite +/// relatively to its top-left corner while rotating it around its +/// center, for example. To do such things, use sf::Transform directly. +/// +/// sf::Transformable can be used as a base class. It is often +/// combined with sf::Drawable -- that's what SFML's sprites, +/// texts and shapes do. +/// \code +/// class MyEntity : public sf::Transformable, public sf::Drawable +/// { +/// virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const +/// { +/// states.transform *= getTransform(); +/// target.draw(..., states); +/// } +/// }; +/// +/// MyEntity entity; +/// entity.setPosition(10, 20); +/// entity.setRotation(45); +/// window.draw(entity); +/// \endcode +/// +/// It can also be used as a member, if you don't want to use +/// its API directly (because you don't need all its functions, +/// or you have different naming conventions for example). +/// \code +/// class MyEntity +/// { +/// public : +/// void SetPosition(const MyVector& v) +/// { +/// myTransform.setPosition(v.x(), v.y()); +/// } +/// +/// void Draw(sf::RenderTarget& target) const +/// { +/// target.draw(..., myTransform.getTransform()); +/// } +/// +/// private : +/// sf::Transformable myTransform; +/// }; +/// \endcode +/// +/// \see sf::Transform +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Graphics/Vertex.hpp b/src/include/SFML/include/SFML/Graphics/Vertex.hpp new file mode 100644 index 0000000..b983ef2 --- /dev/null +++ b/src/include/SFML/include/SFML/Graphics/Vertex.hpp @@ -0,0 +1,148 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_VERTEX_HPP +#define SFML_VERTEX_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Define a point with color and texture coordinates +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API Vertex +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + Vertex(); + + //////////////////////////////////////////////////////////// + /// \brief Construct the vertex from its position + /// + /// The vertex color is white and texture coordinates are (0, 0). + /// + /// \param thePosition Vertex position + /// + //////////////////////////////////////////////////////////// + Vertex(const Vector2f& thePosition); + + //////////////////////////////////////////////////////////// + /// \brief Construct the vertex from its position and color + /// + /// The texture coordinates are (0, 0). + /// + /// \param thePosition Vertex position + /// \param theColor Vertex color + /// + //////////////////////////////////////////////////////////// + Vertex(const Vector2f& thePosition, const Color& theColor); + + //////////////////////////////////////////////////////////// + /// \brief Construct the vertex from its position and texture coordinates + /// + /// The vertex color is white. + /// + /// \param thePosition Vertex position + /// \param theTexCoords Vertex texture coordinates + /// + //////////////////////////////////////////////////////////// + Vertex(const Vector2f& thePosition, const Vector2f& theTexCoords); + + //////////////////////////////////////////////////////////// + /// \brief Construct the vertex from its position, color and texture coordinates + /// + /// \param thePosition Vertex position + /// \param theColor Vertex color + /// \param theTexCoords Vertex texture coordinates + /// + //////////////////////////////////////////////////////////// + Vertex(const Vector2f& thePosition, const Color& theColor, const Vector2f& theTexCoords); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + Vector2f position; ///< 2D position of the vertex + Color color; ///< Color of the vertex + Vector2f texCoords; ///< Coordinates of the texture's pixel to map to the vertex +}; + +} // namespace sf + + +#endif // SFML_VERTEX_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Vertex +/// \ingroup graphics +/// +/// A vertex is an improved point. It has a position and other +/// extra attributes that will be used for drawing: in SFML, +/// vertices also have a color and a pair of texture coordinates. +/// +/// The vertex is the building block of drawing. Everything which +/// is visible on screen is made of vertices. They are grouped +/// as 2D primitives (triangles, quads, ...), and these primitives +/// are grouped to create even more complex 2D entities such as +/// sprites, texts, etc. +/// +/// If you use the graphical entities of SFML (sprite, text, shape) +/// you won't have to deal with vertices directly. But if you want +/// to define your own 2D entities, such as tiled maps or particle +/// systems, using vertices will allow you to get maximum performances. +/// +/// Example: +/// \code +/// // define a 100x100 square, red, with a 10x10 texture mapped on it +/// sf::Vertex vertices[] = +/// { +/// sf::Vertex(sf::Vector2f( 0, 0), sf::Color::Red, sf::Vector2f( 0, 0)), +/// sf::Vertex(sf::Vector2f( 0, 100), sf::Color::Red, sf::Vector2f( 0, 10)), +/// sf::Vertex(sf::Vector2f(100, 100), sf::Color::Red, sf::Vector2f(10, 10)), +/// sf::Vertex(sf::Vector2f(100, 0), sf::Color::Red, sf::Vector2f(10, 0)) +/// }; +/// +/// // draw it +/// window.draw(vertices, 4, sf::Quads); +/// \endcode +/// +/// Note: although texture coordinates are supposed to be an integer +/// amount of pixels, their type is float because of some buggy graphics +/// drivers that are not able to process integer coordinates correctly. +/// +/// \see sf::VertexArray +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Graphics/VertexArray.hpp b/src/include/SFML/include/SFML/Graphics/VertexArray.hpp new file mode 100644 index 0000000..fc67845 --- /dev/null +++ b/src/include/SFML/include/SFML/Graphics/VertexArray.hpp @@ -0,0 +1,223 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_VERTEXARRAY_HPP +#define SFML_VERTEXARRAY_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Define a set of one or more 2D primitives +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API VertexArray : public Drawable +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Creates an empty vertex array. + /// + //////////////////////////////////////////////////////////// + VertexArray(); + + //////////////////////////////////////////////////////////// + /// \brief Construct the vertex array with a type and an initial number of vertices + /// + /// \param type Type of primitives + /// \param vertexCount Initial number of vertices in the array + /// + //////////////////////////////////////////////////////////// + explicit VertexArray(PrimitiveType type, unsigned int vertexCount = 0); + + //////////////////////////////////////////////////////////// + /// \brief Return the vertex count + /// + /// \return Number of vertices in the array + /// + //////////////////////////////////////////////////////////// + unsigned int getVertexCount() const; + + //////////////////////////////////////////////////////////// + /// \brief Get a read-write access to a vertex by its index + /// + /// This function doesn't check \a index, it must be in range + /// [0, getVertexCount() - 1]. The behaviour is undefined + /// otherwise. + /// + /// \param index Index of the vertex to get + /// + /// \return Reference to the index-th vertex + /// + /// \see getVertexCount + /// + //////////////////////////////////////////////////////////// + Vertex& operator [](unsigned int index); + + //////////////////////////////////////////////////////////// + /// \brief Get a read-only access to a vertex by its index + /// + /// This function doesn't check \a index, it must be in range + /// [0, getVertexCount() - 1]. The behaviour is undefined + /// otherwise. + /// + /// \param index Index of the vertex to get + /// + /// \return Const reference to the index-th vertex + /// + /// \see getVertexCount + /// + //////////////////////////////////////////////////////////// + const Vertex& operator [](unsigned int index) const; + + //////////////////////////////////////////////////////////// + /// \brief Clear the vertex array + /// + /// This function removes all the vertices from the array. + /// It doesn't deallocate the corresponding memory, so that + /// adding new vertices after clearing doesn't involve + /// reallocating all the memory. + /// + //////////////////////////////////////////////////////////// + void clear(); + + //////////////////////////////////////////////////////////// + /// \brief Resize the vertex array + /// + /// If \a vertexCount is greater than the current size, the previous + /// vertices are kept and new (default-constructed) vertices are + /// added. + /// If \a vertexCount is less than the current size, existing vertices + /// are removed from the array. + /// + /// \param vertexCount New size of the array (number of vertices) + /// + //////////////////////////////////////////////////////////// + void resize(unsigned int vertexCount); + + //////////////////////////////////////////////////////////// + /// \brief Add a vertex to the array + /// + /// \param vertex Vertex to add + /// + //////////////////////////////////////////////////////////// + void append(const Vertex& vertex); + + //////////////////////////////////////////////////////////// + /// \brief Set the type of primitives to draw + /// + /// This function defines how the vertices must be interpreted + /// when it's time to draw them: + /// \li As points + /// \li As lines + /// \li As triangles + /// \li As quads + /// The default primitive type is sf::Points. + /// + /// \param type Type of primitive + /// + //////////////////////////////////////////////////////////// + void setPrimitiveType(PrimitiveType type); + + //////////////////////////////////////////////////////////// + /// \brief Get the type of primitives drawn by the vertex array + /// + /// \return Primitive type + /// + //////////////////////////////////////////////////////////// + PrimitiveType getPrimitiveType() const; + + //////////////////////////////////////////////////////////// + /// \brief Compute the bounding rectangle of the vertex array + /// + /// This function returns the axis-aligned rectangle that + /// contains all the vertices of the array. + /// + /// \return Bounding rectangle of the vertex array + /// + //////////////////////////////////////////////////////////// + FloatRect getBounds() const; + +private : + + //////////////////////////////////////////////////////////// + /// \brief Draw the vertex array to a render target + /// + /// \param target Render target to draw to + /// \param states Current render states + /// + //////////////////////////////////////////////////////////// + virtual void draw(RenderTarget& target, RenderStates states) const; + +private: + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + std::vector m_vertices; ///< Vertices contained in the array + PrimitiveType m_primitiveType; ///< Type of primitives to draw +}; + +} // namespace sf + + +#endif // SFML_VERTEXARRAY_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::VertexArray +/// \ingroup graphics +/// +/// sf::VertexArray is a very simple wrapper around a dynamic +/// array of vertices and a primitives type. +/// +/// It inherits sf::Drawable, but unlike other drawables it +/// is not transformable. +/// +/// Example: +/// \code +/// sf::VertexArray lines(sf::LinesStrip, 4); +/// lines[0].position = sf::Vector2f(10, 0); +/// lines[1].position = sf::Vector2f(20, 0); +/// lines[2].position = sf::Vector2f(30, 5); +/// lines[3].position = sf::Vector2f(40, 2); +/// +/// window.draw(lines); +/// \endcode +/// +/// \see sf::Vertex +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Graphics/View.hpp b/src/include/SFML/include/SFML/Graphics/View.hpp new file mode 100644 index 0000000..3c49879 --- /dev/null +++ b/src/include/SFML/include/SFML/Graphics/View.hpp @@ -0,0 +1,341 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_VIEW_HPP +#define SFML_VIEW_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief 2D camera that defines what region is shown on screen +/// +//////////////////////////////////////////////////////////// +class SFML_GRAPHICS_API View +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// This constructor creates a default view of (0, 0, 1000, 1000) + /// + //////////////////////////////////////////////////////////// + View(); + + //////////////////////////////////////////////////////////// + /// \brief Construct the view from a rectangle + /// + /// \param rectangle Rectangle defining the zone to display + /// + //////////////////////////////////////////////////////////// + explicit View(const FloatRect& rectangle); + + //////////////////////////////////////////////////////////// + /// \brief Construct the view from its center and size + /// + /// \param center Center of the zone to display + /// \param size Size of zone to display + /// + //////////////////////////////////////////////////////////// + View(const Vector2f& center, const Vector2f& size); + + //////////////////////////////////////////////////////////// + /// \brief Set the center of the view + /// + /// \param x X coordinate of the new center + /// \param y Y coordinate of the new center + /// + /// \see setSize, getCenter + /// + //////////////////////////////////////////////////////////// + void setCenter(float x, float y); + + //////////////////////////////////////////////////////////// + /// \brief Set the center of the view + /// + /// \param center New center + /// + /// \see setSize, getCenter + /// + //////////////////////////////////////////////////////////// + void setCenter(const Vector2f& center); + + //////////////////////////////////////////////////////////// + /// \brief Set the size of the view + /// + /// \param width New width of the view + /// \param height New height of the view + /// + /// \see setCenter, getCenter + /// + //////////////////////////////////////////////////////////// + void setSize(float width, float height); + + //////////////////////////////////////////////////////////// + /// \brief Set the size of the view + /// + /// \param size New size + /// + /// \see setCenter, getCenter + /// + //////////////////////////////////////////////////////////// + void setSize(const Vector2f& size); + + //////////////////////////////////////////////////////////// + /// \brief Set the orientation of the view + /// + /// The default rotation of a view is 0 degree. + /// + /// \param angle New angle, in degrees + /// + /// \see getRotation + /// + //////////////////////////////////////////////////////////// + void setRotation(float angle); + + //////////////////////////////////////////////////////////// + /// \brief Set the target viewport + /// + /// The viewport is the rectangle into which the contents of the + /// view are displayed, expressed as a factor (between 0 and 1) + /// of the size of the RenderTarget to which the view is applied. + /// For example, a view which takes the left side of the target would + /// be defined with View.setViewport(sf::FloatRect(0, 0, 0.5, 1)). + /// By default, a view has a viewport which covers the entire target. + /// + /// \param viewport New viewport rectangle + /// + /// \see getViewport + /// + //////////////////////////////////////////////////////////// + void setViewport(const FloatRect& viewport); + + //////////////////////////////////////////////////////////// + /// \brief Reset the view to the given rectangle + /// + /// Note that this function resets the rotation angle to 0. + /// + /// \param rectangle Rectangle defining the zone to display + /// + /// \see setCenter, setSize, setRotation + /// + //////////////////////////////////////////////////////////// + void reset(const FloatRect& rectangle); + + //////////////////////////////////////////////////////////// + /// \brief Get the center of the view + /// + /// \return Center of the view + /// + /// \see getSize, setCenter + /// + //////////////////////////////////////////////////////////// + const Vector2f& getCenter() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the size of the view + /// + /// \return Size of the view + /// + /// \see getCenter, setSize + /// + //////////////////////////////////////////////////////////// + const Vector2f& getSize() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the current orientation of the view + /// + /// \return Rotation angle of the view, in degrees + /// + /// \see setRotation + /// + //////////////////////////////////////////////////////////// + float getRotation() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the target viewport rectangle of the view + /// + /// \return Viewport rectangle, expressed as a factor of the target size + /// + /// \see setViewport + /// + //////////////////////////////////////////////////////////// + const FloatRect& getViewport() const; + + //////////////////////////////////////////////////////////// + /// \brief Move the view relatively to its current position + /// + /// \param offsetX X coordinate of the move offset + /// \param offsetY Y coordinate of the move offset + /// + /// \see setCenter, rotate, zoom + /// + //////////////////////////////////////////////////////////// + void move(float offsetX, float offsetY); + + //////////////////////////////////////////////////////////// + /// \brief Move the view relatively to its current position + /// + /// \param offset Move offset + /// + /// \see setCenter, rotate, zoom + /// + //////////////////////////////////////////////////////////// + void move(const Vector2f& offset); + + //////////////////////////////////////////////////////////// + /// \brief Rotate the view relatively to its current orientation + /// + /// \param angle Angle to rotate, in degrees + /// + /// \see setRotation, move, zoom + /// + //////////////////////////////////////////////////////////// + void rotate(float angle); + + //////////////////////////////////////////////////////////// + /// \brief Resize the view rectangle relatively to its current size + /// + /// Resizing the view simulates a zoom, as the zone displayed on + /// screen grows or shrinks. + /// \a factor is a multiplier: + /// \li 1 keeps the size unchanged + /// \li > 1 makes the view bigger (objects appear smaller) + /// \li < 1 makes the view smaller (objects appear bigger) + /// + /// \param factor Zoom factor to apply + /// + /// \see setSize, move, rotate + /// + //////////////////////////////////////////////////////////// + void zoom(float factor); + + //////////////////////////////////////////////////////////// + /// \brief Get the projection transform of the view + /// + /// This function is meant for internal use only. + /// + /// \return Projection transform defining the view + /// + /// \see getInverseTransform + /// + //////////////////////////////////////////////////////////// + const Transform& getTransform() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the inverse projection transform of the view + /// + /// This function is meant for internal use only. + /// + /// \return Inverse of the projection transform defining the view + /// + /// \see getTransform + /// + //////////////////////////////////////////////////////////// + const Transform& getInverseTransform() const; + +private : + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + Vector2f m_center; ///< Center of the view, in scene coordinates + Vector2f m_size; ///< Size of the view, in scene coordinates + float m_rotation; ///< Angle of rotation of the view rectangle, in degrees + FloatRect m_viewport; ///< Viewport rectangle, expressed as a factor of the render-target's size + mutable Transform m_transform; ///< Precomputed projection transform corresponding to the view + mutable Transform m_inverseTransform; ///< Precomputed inverse projection transform corresponding to the view + mutable bool m_transformUpdated; ///< Internal state telling if the transform needs to be updated + mutable bool m_invTransformUpdated; ///< Internal state telling if the inverse transform needs to be updated +}; + +} // namespace sf + + +#endif // SFML_VIEW_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::View +/// \ingroup graphics +/// +/// sf::View defines a camera in the 2D scene. This is a +/// very powerful concept: you can scroll, rotate or zoom +/// the entire scene without altering the way that your +/// drawable objects are drawn. +/// +/// A view is composed of a source rectangle, which defines +/// what part of the 2D scene is shown, and a target viewport, +/// which defines where the contents of the source rectangle +/// will be displayed on the render target (window or texture). +/// +/// The viewport allows to map the scene to a custom part +/// of the render target, and can be used for split-screen +/// or for displaying a minimap, for example. If the source +/// rectangle has not the same size as the viewport, its +/// contents will be stretched to fit in. +/// +/// To apply a view, you have to assign it to the render target. +/// Then, every objects drawn in this render target will be +/// affected by the view until you use another view. +/// +/// Usage example: +/// \code +/// sf::RenderWindow window; +/// sf::View view; +/// +/// // Initialize the view to a rectangle located at (100, 100) and with a size of 400x200 +/// view.reset(sf::FloatRect(100, 100, 400, 200)); +/// +/// // Rotate it by 45 degrees +/// view.rotate(45); +/// +/// // Set its target viewport to be half of the window +/// view.setViewport(sf::FloatRect(0.f, 0.f, 0.5f, 1.f)); +/// +/// // Apply it +/// window.setView(view); +/// +/// // Render stuff +/// window.draw(someSprite); +/// +/// // Set the default view back +/// window.setView(window.getDefaultView()); +/// +/// // Render stuff not affected by the view +/// window.draw(someText); +/// \endcode +/// +/// \see sf::RenderWindow, sf::RenderTexture +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Network.hpp b/src/include/SFML/include/SFML/Network.hpp new file mode 100644 index 0000000..6cfd2b5 --- /dev/null +++ b/src/include/SFML/include/SFML/Network.hpp @@ -0,0 +1,51 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_NETWORK_HPP +#define SFML_NETWORK_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#endif // SFML_NETWORK_HPP + +//////////////////////////////////////////////////////////// +/// \defgroup network Network module +/// +/// Socket-based communication, utilities and higher-level +/// network protocols (HTTP, FTP). +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Network/Export.hpp b/src/include/SFML/include/SFML/Network/Export.hpp new file mode 100644 index 0000000..7dcd1d0 --- /dev/null +++ b/src/include/SFML/include/SFML/Network/Export.hpp @@ -0,0 +1,48 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_NETWORK_EXPORT_HPP +#define SFML_NETWORK_EXPORT_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +//////////////////////////////////////////////////////////// +// Define portable import / export macros +//////////////////////////////////////////////////////////// +#if defined(SFML_NETWORK_EXPORTS) + + #define SFML_NETWORK_API SFML_API_EXPORT + +#else + + #define SFML_NETWORK_API SFML_API_IMPORT + +#endif + + +#endif // SFML_NETWORK_EXPORT_HPP diff --git a/src/include/SFML/include/SFML/Network/Ftp.hpp b/src/include/SFML/include/SFML/Network/Ftp.hpp new file mode 100644 index 0000000..58cd8f2 --- /dev/null +++ b/src/include/SFML/include/SFML/Network/Ftp.hpp @@ -0,0 +1,591 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_FTP_HPP +#define SFML_FTP_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include + + +namespace sf +{ +class IpAddress; + +//////////////////////////////////////////////////////////// +/// \brief A FTP client +/// +//////////////////////////////////////////////////////////// +class SFML_NETWORK_API Ftp : NonCopyable +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Enumeration of transfer modes + /// + //////////////////////////////////////////////////////////// + enum TransferMode + { + Binary, ///< Binary mode (file is transfered as a sequence of bytes) + Ascii, ///< Text mode using ASCII encoding + Ebcdic ///< Text mode using EBCDIC encoding + }; + + //////////////////////////////////////////////////////////// + /// \brief Define a FTP response + /// + //////////////////////////////////////////////////////////// + class SFML_NETWORK_API Response + { + public : + + //////////////////////////////////////////////////////////// + /// \brief Status codes possibly returned by a FTP response + /// + //////////////////////////////////////////////////////////// + enum Status + { + // 1xx: the requested action is being initiated, + // expect another reply before proceeding with a new command + RestartMarkerReply = 110, ///< Restart marker reply + ServiceReadySoon = 120, ///< Service ready in N minutes + DataConnectionAlreadyOpened = 125, ///< Data connection already opened, transfer starting + OpeningDataConnection = 150, ///< File status ok, about to open data connection + + // 2xx: the requested action has been successfully completed + Ok = 200, ///< Command ok + PointlessCommand = 202, ///< Command not implemented + SystemStatus = 211, ///< System status, or system help reply + DirectoryStatus = 212, ///< Directory status + FileStatus = 213, ///< File status + HelpMessage = 214, ///< Help message + SystemType = 215, ///< NAME system type, where NAME is an official system name from the list in the Assigned Numbers document + ServiceReady = 220, ///< Service ready for new user + ClosingConnection = 221, ///< Service closing control connection + DataConnectionOpened = 225, ///< Data connection open, no transfer in progress + ClosingDataConnection = 226, ///< Closing data connection, requested file action successful + EnteringPassiveMode = 227, ///< Entering passive mode + LoggedIn = 230, ///< User logged in, proceed. Logged out if appropriate + FileActionOk = 250, ///< Requested file action ok + DirectoryOk = 257, ///< PATHNAME created + + // 3xx: the command has been accepted, but the requested action + // is dormant, pending receipt of further information + NeedPassword = 331, ///< User name ok, need password + NeedAccountToLogIn = 332, ///< Need account for login + NeedInformation = 350, ///< Requested file action pending further information + + // 4xx: the command was not accepted and the requested action did not take place, + // but the error condition is temporary and the action may be requested again + ServiceUnavailable = 421, ///< Service not available, closing control connection + DataConnectionUnavailable = 425, ///< Can't open data connection + TransferAborted = 426, ///< Connection closed, transfer aborted + FileActionAborted = 450, ///< Requested file action not taken + LocalError = 451, ///< Requested action aborted, local error in processing + InsufficientStorageSpace = 452, ///< Requested action not taken; insufficient storage space in system, file unavailable + + // 5xx: the command was not accepted and + // the requested action did not take place + CommandUnknown = 500, ///< Syntax error, command unrecognized + ParametersUnknown = 501, ///< Syntax error in parameters or arguments + CommandNotImplemented = 502, ///< Command not implemented + BadCommandSequence = 503, ///< Bad sequence of commands + ParameterNotImplemented = 504, ///< Command not implemented for that parameter + NotLoggedIn = 530, ///< Not logged in + NeedAccountToStore = 532, ///< Need account for storing files + FileUnavailable = 550, ///< Requested action not taken, file unavailable + PageTypeUnknown = 551, ///< Requested action aborted, page type unknown + NotEnoughMemory = 552, ///< Requested file action aborted, exceeded storage allocation + FilenameNotAllowed = 553, ///< Requested action not taken, file name not allowed + + // 10xx: SFML custom codes + InvalidResponse = 1000, ///< Response is not a valid FTP one + ConnectionFailed = 1001, ///< Connection with server failed + ConnectionClosed = 1002, ///< Connection with server closed + InvalidFile = 1003 ///< Invalid file to upload / download + }; + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// This constructor is used by the FTP client to build + /// the response. + /// + /// \param code Response status code + /// \param message Response message + /// + //////////////////////////////////////////////////////////// + explicit Response(Status code = InvalidResponse, const std::string& message = ""); + + //////////////////////////////////////////////////////////// + /// \brief Check if the status code means a success + /// + /// This function is defined for convenience, it is + /// equivalent to testing if the status code is < 400. + /// + /// \return True if the status is a success, false if it is a failure + /// + //////////////////////////////////////////////////////////// + bool isOk() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the status code of the response + /// + /// \return Status code + /// + //////////////////////////////////////////////////////////// + Status getStatus() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the full message contained in the response + /// + /// \return The response message + /// + //////////////////////////////////////////////////////////// + const std::string& getMessage() const; + + private : + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + Status m_status; ///< Status code returned from the server + std::string m_message; ///< Last message received from the server + }; + + //////////////////////////////////////////////////////////// + /// \brief Specialization of FTP response returning a directory + /// + //////////////////////////////////////////////////////////// + class SFML_NETWORK_API DirectoryResponse : public Response + { + public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// \param response Source response + /// + //////////////////////////////////////////////////////////// + DirectoryResponse(const Response& response); + + //////////////////////////////////////////////////////////// + /// \brief Get the directory returned in the response + /// + /// \return Directory name + /// + //////////////////////////////////////////////////////////// + const std::string& getDirectory() const; + + private : + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + std::string m_directory; ///< Directory extracted from the response message + }; + + + //////////////////////////////////////////////////////////// + /// \brief Specialization of FTP response returning a + /// filename lisiting + //////////////////////////////////////////////////////////// + class SFML_NETWORK_API ListingResponse : public Response + { + public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// \param response Source response + /// \param data Data containing the raw listing + /// + //////////////////////////////////////////////////////////// + ListingResponse(const Response& response, const std::vector& data); + + //////////////////////////////////////////////////////////// + /// \brief Return the array of directory/file names + /// + /// \return Array containing the requested listing + /// + //////////////////////////////////////////////////////////// + const std::vector& getListing() const; + + private : + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + std::vector m_listing; ///< Directory/file names extracted from the data + }; + + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + /// Automatically closes the connection with the server if + /// it is still opened. + /// + //////////////////////////////////////////////////////////// + ~Ftp(); + + //////////////////////////////////////////////////////////// + /// \brief Connect to the specified FTP server + /// + /// The port has a default value of 21, which is the standard + /// port used by the FTP protocol. You shouldn't use a different + /// value, unless you really know what you do. + /// This function tries to connect to the server so it may take + /// a while to complete, especially if the server is not + /// reachable. To avoid blocking your application for too long, + /// you can use a timeout. The default value, Time::Zero, means that the + /// system timeout will be used (which is usually pretty long). + /// + /// \param server Name or address of the FTP server to connect to + /// \param port Port used for the connection + /// \param timeout Maximum time to wait + /// + /// \return Server response to the request + /// + /// \see disconnect + /// + //////////////////////////////////////////////////////////// + Response connect(const IpAddress& server, unsigned short port = 21, Time timeout = Time::Zero); + + //////////////////////////////////////////////////////////// + /// \brief Close the connection with the server + /// + /// \return Server response to the request + /// + /// \see connect + /// + //////////////////////////////////////////////////////////// + Response disconnect(); + + //////////////////////////////////////////////////////////// + /// \brief Log in using an anonymous account + /// + /// Logging in is mandatory after connecting to the server. + /// Users that are not logged in cannot perform any operation. + /// + /// \return Server response to the request + /// + //////////////////////////////////////////////////////////// + Response login(); + + //////////////////////////////////////////////////////////// + /// \brief Log in using a username and a password + /// + /// Logging in is mandatory after connecting to the server. + /// Users that are not logged in cannot perform any operation. + /// + /// \param name User name + /// \param password Password + /// + /// \return Server response to the request + /// + //////////////////////////////////////////////////////////// + Response login(const std::string& name, const std::string& password); + + //////////////////////////////////////////////////////////// + /// \brief Send a null command to keep the connection alive + /// + /// This command is useful because the server may close the + /// connection automatically if no command is sent. + /// + /// \return Server response to the request + /// + //////////////////////////////////////////////////////////// + Response keepAlive(); + + //////////////////////////////////////////////////////////// + /// \brief Get the current working directory + /// + /// The working directory is the root path for subsequent + /// operations involving directories and/or filenames. + /// + /// \return Server response to the request + /// + /// \see getDirectoryListing, changeDirectory, parentDirectory + /// + //////////////////////////////////////////////////////////// + DirectoryResponse getWorkingDirectory(); + + //////////////////////////////////////////////////////////// + /// \brief Get the contents of the given directory + /// + /// This function retrieves the sub-directories and files + /// contained in the given directory. It is not recursive. + /// The \a directory parameter is relative to the current + /// working directory. + /// + /// \param directory Directory to list + /// + /// \return Server response to the request + /// + /// \see getWorkingDirectory, changeDirectory, parentDirectory + /// + //////////////////////////////////////////////////////////// + ListingResponse getDirectoryListing(const std::string& directory = ""); + + //////////////////////////////////////////////////////////// + /// \brief Change the current working directory + /// + /// The new directory must be relative to the current one. + /// + /// \param directory New working directory + /// + /// \return Server response to the request + /// + /// \see getWorkingDirectory, getDirectoryListing, parentDirectory + /// + //////////////////////////////////////////////////////////// + Response changeDirectory(const std::string& directory); + + //////////////////////////////////////////////////////////// + /// \brief Go to the parent directory of the current one + /// + /// \return Server response to the request + /// + /// \see getWorkingDirectory, getDirectoryListing, changeDirectory + /// + //////////////////////////////////////////////////////////// + Response parentDirectory(); + + //////////////////////////////////////////////////////////// + /// \brief Create a new directory + /// + /// The new directory is created as a child of the current + /// working directory. + /// + /// \param name Name of the directory to create + /// + /// \return Server response to the request + /// + /// \see deleteDirectory + /// + //////////////////////////////////////////////////////////// + Response createDirectory(const std::string& name); + + //////////////////////////////////////////////////////////// + /// \brief Remove an existing directory + /// + /// The directory to remove must be relative to the + /// current working directory. + /// Use this function with caution, the directory will + /// be removed permanently! + /// + /// \param name Name of the directory to remove + /// + /// \return Server response to the request + /// + /// \see createDirectory + /// + //////////////////////////////////////////////////////////// + Response deleteDirectory(const std::string& name); + + //////////////////////////////////////////////////////////// + /// \brief Rename an existing file + /// + /// The filenames must be relative to the current working + /// directory. + /// + /// \param file File to rename + /// \param newName New name of the file + /// + /// \return Server response to the request + /// + /// \see deleteFile + /// + //////////////////////////////////////////////////////////// + Response renameFile(const std::string& file, const std::string& newName); + + //////////////////////////////////////////////////////////// + /// \brief Remove an existing file + /// + /// The file name must be relative to the current working + /// directory. + /// Use this function with caution, the file will be + /// removed permanently! + /// + /// \param name File to remove + /// + /// \return Server response to the request + /// + /// \see renameFile + /// + //////////////////////////////////////////////////////////// + Response deleteFile(const std::string& name); + + //////////////////////////////////////////////////////////// + /// \brief Download a file from the server + /// + /// The filename of the distant file is relative to the + /// current working directory of the server, and the local + /// destination path is relative to the current directory + /// of your application. + /// + /// \param remoteFile Filename of the distant file to download + /// \param localPath Where to put to file on the local computer + /// \param mode Transfer mode + /// + /// \return Server response to the request + /// + /// \see upload + /// + //////////////////////////////////////////////////////////// + Response download(const std::string& remoteFile, const std::string& localPath, TransferMode mode = Binary); + + //////////////////////////////////////////////////////////// + /// \brief Upload a file to the server + /// + /// The name of the local file is relative to the current + /// working directory of your application, and the + /// remote path is relative to the current directory of the + /// FTP server. + /// + /// \param localFile Path of the local file to upload + /// \param remotePath Where to put to file on the server + /// \param mode Transfer mode + /// + /// \return Server response to the request + /// + /// \see download + /// + //////////////////////////////////////////////////////////// + Response upload(const std::string& localFile, const std::string& remotePath, TransferMode mode = Binary); + +private : + + //////////////////////////////////////////////////////////// + /// \brief Send a command to the FTP server + /// + /// \param command Command to send + /// \param parameter Command parameter + /// + /// \return Server response to the request + /// + //////////////////////////////////////////////////////////// + Response sendCommand(const std::string& command, const std::string& parameter = ""); + + //////////////////////////////////////////////////////////// + /// \brief Receive a response from the server + /// + /// This function must be called after each call to + /// SendCommand that expects a response. + /// + /// \return Server response to the request + /// + //////////////////////////////////////////////////////////// + Response getResponse(); + + //////////////////////////////////////////////////////////// + /// \brief Utility class for exchanging datas with the server + /// on the data channel + /// + //////////////////////////////////////////////////////////// + class DataChannel; + + friend class DataChannel; + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + TcpSocket m_commandSocket; ///< Socket holding the control connection with the server +}; + +} // namespace sf + + +#endif // SFML_FTP_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Ftp +/// \ingroup network +/// +/// sf::Ftp is a very simple FTP client that allows you +/// to communicate with a FTP server. The FTP protocol allows +/// you to manipulate a remote file system (list files, +/// upload, download, create, remove, ...). +/// +/// Using the FTP client consists of 4 parts: +/// \li Connecting to the FTP server +/// \li Logging in (either as a registered user or anonymously) +/// \li Sending commands to the server +/// \li Disconnecting (this part can be done implicitely by the destructor) +/// +/// Every command returns a FTP response, which contains the +/// status code as well as a message from the server. Some +/// commands such as getWorkingDirectory and getDirectoryListing +/// return additional data, and use a class derived from +/// sf::Ftp::Response to provide this data. +/// +/// All commands, especially upload and download, may take some +/// time to complete. This is important to know if you don't want +/// to block your application while the server is completing +/// the task. +/// +/// Usage example: +/// \code +/// // Create a new FTP client +/// sf::Ftp ftp; +/// +/// // Connect to the server +/// sf::Ftp::Response response = ftp.connect("ftp://ftp.myserver.com"); +/// if (response.isOk()) +/// std::cout << "Connected" << std::endl; +/// +/// // Log in +/// response = ftp.login("laurent", "dF6Zm89D"); +/// if (response.isOk()) +/// std::cout << "Logged in" << std::endl; +/// +/// // Print the working directory +/// sf::Ftp::DirectoryResponse directory = ftp.getWorkingDirectory(); +/// if (directory.isOk()) +/// std::cout << "Working directory: " << directory.getDirectory() << std::endl; +/// +/// // Create a new directory +/// response = ftp.createDirectory("files"); +/// if (response.isOk()) +/// std::cout << "Created new directory" << std::endl; +/// +/// // Upload a file to this new directory +/// response = ftp.upload("local-path/file.txt", "files", sf::Ftp::Ascii); +/// if (response.isOk()) +/// std::cout << "File uploaded" << std::endl; +/// +/// // Disconnect from the server (optional) +/// ftp.disconnect(); +/// \endcode +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Network/Http.hpp b/src/include/SFML/include/SFML/Network/Http.hpp new file mode 100644 index 0000000..c21415f --- /dev/null +++ b/src/include/SFML/include/SFML/Network/Http.hpp @@ -0,0 +1,467 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_HTTP_HPP +#define SFML_HTTP_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief A HTTP client +/// +//////////////////////////////////////////////////////////// +class SFML_NETWORK_API Http : NonCopyable +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Define a HTTP request + /// + //////////////////////////////////////////////////////////// + class SFML_NETWORK_API Request + { + public : + + //////////////////////////////////////////////////////////// + /// \brief Enumerate the available HTTP methods for a request + /// + //////////////////////////////////////////////////////////// + enum Method + { + Get, ///< Request in get mode, standard method to retrieve a page + Post, ///< Request in post mode, usually to send data to a page + Head ///< Request a page's header only + }; + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// This constructor creates a GET request, with the root + /// URI ("/") and an empty body. + /// + /// \param uri Target URI + /// \param method Method to use for the request + /// \param body Content of the request's body + /// + //////////////////////////////////////////////////////////// + Request(const std::string& uri = "/", Method method = Get, const std::string& body = ""); + + //////////////////////////////////////////////////////////// + /// \brief Set the value of a field + /// + /// The field is created if it doesn't exist. The name of + /// the field is case insensitive. + /// By default, a request doesn't contain any field (but the + /// mandatory fields are added later by the HTTP client when + /// sending the request). + /// + /// \param field Name of the field to set + /// \param value Value of the field + /// + //////////////////////////////////////////////////////////// + void setField(const std::string& field, const std::string& value); + + //////////////////////////////////////////////////////////// + /// \brief Set the request method + /// + /// See the Method enumeration for a complete list of all + /// the availale methods. + /// The method is Http::Request::Get by default. + /// + /// \param method Method to use for the request + /// + //////////////////////////////////////////////////////////// + void setMethod(Method method); + + //////////////////////////////////////////////////////////// + /// \brief Set the requested URI + /// + /// The URI is the resource (usually a web page or a file) + /// that you want to get or post. + /// The URI is "/" (the root page) by default. + /// + /// \param uri URI to request, relative to the host + /// + //////////////////////////////////////////////////////////// + void setUri(const std::string& uri); + + //////////////////////////////////////////////////////////// + /// \brief Set the HTTP version for the request + /// + /// The HTTP version is 1.0 by default. + /// + /// \param major Major HTTP version number + /// \param minor Minor HTTP version number + /// + //////////////////////////////////////////////////////////// + void setHttpVersion(unsigned int major, unsigned int minor); + + //////////////////////////////////////////////////////////// + /// \brief Set the body of the request + /// + /// The body of a request is optional and only makes sense + /// for POST requests. It is ignored for all other methods. + /// The body is empty by default. + /// + /// \param body Content of the body + /// + //////////////////////////////////////////////////////////// + void setBody(const std::string& body); + + private : + + friend class Http; + + //////////////////////////////////////////////////////////// + /// \brief Prepare the final request to send to the server + /// + /// This is used internally by Http before sending the + /// request to the web server. + /// + /// \return String containing the request, ready to be sent + /// + //////////////////////////////////////////////////////////// + std::string prepare() const; + + //////////////////////////////////////////////////////////// + /// \brief Check if the request defines a field + /// + /// This function uses case-insensitive comparisons. + /// + /// \param field Name of the field to test + /// + /// \return True if the field exists, false otherwise + /// + //////////////////////////////////////////////////////////// + bool hasField(const std::string& field) const; + + //////////////////////////////////////////////////////////// + // Types + //////////////////////////////////////////////////////////// + typedef std::map FieldTable; + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + FieldTable m_fields; ///< Fields of the header associated to their value + Method m_method; ///< Method to use for the request + std::string m_uri; ///< Target URI of the request + unsigned int m_majorVersion; ///< Major HTTP version + unsigned int m_minorVersion; ///< Minor HTTP version + std::string m_body; ///< Body of the request + }; + + //////////////////////////////////////////////////////////// + /// \brief Define a HTTP response + /// + //////////////////////////////////////////////////////////// + class SFML_NETWORK_API Response + { + public : + + //////////////////////////////////////////////////////////// + /// \brief Enumerate all the valid status codes for a response + /// + //////////////////////////////////////////////////////////// + enum Status + { + // 2xx: success + Ok = 200, ///< Most common code returned when operation was successful + Created = 201, ///< The resource has successfully been created + Accepted = 202, ///< The request has been accepted, but will be processed later by the server + NoContent = 204, ///< The server didn't send any data in return + ResetContent = 205, ///< The server informs the client that it should clear the view (form) that caused the request to be sent + PartialContent = 206, ///< The server has sent a part of the resource, as a response to a partial GET request + + // 3xx: redirection + MultipleChoices = 300, ///< The requested page can be accessed from several locations + MovedPermanently = 301, ///< The requested page has permanently moved to a new location + MovedTemporarily = 302, ///< The requested page has temporarily moved to a new location + NotModified = 304, ///< For conditionnal requests, means the requested page hasn't changed and doesn't need to be refreshed + + // 4xx: client error + BadRequest = 400, ///< The server couldn't understand the request (syntax error) + Unauthorized = 401, ///< The requested page needs an authentification to be accessed + Forbidden = 403, ///< The requested page cannot be accessed at all, even with authentification + NotFound = 404, ///< The requested page doesn't exist + RangeNotSatisfiable = 407, ///< The server can't satisfy the partial GET request (with a "Range" header field) + + // 5xx: server error + InternalServerError = 500, ///< The server encountered an unexpected error + NotImplemented = 501, ///< The server doesn't implement a requested feature + BadGateway = 502, ///< The gateway server has received an error from the source server + ServiceNotAvailable = 503, ///< The server is temporarily unavailable (overloaded, in maintenance, ...) + GatewayTimeout = 504, ///< The gateway server couldn't receive a response from the source server + VersionNotSupported = 505, ///< The server doesn't support the requested HTTP version + + // 10xx: SFML custom codes + InvalidResponse = 1000, ///< Response is not a valid HTTP one + ConnectionFailed = 1001 ///< Connection with server failed + }; + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Constructs an empty response. + /// + //////////////////////////////////////////////////////////// + Response(); + + //////////////////////////////////////////////////////////// + /// \brief Get the value of a field + /// + /// If the field \a field is not found in the response header, + /// the empty string is returned. This function uses + /// case-insensitive comparisons. + /// + /// \param field Name of the field to get + /// + /// \return Value of the field, or empty string if not found + /// + //////////////////////////////////////////////////////////// + const std::string& getField(const std::string& field) const; + + //////////////////////////////////////////////////////////// + /// \brief Get the response status code + /// + /// The status code should be the first thing to be checked + /// after receiving a response, it defines whether it is a + /// success, a failure or anything else (see the Status + /// enumeration). + /// + /// \return Status code of the response + /// + //////////////////////////////////////////////////////////// + Status getStatus() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the major HTTP version number of the response + /// + /// \return Major HTTP version number + /// + /// \see getMinorHttpVersion + /// + //////////////////////////////////////////////////////////// + unsigned int getMajorHttpVersion() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the minor HTTP version number of the response + /// + /// \return Minor HTTP version number + /// + /// \see getMajorHttpVersion + /// + //////////////////////////////////////////////////////////// + unsigned int getMinorHttpVersion() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the body of the response + /// + /// The body of a response may contain: + /// \li the requested page (for GET requests) + /// \li a response from the server (for POST requests) + /// \li nothing (for HEAD requests) + /// \li an error message (in case of an error) + /// + /// \return The response body + /// + //////////////////////////////////////////////////////////// + const std::string& getBody() const; + + private : + + friend class Http; + + //////////////////////////////////////////////////////////// + /// \brief Construct the header from a response string + /// + /// This function is used by Http to build the response + /// of a request. + /// + /// \param data Content of the response to parse + /// + //////////////////////////////////////////////////////////// + void parse(const std::string& data); + + //////////////////////////////////////////////////////////// + // Types + //////////////////////////////////////////////////////////// + typedef std::map FieldTable; + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + FieldTable m_fields; ///< Fields of the header + Status m_status; ///< Status code + unsigned int m_majorVersion; ///< Major HTTP version + unsigned int m_minorVersion; ///< Minor HTTP version + std::string m_body; ///< Body of the response + }; + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + Http(); + + //////////////////////////////////////////////////////////// + /// \brief Construct the HTTP client with the target host + /// + /// This is equivalent to calling setHost(host, port). + /// The port has a default value of 0, which means that the + /// HTTP client will use the right port according to the + /// protocol used (80 for HTTP, 443 for HTTPS). You should + /// leave it like this unless you really need a port other + /// than the standard one, or use an unknown protocol. + /// + /// \param host Web server to connect to + /// \param port Port to use for connection + /// + //////////////////////////////////////////////////////////// + Http(const std::string& host, unsigned short port = 0); + + //////////////////////////////////////////////////////////// + /// \brief Set the target host + /// + /// This function just stores the host address and port, it + /// doesn't actually connect to it until you send a request. + /// The port has a default value of 0, which means that the + /// HTTP client will use the right port according to the + /// protocol used (80 for HTTP, 443 for HTTPS). You should + /// leave it like this unless you really need a port other + /// than the standard one, or use an unknown protocol. + /// + /// \param host Web server to connect to + /// \param port Port to use for connection + /// + //////////////////////////////////////////////////////////// + void setHost(const std::string& host, unsigned short port = 0); + + //////////////////////////////////////////////////////////// + /// \brief Send a HTTP request and return the server's response. + /// + /// You must have a valid host before sending a request (see setHost). + /// Any missing mandatory header field in the request will be added + /// with an appropriate value. + /// Warning: this function waits for the server's response and may + /// not return instantly; use a thread if you don't want to block your + /// application, or use a timeout to limit the time to wait. A value + /// of Time::Zero means that the client will use the system defaut timeout + /// (which is usually pretty long). + /// + /// \param request Request to send + /// \param timeout Maximum time to wait + /// + /// \return Server's response + /// + //////////////////////////////////////////////////////////// + Response sendRequest(const Request& request, Time timeout = Time::Zero); + +private : + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + TcpSocket m_connection; ///< Connection to the host + IpAddress m_host; ///< Web host address + std::string m_hostName; ///< Web host name + unsigned short m_port; ///< Port used for connection with host +}; + +} // namespace sf + + +#endif // SFML_HTTP_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Http +/// \ingroup network +/// +/// sf::Http is a very simple HTTP client that allows you +/// to communicate with a web server. You can retrieve +/// web pages, send data to an interactive resource, +/// download a remote file, etc. +/// +/// The HTTP client is split into 3 classes: +/// \li sf::Http::Request +/// \li sf::Http::Response +/// \li sf::Http +/// +/// sf::Http::Request builds the request that will be +/// sent to the server. A request is made of: +/// \li a method (what you want to do) +/// \li a target URI (usually the name of the web page or file) +/// \li one or more header fields (options that you can pass to the server) +/// \li an optional body (for POST requests) +/// +/// sf::Http::Response parse the response from the web server +/// and provides getters to read them. The response contains: +/// \li a status code +/// \li header fields (that may be answers to the ones that you requested) +/// \li a body, which contains the contents of the requested resource +/// +/// sf::Http provides a simple function, SendRequest, to send a +/// sf::Http::Request and return the corresponding sf::Http::Response +/// from the server. +/// +/// Usage example: +/// \code +/// // Create a new HTTP client +/// sf::Http http; +/// +/// // We'll work on http://www.sfml-dev.org +/// http.setHost("http://www.sfml-dev.org"); +/// +/// // Prepare a request to get the 'features.php' page +/// sf::Http::Request request("features.php"); +/// +/// // Send the request +/// sf::Http::Response response = http.sendRequest(request); +/// +/// // Check the status code and display the result +/// sf::Http::Response::Status status = response.getStatus(); +/// if (status == sf::Http::Response::Ok) +/// { +/// std::cout << response.getBody() << std::endl; +/// } +/// else +/// { +/// std::cout << "Error " << status << std::endl; +/// } +/// \endcode +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Network/IpAddress.hpp b/src/include/SFML/include/SFML/Network/IpAddress.hpp new file mode 100644 index 0000000..d2fdda4 --- /dev/null +++ b/src/include/SFML/include/SFML/Network/IpAddress.hpp @@ -0,0 +1,316 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_IPADDRESS_HPP +#define SFML_IPADDRESS_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Encapsulate an IPv4 network address +/// +//////////////////////////////////////////////////////////// +class SFML_NETWORK_API IpAddress +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// This constructor creates an empty (invalid) address + /// + //////////////////////////////////////////////////////////// + IpAddress(); + + //////////////////////////////////////////////////////////// + /// \brief Construct the address from a string + /// + /// Here \a address can be either a decimal address + /// (ex: "192.168.1.56") or a network name (ex: "localhost"). + /// + /// \param address IP address or network name + /// + //////////////////////////////////////////////////////////// + IpAddress(const std::string& address); + + //////////////////////////////////////////////////////////// + /// \brief Construct the address from a string + /// + /// Here \a address can be either a decimal address + /// (ex: "192.168.1.56") or a network name (ex: "localhost"). + /// This is equivalent to the constructor taking a std::string + /// parameter, it is defined for convenience so that the + /// implicit conversions from literal strings to IpAddress work. + /// + /// \param address IP address or network name + /// + //////////////////////////////////////////////////////////// + IpAddress(const char* address); + + //////////////////////////////////////////////////////////// + /// \brief Construct the address from 4 bytes + /// + /// Calling IpAddress(a, b, c, d) is equivalent to calling + /// IpAddress("a.b.c.d"), but safer as it doesn't have to + /// parse a string to get the address components. + /// + /// \param byte0 First byte of the address + /// \param byte1 Second byte of the address + /// \param byte2 Third byte of the address + /// \param byte3 Fourth byte of the address + /// + //////////////////////////////////////////////////////////// + IpAddress(Uint8 byte0, Uint8 byte1, Uint8 byte2, Uint8 byte3); + + //////////////////////////////////////////////////////////// + /// \brief Construct the address from a 32-bits integer + /// + /// This constructor uses the internal representation of + /// the address directly. It should be used for optimization + /// purposes, and only if you got that representation from + /// IpAddress::ToInteger(). + /// + /// \param address 4 bytes of the address packed into a 32-bits integer + /// + /// \see toInteger + /// + //////////////////////////////////////////////////////////// + explicit IpAddress(Uint32 address); + + //////////////////////////////////////////////////////////// + /// \brief Get a string representation of the address + /// + /// The returned string is the decimal representation of the + /// IP address (like "192.168.1.56"), even if it was constructed + /// from a host name. + /// + /// \return String representation of the address + /// + /// \see toInteger + /// + //////////////////////////////////////////////////////////// + std::string toString() const; + + //////////////////////////////////////////////////////////// + /// \brief Get an integer representation of the address + /// + /// The returned number is the internal representation of the + /// address, and should be used for optimization purposes only + /// (like sending the address through a socket). + /// The integer produced by this function can then be converted + /// back to a sf::IpAddress with the proper constructor. + /// + /// \return 32-bits unsigned integer representation of the address + /// + /// \see toString + /// + //////////////////////////////////////////////////////////// + Uint32 toInteger() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the computer's local address + /// + /// The local address is the address of the computer from the + /// LAN point of view, i.e. something like 192.168.1.56. It is + /// meaningful only for communications over the local network. + /// Unlike getPublicAddress, this function is fast and may be + /// used safely anywhere. + /// + /// \return Local IP address of the computer + /// + /// \see getPublicAddress + /// + //////////////////////////////////////////////////////////// + static IpAddress getLocalAddress(); + + //////////////////////////////////////////////////////////// + /// \brief Get the computer's public address + /// + /// The public address is the address of the computer from the + /// internet point of view, i.e. something like 89.54.1.169. + /// It is necessary for communications over the world wide web. + /// The only way to get a public address is to ask it to a + /// distant website; as a consequence, this function depends on + /// both your network connection and the server, and may be + /// very slow. You should use it as few as possible. Because + /// this function depends on the network connection and on a distant + /// server, you may use a time limit if you don't want your program + /// to be possibly stuck waiting in case there is a problem; this + /// limit is deactivated by default. + /// + /// \param timeout Maximum time to wait + /// + /// \return Public IP address of the computer + /// + /// \see getLocalAddress + /// + //////////////////////////////////////////////////////////// + static IpAddress getPublicAddress(Time timeout = Time::Zero); + + //////////////////////////////////////////////////////////// + // Static member data + //////////////////////////////////////////////////////////// + static const IpAddress None; ///< Value representing an empty/invalid address + static const IpAddress LocalHost; ///< The "localhost" address (for connecting a computer to itself locally) + static const IpAddress Broadcast; ///< The "broadcast" address (for sending UDP messages to everyone on a local network) + +private : + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + Uint32 m_address; ///< Address stored as an unsigned 32 bits integer +}; + +//////////////////////////////////////////////////////////// +/// \brief Overload of == operator to compare two IP addresses +/// +/// \param left Left operand (a IP address) +/// \param right Right operand (a IP address) +/// +/// \return True if both addresses are equal +/// +//////////////////////////////////////////////////////////// +SFML_NETWORK_API bool operator ==(const IpAddress& left, const IpAddress& right); + +//////////////////////////////////////////////////////////// +/// \brief Overload of != operator to compare two IP addresses +/// +/// \param left Left operand (a IP address) +/// \param right Right operand (a IP address) +/// +/// \return True if both addresses are different +/// +//////////////////////////////////////////////////////////// +SFML_NETWORK_API bool operator !=(const IpAddress& left, const IpAddress& right); + +//////////////////////////////////////////////////////////// +/// \brief Overload of < operator to compare two IP addresses +/// +/// \param left Left operand (a IP address) +/// \param right Right operand (a IP address) +/// +/// \return True if \a left is lesser than \a right +/// +//////////////////////////////////////////////////////////// +SFML_NETWORK_API bool operator <(const IpAddress& left, const IpAddress& right); + +//////////////////////////////////////////////////////////// +/// \brief Overload of > operator to compare two IP addresses +/// +/// \param left Left operand (a IP address) +/// \param right Right operand (a IP address) +/// +/// \return True if \a left is greater than \a right +/// +//////////////////////////////////////////////////////////// +SFML_NETWORK_API bool operator >(const IpAddress& left, const IpAddress& right); + +//////////////////////////////////////////////////////////// +/// \brief Overload of <= operator to compare two IP addresses +/// +/// \param left Left operand (a IP address) +/// \param right Right operand (a IP address) +/// +/// \return True if \a left is lesser or equal than \a right +/// +//////////////////////////////////////////////////////////// +SFML_NETWORK_API bool operator <=(const IpAddress& left, const IpAddress& right); + +//////////////////////////////////////////////////////////// +/// \brief Overload of >= operator to compare two IP addresses +/// +/// \param left Left operand (a IP address) +/// \param right Right operand (a IP address) +/// +/// \return True if \a left is greater or equal than \a right +/// +//////////////////////////////////////////////////////////// +SFML_NETWORK_API bool operator >=(const IpAddress& left, const IpAddress& right); + +//////////////////////////////////////////////////////////// +/// \brief Overload of >> operator to extract an IP address from an input stream +/// +/// \param stream Input stream +/// \param address IP address to extract +/// +/// \return Reference to the input stream +/// +//////////////////////////////////////////////////////////// +SFML_NETWORK_API std::istream& operator >>(std::istream& stream, IpAddress& address); + +//////////////////////////////////////////////////////////// +/// \brief Overload of << operator to print an IP address to an output stream +/// +/// \param stream Output stream +/// \param address IP address to print +/// +/// \return Reference to the output stream +/// +//////////////////////////////////////////////////////////// +SFML_NETWORK_API std::ostream& operator <<(std::ostream& stream, const IpAddress& address); + +} // namespace sf + + +#endif // SFML_IPADDRESS_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::IpAddress +/// \ingroup network +/// +/// sf::IpAddress is a utility class for manipulating network +/// addresses. It provides a set a implicit constructors and +/// conversion functions to easily build or transform an IP +/// address from/to various representations. +/// +/// Usage example: +/// \code +/// sf::IpAddress a0; // an invalid address +/// sf::IpAddress a1 = sf::IpAddress::None; // an invalid address (same as a0) +/// sf::IpAddress a2("127.0.0.1"); // the local host address +/// sf::IpAddress a3 = sf::IpAddress::Broadcast; // the broadcast address +/// sf::IpAddress a4(192, 168, 1, 56); // a local address +/// sf::IpAddress a5("my_computer"); // a local address created from a network name +/// sf::IpAddress a6("89.54.1.169"); // a distant address +/// sf::IpAddress a7("www.google.com"); // a distant address created from a network name +/// sf::IpAddress a8 = sf::IpAddress::getLocalAddress(); // my address on the local network +/// sf::IpAddress a9 = sf::IpAddress::getPublicAddress(); // my address on the internet +/// \endcode +/// +/// Note that sf::IpAddress currently doesn't support IPv6 +/// nor other types of network addresses. +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Network/Packet.hpp b/src/include/SFML/include/SFML/Network/Packet.hpp new file mode 100644 index 0000000..4b67852 --- /dev/null +++ b/src/include/SFML/include/SFML/Network/Packet.hpp @@ -0,0 +1,407 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_PACKET_HPP +#define SFML_PACKET_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +class String; +class TcpSocket; +class UdpSocket; + +//////////////////////////////////////////////////////////// +/// \brief Utility class to build blocks of data to transfer +/// over the network +/// +//////////////////////////////////////////////////////////// +class SFML_NETWORK_API Packet +{ + // A bool-like type that cannot be converted to integer or pointer types + typedef bool (Packet::*BoolType)(std::size_t); + +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Creates an empty packet. + /// + //////////////////////////////////////////////////////////// + Packet(); + + //////////////////////////////////////////////////////////// + /// \brief Virtual destructor + /// + //////////////////////////////////////////////////////////// + virtual ~Packet(); + + //////////////////////////////////////////////////////////// + /// \brief Append data to the end of the packet + /// + /// \param data Pointer to the sequence of bytes to append + /// \param sizeInBytes Number of bytes to append + /// + /// \see clear + /// + //////////////////////////////////////////////////////////// + void append(const void* data, std::size_t sizeInBytes); + + //////////////////////////////////////////////////////////// + /// \brief Clear the packet + /// + /// After calling Clear, the packet is empty. + /// + /// \see append + /// + //////////////////////////////////////////////////////////// + void clear(); + + //////////////////////////////////////////////////////////// + /// \brief Get a pointer to the data contained in the packet + /// + /// Warning: the returned pointer may become invalid after + /// you append data to the packet, therefore it should never + /// be stored. + /// The return pointer is NULL if the packet is empty. + /// + /// \return Pointer to the data + /// + /// \see getDataSize + /// + //////////////////////////////////////////////////////////// + const void* getData() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the size of the data contained in the packet + /// + /// This function returns the number of bytes pointed to by + /// what getData returns. + /// + /// \return Data size, in bytes + /// + /// \see getData + /// + //////////////////////////////////////////////////////////// + std::size_t getDataSize() const; + + //////////////////////////////////////////////////////////// + /// \brief Tell if the reading position has reached the + /// end of the packet + /// + /// This function is useful to know if there is some data + /// left to be read, without actually reading it. + /// + /// \return True if all data was read, false otherwise + /// + /// \see operator bool + /// + //////////////////////////////////////////////////////////// + bool endOfPacket() const; + +public: + + //////////////////////////////////////////////////////////// + /// \brief Test the validity of the packet, for reading + /// + /// This operator allows to test the packet as a boolean + /// variable, to check if a reading operation was successful. + /// + /// A packet will be in an invalid state if it has no more + /// data to read. + /// + /// This behaviour is the same as standard C++ streams. + /// + /// Usage example: + /// \code + /// float x; + /// packet >> x; + /// if (packet) + /// { + /// // ok, x was extracted successfully + /// } + /// + /// // -- or -- + /// + /// float x; + /// if (packet >> x) + /// { + /// // ok, x was extracted successfully + /// } + /// \endcode + /// + /// Don't focus on the return type, it's equivalent to bool but + /// it disallows unwanted implicit conversions to integer or + /// pointer types. + /// + /// \return True if last data extraction from packet was successful + /// + /// \see endOfPacket + /// + //////////////////////////////////////////////////////////// + operator BoolType() const; + + //////////////////////////////////////////////////////////// + /// Overloads of operator >> to read data from the packet + /// + //////////////////////////////////////////////////////////// + Packet& operator >>(bool& data); + Packet& operator >>(Int8& data); + Packet& operator >>(Uint8& data); + Packet& operator >>(Int16& data); + Packet& operator >>(Uint16& data); + Packet& operator >>(Int32& data); + Packet& operator >>(Uint32& data); + Packet& operator >>(float& data); + Packet& operator >>(double& data); + Packet& operator >>(char* data); + Packet& operator >>(std::string& data); + Packet& operator >>(wchar_t* data); + Packet& operator >>(std::wstring& data); + Packet& operator >>(String& data); + + //////////////////////////////////////////////////////////// + /// Overloads of operator << to write data into the packet + /// + //////////////////////////////////////////////////////////// + Packet& operator <<(bool data); + Packet& operator <<(Int8 data); + Packet& operator <<(Uint8 data); + Packet& operator <<(Int16 data); + Packet& operator <<(Uint16 data); + Packet& operator <<(Int32 data); + Packet& operator <<(Uint32 data); + Packet& operator <<(float data); + Packet& operator <<(double data); + Packet& operator <<(const char* data); + Packet& operator <<(const std::string& data); + Packet& operator <<(const wchar_t* data); + Packet& operator <<(const std::wstring& data); + Packet& operator <<(const String& data); + +protected: + + friend class TcpSocket; + friend class UdpSocket; + + //////////////////////////////////////////////////////////// + /// \brief Called before the packet is sent over the network + /// + /// This function can be defined by derived classes to + /// transform the data before it is sent; this can be + /// used for compression, encryption, etc. + /// The function must return a pointer to the modified data, + /// as well as the number of bytes pointed. + /// The default implementation provides the packet's data + /// without transforming it. + /// + /// \param size Variable to fill with the size of data to send + /// + /// \return Pointer to the array of bytes to send + /// + /// \see onReceive + /// + //////////////////////////////////////////////////////////// + virtual const void* onSend(std::size_t& size); + + //////////////////////////////////////////////////////////// + /// \brief Called after the packet is received over the network + /// + /// This function can be defined by derived classes to + /// transform the data after it is received; this can be + /// used for uncompression, decryption, etc. + /// The function receives a pointer to the received data, + /// and must fill the packet with the transformed bytes. + /// The default implementation fills the packet directly + /// without transforming the data. + /// + /// \param data Pointer to the received bytes + /// \param size Number of bytes + /// + /// \see onSend + /// + //////////////////////////////////////////////////////////// + virtual void onReceive(const void* data, std::size_t size); + +private : + + //////////////////////////////////////////////////////////// + /// Disallow comparisons between packets + /// + //////////////////////////////////////////////////////////// + bool operator ==(const Packet& right) const; + bool operator !=(const Packet& right) const; + + //////////////////////////////////////////////////////////// + /// \brief Check if the packet can extract a given number of bytes + /// + /// This function updates accordingly the state of the packet. + /// + /// \param size Size to check + /// + /// \return True if \a size bytes can be read from the packet + /// + //////////////////////////////////////////////////////////// + bool checkSize(std::size_t size); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + std::vector m_data; ///< Data stored in the packet + std::size_t m_readPos; ///< Current reading position in the packet + bool m_isValid; ///< Reading state of the packet +}; + +} // namespace sf + + +#endif // SFML_PACKET_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Packet +/// \ingroup network +/// +/// Packets provide a safe and easy way to serialize data, +/// in order to send it over the network using sockets +/// (sf::TcpSocket, sf::UdpSocket). +/// +/// Packets solve 2 fundamental problems that arise when +/// transfering data over the network: +/// \li data is interpreted correctly according to the endianness +/// \li the bounds of the packet are preserved (one send == one receive) +/// +/// The sf::Packet class provides both input and output modes. +/// It is designed to follow the behaviour of standard C++ streams, +/// using operators >> and << to extract and insert data. +/// +/// It is recommended to use only fixed-size types (like sf::Int32, etc.), +/// to avoid possible differences between the sender and the receiver. +/// Indeed, the native C++ types may have different sizes on two platforms +/// and your data may be corrupted if that happens. +/// +/// Usage example: +/// \code +/// sf::Uint32 x = 24; +/// std::string s = "hello"; +/// double d = 5.89; +/// +/// // Group the variables to send into a packet +/// sf::Packet packet; +/// packet << x << s << d; +/// +/// // Send it over the network (socket is a valid sf::TcpSocket) +/// socket.send(packet); +/// +/// ----------------------------------------------------------------- +/// +/// // Receive the packet at the other end +/// sf::Packet packet; +/// socket.receive(packet); +/// +/// // Extract the variables contained in the packet +/// sf::Uint32 x; +/// std::string s; +/// double d; +/// if (packet >> x >> s >> d) +/// { +/// // Data extracted successfully... +/// } +/// \endcode +/// +/// Packets have built-in operator >> and << overloads for +/// standard types: +/// \li bool +/// \li fixed-size integer types (sf::Int8/16/32, sf::Uint8/16/32) +/// \li floating point numbers (float, double) +/// \li string types (char*, wchar_t*, std::string, std::wstring, sf::String) +/// +/// Like standard streams, it is also possible to define your own +/// overloads of operators >> and << in order to handle your +/// custom types. +/// +/// \code +/// struct MyStruct +/// { +/// float number; +/// sf::Int8 integer; +/// std::string str; +/// }; +/// +/// sf::Packet& operator <<(sf::Packet& packet, const MyStruct& m) +/// { +/// return packet << m.number << m.integer << m.str; +/// } +/// +/// sf::Packet& operator >>(sf::Packet& packet, MyStruct& m) +/// { +/// return packet >> m.number >> m.integer >> m.str; +/// } +/// \endcode +/// +/// Packets also provide an extra feature that allows to apply +/// custom transformations to the data before it is sent, +/// and after it is received. This is typically used to +/// handle automatic compression or encryption of the data. +/// This is achieved by inheriting from sf::Packet, and overriding +/// the onSend and onReceive functions. +/// +/// Here is an example: +/// \code +/// class ZipPacket : public sf::Packet +/// { +/// virtual const void* onSend(std::size_t& size) +/// { +/// const void* srcData = getData(); +/// std::size_t srcSize = getDataSize(); +/// +/// return MySuperZipFunction(srcData, srcSize, &size); +/// } +/// +/// virtual void onReceive(const void* data, std::size_t size) +/// { +/// std::size_t dstSize; +/// const void* dstData = MySuperUnzipFunction(data, size, &dstSize); +/// +/// append(dstData, dstSize); +/// } +/// }; +/// +/// // Use like regular packets: +/// ZipPacket packet; +/// packet << x << s << d; +/// ... +/// \endcode +/// +/// \see sf::TcpSocket, sf::UdpSocket +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Network/Socket.hpp b/src/include/SFML/include/SFML/Network/Socket.hpp new file mode 100644 index 0000000..c58e8ad --- /dev/null +++ b/src/include/SFML/include/SFML/Network/Socket.hpp @@ -0,0 +1,218 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SOCKET_HPP +#define SFML_SOCKET_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include + + +namespace sf +{ +class SocketSelector; + +//////////////////////////////////////////////////////////// +/// \brief Base class for all the socket types +/// +//////////////////////////////////////////////////////////// +class SFML_NETWORK_API Socket : NonCopyable +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Status codes that may be returned by socket functions + /// + //////////////////////////////////////////////////////////// + enum Status + { + Done, ///< The socket has sent / received the data + NotReady, ///< The socket is not ready to send / receive data yet + Disconnected, ///< The TCP socket has been disconnected + Error ///< An unexpected error happened + }; + + //////////////////////////////////////////////////////////// + /// \brief Some special values used by sockets + /// + //////////////////////////////////////////////////////////// + enum + { + AnyPort = 0 ///< Special value that tells the system to pick any available port + }; + +public : + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + virtual ~Socket(); + + //////////////////////////////////////////////////////////// + /// \brief Set the blocking state of the socket + /// + /// In blocking mode, calls will not return until they have + /// completed their task. For example, a call to Receive in + /// blocking mode won't return until some data was actually + /// received. + /// In non-blocking mode, calls will always return immediately, + /// using the return code to signal whether there was data + /// available or not. + /// By default, all sockets are blocking. + /// + /// \param blocking True to set the socket as blocking, false for non-blocking + /// + /// \see isBlocking + /// + //////////////////////////////////////////////////////////// + void setBlocking(bool blocking); + + //////////////////////////////////////////////////////////// + /// \brief Tell whether the socket is in blocking or non-blocking mode + /// + /// \return True if the socket is blocking, false otherwise + /// + /// \see setBlocking + /// + //////////////////////////////////////////////////////////// + bool isBlocking() const; + +protected : + + //////////////////////////////////////////////////////////// + /// \brief Types of protocols that the socket can use + /// + //////////////////////////////////////////////////////////// + enum Type + { + Tcp, ///< TCP protocol + Udp ///< UDP protocol + }; + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// This constructor can only be accessed by derived classes. + /// + /// \param type Type of the socket (TCP or UDP) + /// + //////////////////////////////////////////////////////////// + Socket(Type type); + + //////////////////////////////////////////////////////////// + /// \brief Return the internal handle of the socket + /// + /// The returned handle may be invalid if the socket + /// was not created yet (or already destroyed). + /// This function can only be accessed by derived classes. + /// + /// \return The internal (OS-specific) handle of the socket + /// + //////////////////////////////////////////////////////////// + SocketHandle getHandle() const; + + //////////////////////////////////////////////////////////// + /// \brief Create the internal representation of the socket + /// + /// This function can only be accessed by derived classes. + /// + //////////////////////////////////////////////////////////// + void create(); + + //////////////////////////////////////////////////////////// + /// \brief Create the internal representation of the socket + /// from a socket handle + /// + /// This function can only be accessed by derived classes. + /// + /// \param handle OS-specific handle of the socket to wrap + /// + //////////////////////////////////////////////////////////// + void create(SocketHandle handle); + + //////////////////////////////////////////////////////////// + /// \brief Close the socket gracefully + /// + /// This function can only be accessed by derived classes. + /// + //////////////////////////////////////////////////////////// + void close(); + +private : + + friend class SocketSelector; + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + Type m_type; ///< Type of the socket (TCP or UDP) + SocketHandle m_socket; ///< Socket descriptor + bool m_isBlocking; ///< Current blocking mode of the socket +}; + +} // namespace sf + + +#endif // SFML_SOCKET_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Socket +/// \ingroup network +/// +/// This class mainly defines internal stuff to be used by +/// derived classes. +/// +/// The only public features that it defines, and which +/// is therefore common to all the socket classes, is the +/// blocking state. All sockets can be set as blocking or +/// non-blocking. +/// +/// In blocking mode, socket functions will hang until +/// the operation completes, which means that the entire +/// program (well, in fact the current thread if you use +/// multiple ones) will be stuck waiting for your socket +/// operation to complete. +/// +/// In non-blocking mode, all the socket functions will +/// return immediately. If the socket is not ready to complete +/// the requested operation, the function simply returns +/// the proper status code (Socket::NotReady). +/// +/// The default mode, which is blocking, is the one that is +/// generally used, in combination with threads or selectors. +/// The non-blocking mode is rather used in real-time +/// applications that run an endless loop that can poll +/// the socket often enough, and cannot afford blocking +/// this loop. +/// +/// \see sf::TcpListener, sf::TcpSocket, sf::UdpSocket +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Network/SocketHandle.hpp b/src/include/SFML/include/SFML/Network/SocketHandle.hpp new file mode 100644 index 0000000..c05a635 --- /dev/null +++ b/src/include/SFML/include/SFML/Network/SocketHandle.hpp @@ -0,0 +1,57 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SOCKETHANDLE_HPP +#define SFML_SOCKETHANDLE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + +#if defined(SFML_SYSTEM_WINDOWS) + #include +#endif + + +namespace sf +{ +//////////////////////////////////////////////////////////// +// Define the low-level socket handle type, specific to +// each platform +//////////////////////////////////////////////////////////// +#if defined(SFML_SYSTEM_WINDOWS) + + typedef UINT_PTR SocketHandle; + +#else + + typedef int SocketHandle; + +#endif + +} // namespace sf + + +#endif // SFML_SOCKETHANDLE_HPP diff --git a/src/include/SFML/include/SFML/Network/SocketSelector.hpp b/src/include/SFML/include/SFML/Network/SocketSelector.hpp new file mode 100644 index 0000000..668b59f --- /dev/null +++ b/src/include/SFML/include/SFML/Network/SocketSelector.hpp @@ -0,0 +1,263 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SOCKETSELECTOR_HPP +#define SFML_SOCKETSELECTOR_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +class Socket; + +//////////////////////////////////////////////////////////// +/// \brief Multiplexer that allows to read from multiple sockets +/// +//////////////////////////////////////////////////////////// +class SFML_NETWORK_API SocketSelector +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + SocketSelector(); + + //////////////////////////////////////////////////////////// + /// \brief Copy constructor + /// + /// \param copy Instance to copy + /// + //////////////////////////////////////////////////////////// + SocketSelector(const SocketSelector& copy); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~SocketSelector(); + + //////////////////////////////////////////////////////////// + /// \brief Add a new socket to the selector + /// + /// This function keeps a weak reference to the socket, + /// so you have to make sure that the socket is not destroyed + /// while it is stored in the selector. + /// This function does nothing if the socket is not valid. + /// + /// \param socket Reference to the socket to add + /// + /// \see remove, clear + /// + //////////////////////////////////////////////////////////// + void add(Socket& socket); + + //////////////////////////////////////////////////////////// + /// \brief Remove a socket from the selector + /// + /// This function doesn't destroy the socket, it simply + /// removes the reference that the selector has to it. + /// + /// \param socket Reference to the socket to remove + /// + /// \see add, clear + /// + //////////////////////////////////////////////////////////// + void remove(Socket& socket); + + //////////////////////////////////////////////////////////// + /// \brief Remove all the sockets stored in the selector + /// + /// This function doesn't destroy any instance, it simply + /// removes all the references that the selector has to + /// external sockets. + /// + /// \see add, remove + /// + //////////////////////////////////////////////////////////// + void clear(); + + //////////////////////////////////////////////////////////// + /// \brief Wait until one or more sockets are ready to receive + /// + /// This function returns as soon as at least one socket has + /// some data available to be received. To know which sockets are + /// ready, use the isReady function. + /// If you use a timeout and no socket is ready before the timeout + /// is over, the function returns false. + /// + /// \param timeout Maximum time to wait, (use Time::Zero for infinity) + /// + /// \return True if there are sockets ready, false otherwise + /// + /// \see isReady + /// + //////////////////////////////////////////////////////////// + bool wait(Time timeout = Time::Zero); + + //////////////////////////////////////////////////////////// + /// \brief Test a socket to know if it is ready to receive data + /// + /// This function must be used after a call to Wait, to know + /// which sockets are ready to receive data. If a socket is + /// ready, a call to receive will never block because we know + /// that there is data available to read. + /// Note that if this function returns true for a TcpListener, + /// this means that it is ready to accept a new connection. + /// + /// \param socket Socket to test + /// + /// \return True if the socket is ready to read, false otherwise + /// + /// \see isReady + /// + //////////////////////////////////////////////////////////// + bool isReady(Socket& socket) const; + + //////////////////////////////////////////////////////////// + /// \brief Overload of assignment operator + /// + /// \param right Instance to assign + /// + /// \return Reference to self + /// + //////////////////////////////////////////////////////////// + SocketSelector& operator =(const SocketSelector& right); + +private : + + struct SocketSelectorImpl; + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + SocketSelectorImpl* m_impl; ///< Opaque pointer to the implementation (which requires OS-specific types) +}; + +} // namespace sf + + +#endif // SFML_SOCKETSELECTOR_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::SocketSelector +/// \ingroup network +/// +/// Socket selectors provide a way to wait until some data is +/// available on a set of sockets, instead of just one. This +/// is convenient when you have multiple sockets that may +/// possibly receive data, but you don't know which one will +/// be ready first. In particular, it avoids to use a thread +/// for each socket; with selectors, a single thread can handle +/// all the sockets. +/// +/// All types of sockets can be used in a selector: +/// \li sf::TcpListener +/// \li sf::TcpSocket +/// \li sf::UdpSocket +/// +/// A selector doesn't store its own copies of the sockets +/// (socket classes are not copyable anyway), it simply keeps +/// a reference to the original sockets that you pass to the +/// "add" function. Therefore, you can't use the selector as a +/// socket container, you must store them oustide and make sure +/// that they are alive as long as they are used in the selector. +/// +/// Using a selector is simple: +/// \li populate the selector with all the sockets that you want to observe +/// \li make it wait until there is data available on any of the sockets +/// \li test each socket to find out which ones are ready +/// +/// Usage example: +/// \code +/// // Create a socket to listen to new connections +/// sf::TcpListener listener; +/// listener.listen(55001); +/// +/// // Create a list to store the future clients +/// std::list clients; +/// +/// // Create a selector +/// sf::SocketSelector selector; +/// +/// // Add the listener to the selector +/// selector.add(listener); +/// +/// // Endless loop that waits for new connections +/// while (running) +/// { +/// // Make the selector wait for data on any socket +/// if (selector.wait()) +/// { +/// // Test the listener +/// if (selector.isReady(listener)) +/// { +/// // The listener is ready: there is a pending connection +/// sf::TcpSocket* client = new sf::TcpSocket; +/// if (listener.accept(*client) == sf::Socket::Done) +/// { +/// // Add the new client to the clients list +/// clients.push_back(client); +/// +/// // Add the new client to the selector so that we will +/// // be notified when he sends something +/// selector.add(*client); +/// } +/// else +/// { +/// // Error, we won't get a new connection, delete the socket +/// delete client; +/// } +/// } +/// else +/// { +/// // The listener socket is not ready, test all other sockets (the clients) +/// for (std::list::iterator it = clients.begin(); it != clients.end(); ++it) +/// { +/// sf::TcpSocket& client = **it; +/// if (selector.isReady(client)) +/// { +/// // The client has sent some data, we can receive it +/// sf::Packet packet; +/// if (client.receive(packet) == sf::Socket::Done) +/// { +/// ... +/// } +/// } +/// } +/// } +/// } +/// } +/// \endcode +/// +/// \see sf::Socket +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Network/TcpListener.hpp b/src/include/SFML/include/SFML/Network/TcpListener.hpp new file mode 100644 index 0000000..c72facd --- /dev/null +++ b/src/include/SFML/include/SFML/Network/TcpListener.hpp @@ -0,0 +1,162 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_TCPLISTENER_HPP +#define SFML_TCPLISTENER_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +class TcpSocket; + +//////////////////////////////////////////////////////////// +/// \brief Socket that listens to new TCP connections +/// +//////////////////////////////////////////////////////////// +class SFML_NETWORK_API TcpListener : public Socket +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + TcpListener(); + + //////////////////////////////////////////////////////////// + /// \brief Get the port to which the socket is bound locally + /// + /// If the socket is not listening to a port, this function + /// returns 0. + /// + /// \return Port to which the socket is bound + /// + /// \see listen + /// + //////////////////////////////////////////////////////////// + unsigned short getLocalPort() const; + + //////////////////////////////////////////////////////////// + /// \brief Start listening for connections + /// + /// This functions makes the socket listen to the specified + /// port, waiting for new connections. + /// If the socket was previously listening to another port, + /// it will be stopped first and bound to the new port. + /// + /// \param port Port to listen for new connections + /// + /// \return Status code + /// + /// \see accept, close + /// + //////////////////////////////////////////////////////////// + Status listen(unsigned short port); + + //////////////////////////////////////////////////////////// + /// \brief Stop listening and close the socket + /// + /// This function gracefully stops the listener. If the + /// socket is not listening, this function has no effect. + /// + /// \see listen + /// + //////////////////////////////////////////////////////////// + void close(); + + //////////////////////////////////////////////////////////// + /// \brief Accept a new connection + /// + /// If the socket is in blocking mode, this function will + /// not return until a connection is actually received. + /// + /// \param socket Socket that will hold the new connection + /// + /// \return Status code + /// + /// \see listen + /// + //////////////////////////////////////////////////////////// + Status accept(TcpSocket& socket); +}; + + +} // namespace sf + + +#endif // SFML_TCPLISTENER_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::TcpListener +/// \ingroup network +/// +/// A listener socket is a special type of socket that listens to +/// a given port and waits for connections on that port. +/// This is all it can do. +/// +/// When a new connection is received, you must call accept and +/// the listener returns a new instance of sf::TcpSocket that +/// is properly initialized and can be used to communicate with +/// the new client. +/// +/// Listener sockets are specific to the TCP protocol, +/// UDP sockets are connectionless and can therefore communicate +/// directly. As a consequence, a listener socket will always +/// return the new connections as sf::TcpSocket instances. +/// +/// A listener is automatically closed on destruction, like all +/// other types of socket. However if you want to stop listening +/// before the socket is destroyed, you can call its close() +/// function. +/// +/// Usage example: +/// \code +/// // Create a listener socket and make it wait for new +/// // connections on port 55001 +/// sf::TcpListener listener; +/// listener.listen(55001); +/// +/// // Endless loop that waits for new connections +/// while (running) +/// { +/// sf::TcpSocket client; +/// if (listener.accept(client) == sf::Socket::Done) +/// { +/// // A new client just connected! +/// std::cout << "New connection received from " << client.getRemoteAddress() << std::endl; +/// doSomethingWith(client); +/// } +/// } +/// \endcode +/// +/// \see sf::TcpSocket, sf::Socket +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Network/TcpSocket.hpp b/src/include/SFML/include/SFML/Network/TcpSocket.hpp new file mode 100644 index 0000000..ff4ee95 --- /dev/null +++ b/src/include/SFML/include/SFML/Network/TcpSocket.hpp @@ -0,0 +1,292 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_TCPSOCKET_HPP +#define SFML_TCPSOCKET_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +class TcpListener; +class IpAddress; +class Packet; + +//////////////////////////////////////////////////////////// +/// \brief Specialized socket using the TCP protocol +/// +//////////////////////////////////////////////////////////// +class SFML_NETWORK_API TcpSocket : public Socket +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + TcpSocket(); + + //////////////////////////////////////////////////////////// + /// \brief Get the port to which the socket is bound locally + /// + /// If the socket is not connected, this function returns 0. + /// + /// \return Port to which the socket is bound + /// + /// \see connect, getRemotePort + /// + //////////////////////////////////////////////////////////// + unsigned short getLocalPort() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the address of the connected peer + /// + /// It the socket is not connected, this function returns + /// sf::IpAddress::None. + /// + /// \return Address of the remote peer + /// + /// \see getRemotePort + /// + //////////////////////////////////////////////////////////// + IpAddress getRemoteAddress() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the port of the connected peer to which + /// the socket is connected + /// + /// If the socket is not connected, this function returns 0. + /// + /// \return Remote port to which the socket is connected + /// + /// \see getRemoteAddress + /// + //////////////////////////////////////////////////////////// + unsigned short getRemotePort() const; + + //////////////////////////////////////////////////////////// + /// \brief Connect the socket to a remote peer + /// + /// In blocking mode, this function may take a while, especially + /// if the remote peer is not reachable. The last parameter allows + /// you to stop trying to connect after a given timeout. + /// If the socket was previously connected, it is first disconnected. + /// + /// \param remoteAddress Address of the remote peer + /// \param remotePort Port of the remote peer + /// \param timeout Optional maximum time to wait + /// + /// \return Status code + /// + /// \see disconnect + /// + //////////////////////////////////////////////////////////// + Status connect(const IpAddress& remoteAddress, unsigned short remotePort, Time timeout = Time::Zero); + + //////////////////////////////////////////////////////////// + /// \brief Disconnect the socket from its remote peer + /// + /// This function gracefully closes the connection. If the + /// socket is not connected, this function has no effect. + /// + /// \see connect + /// + //////////////////////////////////////////////////////////// + void disconnect(); + + //////////////////////////////////////////////////////////// + /// \brief Send raw data to the remote peer + /// + /// This function will fail if the socket is not connected. + /// + /// \param data Pointer to the sequence of bytes to send + /// \param size Number of bytes to send + /// + /// \return Status code + /// + /// \see receive + /// + //////////////////////////////////////////////////////////// + Status send(const void* data, std::size_t size); + + //////////////////////////////////////////////////////////// + /// \brief Receive raw data from the remote peer + /// + /// In blocking mode, this function will wait until some + /// bytes are actually received. + /// This function will fail if the socket is not connected. + /// + /// \param data Pointer to the array to fill with the received bytes + /// \param size Maximum number of bytes that can be received + /// \param received This variable is filled with the actual number of bytes received + /// + /// \return Status code + /// + /// \see send + /// + //////////////////////////////////////////////////////////// + Status receive(void* data, std::size_t size, std::size_t& received); + + //////////////////////////////////////////////////////////// + /// \brief Send a formatted packet of data to the remote peer + /// + /// This function will fail if the socket is not connected. + /// + /// \param packet Packet to send + /// + /// \return Status code + /// + /// \see receive + /// + //////////////////////////////////////////////////////////// + Status send(Packet& packet); + + //////////////////////////////////////////////////////////// + /// \brief Receive a formatted packet of data from the remote peer + /// + /// In blocking mode, this function will wait until the whole packet + /// has been received. + /// This function will fail if the socket is not connected. + /// + /// \param packet Packet to fill with the received data + /// + /// \return Status code + /// + /// \see send + /// + //////////////////////////////////////////////////////////// + Status receive(Packet& packet); + +private: + + friend class TcpListener; + + //////////////////////////////////////////////////////////// + /// \brief Structure holding the data of a pending packet + /// + //////////////////////////////////////////////////////////// + struct PendingPacket + { + PendingPacket(); + + Uint32 Size; ///< Data of packet size + std::size_t SizeReceived; ///< Number of size bytes received so far + std::vector Data; ///< Data of the packet + }; + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + PendingPacket m_pendingPacket; ///< Temporary data of the packet currently being received +}; + +} // namespace sf + + +#endif // SFML_TCPSOCKET_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::TcpSocket +/// \ingroup network +/// +/// TCP is a connected protocol, which means that a TCP +/// socket can only communicate with the host it is connected +/// to. It can't send or receive anything if it is not connected. +/// +/// The TCP protocol is reliable but adds a slight overhead. +/// It ensures that your data will always be received in order +/// and without errors (no data corrupted, lost or duplicated). +/// +/// When a socket is connected to a remote host, you can +/// retrieve informations about this host with the +/// getRemoteAddress and getRemotePort functions. You can +/// also get the local port to which the socket is bound +/// (which is automatically chosen when the socket is connected), +/// with the getLocalPort function. +/// +/// Sending and receiving data can use either the low-level +/// or the high-level functions. The low-level functions +/// process a raw sequence of bytes, and cannot ensure that +/// one call to Send will exactly match one call to Receive +/// at the other end of the socket. +/// +/// The high-level interface uses packets (see sf::Packet), +/// which are easier to use and provide more safety regarding +/// the data that is exchanged. You can look at the sf::Packet +/// class to get more details about how they work. +/// +/// The socket is automatically disconnected when it is destroyed, +/// but if you want to explicitely close the connection while +/// the socket instance is still alive, you can call disconnect. +/// +/// Usage example: +/// \code +/// // ----- The client ----- +/// +/// // Create a socket and connect it to 192.168.1.50 on port 55001 +/// sf::TcpSocket socket; +/// socket.connect("192.168.1.50", 55001); +/// +/// // Send a message to the connected host +/// std::string message = "Hi, I am a client"; +/// socket.send(message.c_str(), message.size() + 1); +/// +/// // Receive an answer from the server +/// char buffer[1024]; +/// std::size_t received = 0; +/// socket.receive(buffer, sizeof(buffer), received); +/// std::cout << "The server said: " << buffer << std::endl; +/// +/// // ----- The server ----- +/// +/// // Create a listener to wait for incoming connections on port 55001 +/// sf::TcpListener listener; +/// listener.listen(55001); +/// +/// // Wait for a connection +/// sf::TcpSocket socket; +/// listener.accept(socket); +/// std::cout << "New client connected: " << socket.getRemoteAddress() << std::endl; +/// +/// // Receive a message from the client +/// char buffer[1024]; +/// std::size_t received = 0; +/// socket.receive(buffer, sizeof(buffer), received); +/// std::cout << "The client said: " << buffer << std::endl; +/// +/// // Send an answer +/// std::string message = "Welcome, client"; +/// socket.send(message.c_str(), message.size() + 1); +/// \endcode +/// +/// \see sf::Socket, sf::UdpSocket, sf::Packet +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Network/UdpSocket.hpp b/src/include/SFML/include/SFML/Network/UdpSocket.hpp new file mode 100644 index 0000000..cafdf8c --- /dev/null +++ b/src/include/SFML/include/SFML/Network/UdpSocket.hpp @@ -0,0 +1,283 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_UDPSOCKET_HPP +#define SFML_UDPSOCKET_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +class IpAddress; +class Packet; + +//////////////////////////////////////////////////////////// +/// \brief Specialized socket using the UDP protocol +/// +//////////////////////////////////////////////////////////// +class SFML_NETWORK_API UdpSocket : public Socket +{ +public : + + //////////////////////////////////////////////////////////// + // Constants + //////////////////////////////////////////////////////////// + enum + { + MaxDatagramSize = 65507 ///< The maximum number of bytes that can be sent in a single UDP datagram + }; + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + UdpSocket(); + + //////////////////////////////////////////////////////////// + /// \brief Get the port to which the socket is bound locally + /// + /// If the socket is not bound to a port, this function + /// returns 0. + /// + /// \return Port to which the socket is bound + /// + /// \see bind + /// + //////////////////////////////////////////////////////////// + unsigned short getLocalPort() const; + + //////////////////////////////////////////////////////////// + /// \brief Bind the socket to a specific port + /// + /// Binding the socket to a port is necessary for being + /// able to receive data on that port. + /// You can use the special value Socket::AnyPort to tell the + /// system to automatically pick an available port, and then + /// call getLocalPort to retrieve the chosen port. + /// + /// \param port Port to bind the socket to + /// + /// \return Status code + /// + /// \see unbind, getLocalPort + /// + //////////////////////////////////////////////////////////// + Status bind(unsigned short port); + + //////////////////////////////////////////////////////////// + /// \brief Unbind the socket from the local port to which it is bound + /// + /// The port that the socket was previously using is immediately + /// available after this function is called. If the + /// socket is not bound to a port, this function has no effect. + /// + /// \see bind + /// + //////////////////////////////////////////////////////////// + void unbind(); + + //////////////////////////////////////////////////////////// + /// \brief Send raw data to a remote peer + /// + /// Make sure that \a size is not greater than + /// UdpSocket::MaxDatagramSize, otherwise this function will + /// fail and no data will be sent. + /// + /// \param data Pointer to the sequence of bytes to send + /// \param size Number of bytes to send + /// \param remoteAddress Address of the receiver + /// \param remotePort Port of the receiver to send the data to + /// + /// \return Status code + /// + /// \see receive + /// + //////////////////////////////////////////////////////////// + Status send(const void* data, std::size_t size, const IpAddress& remoteAddress, unsigned short remotePort); + + //////////////////////////////////////////////////////////// + /// \brief Receive raw data from a remote peer + /// + /// In blocking mode, this function will wait until some + /// bytes are actually received. + /// Be careful to use a buffer which is large enough for + /// the data that you intend to receive, if it is too small + /// then an error will be returned and *all* the data will + /// be lost. + /// + /// \param data Pointer to the array to fill with the received bytes + /// \param size Maximum number of bytes that can be received + /// \param received This variable is filled with the actual number of bytes received + /// \param remoteAddress Address of the peer that sent the data + /// \param remotePort Port of the peer that sent the data + /// + /// \return Status code + /// + /// \see send + /// + //////////////////////////////////////////////////////////// + Status receive(void* data, std::size_t size, std::size_t& received, IpAddress& remoteAddress, unsigned short& remotePort); + + //////////////////////////////////////////////////////////// + /// \brief Send a formatted packet of data to a remote peer + /// + /// Make sure that the packet size is not greater than + /// UdpSocket::MaxDatagramSize, otherwise this function will + /// fail and no data will be sent. + /// + /// \param packet Packet to send + /// \param remoteAddress Address of the receiver + /// \param remotePort Port of the receiver to send the data to + /// + /// \return Status code + /// + /// \see receive + /// + //////////////////////////////////////////////////////////// + Status send(Packet& packet, const IpAddress& remoteAddress, unsigned short remotePort); + + //////////////////////////////////////////////////////////// + /// \brief Receive a formatted packet of data from a remote peer + /// + /// In blocking mode, this function will wait until the whole packet + /// has been received. + /// + /// \param packet Packet to fill with the received data + /// \param remoteAddress Address of the peer that sent the data + /// \param remotePort Port of the peer that sent the data + /// + /// \return Status code + /// + /// \see send + /// + //////////////////////////////////////////////////////////// + Status receive(Packet& packet, IpAddress& remoteAddress, unsigned short& remotePort); + +private: + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + std::vector m_buffer; ///< Temporary buffer holding the received data in Receive(Packet) +}; + +} // namespace sf + + +#endif // SFML_UDPSOCKET_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::UdpSocket +/// \ingroup network +/// +/// A UDP socket is a connectionless socket. Instead of +/// connecting once to a remote host, like TCP sockets, +/// it can send to and receive from any host at any time. +/// +/// It is a datagram protocol: bounded blocks of data (datagrams) +/// are transfered over the network rather than a continuous +/// stream of data (TCP). Therefore, one call to send will always +/// match one call to receive (if the datagram is not lost), +/// with the same data that was sent. +/// +/// The UDP protocol is lightweight but unreliable. Unreliable +/// means that datagrams may be duplicated, be lost or +/// arrive reordered. However, if a datagram arrives, its +/// data is guaranteed to be valid. +/// +/// UDP is generally used for real-time communication +/// (audio or video streaming, real-time games, etc.) where +/// speed is crucial and lost data doesn't matter much. +/// +/// Sending and receiving data can use either the low-level +/// or the high-level functions. The low-level functions +/// process a raw sequence of bytes, whereas the high-level +/// interface uses packets (see sf::Packet), which are easier +/// to use and provide more safety regarding the data that is +/// exchanged. You can look at the sf::Packet class to get +/// more details about how they work. +/// +/// It is important to note that UdpSocket is unable to send +/// datagrams bigger than MaxDatagramSize. In this case, it +/// returns an error and doesn't send anything. This applies +/// to both raw data and packets. Indeed, even packets are +/// unable to split and recompose data, due to the unreliability +/// of the protocol (dropped, mixed or duplicated datagrams may +/// lead to a big mess when trying to recompose a packet). +/// +/// If the socket is bound to a port, it is automatically +/// unbound from it when the socket is destroyed. However, +/// you can unbind the socket explicitely with the Unbind +/// function if necessary, to stop receiving messages or +/// make the port available for other sockets. +/// +/// Usage example: +/// \code +/// // ----- The client ----- +/// +/// // Create a socket and bind it to the port 55001 +/// sf::UdpSocket socket; +/// socket.bind(55001); +/// +/// // Send a message to 192.168.1.50 on port 55002 +/// std::string message = "Hi, I am " + sf::IpAddress::getLocalAddress().toString(); +/// socket.send(message.c_str(), message.size() + 1, "192.168.1.50", 55002); +/// +/// // Receive an answer (most likely from 192.168.1.50, but could be anyone else) +/// char buffer[1024]; +/// std::size_t received = 0; +/// sf::IpAddress sender; +/// unsigned short port; +/// socket.receive(buffer, sizeof(buffer), received, sender, port); +/// std::cout << sender.ToString() << " said: " << buffer << std::endl; +/// +/// // ----- The server ----- +/// +/// // Create a socket and bind it to the port 55002 +/// sf::UdpSocket socket; +/// socket.bind(55002); +/// +/// // Receive a message from anyone +/// char buffer[1024]; +/// std::size_t received = 0; +/// sf::IpAddress sender; +/// unsigned short port; +/// socket.receive(buffer, sizeof(buffer), received, sender, port); +/// std::cout << sender.ToString() << " said: " << buffer << std::endl; +/// +/// // Send an answer +/// std::string message = "Welcome " + sender.toString(); +/// socket.send(message.c_str(), message.size() + 1, sender, port); +/// \endcode +/// +/// \see sf::Socket, sf::TcpSocket, sf::Packet +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/OpenGL.hpp b/src/include/SFML/include/SFML/OpenGL.hpp new file mode 100644 index 0000000..4b43894 --- /dev/null +++ b/src/include/SFML/include/SFML/OpenGL.hpp @@ -0,0 +1,62 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_OPENGL_HPP +#define SFML_OPENGL_HPP + + +//////////////////////////////////////////////////////////// +/// Headers +//////////////////////////////////////////////////////////// +#include + + +//////////////////////////////////////////////////////////// +/// This file just includes the OpenGL (GL and GLU) headers, +/// which have actually different paths on each system +//////////////////////////////////////////////////////////// +#if defined(SFML_SYSTEM_WINDOWS) + + // The Visual C++ version of gl.h uses WINGDIAPI and APIENTRY but doesn't define them + #ifdef _MSC_VER + #include + #endif + + #include + #include + +#elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD) + + #include + #include + +#elif defined(SFML_SYSTEM_MACOS) + + #include + #include + +#endif + + +#endif // SFML_OPENGL_HPP diff --git a/src/include/SFML/include/SFML/System.hpp b/src/include/SFML/include/SFML/System.hpp new file mode 100644 index 0000000..4e47b70 --- /dev/null +++ b/src/include/SFML/include/SFML/System.hpp @@ -0,0 +1,56 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SYSTEM_HPP +#define SFML_SYSTEM_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // SFML_SYSTEM_HPP + +//////////////////////////////////////////////////////////// +/// \defgroup system System module +/// +/// Base module of SFML, defining various utilities. It provides +/// vector classes, unicode strings and conversion functions, +/// threads and mutexes, timing classes. +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/System/Clock.hpp b/src/include/SFML/include/SFML/System/Clock.hpp new file mode 100644 index 0000000..a3e4acc --- /dev/null +++ b/src/include/SFML/include/SFML/System/Clock.hpp @@ -0,0 +1,117 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_CLOCK_HPP +#define SFML_CLOCK_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Utility class that measures the elapsed time +/// +//////////////////////////////////////////////////////////// +class SFML_SYSTEM_API Clock +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// The clock starts automatically after being constructed. + /// + //////////////////////////////////////////////////////////// + Clock(); + + //////////////////////////////////////////////////////////// + /// \brief Get the elapsed time + /// + /// This function returns the time elapsed since the last call + /// to restart() (or the construction of the instance if restart() + /// has not been called). + /// + /// \return Time elapsed + /// + //////////////////////////////////////////////////////////// + Time getElapsedTime() const; + + //////////////////////////////////////////////////////////// + /// \brief Restart the clock + /// + /// This function puts the time counter back to zero. + /// It also returns the time elapsed since the clock was started. + /// + /// \return Time elapsed + /// + //////////////////////////////////////////////////////////// + Time restart(); + +private : + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + Time m_startTime; ///< Time of last reset, in microseconds +}; + +} // namespace sf + + +#endif // SFML_CLOCK_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Clock +/// \ingroup system +/// +/// sf::Clock is a lightweight class for measuring time. +/// +/// Its provides the most precise time that the underlying +/// OS can achieve (generally microseconds or nanoseconds). +/// It also ensures monotonicity, which means that the returned +/// time can never go backward, even if the system time is +/// changed. +/// +/// Usage example: +/// \code +/// sf::Clock clock; +/// ... +/// Time time1 = clock.getElapsedTime(); +/// ... +/// Time time2 = clock.restart(); +/// \endcode +/// +/// The sf::Time value returned by the clock can then be +/// converted to a number of seconds, milliseconds or even +/// microseconds. +/// +/// \see sf::Time +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/System/Err.hpp b/src/include/SFML/include/SFML/System/Err.hpp new file mode 100644 index 0000000..590c635 --- /dev/null +++ b/src/include/SFML/include/SFML/System/Err.hpp @@ -0,0 +1,78 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_ERR_HPP +#define SFML_ERR_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Standard stream used by SFML to output warnings and errors +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API std::ostream& err(); + +} // namespace sf + + +#endif // SFML_ERR_HPP + + +//////////////////////////////////////////////////////////// +/// \fn sf::err +/// \ingroup system +/// +/// By default, sf::err() outputs to the same location as std::cerr, +/// (-> the stderr descriptor) which is the console if there's +/// one available. +/// +/// It is a standard std::ostream instance, so it supports all the +/// insertion operations defined by the STL +/// (operator <<, manipulators, etc.). +/// +/// sf::err() can be redirected to write to another output, independantly +/// of std::cerr, by using the rdbuf() function provided by the +/// std::ostream class. +/// +/// Example: +/// \code +/// // Redirect to a file +/// std::ofstream file("sfml-log.txt"); +/// std::streambuf* previous = sf::err().rdbuf(file.rdbuf()); +/// +/// // Redirect to nothing +/// sf::err().rdbuf(NULL); +/// +/// // Restore the original output +/// sf::err().rdbuf(previous); +/// \endcode +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/System/Export.hpp b/src/include/SFML/include/SFML/System/Export.hpp new file mode 100644 index 0000000..ec08fbe --- /dev/null +++ b/src/include/SFML/include/SFML/System/Export.hpp @@ -0,0 +1,48 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SYSTEM_EXPORT_HPP +#define SFML_SYSTEM_EXPORT_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +//////////////////////////////////////////////////////////// +// Define portable import / export macros +//////////////////////////////////////////////////////////// +#if defined(SFML_SYSTEM_EXPORTS) + + #define SFML_SYSTEM_API SFML_API_EXPORT + +#else + + #define SFML_SYSTEM_API SFML_API_IMPORT + +#endif + + +#endif // SFML_SYSTEM_EXPORT_HPP diff --git a/src/include/SFML/include/SFML/System/InputStream.hpp b/src/include/SFML/include/SFML/System/InputStream.hpp new file mode 100644 index 0000000..b79436a --- /dev/null +++ b/src/include/SFML/include/SFML/System/InputStream.hpp @@ -0,0 +1,151 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_INPUTSTREAM_HPP +#define SFML_INPUTSTREAM_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Abstract class for custom file input streams +/// +//////////////////////////////////////////////////////////// +class InputStream +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Virtual destructor + /// + //////////////////////////////////////////////////////////// + virtual ~InputStream() {} + + //////////////////////////////////////////////////////////// + /// \brief Read data from the stream + /// + /// After reading, the stream's reading position must be + /// advanced by the amount of bytes read. + /// + /// \param data Buffer where to copy the read data + /// \param size Desired number of bytes to read + /// + /// \return The number of bytes actually read, or -1 on error + /// + //////////////////////////////////////////////////////////// + virtual Int64 read(void* data, Int64 size) = 0; + + //////////////////////////////////////////////////////////// + /// \brief Change the current reading position + /// + /// \param position The position to seek to, from the beginning + /// + /// \return The position actually sought to, or -1 on error + /// + //////////////////////////////////////////////////////////// + virtual Int64 seek(Int64 position) = 0; + + //////////////////////////////////////////////////////////// + /// \brief Get the current reading position in the stream + /// + /// \return The current position, or -1 on error. + /// + //////////////////////////////////////////////////////////// + virtual Int64 tell() = 0; + + //////////////////////////////////////////////////////////// + /// \brief Return the size of the stream + /// + /// \return The total number of bytes available in the stream, or -1 on error + /// + //////////////////////////////////////////////////////////// + virtual Int64 getSize() = 0; +}; + +} // namespace sf + + +#endif // SFML_INPUTSTREAM_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::InputStream +/// \ingroup system +/// +/// This class allows users to define their own file input sources +/// from which SFML can load resources. +/// +/// SFML resource classes like sf::Texture and +/// sf::SoundBuffer provide loadFromFile and loadFromMemory functions, +/// which read data from conventional sources. However, if you +/// have data coming from a different source (over a network, +/// embedded, encrypted, compressed, etc) you can derive your +/// own class from sf::InputStream and load SFML resources with +/// their loadFromStream function. +/// +/// Usage example: +/// \code +/// // custom stream class that reads from inside a zip file +/// class ZipStream : public sf::InputStream +/// { +/// public : +/// +/// ZipStream(std::string archive); +/// +/// bool open(std::string filename); +/// +/// Int64 read(void* data, Int64 size); +/// +/// Int64 seek(Int64 position); +/// +/// Int64 tell(); +/// +/// Int64 getSize(); +/// +/// private : +/// +/// ... +/// }; +/// +/// // now you can load textures... +/// sf::Texture texture; +/// ZipStream stream("resources.zip"); +/// stream.open("images/img.png"); +/// texture.loadFromStream(stream); +/// +/// // musics... +/// sf::Music music; +/// ZipStream stream("resources.zip"); +/// stream.open("musics/msc.ogg"); +/// music.openFromStream(stream); +/// +/// // etc. +/// \endcode +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/System/Lock.hpp b/src/include/SFML/include/SFML/System/Lock.hpp new file mode 100644 index 0000000..25713e7 --- /dev/null +++ b/src/include/SFML/include/SFML/System/Lock.hpp @@ -0,0 +1,139 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_LOCK_HPP +#define SFML_LOCK_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +class Mutex; + +//////////////////////////////////////////////////////////// +/// \brief Automatic wrapper for locking and unlocking mutexes +/// +//////////////////////////////////////////////////////////// +class SFML_SYSTEM_API Lock : NonCopyable +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Construct the lock with a target mutex + /// + /// The mutex passed to sf::Lock is automatically locked. + /// + /// \param mutex Mutex to lock + /// + //////////////////////////////////////////////////////////// + explicit Lock(Mutex& mutex); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + /// The destructor of sf::Lock automatically unlocks its mutex. + /// + //////////////////////////////////////////////////////////// + ~Lock(); + +private : + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + Mutex& m_mutex; ///< Mutex to lock / unlock +}; + +} // namespace sf + + +#endif // SFML_LOCK_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Lock +/// \ingroup system +/// +/// sf::Lock is a RAII wrapper for sf::Mutex. By unlocking +/// it in its destructor, it ensures that the mutex will +/// always be released when the current scope (most likely +/// a function) ends. +/// This is even more important when an exception or an early +/// return statement can interrupt the execution flow of the +/// function. +/// +/// For maximum robustness, sf::Lock should always be used +/// to lock/unlock a mutex. +/// +/// Usage example: +/// \code +/// sf::Mutex mutex; +/// +/// void function() +/// { +/// sf::Lock lock(mutex); // mutex is now locked +/// +/// functionThatMayThrowAnException(); // mutex is unlocked if this function throws +/// +/// if (someCondition) +/// return; // mutex is unlocked +/// +/// } // mutex is unlocked +/// \endcode +/// +/// Because the mutex is not explicitely unlocked in the code, +/// it may remain locked longer than needed. If the region +/// of the code that needs to be protected by the mutex is +/// not the entire function, a good practice is to create a +/// smaller, inner scope so that the lock is limited to this +/// part of the code. +/// +/// \code +/// sf::Mutex mutex; +/// +/// void function() +/// { +/// { +/// sf::Lock lock(mutex); +/// codeThatRequiresProtection(); +/// +/// } // mutex is unlocked here +/// +/// codeThatDoesntCareAboutTheMutex(); +/// } +/// \endcode +/// +/// Having a mutex locked longer than required is a bad practice +/// which can lead to bad performances. Don't forget that when +/// a mutex is locked, other threads may be waiting doing nothing +/// until it is released. +/// +/// \see sf::Mutex +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/System/Mutex.hpp b/src/include/SFML/include/SFML/System/Mutex.hpp new file mode 100644 index 0000000..1451ce0 --- /dev/null +++ b/src/include/SFML/include/SFML/System/Mutex.hpp @@ -0,0 +1,148 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_MUTEX_HPP +#define SFML_MUTEX_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +namespace priv +{ + class MutexImpl; +} + +//////////////////////////////////////////////////////////// +/// \brief Blocks concurrent access to shared resources +/// from multiple threads +/// +//////////////////////////////////////////////////////////// +class SFML_SYSTEM_API Mutex : NonCopyable +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + Mutex(); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~Mutex(); + + //////////////////////////////////////////////////////////// + /// \brief Lock the mutex + /// + /// If the mutex is already locked in another thread, + /// this call will block the execution until the mutex + /// is released. + /// + /// \see unlock + /// + //////////////////////////////////////////////////////////// + void lock(); + + //////////////////////////////////////////////////////////// + /// \brief Unlock the mutex + /// + /// \see lock + /// + //////////////////////////////////////////////////////////// + void unlock(); + +private : + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + priv::MutexImpl* m_mutexImpl; ///< OS-specific implementation +}; + +} // namespace sf + + +#endif // SFML_MUTEX_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Mutex +/// \ingroup system +/// +/// Mutex stands for "MUTual EXclusion". A mutex is a +/// synchronization object, used when multiple threads are involved. +/// +/// When you want to protect a part of the code from being accessed +/// simultaneously by multiple threads, you typically use a +/// mutex. When a thread is locked by a mutex, any other thread +/// trying to lock it will be blocked until the mutex is released +/// by the thread that locked it. This way, you can allow only +/// one thread at a time to access a critical region of your code. +/// +/// Usage example: +/// \code +/// Database database; // this is a critical resource that needs some protection +/// sf::Mutex mutex; +/// +/// void thread1() +/// { +/// mutex.lock(); // this call will block the thread if the mutex is already locked by thread2 +/// database.write(...); +/// mutex.unlock(); // if thread2 was waiting, it will now be unblocked +/// } +/// +/// void thread2() +/// { +/// mutex.lock(); // this call will block the thread if the mutex is already locked by thread1 +/// database.write(...); +/// mutex.unlock(); // if thread1 was waiting, it will now be unblocked +/// } +/// \endcode +/// +/// Be very careful with mutexes. A bad usage can lead to bad problems, +/// like deadlocks (two threads are waiting for each other and the +/// application is globally stuck). +/// +/// To make the usage of mutexes more robust, particularly in +/// environments where exceptions can be thrown, you should +/// use the helper class sf::Lock to lock/unlock mutexes. +/// +/// SFML mutexes are recursive, which means that you can lock +/// a mutex multiple times in the same thread without creating +/// a deadlock. In this case, the first call to lock() behaves +/// as usual, and the following ones have no effect. +/// However, you must call unlock() exactly as many times as you +/// called lock(). If you don't, the mutex won't be released. +/// +/// \see sf::Lock +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/System/NonCopyable.hpp b/src/include/SFML/include/SFML/System/NonCopyable.hpp new file mode 100644 index 0000000..b856ae9 --- /dev/null +++ b/src/include/SFML/include/SFML/System/NonCopyable.hpp @@ -0,0 +1,119 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_NONCOPYABLE_HPP +#define SFML_NONCOPYABLE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Utility class that makes any derived +/// class non-copyable +/// +//////////////////////////////////////////////////////////// +class SFML_SYSTEM_API NonCopyable +{ +protected : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Because this class has a copy constructor, the compiler + /// will not automatically generate the default constructor. + /// That's why we must define it explicitely. + /// + //////////////////////////////////////////////////////////// + NonCopyable() {} + +private : + + //////////////////////////////////////////////////////////// + /// \brief Disabled copy constructor + /// + /// By making the copy constructor private, the compiler will + /// trigger an error if anyone outside tries to use it. + /// To prevent NonCopyable or friend classes from using it, + /// we also give no definition, so that the linker will + /// produce an error if the first protection was inefficient. + /// + //////////////////////////////////////////////////////////// + NonCopyable(const NonCopyable&); + + //////////////////////////////////////////////////////////// + /// \brief Disabled assignment operator + /// + /// By making the assignment operator private, the compiler will + /// trigger an error if anyone outside tries to use it. + /// To prevent NonCopyable or friend classes from using it, + /// we also give no definition, so that the linker will + /// produce an error if the first protection was inefficient. + /// + //////////////////////////////////////////////////////////// + NonCopyable& operator =(const NonCopyable&); +}; + +} // namespace sf + + +#endif // SFML_NONCOPYABLE_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::NonCopyable +/// \ingroup system +/// +/// This class makes its instances non-copyable, by explicitely +/// disabling its copy constructor and its assignment operator. +/// +/// To create a non-copyable class, simply inherit from +/// sf::NonCopyable. +/// +/// The type of inheritance (public or private) doesn't matter, +/// the copy constructor and assignment operator are declared private +/// in sf::NonCopyable so they will end up being inaccessible in both +/// cases. Thus you can use a shorter syntax for inheriting from it +/// (see below). +/// +/// Usage example: +/// \code +/// class MyNonCopyableClass : sf::NonCopyable +/// { +/// ... +/// }; +/// \endcode +/// +/// Deciding whether the instances of a class can be copied +/// or not is a very important design choice. You are strongly +/// encouraged to think about it before writing a class, +/// and to use sf::NonCopyable when necessary to prevent +/// many potential future errors when using it. This is also +/// a very important indication to users of your class. +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/System/Sleep.hpp b/src/include/SFML/include/SFML/System/Sleep.hpp new file mode 100644 index 0000000..dcd6fe3 --- /dev/null +++ b/src/include/SFML/include/SFML/System/Sleep.hpp @@ -0,0 +1,52 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SLEEP_HPP +#define SFML_SLEEP_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \ingroup system +/// \brief Make the current thread sleep for a given duration +/// +/// sf::sleep is the best way to block a program or one of its +/// threads, as it doesn't consume any CPU power. +/// +/// \param duration Time to sleep +/// +//////////////////////////////////////////////////////////// +void SFML_SYSTEM_API sleep(Time duration); + +} // namespace sf + + +#endif // SFML_SLEEP_HPP diff --git a/src/include/SFML/include/SFML/System/String.hpp b/src/include/SFML/include/SFML/System/String.hpp new file mode 100644 index 0000000..5eb52a0 --- /dev/null +++ b/src/include/SFML/include/SFML/System/String.hpp @@ -0,0 +1,543 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_STRING_HPP +#define SFML_STRING_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Utility string class that automatically handles +/// conversions between types and encodings +/// +//////////////////////////////////////////////////////////// +class SFML_SYSTEM_API String +{ +public : + + //////////////////////////////////////////////////////////// + // Types + //////////////////////////////////////////////////////////// + typedef std::basic_string::iterator Iterator; ///< Iterator type + typedef std::basic_string::const_iterator ConstIterator; ///< Constant iterator type + + //////////////////////////////////////////////////////////// + // Static member data + //////////////////////////////////////////////////////////// + static const std::size_t InvalidPos; ///< Represents an invalid position in the string + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// This constructor creates an empty string. + /// + //////////////////////////////////////////////////////////// + String(); + + //////////////////////////////////////////////////////////// + /// \brief Construct from a single ANSI character and a locale + /// + /// The source character is converted to UTF-32 according + /// to the given locale. + /// + /// \param ansiChar ANSI character to convert + /// \param locale Locale to use for conversion + /// + //////////////////////////////////////////////////////////// + String(char ansiChar, const std::locale& locale = std::locale()); + + //////////////////////////////////////////////////////////// + /// \brief Construct from single wide character + /// + /// \param wideChar Wide character to convert + /// + //////////////////////////////////////////////////////////// + String(wchar_t wideChar); + + //////////////////////////////////////////////////////////// + /// \brief Construct from single UTF-32 character + /// + /// \param utf32Char UTF-32 character to convert + /// + //////////////////////////////////////////////////////////// + String(Uint32 utf32Char); + + //////////////////////////////////////////////////////////// + /// \brief Construct from a null-terminated C-style ANSI string and a locale + /// + /// The source string is converted to UTF-32 according + /// to the given locale. + /// + /// \param ansiString ANSI string to convert + /// \param locale Locale to use for conversion + /// + //////////////////////////////////////////////////////////// + String(const char* ansiString, const std::locale& locale = std::locale()); + + //////////////////////////////////////////////////////////// + /// \brief Construct from an ANSI string and a locale + /// + /// The source string is converted to UTF-32 according + /// to the given locale. + /// + /// \param ansiString ANSI string to convert + /// \param locale Locale to use for conversion + /// + //////////////////////////////////////////////////////////// + String(const std::string& ansiString, const std::locale& locale = std::locale()); + + //////////////////////////////////////////////////////////// + /// \brief Construct from null-terminated C-style wide string + /// + /// \param wideString Wide string to convert + /// + //////////////////////////////////////////////////////////// + String(const wchar_t* wideString); + + //////////////////////////////////////////////////////////// + /// \brief Construct from a wide string + /// + /// \param wideString Wide string to convert + /// + //////////////////////////////////////////////////////////// + String(const std::wstring& wideString); + + //////////////////////////////////////////////////////////// + /// \brief Construct from a null-terminated C-style UTF-32 string + /// + /// \param utf32String UTF-32 string to assign + /// + //////////////////////////////////////////////////////////// + String(const Uint32* utf32String); + + //////////////////////////////////////////////////////////// + /// \brief Construct from an UTF-32 string + /// + /// \param utf32String UTF-32 string to assign + /// + //////////////////////////////////////////////////////////// + String(const std::basic_string& utf32String); + + //////////////////////////////////////////////////////////// + /// \brief Copy constructor + /// + /// \param copy Instance to copy + /// + //////////////////////////////////////////////////////////// + String(const String& copy); + + //////////////////////////////////////////////////////////// + /// \brief Implicit cast operator to std::string (ANSI string) + /// + /// The current global locale is used for conversion. If you + /// want to explicitely specify a locale, see toAnsiString. + /// Characters that do not fit in the target encoding are + /// discarded from the returned string. + /// This operator is defined for convenience, and is equivalent + /// to calling toAnsiString(). + /// + /// \return Converted ANSI string + /// + /// \see toAnsiString, operator std::wstring + /// + //////////////////////////////////////////////////////////// + operator std::string() const; + + //////////////////////////////////////////////////////////// + /// \brief Implicit cast operator to std::wstring (wide string) + /// + /// Characters that do not fit in the target encoding are + /// discarded from the returned string. + /// This operator is defined for convenience, and is equivalent + /// to calling toWideString(). + /// + /// \return Converted wide string + /// + /// \see toWideString, operator std::string + /// + //////////////////////////////////////////////////////////// + operator std::wstring() const; + + //////////////////////////////////////////////////////////// + /// \brief Convert the unicode string to an ANSI string + /// + /// The UTF-32 string is converted to an ANSI string in + /// the encoding defined by \a locale. + /// Characters that do not fit in the target encoding are + /// discarded from the returned string. + /// + /// \param locale Locale to use for conversion + /// + /// \return Converted ANSI string + /// + /// \see toWideString, operator std::string + /// + //////////////////////////////////////////////////////////// + std::string toAnsiString(const std::locale& locale = std::locale()) const; + + //////////////////////////////////////////////////////////// + /// \brief Convert the unicode string to a wide string + /// + /// Characters that do not fit in the target encoding are + /// discarded from the returned string. + /// + /// \return Converted wide string + /// + /// \see toAnsiString, operator std::wstring + /// + //////////////////////////////////////////////////////////// + std::wstring toWideString() const; + + //////////////////////////////////////////////////////////// + /// \brief Overload of assignment operator + /// + /// \param right Instance to assign + /// + /// \return Reference to self + /// + //////////////////////////////////////////////////////////// + String& operator =(const String& right); + + //////////////////////////////////////////////////////////// + /// \brief Overload of += operator to append an UTF-32 string + /// + /// \param right String to append + /// + /// \return Reference to self + /// + //////////////////////////////////////////////////////////// + String& operator +=(const String& right); + + //////////////////////////////////////////////////////////// + /// \brief Overload of [] operator to access a character by its position + /// + /// This function provides read-only access to characters. + /// Note: this function doesn't throw if \a index is out of range. + /// + /// \param index Index of the character to get + /// + /// \return Character at position \a index + /// + //////////////////////////////////////////////////////////// + Uint32 operator [](std::size_t index) const; + + //////////////////////////////////////////////////////////// + /// \brief Overload of [] operator to access a character by its position + /// + /// This function provides read and write access to characters. + /// Note: this function doesn't throw if \a index is out of range. + /// + /// \param index Index of the character to get + /// + /// \return Reference to the character at position \a index + /// + //////////////////////////////////////////////////////////// + Uint32& operator [](std::size_t index); + + //////////////////////////////////////////////////////////// + /// \brief Clear the string + /// + /// This function removes all the characters from the string. + /// + /// \see isEmpty, erase + /// + //////////////////////////////////////////////////////////// + void clear(); + + //////////////////////////////////////////////////////////// + /// \brief Get the size of the string + /// + /// \return Number of characters in the string + /// + /// \see isEmpty + /// + //////////////////////////////////////////////////////////// + std::size_t getSize() const; + + //////////////////////////////////////////////////////////// + /// \brief Check whether the string is empty or not + /// + /// \return True if the string is empty (i.e. contains no character) + /// + /// \see clear, getSize + /// + //////////////////////////////////////////////////////////// + bool isEmpty() const; + + //////////////////////////////////////////////////////////// + /// \brief Erase one or more characters from the string + /// + /// This function removes a sequence of \a count characters + /// starting from \a position. + /// + /// \param position Position of the first character to erase + /// \param count Number of characters to erase + /// + //////////////////////////////////////////////////////////// + void erase(std::size_t position, std::size_t count = 1); + + //////////////////////////////////////////////////////////// + /// \brief Insert one or more characters into the string + /// + /// This function inserts the characters of \a str + /// into the string, starting from \a position. + /// + /// \param position Position of insertion + /// \param str Characters to insert + /// + //////////////////////////////////////////////////////////// + void insert(std::size_t position, const String& str); + + //////////////////////////////////////////////////////////// + /// \brief Find a sequence of one or more characters in the string + /// + /// This function searches for the characters of \a str + /// into the string, starting from \a start. + /// + /// \param str Characters to find + /// \param start Where to begin searching + /// + /// \return Position of \a str in the string, or String::InvalidPos if not found + /// + //////////////////////////////////////////////////////////// + std::size_t find(const String& str, std::size_t start = 0) const; + + //////////////////////////////////////////////////////////// + /// \brief Get a pointer to the C-style array of characters + /// + /// This functions provides a read-only access to a + /// null-terminated C-style representation of the string. + /// The returned pointer is temporary and is meant only for + /// immediate use, thus it is not recommended to store it. + /// + /// \return Read-only pointer to the array of characters + /// + //////////////////////////////////////////////////////////// + const Uint32* getData() const; + + //////////////////////////////////////////////////////////// + /// \brief Return an iterator to the beginning of the string + /// + /// \return Read-write iterator to the beginning of the string characters + /// + /// \see end + /// + //////////////////////////////////////////////////////////// + Iterator begin(); + + //////////////////////////////////////////////////////////// + /// \brief Return an iterator to the beginning of the string + /// + /// \return Read-only iterator to the beginning of the string characters + /// + /// \see end + /// + //////////////////////////////////////////////////////////// + ConstIterator begin() const; + + //////////////////////////////////////////////////////////// + /// \brief Return an iterator to the beginning of the string + /// + /// The end iterator refers to 1 position past the last character; + /// thus it represents an invalid character and should never be + /// accessed. + /// + /// \return Read-write iterator to the end of the string characters + /// + /// \see begin + /// + //////////////////////////////////////////////////////////// + Iterator end(); + + //////////////////////////////////////////////////////////// + /// \brief Return an iterator to the beginning of the string + /// + /// The end iterator refers to 1 position past the last character; + /// thus it represents an invalid character and should never be + /// accessed. + /// + /// \return Read-only iterator to the end of the string characters + /// + /// \see begin + /// + //////////////////////////////////////////////////////////// + ConstIterator end() const; + +private : + + friend SFML_SYSTEM_API bool operator ==(const String& left, const String& right); + friend SFML_SYSTEM_API bool operator <(const String& left, const String& right); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + std::basic_string m_string; ///< Internal string of UTF-32 characters +}; + +//////////////////////////////////////////////////////////// +/// \relates String +/// \brief Overload of == operator to compare two UTF-32 strings +/// +/// \param left Left operand (a string) +/// \param right Right operand (a string) +/// +/// \return True if both strings are equal +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API bool operator ==(const String& left, const String& right); + +//////////////////////////////////////////////////////////// +/// \relates String +/// \brief Overload of != operator to compare two UTF-32 strings +/// +/// \param left Left operand (a string) +/// \param right Right operand (a string) +/// +/// \return True if both strings are different +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API bool operator !=(const String& left, const String& right); + +//////////////////////////////////////////////////////////// +/// \relates String +/// \brief Overload of < operator to compare two UTF-32 strings +/// +/// \param left Left operand (a string) +/// \param right Right operand (a string) +/// +/// \return True if \a left is alphabetically lesser than \a right +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API bool operator <(const String& left, const String& right); + +//////////////////////////////////////////////////////////// +/// \relates String +/// \brief Overload of > operator to compare two UTF-32 strings +/// +/// \param left Left operand (a string) +/// \param right Right operand (a string) +/// +/// \return True if \a left is alphabetically greater than \a right +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API bool operator >(const String& left, const String& right); + +//////////////////////////////////////////////////////////// +/// \relates String +/// \brief Overload of <= operator to compare two UTF-32 strings +/// +/// \param left Left operand (a string) +/// \param right Right operand (a string) +/// +/// \return True if \a left is alphabetically lesser or equal than \a right +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API bool operator <=(const String& left, const String& right); + +//////////////////////////////////////////////////////////// +/// \relates String +/// \brief Overload of >= operator to compare two UTF-32 strings +/// +/// \param left Left operand (a string) +/// \param right Right operand (a string) +/// +/// \return True if \a left is alphabetically greater or equal than \a right +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API bool operator >=(const String& left, const String& right); + +//////////////////////////////////////////////////////////// +/// \relates String +/// \brief Overload of binary + operator to concatenate two strings +/// +/// \param left Left operand (a string) +/// \param right Right operand (a string) +/// +/// \return Concatenated string +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API String operator +(const String& left, const String& right); + +} // namespace sf + + +#endif // SFML_STRING_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::String +/// \ingroup system +/// +/// sf::String is a utility string class defined mainly for +/// convenience. It is a Unicode string (implemented using +/// UTF-32), thus it can store any character in the world +/// (european, chinese, arabic, hebrew, etc.). +/// +/// It automatically handles conversions from/to ANSI and +/// wide strings, so that you can work with standard string +/// classes and still be compatible with functions taking a +/// sf::String. +/// +/// \code +/// sf::String s; +/// +/// std::string s1 = s; // automatically converted to ANSI string +/// std::wstring s2 = s; // automatically converted to wide string +/// s = "hello"; // automatically converted from ANSI string +/// s = L"hello"; // automatically converted from wide string +/// s += 'a'; // automatically converted from ANSI string +/// s += L'a'; // automatically converted from wide string +/// \endcode +/// +/// Conversions involving ANSI strings use the default user locale. However +/// it is possible to use a custom locale if necessary: +/// \code +/// std::locale locale; +/// sf::String s; +/// ... +/// std::string s1 = s.toAnsiString(locale); +/// s = sf::String("hello", locale); +/// \endcode +/// +/// sf::String defines the most important functions of the +/// standard std::string class: removing, random access, iterating, +/// appending, comparing, etc. However it is a simple class +/// provided for convenience, and you may have to consider using +/// a more optimized class if your program requires complex string +/// handling. The automatic conversion functions will then take +/// care of converting your string to sf::String whenever SFML +/// requires it. +/// +/// Please note that SFML also defines a low-level, generic +/// interface for Unicode handling, see the sf::Utf classes. +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/System/Thread.hpp b/src/include/SFML/include/SFML/System/Thread.hpp new file mode 100644 index 0000000..589c20f --- /dev/null +++ b/src/include/SFML/include/SFML/System/Thread.hpp @@ -0,0 +1,282 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_THREAD_HPP +#define SFML_THREAD_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +namespace priv +{ + class ThreadImpl; + struct ThreadFunc; +} + +//////////////////////////////////////////////////////////// +/// \brief Utility class to manipulate threads +/// +//////////////////////////////////////////////////////////// +class SFML_SYSTEM_API Thread : NonCopyable +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Construct the thread from a functor with no argument + /// + /// This constructor works for function objects, as well + /// as free function. + /// + /// Use this constructor for this kind of function: + /// \code + /// void function(); + /// + /// // --- or ---- + /// + /// struct Functor + /// { + /// void operator()(); + /// }; + /// \endcode + /// Note: this does *not* run the thread, use Launch(). + /// + /// \param function Functor or free function to use as the entry point of the thread + /// + //////////////////////////////////////////////////////////// + template + Thread(F function); + + //////////////////////////////////////////////////////////// + /// \brief Construct the thread from a functor with an argument + /// + /// This constructor works for function objects, as well + /// as free function. + /// It is a template, which means that the argument can + /// have any type (int, std::string, void*, Toto, ...). + /// + /// Use this constructor for this kind of function: + /// \code + /// void function(int arg); + /// + /// // --- or ---- + /// + /// struct Functor + /// { + /// void operator()(std::string arg); + /// }; + /// \endcode + /// Note: this does *not* run the thread, use Launch(). + /// + /// \param function Functor or free function to use as the entry point of the thread + /// \param argument argument to forward to the function + /// + //////////////////////////////////////////////////////////// + template + Thread(F function, A argument); + + //////////////////////////////////////////////////////////// + /// \brief Construct the thread from a member function and an object + /// + /// This constructor is template, which means that you can + /// use it with any class. + /// Use this constructor for this kind of function: + /// \code + /// class MyClass + /// { + /// public : + /// + /// void function(); + /// }; + /// \endcode + /// Note: this does *not* run the thread, use Launch(). + /// + /// \param function Entry point of the thread + /// \param object Pointer to the object to use + /// + //////////////////////////////////////////////////////////// + template + Thread(void(C::*function)(), C* object); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + /// This destructor calls Wait(), so that the internal thread + /// cannot survive after its sf::Thread instance is destroyed. + /// + //////////////////////////////////////////////////////////// + ~Thread(); + + //////////////////////////////////////////////////////////// + /// \brief Run the thread + /// + /// This function starts the entry point passed to the + /// thread's constructor, and returns immediately. + /// After this function returns, the thread's function is + /// running in parallel to the calling code. + /// + //////////////////////////////////////////////////////////// + void launch(); + + //////////////////////////////////////////////////////////// + /// \brief Wait until the thread finishes + /// + /// This function will block the execution until the + /// thread's function ends. + /// Warning: if the thread function never ends, the calling + /// thread will block forever. + /// If this function is called from its owner thread, it + /// returns without doing anything. + /// + //////////////////////////////////////////////////////////// + void wait(); + + //////////////////////////////////////////////////////////// + /// \brief Terminate the thread + /// + /// This function immediately stops the thread, without waiting + /// for its function to finish. + /// Terminating a thread with this function is not safe, + /// and can lead to local variables not being destroyed + /// on some operating systems. You should rather try to make + /// the thread function terminate by itself. + /// + //////////////////////////////////////////////////////////// + void terminate(); + +private : + + friend class priv::ThreadImpl; + + //////////////////////////////////////////////////////////// + /// \brief Internal entry point of the thread + /// + /// This function is called by the thread implementation. + /// + //////////////////////////////////////////////////////////// + void run(); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + priv::ThreadImpl* m_impl; ///< OS-specific implementation of the thread + priv::ThreadFunc* m_entryPoint; ///< Abstraction of the function to run +}; + +#include + +} // namespace sf + +#endif // SFML_THREAD_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Thread +/// \ingroup system +/// +/// Threads provide a way to run multiple parts of the code +/// in parallel. When you launch a new thread, the execution +/// is split and both the new thread and the caller run +/// in parallel. +/// +/// To use a sf::Thread, you construct it directly with the +/// function to execute as the entry point of the thread. +/// sf::Thread has multiple template constructors, which means +/// that you can use several types of entry points: +/// \li non-member functions with no argument +/// \li non-member functions with one argument of any type +/// \li functors with no argument (this one is particularly useful for compatibility with boost/std::bind) +/// \li functors with one argument of any type +/// \li member functions from any class with no argument +/// +/// The function argument, if any, is copied in the sf::Thread +/// instance, as well as the functor (if the corresponding +/// constructor is used). Class instances, however, are passed +/// by pointer so you must make sure that the object won't be +/// destroyed while the thread is still using it. +/// +/// The thread ends when its function is terminated. If the +/// owner sf::Thread instance is destroyed before the +/// thread is finished, the destructor will wait (see wait()) +/// +/// Usage examples: +/// \code +/// // example 1: non member function with one argument +/// +/// void threadFunc(int argument) +/// { +/// ... +/// } +/// +/// sf::Thread thread(&threadFunc, 5); +/// thread.launch(); // start the thread (internally calls threadFunc(5)) +/// \endcode +/// +/// \code +/// // example 2: member function +/// +/// class Task +/// { +/// public : +/// void run() +/// { +/// ... +/// } +/// }; +/// +/// Task task; +/// sf::Thread thread(&Task::run, &task); +/// thread.launch(); // start the thread (internally calls task.run()) +/// \endcode +/// +/// \code +/// // example 3: functor +/// +/// struct Task +/// { +/// void operator()() +/// { +/// ... +/// } +/// }; +/// +/// sf::Thread thread(Task()); +/// thread.launch(); // start the thread (internally calls operator() on the Task instance) +/// \endcode +/// +/// Creating parallel threads of execution can be dangerous: +/// all threads inside the same process share the same memory space, +/// which means that you may end up accessing the same variable +/// from multiple threads at the same time. To prevent this +/// kind of situations, you can use mutexes (see sf::Mutex). +/// +/// \see sf::Mutex +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/System/Thread.inl b/src/include/SFML/include/SFML/System/Thread.inl new file mode 100644 index 0000000..114e54e --- /dev/null +++ b/src/include/SFML/include/SFML/System/Thread.inl @@ -0,0 +1,90 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2012 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +namespace priv +{ +// Base class for abstract thread functions +struct ThreadFunc +{ + virtual ~ThreadFunc() {} + virtual void run() = 0; +}; + +// Specialization using a functor (including free functions) with no argument +template +struct ThreadFunctor : ThreadFunc +{ + ThreadFunctor(T functor) : m_functor(functor) {} + virtual void run() {m_functor();} + T m_functor; +}; + +// Specialization using a functor (including free functions) with one argument +template +struct ThreadFunctorWithArg : ThreadFunc +{ + ThreadFunctorWithArg(F function, A arg) : m_function(function), m_arg(arg) {} + virtual void run() {m_function(m_arg);} + F m_function; + A m_arg; +}; + +// Specialization using a member function +template +struct ThreadMemberFunc : ThreadFunc +{ + ThreadMemberFunc(void(C::*function)(), C* object) : m_function(function), m_object(object) {} + virtual void run() {(m_object->*m_function)();} + void(C::*m_function)(); + C* m_object; +}; + +} // namespace priv + + +//////////////////////////////////////////////////////////// +template +Thread::Thread(F functor) : +m_impl (NULL), +m_entryPoint(new priv::ThreadFunctor(functor)) +{ +} + + +//////////////////////////////////////////////////////////// +template +Thread::Thread(F function, A argument) : +m_impl (NULL), +m_entryPoint(new priv::ThreadFunctorWithArg(function, argument)) +{ +} + + +//////////////////////////////////////////////////////////// +template +Thread::Thread(void(C::*function)(), C* object) : +m_impl (NULL), +m_entryPoint(new priv::ThreadMemberFunc(function, object)) +{ +} diff --git a/src/include/SFML/include/SFML/System/ThreadLocal.hpp b/src/include/SFML/include/SFML/System/ThreadLocal.hpp new file mode 100644 index 0000000..8a8a242 --- /dev/null +++ b/src/include/SFML/include/SFML/System/ThreadLocal.hpp @@ -0,0 +1,103 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_THREADLOCAL_HPP +#define SFML_THREADLOCAL_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +namespace priv +{ + class ThreadLocalImpl; +} + +//////////////////////////////////////////////////////////// +/// \brief Defines variables with thread-local storage +/// +//////////////////////////////////////////////////////////// +class SFML_SYSTEM_API ThreadLocal : NonCopyable +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// \param value Optional value to initalize the variable + /// + //////////////////////////////////////////////////////////// + ThreadLocal(void* value = NULL); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~ThreadLocal(); + + //////////////////////////////////////////////////////////// + /// \brief Set the thread-specific value of the variable + /// + /// \param value Value of the variable for the current thread + /// + //////////////////////////////////////////////////////////// + void setValue(void* value); + + //////////////////////////////////////////////////////////// + /// \brief Retrieve the thread-specific value of the variable + /// + /// \return Value of the variable for the current thread + /// + //////////////////////////////////////////////////////////// + void* getValue() const; + +private : + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + priv::ThreadLocalImpl* m_impl; ///< Pointer to the OS specific implementation +}; + +} // namespace sf + + +#endif // SFML_THREADLOCAL_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::ThreadLocal +/// \ingroup system +/// +/// This class manipulates void* parameters and thus is not +/// appropriate for strongly-typed variables. You should rather +/// use the sf::ThreadLocalPtr template class. +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/System/ThreadLocalPtr.hpp b/src/include/SFML/include/SFML/System/ThreadLocalPtr.hpp new file mode 100644 index 0000000..c03ba18 --- /dev/null +++ b/src/include/SFML/include/SFML/System/ThreadLocalPtr.hpp @@ -0,0 +1,158 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_THREADLOCALPTR_HPP +#define SFML_THREADLOCALPTR_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Pointer to a thread-local variable +/// +//////////////////////////////////////////////////////////// +template +class ThreadLocalPtr : private ThreadLocal +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// \param value Optional value to initalize the variable + /// + //////////////////////////////////////////////////////////// + ThreadLocalPtr(T* value = NULL); + + //////////////////////////////////////////////////////////// + /// \brief Overload of unary operator * + /// + /// Like raw pointers, applying the * operator returns a + /// reference to the pointed object. + /// + /// \return Reference to the pointed object + /// + //////////////////////////////////////////////////////////// + T& operator *() const; + + //////////////////////////////////////////////////////////// + /// \brief Overload of operator -> + /// + /// Like raw pointers, applying the -> operator returns the + /// pointed object. + /// + /// \return Pointed object + /// + //////////////////////////////////////////////////////////// + T* operator ->() const; + + //////////////////////////////////////////////////////////// + /// \brief Cast operator to implicitely convert the + /// pointer to its raw pointer type (T*) + /// + /// \return Pointer to the actual object + /// + //////////////////////////////////////////////////////////// + operator T*() const; + + //////////////////////////////////////////////////////////// + /// \brief Assignment operator for a raw pointer parameter + /// + /// \param value Pointer to assign + /// + /// \return Reference to self + /// + //////////////////////////////////////////////////////////// + ThreadLocalPtr& operator =(T* value); + + //////////////////////////////////////////////////////////// + /// \brief Assignment operator for a ThreadLocalPtr parameter + /// + /// \param right ThreadLocalPtr to assign + /// + /// \return Reference to self + /// + //////////////////////////////////////////////////////////// + ThreadLocalPtr& operator =(const ThreadLocalPtr& right); +}; + +} // namespace sf + +#include + + +#endif // SFML_THREADLOCALPTR_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::ThreadLocalPtr +/// \ingroup system +/// +/// sf::ThreadLocalPtr is a type-safe wrapper for storing +/// pointers to thread-local variables. A thread-local +/// variable holds a different value for each different +/// thread, unlike normal variable that are shared. +/// +/// Its usage is completely transparent, so that it is similar +/// to manipulating the raw pointer directly (like any smart pointer). +/// +/// Usage example: +/// \code +/// MyClass object1; +/// MyClass object2; +/// sf::ThreadLocalPtr objectPtr; +/// +/// void thread1() +/// { +/// objectPtr = &object1; // doesn't impact thread2 +/// ... +/// } +/// +/// void thread2() +/// { +/// objectPtr = &object2; // doesn't impact thread1 +/// ... +/// } +/// +/// int main() +/// { +/// // Create and launch the two threads +/// sf::Thread t1(&thread1); +/// sf::Thread t2(&thread2); +/// t1.launch(); +/// t2.launch(); +/// +/// return 0; +/// } +/// \endcode +/// +/// ThreadLocalPtr is designed for internal use; however you +/// can use it if you feel like it fits well your implementation. +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/System/ThreadLocalPtr.inl b/src/include/SFML/include/SFML/System/ThreadLocalPtr.inl new file mode 100644 index 0000000..8678ace --- /dev/null +++ b/src/include/SFML/include/SFML/System/ThreadLocalPtr.inl @@ -0,0 +1,77 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2012 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + + +namespace sf +{ +//////////////////////////////////////////////////////////// +template +ThreadLocalPtr::ThreadLocalPtr(T* value) : +ThreadLocal(value) +{ +} + + +//////////////////////////////////////////////////////////// +template +T& ThreadLocalPtr::operator *() const +{ + return *static_cast(getValue()); +} + + +//////////////////////////////////////////////////////////// +template +T* ThreadLocalPtr::operator ->() const +{ + return static_cast(getValue()); +} + + +//////////////////////////////////////////////////////////// +template +ThreadLocalPtr::operator T*() const +{ + return static_cast(getValue()); +} + + +//////////////////////////////////////////////////////////// +template +ThreadLocalPtr& ThreadLocalPtr::operator =(T* value) +{ + setValue(value); + return *this; +} + + +//////////////////////////////////////////////////////////// +template +ThreadLocalPtr& ThreadLocalPtr::operator =(const ThreadLocalPtr& right) +{ + setValue(right.getValue()); + return *this; +} + +} // namespace sf diff --git a/src/include/SFML/include/SFML/System/Time.hpp b/src/include/SFML/include/SFML/System/Time.hpp new file mode 100644 index 0000000..5037f52 --- /dev/null +++ b/src/include/SFML/include/SFML/System/Time.hpp @@ -0,0 +1,452 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_TIME_HPP +#define SFML_TIME_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Represents a time value +/// +//////////////////////////////////////////////////////////// +class SFML_SYSTEM_API Time +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Sets the time value to zero. + /// + //////////////////////////////////////////////////////////// + Time(); + + //////////////////////////////////////////////////////////// + /// \brief Return the time value as a number of seconds + /// + /// \return Time in seconds + /// + /// \see asMilliseconds, asMicroseconds + /// + //////////////////////////////////////////////////////////// + float asSeconds() const; + + //////////////////////////////////////////////////////////// + /// \brief Return the time value as a number of milliseconds + /// + /// \return Time in milliseconds + /// + /// \see asSeconds, asMicroseconds + /// + //////////////////////////////////////////////////////////// + Int32 asMilliseconds() const; + + //////////////////////////////////////////////////////////// + /// \brief Return the time value as a number of microseconds + /// + /// \return Time in microseconds + /// + /// \see asSeconds, asMilliseconds + /// + //////////////////////////////////////////////////////////// + Int64 asMicroseconds() const; + + //////////////////////////////////////////////////////////// + // Static member data + //////////////////////////////////////////////////////////// + static const Time Zero; ///< Predefined "zero" time value + +private : + + friend SFML_SYSTEM_API Time seconds(float); + friend SFML_SYSTEM_API Time milliseconds(Int32); + friend SFML_SYSTEM_API Time microseconds(Int64); + + //////////////////////////////////////////////////////////// + /// \brief Construct from a number of microseconds + /// + /// This function is internal. To construct time values, + /// use sf::seconds, sf::milliseconds or sf::microseconds instead. + /// + /// \param microseconds Number of microseconds + /// + //////////////////////////////////////////////////////////// + explicit Time(Int64 microseconds); + +private : + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + Int64 m_microseconds; ///< Time value stored as microseconds +}; + +//////////////////////////////////////////////////////////// +/// \relates Time +/// \brief Construct a time value from a number of seconds +/// +/// \param amount Number of seconds +/// +/// \return Time value constructed from the amount of seconds +/// +/// \see milliseconds, microseconds +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API Time seconds(float amount); + +//////////////////////////////////////////////////////////// +/// \relates Time +/// \brief Construct a time value from a number of milliseconds +/// +/// \param amount Number of milliseconds +/// +/// \return Time value constructed from the amount of milliseconds +/// +/// \see seconds, microseconds +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API Time milliseconds(Int32 amount); + +//////////////////////////////////////////////////////////// +/// \relates Time +/// \brief Construct a time value from a number of microseconds +/// +/// \param amount Number of microseconds +/// +/// \return Time value constructed from the amount of microseconds +/// +/// \see seconds, milliseconds +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API Time microseconds(Int64 amount); + +//////////////////////////////////////////////////////////// +/// \relates Time +/// \brief Overload of == operator to compare two time values +/// +/// \param left Left operand (a time) +/// \param right Right operand (a time) +/// +/// \return True if both time values are equal +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API bool operator ==(Time left, Time right); + +//////////////////////////////////////////////////////////// +/// \relates Time +/// \brief Overload of != operator to compare two time values +/// +/// \param left Left operand (a time) +/// \param right Right operand (a time) +/// +/// \return True if both time values are different +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API bool operator !=(Time left, Time right); + +//////////////////////////////////////////////////////////// +/// \relates Time +/// \brief Overload of < operator to compare two time values +/// +/// \param left Left operand (a time) +/// \param right Right operand (a time) +/// +/// \return True if \a left is lesser than \a right +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API bool operator <(Time left, Time right); + +//////////////////////////////////////////////////////////// +/// \relates Time +/// \brief Overload of > operator to compare two time values +/// +/// \param left Left operand (a time) +/// \param right Right operand (a time) +/// +/// \return True if \a left is greater than \a right +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API bool operator >(Time left, Time right); + +//////////////////////////////////////////////////////////// +/// \relates Time +/// \brief Overload of <= operator to compare two time values +/// +/// \param left Left operand (a time) +/// \param right Right operand (a time) +/// +/// \return True if \a left is lesser or equal than \a right +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API bool operator <=(Time left, Time right); + +//////////////////////////////////////////////////////////// +/// \relates Time +/// \brief Overload of >= operator to compare two time values +/// +/// \param left Left operand (a time) +/// \param right Right operand (a time) +/// +/// \return True if \a left is greater or equal than \a right +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API bool operator >=(Time left, Time right); + +//////////////////////////////////////////////////////////// +/// \relates Time +/// \brief Overload of unary - operator to negate a time value +/// +/// \param right Right operand (a time) +/// +/// \return Opposite of the time value +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API Time operator -(Time right); + +//////////////////////////////////////////////////////////// +/// \relates Time +/// \brief Overload of binary + operator to add two time values +/// +/// \param left Left operand (a time) +/// \param right Right operand (a time) +/// +/// \return Sum of the two times values +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API Time operator +(Time left, Time right); + +//////////////////////////////////////////////////////////// +/// \relates Time +/// \brief Overload of binary += operator to add/assign two time values +/// +/// \param left Left operand (a time) +/// \param right Right operand (a time) +/// +/// \return Sum of the two times values +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API Time& operator +=(Time& left, Time right); + +//////////////////////////////////////////////////////////// +/// \relates Time +/// \brief Overload of binary - operator to subtract two time values +/// +/// \param left Left operand (a time) +/// \param right Right operand (a time) +/// +/// \return Difference of the two times values +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API Time operator -(Time left, Time right); + +//////////////////////////////////////////////////////////// +/// \relates Time +/// \brief Overload of binary -= operator to subtract/assign two time values +/// +/// \param left Left operand (a time) +/// \param right Right operand (a time) +/// +/// \return Difference of the two times values +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API Time& operator -=(Time& left, Time right); + +//////////////////////////////////////////////////////////// +/// \relates Time +/// \brief Overload of binary * operator to scale a time value +/// +/// \param left Left operand (a time) +/// \param right Right operand (a number) +/// +/// \return \a left multiplied by \a right +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API Time operator *(Time left, float right); + +//////////////////////////////////////////////////////////// +/// \relates Time +/// \brief Overload of binary * operator to scale a time value +/// +/// \param left Left operand (a time) +/// \param right Right operand (a number) +/// +/// \return \a left multiplied by \a right +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API Time operator *(Time left, Int64 right); + +//////////////////////////////////////////////////////////// +/// \relates Time +/// \brief Overload of binary * operator to scale a time value +/// +/// \param left Left operand (a number) +/// \param right Right operand (a time) +/// +/// \return \a left multiplied by \a right +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API Time operator *(float left, Time right); + +//////////////////////////////////////////////////////////// +/// \relates Time +/// \brief Overload of binary * operator to scale a time value +/// +/// \param left Left operand (a number) +/// \param right Right operand (a time) +/// +/// \return \a left multiplied by \a right +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API Time operator *(Int64 left, Time right); + +//////////////////////////////////////////////////////////// +/// \relates Time +/// \brief Overload of binary *= operator to scale/assign a time value +/// +/// \param left Left operand (a time) +/// \param right Right operand (a number) +/// +/// \return \a left multiplied by \a right +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API Time& operator *=(Time& left, float right); + +//////////////////////////////////////////////////////////// +/// \relates Time +/// \brief Overload of binary *= operator to scale/assign a time value +/// +/// \param left Left operand (a time) +/// \param right Right operand (a number) +/// +/// \return \a left multiplied by \a right +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API Time& operator *=(Time& left, Int64 right); + +//////////////////////////////////////////////////////////// +/// \relates Time +/// \brief Overload of binary / operator to scale a time value +/// +/// \param left Left operand (a time) +/// \param right Right operand (a number) +/// +/// \return \a left divided by \a right +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API Time operator /(Time left, float right); + +//////////////////////////////////////////////////////////// +/// \relates Time +/// \brief Overload of binary / operator to scale a time value +/// +/// \param left Left operand (a time) +/// \param right Right operand (a number) +/// +/// \return \a left divided by \a right +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API Time operator /(Time left, Int64 right); + +//////////////////////////////////////////////////////////// +/// \relates Time +/// \brief Overload of binary /= operator to scale/assign a time value +/// +/// \param left Left operand (a time) +/// \param right Right operand (a number) +/// +/// \return \a left divided by \a right +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API Time& operator /=(Time& left, float right); + +//////////////////////////////////////////////////////////// +/// \relates Time +/// \brief Overload of binary /= operator to scale/assign a time value +/// +/// \param left Left operand (a time) +/// \param right Right operand (a number) +/// +/// \return \a left divided by \a right +/// +//////////////////////////////////////////////////////////// +SFML_SYSTEM_API Time& operator /=(Time& left, Int64 right); + +} // namespace sf + + +#endif // SFML_TIME_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Time +/// \ingroup system +/// +/// sf::Time encapsulates a time value in a flexible way. +/// It allows to define a time value either as a number of +/// seconds, milliseconds or microseconds. It also works the +/// other way round: you can read a time value as either +/// a number of seconds, milliseconds or microseconds. +/// +/// By using such a flexible interface, the API doesn't +/// impose any fixed type or resolution for time values, +/// and let the user choose its own favorite representation. +/// +/// Time values support the usual mathematical operations: +/// you can add or subtract two times, multiply or divide +/// a time by a number, compare two times, etc. +/// +/// Since they represent a time span and not an absolute time +/// value, times can also be negative. +/// +/// Usage example: +/// \code +/// sf::Time t1 = sf::seconds(0.1f); +/// Int32 milli = t1.asMilliseconds(); // 100 +/// +/// sf::Time t2 = sf::milliseconds(30); +/// Int64 micro = t2.asMicroseconds(); // 30000 +/// +/// sf::Time t3 = sf::microseconds(-800000); +/// float sec = t3.asSeconds(); // -0.8 +/// \endcode +/// +/// \code +/// void update(sf::Time elapsed) +/// { +/// position += speed * elapsed.asSeconds(); +/// } +/// +/// update(sf::milliseconds(100)); +/// \endcode +/// +/// \see sf::Clock +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/System/Utf.hpp b/src/include/SFML/include/SFML/System/Utf.hpp new file mode 100644 index 0000000..0b965dc --- /dev/null +++ b/src/include/SFML/include/SFML/System/Utf.hpp @@ -0,0 +1,763 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_UTF_HPP +#define SFML_UTF_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include + + +namespace sf +{ +template +class Utf; + +//////////////////////////////////////////////////////////// +/// \brief Specialization of the Utf template for UTF-8 +/// +//////////////////////////////////////////////////////////// +template <> +class Utf<8> +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Decode a single UTF-8 character + /// + /// Decoding a character means finding its unique 32-bits + /// code (called the codepoint) in the Unicode standard. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Codepoint of the decoded UTF-8 character + /// \param replacement Replacement character to use in case the UTF-8 sequence is invalid + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template + static In decode(In begin, In end, Uint32& output, Uint32 replacement = 0); + + //////////////////////////////////////////////////////////// + /// \brief Encode a single UTF-8 character + /// + /// Encoding a character means converting a unique 32-bits + /// code (called the codepoint) in the target encoding, UTF-8. + /// + /// \param input Codepoint to encode as UTF-8 + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to UTF-8 (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out encode(Uint32 input, Out output, Uint8 replacement = 0); + + //////////////////////////////////////////////////////////// + /// \brief Advance to the next UTF-8 character + /// + /// This function is necessary for multi-elements encodings, as + /// a single character may use more than 1 storage element. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template + static In next(In begin, In end); + + //////////////////////////////////////////////////////////// + /// \brief Count the number of characters of a UTF-8 sequence + /// + /// This function is necessary for multi-elements encodings, as + /// a single character may use more than 1 storage element, thus the + /// total size can be different from (begin - end). + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template + static std::size_t count(In begin, In end); + + //////////////////////////////////////////////////////////// + /// \brief Convert an ANSI characters range to UTF-8 + /// + /// The current global locale will be used by default, unless you + /// pass a custom one in the \a locale parameter. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param locale Locale to use for conversion + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out fromAnsi(In begin, In end, Out output, const std::locale& locale = std::locale()); + + //////////////////////////////////////////////////////////// + /// \brief Convert a wide characters range to UTF-8 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out fromWide(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-8 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out fromLatin1(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-8 characters range to ANSI characters + /// + /// The current global locale will be used by default, unless you + /// pass a custom one in the \a locale parameter. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them) + /// \param locale Locale to use for conversion + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toAnsi(In begin, In end, Out output, char replacement = 0, const std::locale& locale = std::locale()); + + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-8 characters range to wide characters + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toWide(In begin, In end, Out output, wchar_t replacement = 0); + + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-8 characters range to latin-1 (ISO-5589-1) characters + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toLatin1(In begin, In end, Out output, char replacement = 0); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-8 characters range to UTF-8 + /// + /// This functions does nothing more than a direct copy; + /// it is defined only to provide the same interface as other + /// specializations of the sf::Utf<> template, and allow + /// generic code to be written on top of it. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toUtf8(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-8 characters range to UTF-16 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toUtf16(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-8 characters range to UTF-32 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toUtf32(In begin, In end, Out output); +}; + +//////////////////////////////////////////////////////////// +/// \brief Specialization of the Utf template for UTF-16 +/// +//////////////////////////////////////////////////////////// +template <> +class Utf<16> +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Decode a single UTF-16 character + /// + /// Decoding a character means finding its unique 32-bits + /// code (called the codepoint) in the Unicode standard. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Codepoint of the decoded UTF-16 character + /// \param replacement Replacement character to use in case the UTF-8 sequence is invalid + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template + static In decode(In begin, In end, Uint32& output, Uint32 replacement = 0); + + //////////////////////////////////////////////////////////// + /// \brief Encode a single UTF-16 character + /// + /// Encoding a character means converting a unique 32-bits + /// code (called the codepoint) in the target encoding, UTF-16. + /// + /// \param input Codepoint to encode as UTF-16 + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to UTF-16 (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out encode(Uint32 input, Out output, Uint16 replacement = 0); + + //////////////////////////////////////////////////////////// + /// \brief Advance to the next UTF-16 character + /// + /// This function is necessary for multi-elements encodings, as + /// a single character may use more than 1 storage element. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template + static In next(In begin, In end); + + //////////////////////////////////////////////////////////// + /// \brief Count the number of characters of a UTF-16 sequence + /// + /// This function is necessary for multi-elements encodings, as + /// a single character may use more than 1 storage element, thus the + /// total size can be different from (begin - end). + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template + static std::size_t count(In begin, In end); + + //////////////////////////////////////////////////////////// + /// \brief Convert an ANSI characters range to UTF-16 + /// + /// The current global locale will be used by default, unless you + /// pass a custom one in the \a locale parameter. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param locale Locale to use for conversion + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out fromAnsi(In begin, In end, Out output, const std::locale& locale = std::locale()); + + //////////////////////////////////////////////////////////// + /// \brief Convert a wide characters range to UTF-16 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out fromWide(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-16 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out fromLatin1(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-16 characters range to ANSI characters + /// + /// The current global locale will be used by default, unless you + /// pass a custom one in the \a locale parameter. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them) + /// \param locale Locale to use for conversion + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toAnsi(In begin, In end, Out output, char replacement = 0, const std::locale& locale = std::locale()); + + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-16 characters range to wide characters + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toWide(In begin, In end, Out output, wchar_t replacement = 0); + + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-16 characters range to latin-1 (ISO-5589-1) characters + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toLatin1(In begin, In end, Out output, char replacement = 0); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-16 characters range to UTF-8 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toUtf8(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-16 characters range to UTF-16 + /// + /// This functions does nothing more than a direct copy; + /// it is defined only to provide the same interface as other + /// specializations of the sf::Utf<> template, and allow + /// generic code to be written on top of it. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toUtf16(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-16 characters range to UTF-32 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toUtf32(In begin, In end, Out output); +}; + +//////////////////////////////////////////////////////////// +/// \brief Specialization of the Utf template for UTF-32 +/// +//////////////////////////////////////////////////////////// +template <> +class Utf<32> +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Decode a single UTF-32 character + /// + /// Decoding a character means finding its unique 32-bits + /// code (called the codepoint) in the Unicode standard. + /// For UTF-32, the character value is the same as the codepoint. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Codepoint of the decoded UTF-32 character + /// \param replacement Replacement character to use in case the UTF-8 sequence is invalid + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template + static In decode(In begin, In end, Uint32& output, Uint32 replacement = 0); + + //////////////////////////////////////////////////////////// + /// \brief Encode a single UTF-32 character + /// + /// Encoding a character means converting a unique 32-bits + /// code (called the codepoint) in the target encoding, UTF-32. + /// For UTF-32, the codepoint is the same as the character value. + /// + /// \param input Codepoint to encode as UTF-32 + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to UTF-32 (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out encode(Uint32 input, Out output, Uint32 replacement = 0); + + //////////////////////////////////////////////////////////// + /// \brief Advance to the next UTF-32 character + /// + /// This function is trivial for UTF-32, which can store + /// every character in a single storage element. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template + static In next(In begin, In end); + + //////////////////////////////////////////////////////////// + /// \brief Count the number of characters of a UTF-32 sequence + /// + /// This function is trivial for UTF-32, which can store + /// every character in a single storage element. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// + /// \return Iterator pointing to one past the last read element of the input sequence + /// + //////////////////////////////////////////////////////////// + template + static std::size_t count(In begin, In end); + + //////////////////////////////////////////////////////////// + /// \brief Convert an ANSI characters range to UTF-32 + /// + /// The current global locale will be used by default, unless you + /// pass a custom one in the \a locale parameter. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param locale Locale to use for conversion + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out fromAnsi(In begin, In end, Out output, const std::locale& locale = std::locale()); + + //////////////////////////////////////////////////////////// + /// \brief Convert a wide characters range to UTF-32 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out fromWide(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-32 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out fromLatin1(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-32 characters range to ANSI characters + /// + /// The current global locale will be used by default, unless you + /// pass a custom one in the \a locale parameter. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them) + /// \param locale Locale to use for conversion + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toAnsi(In begin, In end, Out output, char replacement = 0, const std::locale& locale = std::locale()); + + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-32 characters range to wide characters + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toWide(In begin, In end, Out output, wchar_t replacement = 0); + + //////////////////////////////////////////////////////////// + /// \brief Convert an UTF-16 characters range to latin-1 (ISO-5589-1) characters + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toLatin1(In begin, In end, Out output, char replacement = 0); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-32 characters range to UTF-8 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toUtf8(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-32 characters range to UTF-16 + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toUtf16(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Convert a UTF-32 characters range to UTF-32 + /// + /// This functions does nothing more than a direct copy; + /// it is defined only to provide the same interface as other + /// specializations of the sf::Utf<> template, and allow + /// generic code to be written on top of it. + /// + /// \param begin Iterator pointing to the beginning of the input sequence + /// \param end Iterator pointing to the end of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out toUtf32(In begin, In end, Out output); + + //////////////////////////////////////////////////////////// + /// \brief Decode a single ANSI character to UTF-32 + /// + /// This function does not exist in other specializations + /// of sf::Utf<>, it is defined for convenience (it is used by + /// several other conversion functions). + /// + /// \param input Input ANSI character + /// \param locale Locale to use for conversion + /// + /// \return Converted character + /// + //////////////////////////////////////////////////////////// + template + static Uint32 decodeAnsi(In input, const std::locale& locale = std::locale()); + + //////////////////////////////////////////////////////////// + /// \brief Decode a single wide character to UTF-32 + /// + /// This function does not exist in other specializations + /// of sf::Utf<>, it is defined for convenience (it is used by + /// several other conversion functions). + /// + /// \param input Input wide character + /// + /// \return Converted character + /// + //////////////////////////////////////////////////////////// + template + static Uint32 decodeWide(In input); + + //////////////////////////////////////////////////////////// + /// \brief Encode a single UTF-32 character to ANSI + /// + /// This function does not exist in other specializations + /// of sf::Utf<>, it is defined for convenience (it is used by + /// several other conversion functions). + /// + /// \param codepoint Iterator pointing to the beginning of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement if the input character is not convertible to ANSI (use 0 to skip it) + /// \param locale Locale to use for conversion + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out encodeAnsi(Uint32 codepoint, Out output, char replacement = 0, const std::locale& locale = std::locale()); + + //////////////////////////////////////////////////////////// + /// \brief Encode a single UTF-32 character to wide + /// + /// This function does not exist in other specializations + /// of sf::Utf<>, it is defined for convenience (it is used by + /// several other conversion functions). + /// + /// \param codepoint Iterator pointing to the beginning of the input sequence + /// \param output Iterator pointing to the beginning of the output sequence + /// \param replacement Replacement if the input character is not convertible to wide (use 0 to skip it) + /// + /// \return Iterator to the end of the output sequence which has been written + /// + //////////////////////////////////////////////////////////// + template + static Out encodeWide(Uint32 codepoint, Out output, wchar_t replacement = 0); +}; + +#include + +// Make typedefs to get rid of the template syntax +typedef Utf<8> Utf8; +typedef Utf<16> Utf16; +typedef Utf<32> Utf32; + +} // namespace sf + + +#endif // SFML_UTF_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Utf +/// \ingroup system +/// +/// Utility class providing generic functions for UTF conversions. +/// +/// sf::Utf is a low-level, generic interface for counting, iterating, +/// encoding and decoding Unicode characters and strings. It is able +/// to handle ANSI, wide, latin-1, UTF-8, UTF-16 and UTF-32 encodings. +/// +/// sf::Utf functions are all static, these classes are not meant to +/// be instanciated. All the functions are template, so that you +/// can use any character / string type for a given encoding. +/// +/// It has 3 specializations: +/// \li sf::Utf<8> (typedef'd to sf::Utf8) +/// \li sf::Utf<16> (typedef'd to sf::Utf16) +/// \li sf::Utf<32> (typedef'd to sf::Utf32) +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/System/Utf.inl b/src/include/SFML/include/SFML/System/Utf.inl new file mode 100644 index 0000000..bf897df --- /dev/null +++ b/src/include/SFML/include/SFML/System/Utf.inl @@ -0,0 +1,752 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2012 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////// +// References : +// +// http://www.unicode.org/ +// http://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.c +// http://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.h +// http://people.w3.org/rishida/scripts/uniview/conversion +// +//////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////// +template +In Utf<8>::decode(In begin, In end, Uint32& output, Uint32 replacement) +{ + // Some useful precomputed data + static const int trailing[256] = + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5 + }; + static const Uint32 offsets[6] = + { + 0x00000000, 0x00003080, 0x000E2080, 0x03C82080, 0xFA082080, 0x82082080 + }; + + // decode the character + int trailingBytes = trailing[static_cast(*begin)]; + if (begin + trailingBytes < end) + { + output = 0; + switch (trailingBytes) + { + case 5 : output += static_cast(*begin++); output <<= 6; + case 4 : output += static_cast(*begin++); output <<= 6; + case 3 : output += static_cast(*begin++); output <<= 6; + case 2 : output += static_cast(*begin++); output <<= 6; + case 1 : output += static_cast(*begin++); output <<= 6; + case 0 : output += static_cast(*begin++); + } + output -= offsets[trailingBytes]; + } + else + { + // Incomplete character + begin = end; + output = replacement; + } + + return begin; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<8>::encode(Uint32 input, Out output, Uint8 replacement) +{ + // Some useful precomputed data + static const Uint8 firstBytes[7] = + { + 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC + }; + + // encode the character + if ((input > 0x0010FFFF) || ((input >= 0xD800) && (input <= 0xDBFF))) + { + // Invalid character + if (replacement) + *output++ = replacement; + } + else + { + // Valid character + + // Get the number of bytes to write + std::size_t bytestoWrite = 1; + if (input < 0x80) bytestoWrite = 1; + else if (input < 0x800) bytestoWrite = 2; + else if (input < 0x10000) bytestoWrite = 3; + else if (input <= 0x0010FFFF) bytestoWrite = 4; + + // Extract the bytes to write + Uint8 bytes[4]; + switch (bytestoWrite) + { + case 4 : bytes[3] = static_cast((input | 0x80) & 0xBF); input >>= 6; + case 3 : bytes[2] = static_cast((input | 0x80) & 0xBF); input >>= 6; + case 2 : bytes[1] = static_cast((input | 0x80) & 0xBF); input >>= 6; + case 1 : bytes[0] = static_cast (input | firstBytes[bytestoWrite]); + } + + // Add them to the output + output = std::copy(bytes, bytes + bytestoWrite, output); + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +In Utf<8>::next(In begin, In end) +{ + Uint32 codepoint; + return decode(begin, end, codepoint); +} + + +//////////////////////////////////////////////////////////// +template +std::size_t Utf<8>::count(In begin, In end) +{ + std::size_t length = 0; + while (begin < end) + { + begin = next(begin, end); + ++length; + } + + return length; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<8>::fromAnsi(In begin, In end, Out output, const std::locale& locale) +{ + while (begin < end) + { + Uint32 codepoint = Utf<32>::decodeAnsi(*begin++, locale); + output = encode(codepoint, output); + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<8>::fromWide(In begin, In end, Out output) +{ + while (begin < end) + { + Uint32 codepoint = Utf<32>::decodeWide(*begin++); + output = encode(codepoint, output); + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<8>::fromLatin1(In begin, In end, Out output) +{ + // Latin-1 is directly compatible with Unicode encodings, + // and can thus be treated as (a sub-range of) UTF-32 + while (begin < end) + output = encode(*begin++, output); + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<8>::toAnsi(In begin, In end, Out output, char replacement, const std::locale& locale) +{ + while (begin < end) + { + Uint32 codepoint; + begin = decode(begin, end, codepoint); + output = Utf<32>::encodeAnsi(codepoint, output, replacement, locale); + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<8>::toWide(In begin, In end, Out output, wchar_t replacement) +{ + while (begin < end) + { + Uint32 codepoint; + begin = decode(begin, end, codepoint); + output = Utf<32>::encodeWide(codepoint, output, replacement); + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<8>::toLatin1(In begin, In end, Out output, char replacement) +{ + // Latin-1 is directly compatible with Unicode encodings, + // and can thus be treated as (a sub-range of) UTF-32 + while (begin < end) + { + Uint32 codepoint; + begin = decode(begin, end, codepoint); + *output++ = codepoint < 256 ? static_cast(codepoint) : replacement; + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<8>::toUtf8(In begin, In end, Out output) +{ + return std::copy(begin, end, output); +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<8>::toUtf16(In begin, In end, Out output) +{ + while (begin < end) + { + Uint32 codepoint; + begin = decode(begin, end, codepoint); + output = Utf<16>::encode(codepoint, output); + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<8>::toUtf32(In begin, In end, Out output) +{ + while (begin < end) + { + Uint32 codepoint; + begin = decode(begin, end, codepoint); + *output++ = codepoint; + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +In Utf<16>::decode(In begin, In end, Uint32& output, Uint32 replacement) +{ + Uint16 first = *begin++; + + // If it's a surrogate pair, first convert to a single UTF-32 character + if ((first >= 0xD800) && (first <= 0xDBFF)) + { + if (begin < end) + { + Uint32 second = *begin++; + if ((second >= 0xDC00) && (second <= 0xDFFF)) + { + // The second element is valid: convert the two elements to a UTF-32 character + output = static_cast(((first - 0xD800) << 10) + (second - 0xDC00) + 0x0010000); + } + else + { + // Invalid character + output = replacement; + } + } + else + { + // Invalid character + begin = end; + output = replacement; + } + } + else + { + // We can make a direct copy + output = first; + } + + return begin; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<16>::encode(Uint32 input, Out output, Uint16 replacement) +{ + if (input < 0xFFFF) + { + // The character can be copied directly, we just need to check if it's in the valid range + if ((input >= 0xD800) && (input <= 0xDFFF)) + { + // Invalid character (this range is reserved) + if (replacement) + *output++ = replacement; + } + else + { + // Valid character directly convertible to a single UTF-16 character + *output++ = static_cast(input); + } + } + else if (input > 0x0010FFFF) + { + // Invalid character (greater than the maximum unicode value) + if (replacement) + *output++ = replacement; + } + else + { + // The input character will be converted to two UTF-16 elements + input -= 0x0010000; + *output++ = static_cast((input >> 10) + 0xD800); + *output++ = static_cast((input & 0x3FFUL) + 0xDC00); + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +In Utf<16>::next(In begin, In end) +{ + Uint32 codepoint; + return decode(begin, end, codepoint); +} + + +//////////////////////////////////////////////////////////// +template +std::size_t Utf<16>::count(In begin, In end) +{ + std::size_t length = 0; + while (begin < end) + { + begin = next(begin, end); + ++length; + } + + return length; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<16>::fromAnsi(In begin, In end, Out output, const std::locale& locale) +{ + while (begin < end) + { + Uint32 codepoint = Utf<32>::decodeAnsi(*begin++, locale); + output = encode(codepoint, output); + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<16>::fromWide(In begin, In end, Out output) +{ + while (begin < end) + { + Uint32 codepoint = Utf<32>::decodeWide(*begin++); + output = encode(codepoint, output); + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<16>::fromLatin1(In begin, In end, Out output) +{ + // Latin-1 is directly compatible with Unicode encodings, + // and can thus be treated as (a sub-range of) UTF-32 + return std::copy(begin, end, output); +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<16>::toAnsi(In begin, In end, Out output, char replacement, const std::locale& locale) +{ + while (begin < end) + { + Uint32 codepoint; + begin = decode(begin, end, codepoint); + output = Utf<32>::encodeAnsi(codepoint, output, replacement, locale); + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<16>::toWide(In begin, In end, Out output, wchar_t replacement) +{ + while (begin < end) + { + Uint32 codepoint; + begin = decode(begin, end, codepoint); + output = Utf<32>::encodeWide(codepoint, output, replacement); + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<16>::toLatin1(In begin, In end, Out output, char replacement) +{ + // Latin-1 is directly compatible with Unicode encodings, + // and can thus be treated as (a sub-range of) UTF-32 + while (begin < end) + { + *output++ = *begin < 256 ? static_cast(*begin) : replacement; + begin++; + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<16>::toUtf8(In begin, In end, Out output) +{ + while (begin < end) + { + Uint32 codepoint; + begin = decode(begin, end, codepoint); + output = Utf<8>::encode(codepoint, output); + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<16>::toUtf16(In begin, In end, Out output) +{ + return std::copy(begin, end, output); +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<16>::toUtf32(In begin, In end, Out output) +{ + while (begin < end) + { + Uint32 codepoint; + begin = decode(begin, end, codepoint); + *output++ = codepoint; + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +In Utf<32>::decode(In begin, In /*end*/, Uint32& output, Uint32 /*replacement*/) +{ + output = *begin++; + return begin; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::encode(Uint32 input, Out output, Uint32 /*replacement*/) +{ + *output++ = input; + return output; +} + + +//////////////////////////////////////////////////////////// +template +In Utf<32>::next(In begin, In /*end*/) +{ + return ++begin; +} + + +//////////////////////////////////////////////////////////// +template +std::size_t Utf<32>::count(In begin, In end) +{ + return begin - end; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::fromAnsi(In begin, In end, Out output, const std::locale& locale) +{ + while (begin < end) + *output++ = decodeAnsi(*begin++, locale); + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::fromWide(In begin, In end, Out output) +{ + while (begin < end) + *output++ = decodeWide(*begin++); + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::fromLatin1(In begin, In end, Out output) +{ + // Latin-1 is directly compatible with Unicode encodings, + // and can thus be treated as (a sub-range of) UTF-32 + return std::copy(begin, end, output); +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::toAnsi(In begin, In end, Out output, char replacement, const std::locale& locale) +{ + while (begin < end) + output = encodeAnsi(*begin++, output, replacement, locale); + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::toWide(In begin, In end, Out output, wchar_t replacement) +{ + while (begin < end) + output = encodeWide(*begin++, output, replacement); + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::toLatin1(In begin, In end, Out output, char replacement) +{ + // Latin-1 is directly compatible with Unicode encodings, + // and can thus be treated as (a sub-range of) UTF-32 + while (begin < end) + { + *output++ = *begin < 256 ? static_cast(*begin) : replacement; + begin++; + } + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::toUtf8(In begin, In end, Out output) +{ + while (begin < end) + output = Utf<8>::encode(*begin++, output); + + return output; +} + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::toUtf16(In begin, In end, Out output) +{ + while (begin < end) + output = Utf<16>::encode(*begin++, output); + + return output; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::toUtf32(In begin, In end, Out output) +{ + return std::copy(begin, end, output); +} + + +//////////////////////////////////////////////////////////// +template +Uint32 Utf<32>::decodeAnsi(In input, const std::locale& locale) +{ + // On Windows, gcc's standard library (glibc++) has almost + // no support for Unicode stuff. As a consequence, in this + // context we can only use the default locale and ignore + // the one passed as parameter. + + #if defined(SFML_SYSTEM_WINDOWS) && /* if Windows ... */ \ + (defined(__GLIBCPP__) || defined (__GLIBCXX__)) && /* ... and standard library is glibc++ ... */ \ + !(defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) /* ... and STLPort is not used on top of it */ + + (void)locale; // to avoid warnings + + wchar_t character = 0; + mbtowc(&character, &input, 1); + return static_cast(character); + + #else + + // Get the facet of the locale which deals with character conversion + const std::ctype& facet = std::use_facet< std::ctype >(locale); + + // Use the facet to convert each character of the input string + return static_cast(facet.widen(input)); + + #endif +} + + +//////////////////////////////////////////////////////////// +template +Uint32 Utf<32>::decodeWide(In input) +{ + // The encoding of wide characters is not well defined and is left to the system; + // however we can safely assume that it is UCS-2 on Windows and + // UCS-4 on Unix systems. + // In both cases, a simple copy is enough (UCS-2 is a subset of UCS-4, + // and UCS-4 *is* UTF-32). + + return input; +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::encodeAnsi(Uint32 codepoint, Out output, char replacement, const std::locale& locale) +{ + // On Windows, gcc's standard library (glibc++) has almost + // no support for Unicode stuff. As a consequence, in this + // context we can only use the default locale and ignore + // the one passed as parameter. + + #if defined(SFML_SYSTEM_WINDOWS) && /* if Windows ... */ \ + (defined(__GLIBCPP__) || defined (__GLIBCXX__)) && /* ... and standard library is glibc++ ... */ \ + !(defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) /* ... and STLPort is not used on top of it */ + + (void)locale; // to avoid warnings + + char character = 0; + if (wctomb(&character, static_cast(codepoint)) >= 0) + *output++ = character; + else if (replacement) + *output++ = replacement; + + return output; + + #else + + // Get the facet of the locale which deals with character conversion + const std::ctype& facet = std::use_facet< std::ctype >(locale); + + // Use the facet to convert each character of the input string + *output++ = facet.narrow(static_cast(codepoint), replacement); + + return output; + + #endif +} + + +//////////////////////////////////////////////////////////// +template +Out Utf<32>::encodeWide(Uint32 codepoint, Out output, wchar_t replacement) +{ + // The encoding of wide characters is not well defined and is left to the system; + // however we can safely assume that it is UCS-2 on Windows and + // UCS-4 on Unix systems. + // For UCS-2 we need to check if the source characters fits in (UCS-2 is a subset of UCS-4). + // For UCS-4 we can do a direct copy (UCS-4 *is* UTF-32). + + switch (sizeof(wchar_t)) + { + case 4: + { + *output++ = static_cast(codepoint); + break; + } + + default: + { + if ((codepoint <= 0xFFFF) && ((codepoint < 0xD800) || (codepoint > 0xDFFF))) + { + *output++ = static_cast(codepoint); + } + else if (replacement) + { + *output++ = replacement; + } + break; + } + } + + return output; +} diff --git a/src/include/SFML/include/SFML/System/Vector2.hpp b/src/include/SFML/include/SFML/System/Vector2.hpp new file mode 100644 index 0000000..3310633 --- /dev/null +++ b/src/include/SFML/include/SFML/System/Vector2.hpp @@ -0,0 +1,301 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_VECTOR2_HPP +#define SFML_VECTOR2_HPP + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Utility template class for manipulating +/// 2-dimensional vectors +/// +//////////////////////////////////////////////////////////// +template +class Vector2 +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Creates a Vector2(0, 0). + /// + //////////////////////////////////////////////////////////// + Vector2(); + + //////////////////////////////////////////////////////////// + /// \brief Construct the vector from its coordinates + /// + /// \param X X coordinate + /// \param Y Y coordinate + /// + //////////////////////////////////////////////////////////// + Vector2(T X, T Y); + + //////////////////////////////////////////////////////////// + /// \brief Construct the vector from another type of vector + /// + /// This constructor doesn't replace the copy constructor, + /// it's called only when U != T. + /// A call to this constructor will fail to compile if U + /// is not convertible to T. + /// + /// \param vector Vector to convert + /// + //////////////////////////////////////////////////////////// + template + explicit Vector2(const Vector2& vector); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + T x; ///< X coordinate of the vector + T y; ///< Y coordinate of the vector +}; + +//////////////////////////////////////////////////////////// +/// \relates Vector2 +/// \brief Overload of unary operator - +/// +/// \param right Vector to negate +/// +/// \return Memberwise opposite of the vector +/// +//////////////////////////////////////////////////////////// +template +Vector2 operator -(const Vector2& right); + +//////////////////////////////////////////////////////////// +/// \relates Vector2 +/// \brief Overload of binary operator += +/// +/// This operator performs a memberwise addition of both vectors, +/// and assigns the result to \a left. +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a vector) +/// +/// \return Reference to \a left +/// +//////////////////////////////////////////////////////////// +template +Vector2& operator +=(Vector2& left, const Vector2& right); + +//////////////////////////////////////////////////////////// +/// \relates Vector2 +/// \brief Overload of binary operator -= +/// +/// This operator performs a memberwise subtraction of both vectors, +/// and assigns the result to \a left. +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a vector) +/// +/// \return Reference to \a left +/// +//////////////////////////////////////////////////////////// +template +Vector2& operator -=(Vector2& left, const Vector2& right); + +//////////////////////////////////////////////////////////// +/// \relates Vector2 +/// \brief Overload of binary operator + +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a vector) +/// +/// \return Memberwise addition of both vectors +/// +//////////////////////////////////////////////////////////// +template +Vector2 operator +(const Vector2& left, const Vector2& right); + +//////////////////////////////////////////////////////////// +/// \relates Vector2 +/// \brief Overload of binary operator - +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a vector) +/// +/// \return Memberwise subtraction of both vectors +/// +//////////////////////////////////////////////////////////// +template +Vector2 operator -(const Vector2& left, const Vector2& right); + +//////////////////////////////////////////////////////////// +/// \relates Vector2 +/// \brief Overload of binary operator * +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a scalar value) +/// +/// \return Memberwise multiplication by \a right +/// +//////////////////////////////////////////////////////////// +template +Vector2 operator *(const Vector2& left, T right); + +//////////////////////////////////////////////////////////// +/// \relates Vector2 +/// \brief Overload of binary operator * +/// +/// \param left Left operand (a scalar value) +/// \param right Right operand (a vector) +/// +/// \return Memberwise multiplication by \a left +/// +//////////////////////////////////////////////////////////// +template +Vector2 operator *(T left, const Vector2& right); + +//////////////////////////////////////////////////////////// +/// \relates Vector2 +/// \brief Overload of binary operator *= +/// +/// This operator performs a memberwise multiplication by \a right, +/// and assigns the result to \a left. +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a scalar value) +/// +/// \return Reference to \a left +/// +//////////////////////////////////////////////////////////// +template +Vector2& operator *=(Vector2& left, T right); + +//////////////////////////////////////////////////////////// +/// \relates Vector2 +/// \brief Overload of binary operator / +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a scalar value) +/// +/// \return Memberwise division by \a right +/// +//////////////////////////////////////////////////////////// +template +Vector2 operator /(const Vector2& left, T right); + +//////////////////////////////////////////////////////////// +/// \relates Vector2 +/// \brief Overload of binary operator /= +/// +/// This operator performs a memberwise division by \a right, +/// and assigns the result to \a left. +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a scalar value) +/// +/// \return Reference to \a left +/// +//////////////////////////////////////////////////////////// +template +Vector2& operator /=(Vector2& left, T right); + +//////////////////////////////////////////////////////////// +/// \relates Vector2 +/// \brief Overload of binary operator == +/// +/// This operator compares strict equality between two vectors. +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a vector) +/// +/// \return True if \a left is equal to \a right +/// +//////////////////////////////////////////////////////////// +template +bool operator ==(const Vector2& left, const Vector2& right); + +//////////////////////////////////////////////////////////// +/// \relates Vector2 +/// \brief Overload of binary operator != +/// +/// This operator compares strict difference between two vectors. +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a vector) +/// +/// \return True if \a left is not equal to \a right +/// +//////////////////////////////////////////////////////////// +template +bool operator !=(const Vector2& left, const Vector2& right); + +#include + +// Define the most common types +typedef Vector2 Vector2i; +typedef Vector2 Vector2u; +typedef Vector2 Vector2f; + +} // namespace sf + + +#endif // SFML_VECTOR2_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Vector2 +/// \ingroup system +/// +/// sf::Vector2 is a simple class that defines a mathematical +/// vector with two coordinates (x and y). It can be used to +/// represent anything that has two dimensions: a size, a point, +/// a velocity, etc. +/// +/// The template parameter T is the type of the coordinates. It +/// can be any type that supports arithmetic operations (+, -, /, *) +/// and comparisons (==, !=), for example int or float. +/// +/// You generally don't have to care about the templated form (sf::Vector2), +/// the most common specializations have special typedefs: +/// \li sf::Vector2 is sf::Vector2f +/// \li sf::Vector2 is sf::Vector2i +/// \li sf::Vector2 is sf::Vector2u +/// +/// The sf::Vector2 class has a small and simple interface, its x and y members +/// can be accessed directly (there's no accessor like setX(), getX()) and it +/// contains no mathematical function like dot product, cross product, length, etc. +/// +/// Usage example: +/// \code +/// sf::Vector2f v1(16.5f, 24.f); +/// v1.x = 18.2f; +/// float y = v1.y; +/// +/// sf::Vector2f v2 = v1 * 5.f; +/// sf::Vector2f v3; +/// v3 = v1 + v2; +/// +/// bool different = (v2 != v3); +/// \endcode +/// +/// Note: for 3-dimensional vectors, see sf::Vector3. +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/System/Vector2.inl b/src/include/SFML/include/SFML/System/Vector2.inl new file mode 100644 index 0000000..b59d901 --- /dev/null +++ b/src/include/SFML/include/SFML/System/Vector2.inl @@ -0,0 +1,161 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2012 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////// +template +inline Vector2::Vector2() : +x(0), +y(0) +{ + +} + + +//////////////////////////////////////////////////////////// +template +inline Vector2::Vector2(T X, T Y) : +x(X), +y(Y) +{ + +} + + +//////////////////////////////////////////////////////////// +template +template +inline Vector2::Vector2(const Vector2& vector) : +x(static_cast(vector.x)), +y(static_cast(vector.y)) +{ +} + + +//////////////////////////////////////////////////////////// +template +inline Vector2 operator -(const Vector2& right) +{ + return Vector2(-right.x, -right.y); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector2& operator +=(Vector2& left, const Vector2& right) +{ + left.x += right.x; + left.y += right.y; + + return left; +} + + +//////////////////////////////////////////////////////////// +template +inline Vector2& operator -=(Vector2& left, const Vector2& right) +{ + left.x -= right.x; + left.y -= right.y; + + return left; +} + + +//////////////////////////////////////////////////////////// +template +inline Vector2 operator +(const Vector2& left, const Vector2& right) +{ + return Vector2(left.x + right.x, left.y + right.y); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector2 operator -(const Vector2& left, const Vector2& right) +{ + return Vector2(left.x - right.x, left.y - right.y); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector2 operator *(const Vector2& left, T right) +{ + return Vector2(left.x * right, left.y * right); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector2 operator *(T left, const Vector2& right) +{ + return Vector2(right.x * left, right.y * left); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector2& operator *=(Vector2& left, T right) +{ + left.x *= right; + left.y *= right; + + return left; +} + + +//////////////////////////////////////////////////////////// +template +inline Vector2 operator /(const Vector2& left, T right) +{ + return Vector2(left.x / right, left.y / right); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector2& operator /=(Vector2& left, T right) +{ + left.x /= right; + left.y /= right; + + return left; +} + + +//////////////////////////////////////////////////////////// +template +inline bool operator ==(const Vector2& left, const Vector2& right) +{ + return (left.x == right.x) && (left.y == right.y); +} + + +//////////////////////////////////////////////////////////// +template +inline bool operator !=(const Vector2& left, const Vector2& right) +{ + return (left.x != right.x) || (left.y != right.y); +} diff --git a/src/include/SFML/include/SFML/System/Vector3.hpp b/src/include/SFML/include/SFML/System/Vector3.hpp new file mode 100644 index 0000000..0711cd8 --- /dev/null +++ b/src/include/SFML/include/SFML/System/Vector3.hpp @@ -0,0 +1,302 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_VECTOR3_HPP +#define SFML_VECTOR3_HPP + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Utility template class for manipulating +/// 3-dimensional vectors +/// +//////////////////////////////////////////////////////////// +template +class Vector3 +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Creates a Vector3(0, 0, 0). + /// + //////////////////////////////////////////////////////////// + Vector3(); + + //////////////////////////////////////////////////////////// + /// \brief Construct the vector from its coordinates + /// + /// \param X X coordinate + /// \param Y Y coordinate + /// \param Z Z coordinate + /// + //////////////////////////////////////////////////////////// + Vector3(T X, T Y, T Z); + + //////////////////////////////////////////////////////////// + /// \brief Construct the vector from another type of vector + /// + /// This constructor doesn't replace the copy constructor, + /// it's called only when U != T. + /// A call to this constructor will fail to compile if U + /// is not convertible to T. + /// + /// \param vector Vector to convert + /// + //////////////////////////////////////////////////////////// + template + explicit Vector3(const Vector3& vector); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + T x; ///< X coordinate of the vector + T y; ///< Y coordinate of the vector + T z; ///< Z coordinate of the vector +}; + +//////////////////////////////////////////////////////////// +/// \relates Vector3 +/// \brief Overload of unary operator - +/// +/// \param left Vector to negate +/// +/// \return Memberwise opposite of the vector +/// +//////////////////////////////////////////////////////////// +template +Vector3 operator -(const Vector3& left); + +//////////////////////////////////////////////////////////// +/// \relates Vector3 +/// \brief Overload of binary operator += +/// +/// This operator performs a memberwise addition of both vectors, +/// and assigns the result to \a left. +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a vector) +/// +/// \return Reference to \a left +/// +//////////////////////////////////////////////////////////// +template +Vector3& operator +=(Vector3& left, const Vector3& right); + +//////////////////////////////////////////////////////////// +/// \relates Vector3 +/// \brief Overload of binary operator -= +/// +/// This operator performs a memberwise subtraction of both vectors, +/// and assigns the result to \a left. +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a vector) +/// +/// \return Reference to \a left +/// +//////////////////////////////////////////////////////////// +template +Vector3& operator -=(Vector3& left, const Vector3& right); + +//////////////////////////////////////////////////////////// +/// \relates Vector3 +/// \brief Overload of binary operator + +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a vector) +/// +/// \return Memberwise addition of both vectors +/// +//////////////////////////////////////////////////////////// +template +Vector3 operator +(const Vector3& left, const Vector3& right); + +//////////////////////////////////////////////////////////// +/// \relates Vector3 +/// \brief Overload of binary operator - +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a vector) +/// +/// \return Memberwise subtraction of both vectors +/// +//////////////////////////////////////////////////////////// +template +Vector3 operator -(const Vector3& left, const Vector3& right); + +//////////////////////////////////////////////////////////// +/// \relates Vector3 +/// \brief Overload of binary operator * +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a scalar value) +/// +/// \return Memberwise multiplication by \a right +/// +//////////////////////////////////////////////////////////// +template +Vector3 operator *(const Vector3& left, T right); + +//////////////////////////////////////////////////////////// +/// \relates Vector3 +/// \brief Overload of binary operator * +/// +/// \param left Left operand (a scalar value) +/// \param right Right operand (a vector) +/// +/// \return Memberwise multiplication by \a left +/// +//////////////////////////////////////////////////////////// +template +Vector3 operator *(T left, const Vector3& right); + +//////////////////////////////////////////////////////////// +/// \relates Vector3 +/// \brief Overload of binary operator *= +/// +/// This operator performs a memberwise multiplication by \a right, +/// and assigns the result to \a left. +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a scalar value) +/// +/// \return Reference to \a left +/// +//////////////////////////////////////////////////////////// +template +Vector3& operator *=(Vector3& left, T right); + +//////////////////////////////////////////////////////////// +/// \relates Vector3 +/// \brief Overload of binary operator / +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a scalar value) +/// +/// \return Memberwise division by \a right +/// +//////////////////////////////////////////////////////////// +template +Vector3 operator /(const Vector3& left, T right); + +//////////////////////////////////////////////////////////// +/// \relates Vector3 +/// \brief Overload of binary operator /= +/// +/// This operator performs a memberwise division by \a right, +/// and assigns the result to \a left. +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a scalar value) +/// +/// \return Reference to \a left +/// +//////////////////////////////////////////////////////////// +template +Vector3& operator /=(Vector3& left, T right); + +//////////////////////////////////////////////////////////// +/// \relates Vector3 +/// \brief Overload of binary operator == +/// +/// This operator compares strict equality between two vectors. +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a vector) +/// +/// \return True if \a left is equal to \a right +/// +//////////////////////////////////////////////////////////// +template +bool operator ==(const Vector3& left, const Vector3& right); + +//////////////////////////////////////////////////////////// +/// \relates Vector3 +/// \brief Overload of binary operator != +/// +/// This operator compares strict difference between two vectors. +/// +/// \param left Left operand (a vector) +/// \param right Right operand (a vector) +/// +/// \return True if \a left is not equal to \a right +/// +//////////////////////////////////////////////////////////// +template +bool operator !=(const Vector3& left, const Vector3& right); + +#include + +// Define the most common types +typedef Vector3 Vector3i; +typedef Vector3 Vector3f; + +} // namespace sf + + +#endif // SFML_VECTOR3_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Vector3 +/// \ingroup system +/// +/// sf::Vector3 is a simple class that defines a mathematical +/// vector with three coordinates (x, y and z). It can be used to +/// represent anything that has three dimensions: a size, a point, +/// a velocity, etc. +/// +/// The template parameter T is the type of the coordinates. It +/// can be any type that supports arithmetic operations (+, -, /, *) +/// and comparisons (==, !=), for example int or float. +/// +/// You generally don't have to care about the templated form (sf::Vector3), +/// the most common specializations have special typedefs: +/// \li sf::Vector3 is sf::Vector3f +/// \li sf::Vector3 is sf::Vector3i +/// +/// The sf::Vector3 class has a small and simple interface, its x and y members +/// can be accessed directly (there's no accessor like setX(), getX()) and it +/// contains no mathematical function like dot product, cross product, length, etc. +/// +/// Usage example: +/// \code +/// sf::Vector3f v1(16.5f, 24.f, -8.2f); +/// v1.x = 18.2f; +/// float y = v1.y; +/// float z = v1.z; +/// +/// sf::Vector3f v2 = v1 * 5.f; +/// sf::Vector3f v3; +/// v3 = v1 + v2; +/// +/// bool different = (v2 != v3); +/// \endcode +/// +/// Note: for 2-dimensional vectors, see sf::Vector2. +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/System/Vector3.inl b/src/include/SFML/include/SFML/System/Vector3.inl new file mode 100644 index 0000000..9fcc007 --- /dev/null +++ b/src/include/SFML/include/SFML/System/Vector3.inl @@ -0,0 +1,168 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2012 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////// +template +inline Vector3::Vector3() : +x(0), +y(0), +z(0) +{ + +} + + +//////////////////////////////////////////////////////////// +template +inline Vector3::Vector3(T X, T Y, T Z) : +x(X), +y(Y), +z(Z) +{ + +} + + +//////////////////////////////////////////////////////////// +template +template +inline Vector3::Vector3(const Vector3& vector) : +x(static_cast(vector.x)), +y(static_cast(vector.y)), +z(static_cast(vector.z)) +{ +} + + +//////////////////////////////////////////////////////////// +template +inline Vector3 operator -(const Vector3& left) +{ + return Vector3(-left.x, -left.y, -left.z); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector3& operator +=(Vector3& left, const Vector3& right) +{ + left.x += right.x; + left.y += right.y; + left.z += right.z; + + return left; +} + + +//////////////////////////////////////////////////////////// +template +inline Vector3& operator -=(Vector3& left, const Vector3& right) +{ + left.x -= right.x; + left.y -= right.y; + left.z -= right.z; + + return left; +} + + +//////////////////////////////////////////////////////////// +template +inline Vector3 operator +(const Vector3& left, const Vector3& right) +{ + return Vector3(left.x + right.x, left.y + right.y, left.z + right.z); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector3 operator -(const Vector3& left, const Vector3& right) +{ + return Vector3(left.x - right.x, left.y - right.y, left.z - right.z); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector3 operator *(const Vector3& left, T right) +{ + return Vector3(left.x * right, left.y * right, left.z * right); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector3 operator *(T left, const Vector3& right) +{ + return Vector3(right.x * left, right.y * left, right.z * left); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector3& operator *=(Vector3& left, T right) +{ + left.x *= right; + left.y *= right; + left.z *= right; + + return left; +} + + +//////////////////////////////////////////////////////////// +template +inline Vector3 operator /(const Vector3& left, T right) +{ + return Vector3(left.x / right, left.y / right, left.z / right); +} + + +//////////////////////////////////////////////////////////// +template +inline Vector3& operator /=(Vector3& left, T right) +{ + left.x /= right; + left.y /= right; + left.z /= right; + + return left; +} + + +//////////////////////////////////////////////////////////// +template +inline bool operator ==(const Vector3& left, const Vector3& right) +{ + return (left.x == right.x) && (left.y == right.y) && (left.z == right.z); +} + + +//////////////////////////////////////////////////////////// +template +inline bool operator !=(const Vector3& left, const Vector3& right) +{ + return (left.x != right.x) || (left.y != right.y) || (left.z != right.z); +} diff --git a/src/include/SFML/include/SFML/Window.hpp b/src/include/SFML/include/SFML/Window.hpp new file mode 100644 index 0000000..76fedda --- /dev/null +++ b/src/include/SFML/include/SFML/Window.hpp @@ -0,0 +1,52 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SFML_WINDOW_HPP +#define SFML_SFML_WINDOW_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#endif // SFML_SFML_WINDOW_HPP + +//////////////////////////////////////////////////////////// +/// \defgroup window Window module +/// +/// Provides OpenGL-based windows, and abstractions for +/// events and input handling. +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Window/Context.hpp b/src/include/SFML/include/SFML/Window/Context.hpp new file mode 100644 index 0000000..52084ea --- /dev/null +++ b/src/include/SFML/include/SFML/Window/Context.hpp @@ -0,0 +1,140 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_CONTEXT_HPP +#define SFML_CONTEXT_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include + + +namespace sf +{ +namespace priv +{ + class GlContext; +} + +//////////////////////////////////////////////////////////// +/// \brief Class holding a valid drawing context +/// +//////////////////////////////////////////////////////////// +class SFML_WINDOW_API Context : GlResource, NonCopyable +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// The constructor creates and activates the context + /// + //////////////////////////////////////////////////////////// + Context(); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + /// The desctructor deactivates and destroys the context + /// + //////////////////////////////////////////////////////////// + ~Context(); + + //////////////////////////////////////////////////////////// + /// \brief Activate or deactivate explicitely the context + /// + /// \param active True to activate, false to deactivate + /// + /// \return True on success, false on failure + /// + //////////////////////////////////////////////////////////// + bool setActive(bool active); + +public : + + //////////////////////////////////////////////////////////// + /// \brief Construct a in-memory context + /// + /// This constructor is for internal use, you don't need + /// to bother with it. + /// + /// \param settings Creation parameters + /// \param width Back buffer width + /// \param height Back buffer height + /// + //////////////////////////////////////////////////////////// + Context(const ContextSettings& settings, unsigned int width, unsigned int height); + +private : + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + priv::GlContext* m_context; ///< Internal OpenGL context +}; + +} // namespace sf + + +#endif // SFML_CONTEXT_HPP + +//////////////////////////////////////////////////////////// +/// \class sf::Context +/// \ingroup window +/// +/// If you need to make OpenGL calls without having an +/// active window (like in a thread), you can use an +/// instance of this class to get a valid context. +/// +/// Having a valid context is necessary for *every* OpenGL call. +/// +/// Note that a context is only active in its current thread, +/// if you create a new thread it will have no valid context +/// by default. +/// +/// To use a sf::Context instance, just construct it and let it +/// live as long as you need a valid context. No explicit activation +/// is needed, all it has to do is to exist. Its destructor +/// will take care of deactivating and freeing all the attached +/// resources. +/// +/// Usage example: +/// \code +/// void threadFunction(void*) +/// { +/// sf::Context context; +/// // from now on, you have a valid context +/// +/// // you can make OpenGL calls +/// glClear(GL_DEPTH_BUFFER_BIT); +/// } +/// // the context is automatically deactivated and destroyed +/// // by the sf::Context destructor +/// \endcode +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Window/ContextSettings.hpp b/src/include/SFML/include/SFML/Window/ContextSettings.hpp new file mode 100644 index 0000000..a5481ab --- /dev/null +++ b/src/include/SFML/include/SFML/Window/ContextSettings.hpp @@ -0,0 +1,104 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_CONTEXTSETTINGS_HPP +#define SFML_CONTEXTSETTINGS_HPP + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Structure defining the settings of the OpenGL +/// context attached to a window +/// +//////////////////////////////////////////////////////////// +struct ContextSettings +{ + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// \param depth Depth buffer bits + /// \param stencil Stencil buffer bits + /// \param antialiasing Antialiasing level + /// \param major Major number of the context version + /// \param minor Minor number of the context version + /// + //////////////////////////////////////////////////////////// + explicit ContextSettings(unsigned int depth = 0, unsigned int stencil = 0, unsigned int antialiasing = 0, unsigned int major = 2, unsigned int minor = 0) : + depthBits (depth), + stencilBits (stencil), + antialiasingLevel(antialiasing), + majorVersion (major), + minorVersion (minor) + { + } + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + unsigned int depthBits; ///< Bits of the depth buffer + unsigned int stencilBits; ///< Bits of the stencil buffer + unsigned int antialiasingLevel; ///< Level of antialiasing + unsigned int majorVersion; ///< Major number of the context version to create + unsigned int minorVersion; ///< Minor number of the context version to create +}; + +} // namespace sf + + +#endif // SFML_CONTEXTSETTINGS_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::ContextSettings +/// \ingroup window +/// +/// ContextSettings allows to define several advanced settings +/// of the OpenGL context attached to a window. All these +/// settings have no impact on the regular SFML rendering +/// (graphics module) -- except the anti-aliasing level, so +/// you may need to use this structure only if you're using +/// SFML as a windowing system for custom OpenGL rendering. +/// +/// The depthBits and stencilBits members define the number +/// of bits per pixel requested for the (respectively) depth +/// and stencil buffers. +/// +/// antialiasingLevel represents the requested number of +/// multisampling levels for anti-aliasing. +/// +/// majorVersion and minorVersion define the version of the +/// OpenGL context that you want. Only versions greater or +/// equal to 3.0 are relevant; versions lesser than 3.0 are +/// all handled the same way (i.e. you can use any version +/// < 3.0 if you don't want an OpenGL 3 context). +/// +/// Please note that these values are only a hint. +/// No failure will be reported if one or more of these values +/// are not supported by the system; instead, SFML will try to +/// find the closest valid match. You can then retrieve the +/// settings that the window actually used to create its context, +/// with Window::getSettings(). +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Window/Event.hpp b/src/include/SFML/include/SFML/Window/Event.hpp new file mode 100644 index 0000000..c96546e --- /dev/null +++ b/src/include/SFML/include/SFML/Window/Event.hpp @@ -0,0 +1,237 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_EVENT_HPP +#define SFML_EVENT_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Defines a system event and its parameters +/// +//////////////////////////////////////////////////////////// +class Event +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Size events parameters (Resized) + /// + //////////////////////////////////////////////////////////// + struct SizeEvent + { + unsigned int width; ///< New width, in pixels + unsigned int height; ///< New height, in pixels + }; + + //////////////////////////////////////////////////////////// + /// \brief Keyboard event parameters (KeyPressed, KeyReleased) + /// + //////////////////////////////////////////////////////////// + struct KeyEvent + { + Keyboard::Key code; ///< Code of the key that has been pressed + bool alt; ///< Is the Alt key pressed? + bool control; ///< Is the Control key pressed? + bool shift; ///< Is the Shift key pressed? + bool system; ///< Is the System key pressed? + }; + + //////////////////////////////////////////////////////////// + /// \brief Text event parameters (TextEntered) + /// + //////////////////////////////////////////////////////////// + struct TextEvent + { + Uint32 unicode; ///< UTF-32 unicode value of the character + }; + + //////////////////////////////////////////////////////////// + /// \brief Mouse move event parameters (MouseMoved) + /// + //////////////////////////////////////////////////////////// + struct MouseMoveEvent + { + int x; ///< X position of the mouse pointer, relative to the left of the owner window + int y; ///< Y position of the mouse pointer, relative to the top of the owner window + }; + + //////////////////////////////////////////////////////////// + /// \brief Mouse buttons events parameters + /// (MouseButtonPressed, MouseButtonReleased) + /// + //////////////////////////////////////////////////////////// + struct MouseButtonEvent + { + Mouse::Button button; ///< Code of the button that has been pressed + int x; ///< X position of the mouse pointer, relative to the left of the owner window + int y; ///< Y position of the mouse pointer, relative to the top of the owner window + }; + + //////////////////////////////////////////////////////////// + /// \brief Mouse wheel events parameters (MouseWheelMoved) + /// + //////////////////////////////////////////////////////////// + struct MouseWheelEvent + { + int delta; ///< Number of ticks the wheel has moved (positive is up, negative is down) + int x; ///< X position of the mouse pointer, relative to the left of the owner window + int y; ///< Y position of the mouse pointer, relative to the top of the owner window + }; + + //////////////////////////////////////////////////////////// + /// \brief Joystick connection events parameters + /// (JoystickConnected, JoystickDisconnected) + /// + //////////////////////////////////////////////////////////// + struct JoystickConnectEvent + { + unsigned int joystickId; ///< Index of the joystick (in range [0 .. Joystick::Count - 1]) + }; + + //////////////////////////////////////////////////////////// + /// \brief Joystick axis move event parameters (JoystickMoved) + /// + //////////////////////////////////////////////////////////// + struct JoystickMoveEvent + { + unsigned int joystickId; ///< Index of the joystick (in range [0 .. Joystick::Count - 1]) + Joystick::Axis axis; ///< Axis on which the joystick moved + float position; ///< New position on the axis (in range [-100 .. 100]) + }; + + //////////////////////////////////////////////////////////// + /// \brief Joystick buttons events parameters + /// (JoystickButtonPressed, JoystickButtonReleased) + /// + //////////////////////////////////////////////////////////// + struct JoystickButtonEvent + { + unsigned int joystickId; ///< Index of the joystick (in range [0 .. Joystick::Count - 1]) + unsigned int button; ///< Index of the button that has been pressed (in range [0 .. Joystick::ButtonCount - 1]) + }; + + //////////////////////////////////////////////////////////// + /// \brief Enumeration of the different types of events + /// + //////////////////////////////////////////////////////////// + enum EventType + { + Closed, ///< The window requested to be closed (no data) + Resized, ///< The window was resized (data in event.size) + LostFocus, ///< The window lost the focus (no data) + GainedFocus, ///< The window gained the focus (no data) + TextEntered, ///< A character was entered (data in event.text) + KeyPressed, ///< A key was pressed (data in event.key) + KeyReleased, ///< A key was released (data in event.key) + MouseWheelMoved, ///< The mouse wheel was scrolled (data in event.mouseWheel) + MouseButtonPressed, ///< A mouse button was pressed (data in event.mouseButton) + MouseButtonReleased, ///< A mouse button was released (data in event.mouseButton) + MouseMoved, ///< The mouse cursor moved (data in event.mouseMove) + MouseEntered, ///< The mouse cursor entered the area of the window (no data) + MouseLeft, ///< The mouse cursor left the area of the window (no data) + JoystickButtonPressed, ///< A joystick button was pressed (data in event.joystickButton) + JoystickButtonReleased, ///< A joystick button was released (data in event.joystickButton) + JoystickMoved, ///< The joystick moved along an axis (data in event.joystickMove) + JoystickConnected, ///< A joystick was connected (data in event.joystickConnect) + JoystickDisconnected, ///< A joystick was disconnected (data in event.joystickConnect) + + Count ///< Keep last -- the total number of event types + }; + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + EventType type; ///< Type of the event + + union + { + SizeEvent size; ///< Size event parameters (Event::Resized) + KeyEvent key; ///< Key event parameters (Event::KeyPressed, Event::KeyReleased) + TextEvent text; ///< Text event parameters (Event::TextEntered) + MouseMoveEvent mouseMove; ///< Mouse move event parameters (Event::MouseMoved) + MouseButtonEvent mouseButton; ///< Mouse button event parameters (Event::MouseButtonPressed, Event::MouseButtonReleased) + MouseWheelEvent mouseWheel; ///< Mouse wheel event parameters (Event::MouseWheelMoved) + JoystickMoveEvent joystickMove; ///< Joystick move event parameters (Event::JoystickMoved) + JoystickButtonEvent joystickButton; ///< Joystick button event parameters (Event::JoystickButtonPressed, Event::JoystickButtonReleased) + JoystickConnectEvent joystickConnect; ///< Joystick (dis)connect event parameters (Event::JoystickConnected, Event::JoystickDisconnected) + }; +}; + +} // namespace sf + + +#endif // SFML_EVENT_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Event +/// \ingroup window +/// +/// sf::Event holds all the informations about a system event +/// that just happened. Events are retrieved using the +/// sf::Window::pollEvent and sf::Window::waitEvent functions. +/// +/// A sf::Event instance contains the type of the event +/// (mouse moved, key pressed, window closed, ...) as well +/// as the details about this particular event. Please note that +/// the event parameters are defined in a union, which means that +/// only the member matching the type of the event will be properly +/// filled; all other members will have undefined values and must not +/// be read if the type of the event doesn't match. For example, +/// if you received a KeyPressed event, then you must read the +/// event.key member, all other members such as event.MouseMove +/// or event.text will have undefined values. +/// +/// Usage example: +/// \code +/// sf::Event event; +/// while (window.pollEvent(event)) +/// { +/// // Request for closing the window +/// if (event.type == sf::Event::Closed) +/// window.close(); +/// +/// // The escape key was pressed +/// if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape)) +/// window.close(); +/// +/// // The window was resized +/// if (event.type == sf::Event::Resized) +/// doSomethingWithTheNewSize(event.size.width, event.size.height); +/// +/// // etc ... +/// } +/// \endcode +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Window/Export.hpp b/src/include/SFML/include/SFML/Window/Export.hpp new file mode 100644 index 0000000..ff06576 --- /dev/null +++ b/src/include/SFML/include/SFML/Window/Export.hpp @@ -0,0 +1,48 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_WINDOW_EXPORT_HPP +#define SFML_WINDOW_EXPORT_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +//////////////////////////////////////////////////////////// +// Define portable import / export macros +//////////////////////////////////////////////////////////// +#if defined(SFML_WINDOW_EXPORTS) + + #define SFML_WINDOW_API SFML_API_EXPORT + +#else + + #define SFML_WINDOW_API SFML_API_IMPORT + +#endif + + +#endif // SFML_WINDOW_EXPORT_HPP diff --git a/src/include/SFML/include/SFML/Window/GlResource.hpp b/src/include/SFML/include/SFML/Window/GlResource.hpp new file mode 100644 index 0000000..1e1ed31 --- /dev/null +++ b/src/include/SFML/include/SFML/Window/GlResource.hpp @@ -0,0 +1,76 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_GLRESOURCE_HPP +#define SFML_GLRESOURCE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Base class for classes that require an OpenGL context +/// +//////////////////////////////////////////////////////////// +class SFML_WINDOW_API GlResource +{ +protected : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + GlResource(); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~GlResource(); + + //////////////////////////////////////////////////////////// + /// \brief Make sure that a valid OpenGL context exists in the current thread + /// + //////////////////////////////////////////////////////////// + static void ensureGlContext(); +}; + +} // namespace sf + + +#endif // SFML_GLRESOURCE_HPP + +//////////////////////////////////////////////////////////// +/// \class sf::GlResource +/// \ingroup window +/// +/// This class is for internal use only, it must be the base +/// of every class that requires a valid OpenGL context in +/// order to work. +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Window/Joystick.hpp b/src/include/SFML/include/SFML/Window/Joystick.hpp new file mode 100644 index 0000000..8e65309 --- /dev/null +++ b/src/include/SFML/include/SFML/Window/Joystick.hpp @@ -0,0 +1,203 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_JOYSTICK_HPP +#define SFML_JOYSTICK_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Give access to the real-time state of the joysticks +/// +//////////////////////////////////////////////////////////// +class SFML_WINDOW_API Joystick +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Constants related to joysticks capabilities + /// + //////////////////////////////////////////////////////////// + enum + { + Count = 8, ///< Maximum number of supported joysticks + ButtonCount = 32, ///< Maximum number of supported buttons + AxisCount = 8 ///< Maximum number of supported axes + }; + + //////////////////////////////////////////////////////////// + /// \brief Axes supported by SFML joysticks + /// + //////////////////////////////////////////////////////////// + enum Axis + { + X, ///< The X axis + Y, ///< The Y axis + Z, ///< The Z axis + R, ///< The R axis + U, ///< The U axis + V, ///< The V axis + PovX, ///< The X axis of the point-of-view hat + PovY ///< The Y axis of the point-of-view hat + }; + + //////////////////////////////////////////////////////////// + /// \brief Check if a joystick is connected + /// + /// \param joystick Index of the joystick to check + /// + /// \return True if the joystick is connected, false otherwise + /// + //////////////////////////////////////////////////////////// + static bool isConnected(unsigned int joystick); + + //////////////////////////////////////////////////////////// + /// \brief Return the number of buttons supported by a joystick + /// + /// If the joystick is not connected, this function returns 0. + /// + /// \param joystick Index of the joystick + /// + /// \return Number of buttons supported by the joystick + /// + //////////////////////////////////////////////////////////// + static unsigned int getButtonCount(unsigned int joystick); + + //////////////////////////////////////////////////////////// + /// \brief Check if a joystick supports a given axis + /// + /// If the joystick is not connected, this function returns false. + /// + /// \param joystick Index of the joystick + /// \param axis Axis to check + /// + /// \return True if the joystick supports the axis, false otherwise + /// + //////////////////////////////////////////////////////////// + static bool hasAxis(unsigned int joystick, Axis axis); + + //////////////////////////////////////////////////////////// + /// \brief Check if a joystick button is pressed + /// + /// If the joystick is not connected, this function returns false. + /// + /// \param joystick Index of the joystick + /// \param button Button to check + /// + /// \return True if the button is pressed, false otherwise + /// + //////////////////////////////////////////////////////////// + static bool isButtonPressed(unsigned int joystick, unsigned int button); + + //////////////////////////////////////////////////////////// + /// \brief Get the current position of a joystick axis + /// + /// If the joystick is not connected, this function returns 0. + /// + /// \param joystick Index of the joystick + /// \param axis Axis to check + /// + /// \return Current position of the axis, in range [-100 .. 100] + /// + //////////////////////////////////////////////////////////// + static float getAxisPosition(unsigned int joystick, Axis axis); + + //////////////////////////////////////////////////////////// + /// \brief Update the states of all joysticks + /// + /// This function is used internally by SFML, so you normally + /// don't have to call it explicitely. However, you may need to + /// call it if you have no window yet (or no window at all): + /// in this case the joysticks states are not updated automatically. + /// + //////////////////////////////////////////////////////////// + static void update(); +}; + +} // namespace sf + + +#endif // SFML_JOYSTICK_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Joystick +/// \ingroup window +/// +/// sf::Joystick provides an interface to the state of the +/// joysticks. It only contains static functions, so it's not +/// meant to be instanciated. Instead, each joystick is identified +/// by an index that is passed to the functions of this class. +/// +/// This class allows users to query the state of joysticks at any +/// time and directly, without having to deal with a window and +/// its events. Compared to the JoystickMoved, JoystickButtonPressed +/// and JoystickButtonReleased events, sf::Joystick can retrieve the +/// state of axes and buttons of joysticks at any time +/// (you don't need to store and update a boolean on your side +/// in order to know if a button is pressed or released), and you +/// always get the real state of joysticks, even if they are +/// moved, pressed or released when your window is out of focus +/// and no event is triggered. +/// +/// SFML supports: +/// \li 8 joysticks (sf::Joystick::Count) +/// \li 32 buttons per joystick (sf::Joystick::ButtonCount) +/// \li 8 axes per joystick (sf::Joystick::AxisCount) +/// +/// Unlike the keyboard or mouse, the state of joysticks is sometimes +/// not directly available (depending on the OS), therefore an update() +/// function must be called in order to update the current state of +/// joysticks. When you have a window with event handling, this is done +/// automatically, you don't need to call anything. But if you have no +/// window, or if you want to check joysticks state before creating one, +/// you must call sf::Joystick::update explicitely. +/// +/// Usage example: +/// \code +/// // Is joystick #0 connected? +/// bool connected = sf::Joystick::isConnected(0); +/// +/// // How many buttons does joystick #0 support? +/// unsigned int buttons = sf::Joystick::getButtonCount(0); +/// +/// // Does joystick #0 define a X axis? +/// bool hasX = sf::Joystick::hasAxis(0, sf::Joystick::X); +/// +/// // Is button #2 pressed on joystick #0? +/// bool pressed = sf::Joystick::isButtonPressed(0, 2); +/// +/// // What's the current position of the Y axis on joystick #0? +/// float position = sf::Joystick::getAxisPosition(0, sf::Joystick::Y); +/// \endcode +/// +/// \see sf::Keyboard, sf::Mouse +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Window/Keyboard.hpp b/src/include/SFML/include/SFML/Window/Keyboard.hpp new file mode 100644 index 0000000..f10dc7c --- /dev/null +++ b/src/include/SFML/include/SFML/Window/Keyboard.hpp @@ -0,0 +1,209 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_KEYBOARD_HPP +#define SFML_KEYBOARD_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Give access to the real-time state of the keyboard +/// +//////////////////////////////////////////////////////////// +class SFML_WINDOW_API Keyboard +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Key codes + /// + //////////////////////////////////////////////////////////// + enum Key + { + Unknown = -1, ///< Unhandled key + A = 0, ///< The A key + B, ///< The B key + C, ///< The C key + D, ///< The D key + E, ///< The E key + F, ///< The F key + G, ///< The G key + H, ///< The H key + I, ///< The I key + J, ///< The J key + K, ///< The K key + L, ///< The L key + M, ///< The M key + N, ///< The N key + O, ///< The O key + P, ///< The P key + Q, ///< The Q key + R, ///< The R key + S, ///< The S key + T, ///< The T key + U, ///< The U key + V, ///< The V key + W, ///< The W key + X, ///< The X key + Y, ///< The Y key + Z, ///< The Z key + Num0, ///< The 0 key + Num1, ///< The 1 key + Num2, ///< The 2 key + Num3, ///< The 3 key + Num4, ///< The 4 key + Num5, ///< The 5 key + Num6, ///< The 6 key + Num7, ///< The 7 key + Num8, ///< The 8 key + Num9, ///< The 9 key + Escape, ///< The Escape key + LControl, ///< The left Control key + LShift, ///< The left Shift key + LAlt, ///< The left Alt key + LSystem, ///< The left OS specific key: window (Windows and Linux), apple (MacOS X), ... + RControl, ///< The right Control key + RShift, ///< The right Shift key + RAlt, ///< The right Alt key + RSystem, ///< The right OS specific key: window (Windows and Linux), apple (MacOS X), ... + Menu, ///< The Menu key + LBracket, ///< The [ key + RBracket, ///< The ] key + SemiColon, ///< The ; key + Comma, ///< The , key + Period, ///< The . key + Quote, ///< The ' key + Slash, ///< The / key + BackSlash, ///< The \ key + Tilde, ///< The ~ key + Equal, ///< The = key + Dash, ///< The - key + Space, ///< The Space key + Return, ///< The Return key + BackSpace, ///< The Backspace key + Tab, ///< The Tabulation key + PageUp, ///< The Page up key + PageDown, ///< The Page down key + End, ///< The End key + Home, ///< The Home key + Insert, ///< The Insert key + Delete, ///< The Delete key + Add, ///< The + key + Subtract, ///< The - key + Multiply, ///< The * key + Divide, ///< The / key + Left, ///< Left arrow + Right, ///< Right arrow + Up, ///< Up arrow + Down, ///< Down arrow + Numpad0, ///< The numpad 0 key + Numpad1, ///< The numpad 1 key + Numpad2, ///< The numpad 2 key + Numpad3, ///< The numpad 3 key + Numpad4, ///< The numpad 4 key + Numpad5, ///< The numpad 5 key + Numpad6, ///< The numpad 6 key + Numpad7, ///< The numpad 7 key + Numpad8, ///< The numpad 8 key + Numpad9, ///< The numpad 9 key + F1, ///< The F1 key + F2, ///< The F2 key + F3, ///< The F3 key + F4, ///< The F4 key + F5, ///< The F5 key + F6, ///< The F6 key + F7, ///< The F7 key + F8, ///< The F8 key + F9, ///< The F9 key + F10, ///< The F10 key + F11, ///< The F11 key + F12, ///< The F12 key + F13, ///< The F13 key + F14, ///< The F14 key + F15, ///< The F15 key + Pause, ///< The Pause key + + KeyCount ///< Keep last -- the total number of keyboard keys + }; + + //////////////////////////////////////////////////////////// + /// \brief Check if a key is pressed + /// + /// \param key Key to check + /// + /// \return True if the key is pressed, false otherwise + /// + //////////////////////////////////////////////////////////// + static bool isKeyPressed(Key key); +}; + +} // namespace sf + + +#endif // SFML_KEYBOARD_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Keyboard +/// \ingroup window +/// +/// sf::Keyboard provides an interface to the state of the +/// keyboard. It only contains static functions (a single +/// keyboard is assumed), so it's not meant to be instanciated. +/// +/// This class allows users to query the keyboard state at any +/// time and directly, without having to deal with a window and +/// its events. Compared to the KeyPressed and KeyReleased events, +/// sf::Keyboard can retrieve the state of a key at any time +/// (you don't need to store and update a boolean on your side +/// in order to know if a key is pressed or released), and you +/// always get the real state of the keyboard, even if keys are +/// pressed or released when your window is out of focus and no +/// event is triggered. +/// +/// Usage example: +/// \code +/// if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) +/// { +/// // move left... +/// } +/// else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) +/// { +/// // move right... +/// } +/// else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape)) +/// { +/// // quit... +/// } +/// \endcode +/// +/// \see sf::Joystick, sf::Mouse +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Window/Mouse.hpp b/src/include/SFML/include/SFML/Window/Mouse.hpp new file mode 100644 index 0000000..dd26d1a --- /dev/null +++ b/src/include/SFML/include/SFML/Window/Mouse.hpp @@ -0,0 +1,167 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_MOUSE_HPP +#define SFML_MOUSE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +class Window; + +//////////////////////////////////////////////////////////// +/// \brief Give access to the real-time state of the mouse +/// +//////////////////////////////////////////////////////////// +class SFML_WINDOW_API Mouse +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Mouse buttons + /// + //////////////////////////////////////////////////////////// + enum Button + { + Left, ///< The left mouse button + Right, ///< The right mouse button + Middle, ///< The middle (wheel) mouse button + XButton1, ///< The first extra mouse button + XButton2, ///< The second extra mouse button + + ButtonCount ///< Keep last -- the total number of mouse buttons + }; + + //////////////////////////////////////////////////////////// + /// \brief Check if a mouse button is pressed + /// + /// \param button Button to check + /// + /// \return True if the button is pressed, false otherwise + /// + //////////////////////////////////////////////////////////// + static bool isButtonPressed(Button button); + + //////////////////////////////////////////////////////////// + /// \brief Get the current position of the mouse in desktop coordinates + /// + /// This function returns the global position of the mouse + /// cursor on the desktop. + /// + /// \return Current position of the mouse + /// + //////////////////////////////////////////////////////////// + static Vector2i getPosition(); + + //////////////////////////////////////////////////////////// + /// \brief Get the current position of the mouse in window coordinates + /// + /// This function returns the current position of the mouse + /// cursor, relative to the given window. + /// + /// \param relativeTo Reference window + /// + /// \return Current position of the mouse + /// + //////////////////////////////////////////////////////////// + static Vector2i getPosition(const Window& relativeTo); + + //////////////////////////////////////////////////////////// + /// \brief Set the current position of the mouse in desktop coordinates + /// + /// This function sets the global position of the mouse + /// cursor on the desktop. + /// + /// \param position New position of the mouse + /// + //////////////////////////////////////////////////////////// + static void setPosition(const Vector2i& position); + + //////////////////////////////////////////////////////////// + /// \brief Set the current position of the mouse in window coordinates + /// + /// This function sets the current position of the mouse + /// cursor, relative to the given window. + /// + /// \param position New position of the mouse + /// \param relativeTo Reference window + /// + //////////////////////////////////////////////////////////// + static void setPosition(const Vector2i& position, const Window& relativeTo); +}; + +} // namespace sf + + +#endif // SFML_MOUSE_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Mouse +/// \ingroup window +/// +/// sf::Mouse provides an interface to the state of the +/// mouse. It only contains static functions (a single +/// mouse is assumed), so it's not meant to be instanciated. +/// +/// This class allows users to query the mouse state at any +/// time and directly, without having to deal with a window and +/// its events. Compared to the MouseMoved, MouseButtonPressed +/// and MouseButtonReleased events, sf::Mouse can retrieve the +/// state of the cursor and the buttons at any time +/// (you don't need to store and update a boolean on your side +/// in order to know if a button is pressed or released), and you +/// always get the real state of the mouse, even if it is +/// moved, pressed or released when your window is out of focus +/// and no event is triggered. +/// +/// The setPosition and getPosition functions can be used to change +/// or retrieve the current position of the mouse pointer. There are +/// two versions: one that operates in global coordinates (relative +/// to the desktop) and one that operates in window coordinates +/// (relative to a specific window). +/// +/// Usage example: +/// \code +/// if (sf::Mouse::isButtonPressed(sf::Mouse::Left)) +/// { +/// // left click... +/// } +/// +/// // get global mouse position +/// sf::Vector2i position = sf::Mouse::getPosition(); +/// +/// // set mouse position relative to a window +/// sf::Mouse::setPosition(sf::Vector2i(100, 200), window); +/// \endcode +/// +/// \see sf::Joystick, sf::Keyboard +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Window/VideoMode.hpp b/src/include/SFML/include/SFML/Window/VideoMode.hpp new file mode 100644 index 0000000..c651bd0 --- /dev/null +++ b/src/include/SFML/include/SFML/Window/VideoMode.hpp @@ -0,0 +1,228 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_VIDEOMODE_HPP +#define SFML_VIDEOMODE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief VideoMode defines a video mode (width, height, bpp) +/// +//////////////////////////////////////////////////////////// +class SFML_WINDOW_API VideoMode +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// This constructors initializes all members to 0. + /// + //////////////////////////////////////////////////////////// + VideoMode(); + + //////////////////////////////////////////////////////////// + /// \brief Construct the video mode with its attributes + /// + /// \param modeWidth Width in pixels + /// \param modeHeight Height in pixels + /// \param modeBitsPerPixel Pixel depths in bits per pixel + /// + //////////////////////////////////////////////////////////// + VideoMode(unsigned int modeWidth, unsigned int modeHeight, unsigned int modeBitsPerPixel = 32); + + //////////////////////////////////////////////////////////// + /// \brief Get the current desktop video mode + /// + /// \return Current desktop video mode + /// + //////////////////////////////////////////////////////////// + static VideoMode getDesktopMode(); + + //////////////////////////////////////////////////////////// + /// \brief Retrieve all the video modes supported in fullscreen mode + /// + /// When creating a fullscreen window, the video mode is restricted + /// to be compatible with what the graphics driver and monitor + /// support. This function returns the complete list of all video + /// modes that can be used in fullscreen mode. + /// The returned array is sorted from best to worst, so that + /// the first element will always give the best mode (higher + /// width, height and bits-per-pixel). + /// + /// \return Array containing all the supported fullscreen modes + /// + //////////////////////////////////////////////////////////// + static const std::vector& getFullscreenModes(); + + //////////////////////////////////////////////////////////// + /// \brief Tell whether or not the video mode is valid + /// + /// The validity of video modes is only relevant when using + /// fullscreen windows; otherwise any video mode can be used + /// with no restriction. + /// + /// \return True if the video mode is valid for fullscreen mode + /// + //////////////////////////////////////////////////////////// + bool isValid() const; + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + unsigned int width; ///< Video mode width, in pixels + unsigned int height; ///< Video mode height, in pixels + unsigned int bitsPerPixel; ///< Video mode pixel depth, in bits per pixels +}; + +//////////////////////////////////////////////////////////// +/// \relates VideoMode +/// \brief Overload of == operator to compare two video modes +/// +/// \param left Left operand (a video mode) +/// \param right Right operand (a video mode) +/// +/// \return True if modes are equal +/// +//////////////////////////////////////////////////////////// +SFML_WINDOW_API bool operator ==(const VideoMode& left, const VideoMode& right); + +//////////////////////////////////////////////////////////// +/// \relates VideoMode +/// \brief Overload of != operator to compare two video modes +/// +/// \param left Left operand (a video mode) +/// \param right Right operand (a video mode) +/// +/// \return True if modes are different +/// +//////////////////////////////////////////////////////////// +SFML_WINDOW_API bool operator !=(const VideoMode& left, const VideoMode& right); + +//////////////////////////////////////////////////////////// +/// \relates VideoMode +/// \brief Overload of < operator to compare video modes +/// +/// \param left Left operand (a video mode) +/// \param right Right operand (a video mode) +/// +/// \return True if \a left is lesser than \a right +/// +//////////////////////////////////////////////////////////// +SFML_WINDOW_API bool operator <(const VideoMode& left, const VideoMode& right); + +//////////////////////////////////////////////////////////// +/// \relates VideoMode +/// \brief Overload of > operator to compare video modes +/// +/// \param left Left operand (a video mode) +/// \param right Right operand (a video mode) +/// +/// \return True if \a left is greater than \a right +/// +//////////////////////////////////////////////////////////// +SFML_WINDOW_API bool operator >(const VideoMode& left, const VideoMode& right); + +//////////////////////////////////////////////////////////// +/// \relates VideoMode +/// \brief Overload of <= operator to compare video modes +/// +/// \param left Left operand (a video mode) +/// \param right Right operand (a video mode) +/// +/// \return True if \a left is lesser or equal than \a right +/// +//////////////////////////////////////////////////////////// +SFML_WINDOW_API bool operator <=(const VideoMode& left, const VideoMode& right); + +//////////////////////////////////////////////////////////// +/// \relates VideoMode +/// \brief Overload of >= operator to compare video modes +/// +/// \param left Left operand (a video mode) +/// \param right Right operand (a video mode) +/// +/// \return True if \a left is greater or equal than \a right +/// +//////////////////////////////////////////////////////////// +SFML_WINDOW_API bool operator >=(const VideoMode& left, const VideoMode& right); + +} // namespace sf + + +#endif // SFML_VIDEOMODE_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::VideoMode +/// \ingroup window +/// +/// A video mode is defined by a width and a height (in pixels) +/// and a depth (in bits per pixel). Video modes are used to +/// setup windows (sf::Window) at creation time. +/// +/// The main usage of video modes is for fullscreen mode: +/// indeed you must use one of the valid video modes +/// allowed by the OS (which are defined by what the monitor +/// and the graphics card support), otherwise your window +/// creation will just fail. +/// +/// sf::VideoMode provides a static function for retrieving +/// the list of all the video modes supported by the system: +/// getFullscreenModes(). +/// +/// A custom video mode can also be checked directly for +/// fullscreen compatibility with its isValid() function. +/// +/// Additionnally, sf::VideoMode provides a static function +/// to get the mode currently used by the desktop: getDesktopMode(). +/// This allows to build windows with the same size or pixel +/// depth as the current resolution. +/// +/// Usage example: +/// \code +/// // Display the list of all the video modes available for fullscreen +/// std::vector modes = sf::VideoMode::getFullscreenModes(); +/// for (std::size_t i = 0; i < modes.size(); ++i) +/// { +/// sf::VideoMode mode = modes[i]; +/// std::cout << "Mode #" << i << ": " +/// << mode.width << "x" << mode.height << " - " +/// << mode.bitsPerPixel << " bpp" << std::endl; +/// } +/// +/// // Create a window with the same pixel depth as the desktop +/// sf::VideoMode desktop = sf::VideoMode::getDesktopMode(); +/// window.create(sf::VideoMode(1024, 768, desktop.bitsPerPixel), "SFML window"); +/// \endcode +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Window/Window.hpp b/src/include/SFML/include/SFML/Window/Window.hpp new file mode 100644 index 0000000..62eff43 --- /dev/null +++ b/src/include/SFML/include/SFML/Window/Window.hpp @@ -0,0 +1,541 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_WINDOW_HPP +#define SFML_WINDOW_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace sf +{ +namespace priv +{ + class GlContext; + class WindowImpl; +} + +class Event; + +//////////////////////////////////////////////////////////// +/// \brief Window that serves as a target for OpenGL rendering +/// +//////////////////////////////////////////////////////////// +class SFML_WINDOW_API Window : GlResource, NonCopyable +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// This constructor doesn't actually create the window, + /// use the other constructors or call "create" to do so. + /// + //////////////////////////////////////////////////////////// + Window(); + + //////////////////////////////////////////////////////////// + /// \brief Construct a new window + /// + /// This constructor creates the window with the size and pixel + /// depth defined in \a mode. An optional style can be passed to + /// customize the look and behaviour of the window (borders, + /// title bar, resizable, closable, ...). If \a style contains + /// Style::Fullscreen, then \a mode must be a valid video mode. + /// + /// The fourth parameter is an optional structure specifying + /// advanced OpenGL context settings such as antialiasing, + /// depth-buffer bits, etc. + /// + /// \param mode Video mode to use (defines the width, height and depth of the rendering area of the window) + /// \param title Title of the window + /// \param style Window style + /// \param settings Additional settings for the underlying OpenGL context + /// + //////////////////////////////////////////////////////////// + Window(VideoMode mode, const String& title, Uint32 style = Style::Default, const ContextSettings& settings = ContextSettings()); + + //////////////////////////////////////////////////////////// + /// \brief Construct the window from an existing control + /// + /// Use this constructor if you want to create an OpenGL + /// rendering area into an already existing control. + /// + /// The second parameter is an optional structure specifying + /// advanced OpenGL context settings such as antialiasing, + /// depth-buffer bits, etc. + /// + /// \param handle Platform-specific handle of the control + /// \param settings Additional settings for the underlying OpenGL context + /// + //////////////////////////////////////////////////////////// + explicit Window(WindowHandle handle, const ContextSettings& settings = ContextSettings()); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + /// Closes the window and free all the resources attached to it. + /// + //////////////////////////////////////////////////////////// + virtual ~Window(); + + //////////////////////////////////////////////////////////// + /// \brief Create (or recreate) the window + /// + /// If the window was already created, it closes it first. + /// If \a style contains Style::Fullscreen, then \a mode + /// must be a valid video mode. + /// + /// \param mode Video mode to use (defines the width, height and depth of the rendering area of the window) + /// \param title Title of the window + /// \param style Window style + /// \param settings Additional settings for the underlying OpenGL context + /// + //////////////////////////////////////////////////////////// + void create(VideoMode mode, const String& title, Uint32 style = Style::Default, const ContextSettings& settings = ContextSettings()); + + //////////////////////////////////////////////////////////// + /// \brief Create (or recreate) the window from an existing control + /// + /// Use this function if you want to create an OpenGL + /// rendering area into an already existing control. + /// If the window was already created, it closes it first. + /// + /// \param handle Platform-specific handle of the control + /// \param settings Additional settings for the underlying OpenGL context + /// + //////////////////////////////////////////////////////////// + void create(WindowHandle handle, const ContextSettings& settings = ContextSettings()); + + //////////////////////////////////////////////////////////// + /// \brief Close the window and destroy all the attached resources + /// + /// After calling this function, the sf::Window instance remains + /// valid and you can call create() to recreate the window. + /// All other functions such as pollEvent() or display() will + /// still work (i.e. you don't have to test isOpen() every time), + /// and will have no effect on closed windows. + /// + //////////////////////////////////////////////////////////// + void close(); + + //////////////////////////////////////////////////////////// + /// \brief Tell whether or not the window is open + /// + /// This function returns whether or not the window exists. + /// Note that a hidden window (setVisible(false)) is open + /// (therefore this function would return true). + /// + /// \return True if the window is open, false if it has been closed + /// + //////////////////////////////////////////////////////////// + bool isOpen() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the settings of the OpenGL context of the window + /// + /// Note that these settings may be different from what was + /// passed to the constructor or the create() function, + /// if one or more settings were not supported. In this case, + /// SFML chose the closest match. + /// + /// \return Structure containing the OpenGL context settings + /// + //////////////////////////////////////////////////////////// + const ContextSettings& getSettings() const; + + //////////////////////////////////////////////////////////// + /// \brief Pop the event on top of the event queue, if any, and return it + /// + /// This function is not blocking: if there's no pending event then + /// it will return false and leave \a event unmodified. + /// Note that more than one event may be present in the event queue, + /// thus you should always call this function in a loop + /// to make sure that you process every pending event. + /// \code + /// sf::Event event; + /// while (window.pollEvent(event)) + /// { + /// // process event... + /// } + /// \endcode + /// + /// \param event Event to be returned + /// + /// \return True if an event was returned, or false if the event queue was empty + /// + /// \see waitEvent + /// + //////////////////////////////////////////////////////////// + bool pollEvent(Event& event); + + //////////////////////////////////////////////////////////// + /// \brief Wait for an event and return it + /// + /// This function is blocking: if there's no pending event then + /// it will wait until an event is received. + /// After this function returns (and no error occured), + /// the \a event object is always valid and filled properly. + /// This function is typically used when you have a thread that + /// is dedicated to events handling: you want to make this thread + /// sleep as long as no new event is received. + /// \code + /// sf::Event event; + /// if (window.waitEvent(event)) + /// { + /// // process event... + /// } + /// \endcode + /// + /// \param event Event to be returned + /// + /// \return False if any error occured + /// + /// \see pollEvent + /// + //////////////////////////////////////////////////////////// + bool waitEvent(Event& event); + + //////////////////////////////////////////////////////////// + /// \brief Get the position of the window + /// + /// \return Position of the window, in pixels + /// + /// \see setPosition + /// + //////////////////////////////////////////////////////////// + Vector2i getPosition() const; + + //////////////////////////////////////////////////////////// + /// \brief Change the position of the window on screen + /// + /// This function only works for top-level windows + /// (i.e. it will be ignored for windows created from + /// the handle of a child window/control). + /// + /// \param position New position, in pixels + /// + /// \see getPosition + /// + //////////////////////////////////////////////////////////// + void setPosition(const Vector2i& position); + + //////////////////////////////////////////////////////////// + /// \brief Get the size of the rendering region of the window + /// + /// The size doesn't include the titlebar and borders + /// of the window. + /// + /// \return Size in pixels + /// + /// \see setSize + /// + //////////////////////////////////////////////////////////// + Vector2u getSize() const; + + //////////////////////////////////////////////////////////// + /// \brief Change the size of the rendering region of the window + /// + /// \param size New size, in pixels + /// + /// \see getSize + /// + //////////////////////////////////////////////////////////// + void setSize(const Vector2u size); + + //////////////////////////////////////////////////////////// + /// \brief Change the title of the window + /// + /// \param title New title + /// + /// \see setIcon + /// + //////////////////////////////////////////////////////////// + void setTitle(const String& title); + + //////////////////////////////////////////////////////////// + /// \brief Change the window's icon + /// + /// \a pixels must be an array of \a width x \a height pixels + /// in 32-bits RGBA format. + /// + /// The OS default icon is used by default. + /// + /// \param width Icon's width, in pixels + /// \param height Icon's height, in pixels + /// \param pixels Pointer to the array of pixels in memory + /// + /// \see setTitle + /// + //////////////////////////////////////////////////////////// + void setIcon(unsigned int width, unsigned int height, const Uint8* pixels); + + //////////////////////////////////////////////////////////// + /// \brief Show or hide the window + /// + /// The window is shown by default. + /// + /// \param visible True to show the window, false to hide it + /// + //////////////////////////////////////////////////////////// + void setVisible(bool visible); + + //////////////////////////////////////////////////////////// + /// \brief Enable or disable vertical synchronization + /// + /// Activating vertical synchronization will limit the number + /// of frames displayed to the refresh rate of the monitor. + /// This can avoid some visual artifacts, and limit the framerate + /// to a good value (but not constant across different computers). + /// + /// Vertical synchronization is disabled by default. + /// + /// \param enabled True to enable v-sync, false to deactivate it + /// + //////////////////////////////////////////////////////////// + void setVerticalSyncEnabled(bool enabled); + + //////////////////////////////////////////////////////////// + /// \brief Show or hide the mouse cursor + /// + /// The mouse cursor is visible by default. + /// + /// \param visible True to show the mouse cursor, false to hide it + /// + //////////////////////////////////////////////////////////// + void setMouseCursorVisible(bool visible); + + //////////////////////////////////////////////////////////// + /// \brief Enable or disable automatic key-repeat + /// + /// If key repeat is enabled, you will receive repeated + /// KeyPressed events while keeping a key pressed. If it is disabled, + /// you will only get a single event when the key is pressed. + /// + /// Key repeat is enabled by default. + /// + /// \param enabled True to enable, false to disable + /// + //////////////////////////////////////////////////////////// + void setKeyRepeatEnabled(bool enabled); + + //////////////////////////////////////////////////////////// + /// \brief Limit the framerate to a maximum fixed frequency + /// + /// If a limit is set, the window will use a small delay after + /// each call to display() to ensure that the current frame + /// lasted long enough to match the framerate limit. + /// SFML will try to match the given limit as much as it can, + /// but since it internally uses sf::sleep, whose precision + /// depends on the underlying OS, the results may be a little + /// unprecise as well (for example, you can get 65 FPS when + /// requesting 60). + /// + /// \param limit Framerate limit, in frames per seconds (use 0 to disable limit) + /// + //////////////////////////////////////////////////////////// + void setFramerateLimit(unsigned int limit); + + //////////////////////////////////////////////////////////// + /// \brief Change the joystick threshold + /// + /// The joystick threshold is the value below which + /// no JoystickMoved event will be generated. + /// + /// The threshold value is 0.1 by default. + /// + /// \param threshold New threshold, in the range [0, 100] + /// + //////////////////////////////////////////////////////////// + void setJoystickThreshold(float threshold); + + //////////////////////////////////////////////////////////// + /// \brief Activate or deactivate the window as the current target + /// for OpenGL rendering + /// + /// A window is active only on the current thread, if you want to + /// make it active on another thread you have to deactivate it + /// on the previous thread first if it was active. + /// Only one window can be active on a thread at a time, thus + /// the window previously active (if any) automatically gets deactivated. + /// + /// \param active True to activate, false to deactivate + /// + /// \return True if operation was successful, false otherwise + /// + //////////////////////////////////////////////////////////// + bool setActive(bool active = true) const; + + //////////////////////////////////////////////////////////// + /// \brief Display on screen what has been rendered to the window so far + /// + /// This function is typically called after all OpenGL rendering + /// has been done for the current frame, in order to show + /// it on screen. + /// + //////////////////////////////////////////////////////////// + void display(); + + //////////////////////////////////////////////////////////// + /// \brief Get the OS-specific handle of the window + /// + /// The type of the returned handle is sf::WindowHandle, + /// which is a typedef to the handle type defined by the OS. + /// You shouldn't need to use this function, unless you have + /// very specific stuff to implement that SFML doesn't support, + /// or implement a temporary workaround until a bug is fixed. + /// + /// \return System handle of the window + /// + //////////////////////////////////////////////////////////// + WindowHandle getSystemHandle() const; + +protected : + + //////////////////////////////////////////////////////////// + /// \brief Function called after the window has been created + /// + /// This function is called so that derived classes can + /// perform their own specific initialization as soon as + /// the window is created. + /// + //////////////////////////////////////////////////////////// + virtual void onCreate(); + + //////////////////////////////////////////////////////////// + /// \brief Function called after the window has been resized + /// + /// This function is called so that derived classes can + /// perform custom actions when the size of the window changes. + /// + //////////////////////////////////////////////////////////// + virtual void onResize(); + +private: + + //////////////////////////////////////////////////////////// + /// \brief Processes an event before it is sent to the user + /// + /// This function is called every time an event is received + /// from the internal window (through pollEvent or waitEvent). + /// It filters out unwanted events, and performs whatever internal + /// stuff the window needs before the event is returned to the + /// user. + /// + /// \param event Event to filter + /// + //////////////////////////////////////////////////////////// + bool filterEvent(const Event& event); + + //////////////////////////////////////////////////////////// + /// \brief Perform some common internal initializations + /// + //////////////////////////////////////////////////////////// + void initialize(); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + priv::WindowImpl* m_impl; ///< Platform-specific implementation of the window + priv::GlContext* m_context; ///< Platform-specific implementation of the OpenGL context + Clock m_clock; ///< Clock for measuring the elapsed time between frames + Time m_frameTimeLimit; ///< Current framerate limit + Vector2u m_size; ///< Current size of the window +}; + +} // namespace sf + + +#endif // SFML_WINDOW_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Window +/// \ingroup window +/// +/// sf::Window is the main class of the Window module. It defines +/// an OS window that is able to receive an OpenGL rendering. +/// +/// A sf::Window can create its own new window, or be embedded into +/// an already existing control using the create(handle) function. +/// This can be useful for embedding an OpenGL rendering area into +/// a view which is part of a bigger GUI with existing windows, +/// controls, etc. It can also serve as embedding an OpenGL rendering +/// area into a window created by another (probably richer) GUI library +/// like Qt or wxWidgets. +/// +/// The sf::Window class provides a simple interface for manipulating +/// the window: move, resize, show/hide, control mouse cursor, etc. +/// It also provides event handling through its pollEvent() and waitEvent() +/// functions. +/// +/// Note that OpenGL experts can pass their own parameters (antialiasing +/// level, bits for the depth and stencil buffers, etc.) to the +/// OpenGL context attached to the window, with the sf::ContextSettings +/// structure which is passed as an optional argument when creating the +/// window. +/// +/// Usage example: +/// \code +/// // Declare and create a new window +/// sf::Window window(sf::VideoMode(800, 600), "SFML window"); +/// +/// // Limit the framerate to 60 frames per second (this step is optional) +/// window.setFramerateLimit(60); +/// +/// // The main loop - ends as soon as the window is closed +/// while (window.isOpen()) +/// { +/// // Event processing +/// sf::Event event; +/// while (window.pollEvent(event)) +/// { +/// // Request for closing the window +/// if (event.type == sf::Event::Closed) +/// window.close(); +/// } +/// +/// // Activate the window for OpenGL rendering +/// window.setActive(); +/// +/// // OpenGL drawing commands go here... +/// +/// // End the current frame and display its contents on screen +/// window.display(); +/// } +/// \endcode +/// +//////////////////////////////////////////////////////////// diff --git a/src/include/SFML/include/SFML/Window/WindowHandle.hpp b/src/include/SFML/include/SFML/Window/WindowHandle.hpp new file mode 100644 index 0000000..7fb2bb8 --- /dev/null +++ b/src/include/SFML/include/SFML/Window/WindowHandle.hpp @@ -0,0 +1,64 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_WINDOWHANDLE_HPP +#define SFML_WINDOWHANDLE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + +// Windows' HWND is a typedef on struct HWND__* +#if defined(SFML_SYSTEM_WINDOWS) + struct HWND__; +#endif + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// Define a low-level window handle type, specific to +/// each platform +//////////////////////////////////////////////////////////// +#if defined(SFML_SYSTEM_WINDOWS) + + // Window handle is HWND (HWND__*) on Windows + typedef HWND__* WindowHandle; + +#elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD) + + // Window handle is Window (unsigned long) on Unix - X11 + typedef unsigned long WindowHandle; + +#elif defined(SFML_SYSTEM_MACOS) + + // Window handle is NSWindow (void*) on Mac OS X - Cocoa + typedef void* WindowHandle; + +#endif + +} // namespace sf + + +#endif // SFML_WINDOWHANDLE_HPP diff --git a/src/include/SFML/include/SFML/Window/WindowStyle.hpp b/src/include/SFML/include/SFML/Window/WindowStyle.hpp new file mode 100644 index 0000000..f0ce33b --- /dev/null +++ b/src/include/SFML/include/SFML/Window/WindowStyle.hpp @@ -0,0 +1,53 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_WINDOWSTYLE_HPP +#define SFML_WINDOWSTYLE_HPP + + +namespace sf +{ +namespace Style +{ + //////////////////////////////////////////////////////////// + /// \ingroup window + /// \brief Enumeration of the window styles + /// + //////////////////////////////////////////////////////////// + enum + { + None = 0, ///< No border / title bar (this flag and all others are mutually exclusive) + Titlebar = 1 << 0, ///< Title bar + fixed border + Resize = 1 << 1, ///< Titlebar + resizable border + maximize button + Close = 1 << 2, ///< Titlebar + close button + Fullscreen = 1 << 3, ///< Fullscreen mode (this flag and all others are mutually exclusive) + + Default = Titlebar | Resize | Close ///< Default window style + }; +} + +} // namespace sf + + +#endif // SFML_WINDOWSTYLE_HPP diff --git a/src/include/SFML/lib/libsfml-audio-d.a b/src/include/SFML/lib/libsfml-audio-d.a new file mode 100644 index 0000000..f9e17d1 Binary files /dev/null and b/src/include/SFML/lib/libsfml-audio-d.a differ diff --git a/src/include/SFML/lib/libsfml-audio-s-d.a b/src/include/SFML/lib/libsfml-audio-s-d.a new file mode 100644 index 0000000..c466151 Binary files /dev/null and b/src/include/SFML/lib/libsfml-audio-s-d.a differ diff --git a/src/include/SFML/lib/libsfml-audio-s.a b/src/include/SFML/lib/libsfml-audio-s.a new file mode 100644 index 0000000..81e0bc9 Binary files /dev/null and b/src/include/SFML/lib/libsfml-audio-s.a differ diff --git a/src/include/SFML/lib/libsfml-audio.a b/src/include/SFML/lib/libsfml-audio.a new file mode 100644 index 0000000..f1c629e Binary files /dev/null and b/src/include/SFML/lib/libsfml-audio.a differ diff --git a/src/include/SFML/lib/libsfml-graphics-d.a b/src/include/SFML/lib/libsfml-graphics-d.a new file mode 100644 index 0000000..ae3cc5f Binary files /dev/null and b/src/include/SFML/lib/libsfml-graphics-d.a differ diff --git a/src/include/SFML/lib/libsfml-graphics-s-d.a b/src/include/SFML/lib/libsfml-graphics-s-d.a new file mode 100644 index 0000000..7d94039 Binary files /dev/null and b/src/include/SFML/lib/libsfml-graphics-s-d.a differ diff --git a/src/include/SFML/lib/libsfml-graphics-s.a b/src/include/SFML/lib/libsfml-graphics-s.a new file mode 100644 index 0000000..623ecaa Binary files /dev/null and b/src/include/SFML/lib/libsfml-graphics-s.a differ diff --git a/src/include/SFML/lib/libsfml-main-d.a b/src/include/SFML/lib/libsfml-main-d.a new file mode 100644 index 0000000..e8007e4 Binary files /dev/null and b/src/include/SFML/lib/libsfml-main-d.a differ diff --git a/src/include/SFML/lib/libsfml-main.a b/src/include/SFML/lib/libsfml-main.a new file mode 100644 index 0000000..20de569 Binary files /dev/null and b/src/include/SFML/lib/libsfml-main.a differ diff --git a/src/include/SFML/lib/libsfml-network-d.a b/src/include/SFML/lib/libsfml-network-d.a new file mode 100644 index 0000000..c6dfe05 Binary files /dev/null and b/src/include/SFML/lib/libsfml-network-d.a differ diff --git a/src/include/SFML/lib/libsfml-network-s-d.a b/src/include/SFML/lib/libsfml-network-s-d.a new file mode 100644 index 0000000..de0ffe8 Binary files /dev/null and b/src/include/SFML/lib/libsfml-network-s-d.a differ diff --git a/src/include/SFML/lib/libsfml-network-s.a b/src/include/SFML/lib/libsfml-network-s.a new file mode 100644 index 0000000..bfb3f62 Binary files /dev/null and b/src/include/SFML/lib/libsfml-network-s.a differ diff --git a/src/include/SFML/lib/libsfml-network.a b/src/include/SFML/lib/libsfml-network.a new file mode 100644 index 0000000..8850ebd Binary files /dev/null and b/src/include/SFML/lib/libsfml-network.a differ diff --git a/src/include/SFML/lib/libsfml-system-d.a b/src/include/SFML/lib/libsfml-system-d.a new file mode 100644 index 0000000..231d8d2 Binary files /dev/null and b/src/include/SFML/lib/libsfml-system-d.a differ diff --git a/src/include/SFML/lib/libsfml-system-s-d.a b/src/include/SFML/lib/libsfml-system-s-d.a new file mode 100644 index 0000000..65ff80c Binary files /dev/null and b/src/include/SFML/lib/libsfml-system-s-d.a differ diff --git a/src/include/SFML/lib/libsfml-system-s.a b/src/include/SFML/lib/libsfml-system-s.a new file mode 100644 index 0000000..a261232 Binary files /dev/null and b/src/include/SFML/lib/libsfml-system-s.a differ diff --git a/src/include/SFML/lib/libsfml-system.a b/src/include/SFML/lib/libsfml-system.a new file mode 100644 index 0000000..df40b6a Binary files /dev/null and b/src/include/SFML/lib/libsfml-system.a differ diff --git a/src/include/SFML/lib/libsfml-window-d.a b/src/include/SFML/lib/libsfml-window-d.a new file mode 100644 index 0000000..00fb543 Binary files /dev/null and b/src/include/SFML/lib/libsfml-window-d.a differ diff --git a/src/include/SFML/lib/libsfml-window-s-d.a b/src/include/SFML/lib/libsfml-window-s-d.a new file mode 100644 index 0000000..c8ab6ed Binary files /dev/null and b/src/include/SFML/lib/libsfml-window-s-d.a differ diff --git a/src/include/SFML/lib/libsfml-window-s.a b/src/include/SFML/lib/libsfml-window-s.a new file mode 100644 index 0000000..b54fd00 Binary files /dev/null and b/src/include/SFML/lib/libsfml-window-s.a differ diff --git a/src/include/SFML/lib/libsfml-window.a b/src/include/SFML/lib/libsfml-window.a new file mode 100644 index 0000000..2c727a9 Binary files /dev/null and b/src/include/SFML/lib/libsfml-window.a differ diff --git a/src/include/rapidjson/allocators.h b/src/include/rapidjson/allocators.h new file mode 100644 index 0000000..0bd2d28 --- /dev/null +++ b/src/include/rapidjson/allocators.h @@ -0,0 +1,245 @@ +// Copyright (C) 2011 Milo Yip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef RAPIDJSON_ALLOCATORS_H_ +#define RAPIDJSON_ALLOCATORS_H_ + +#include "rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// Allocator + +/*! \class rapidjson::Allocator + \brief Concept for allocating, resizing and freeing memory block. + + Note that Malloc() and Realloc() are non-static but Free() is static. + + So if an allocator need to support Free(), it needs to put its pointer in + the header of memory block. + +\code +concept Allocator { + static const bool kNeedFree; //!< Whether this allocator needs to call Free(). + + // Allocate a memory block. + // \param size of the memory block in bytes. + // \returns pointer to the memory block. + void* Malloc(size_t size); + + // Resize a memory block. + // \param originalPtr The pointer to current memory block. Null pointer is permitted. + // \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.) + // \param newSize the new size in bytes. + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize); + + // Free a memory block. + // \param pointer to the memory block. Null pointer is permitted. + static void Free(void *ptr); +}; +\endcode +*/ + +/////////////////////////////////////////////////////////////////////////////// +// CrtAllocator + +//! C-runtime library allocator. +/*! This class is just wrapper for standard C library memory routines. + \note implements Allocator concept +*/ +class CrtAllocator { +public: + static const bool kNeedFree = true; + void* Malloc(size_t size) { return std::malloc(size); } + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { (void)originalSize; return std::realloc(originalPtr, newSize); } + static void Free(void *ptr) { std::free(ptr); } +}; + +/////////////////////////////////////////////////////////////////////////////// +// MemoryPoolAllocator + +//! Default memory allocator used by the parser and DOM. +/*! This allocator allocate memory blocks from pre-allocated memory chunks. + + It does not free memory blocks. And Realloc() only allocate new memory. + + The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default. + + User may also supply a buffer as the first chunk. + + If the user-buffer is full then additional chunks are allocated by BaseAllocator. + + The user-buffer is not deallocated by this allocator. + + \tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator. + \note implements Allocator concept +*/ +template +class MemoryPoolAllocator { +public: + static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator) + + //! Constructor with chunkSize. + /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. + \param baseAllocator The allocator for allocating memory chunks. + */ + MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : + chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0) + { + } + + //! Constructor with user-supplied buffer. + /*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size. + + The user buffer will not be deallocated when this allocator is destructed. + + \param buffer User supplied buffer. + \param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader). + \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. + \param baseAllocator The allocator for allocating memory chunks. + */ + MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : + chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0) + { + RAPIDJSON_ASSERT(buffer != 0); + RAPIDJSON_ASSERT(size > sizeof(ChunkHeader)); + chunkHead_ = reinterpret_cast(buffer); + chunkHead_->capacity = size - sizeof(ChunkHeader); + chunkHead_->size = 0; + chunkHead_->next = 0; + } + + //! Destructor. + /*! This deallocates all memory chunks, excluding the user-supplied buffer. + */ + ~MemoryPoolAllocator() { + Clear(); + RAPIDJSON_DELETE(ownBaseAllocator_); + } + + //! Deallocates all memory chunks, excluding the user-supplied buffer. + void Clear() { + while(chunkHead_ != 0 && chunkHead_ != userBuffer_) { + ChunkHeader* next = chunkHead_->next; + baseAllocator_->Free(chunkHead_); + chunkHead_ = next; + } + } + + //! Computes the total capacity of allocated memory chunks. + /*! \return total capacity in bytes. + */ + size_t Capacity() const { + size_t capacity = 0; + for (ChunkHeader* c = chunkHead_; c != 0; c = c->next) + capacity += c->capacity; + return capacity; + } + + //! Computes the memory blocks allocated. + /*! \return total used bytes. + */ + size_t Size() const { + size_t size = 0; + for (ChunkHeader* c = chunkHead_; c != 0; c = c->next) + size += c->size; + return size; + } + + //! Allocates a memory block. (concept Allocator) + void* Malloc(size_t size) { + size = RAPIDJSON_ALIGN(size); + if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity) + AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size); + + void *buffer = reinterpret_cast(chunkHead_ + 1) + chunkHead_->size; + chunkHead_->size += size; + return buffer; + } + + //! Resizes a memory block (concept Allocator) + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { + if (originalPtr == 0) + return Malloc(newSize); + + // Do not shrink if new size is smaller than original + if (originalSize >= newSize) + return originalPtr; + + // Simply expand it if it is the last allocation and there is sufficient space + if (originalPtr == (char *)(chunkHead_ + 1) + chunkHead_->size - originalSize) { + size_t increment = static_cast(newSize - originalSize); + increment = RAPIDJSON_ALIGN(increment); + if (chunkHead_->size + increment <= chunkHead_->capacity) { + chunkHead_->size += increment; + return originalPtr; + } + } + + // Realloc process: allocate and copy memory, do not free original buffer. + void* newBuffer = Malloc(newSize); + RAPIDJSON_ASSERT(newBuffer != 0); // Do not handle out-of-memory explicitly. + return std::memcpy(newBuffer, originalPtr, originalSize); + } + + //! Frees a memory block (concept Allocator) + static void Free(void *ptr) { (void)ptr; } // Do nothing + +private: + //! Copy constructor is not permitted. + MemoryPoolAllocator(const MemoryPoolAllocator& rhs) /* = delete */; + //! Copy assignment operator is not permitted. + MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) /* = delete */; + + //! Creates a new chunk. + /*! \param capacity Capacity of the chunk in bytes. + */ + void AddChunk(size_t capacity) { + if (!baseAllocator_) + ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator()); + ChunkHeader* chunk = reinterpret_cast(baseAllocator_->Malloc(sizeof(ChunkHeader) + capacity)); + chunk->capacity = capacity; + chunk->size = 0; + chunk->next = chunkHead_; + chunkHead_ = chunk; + } + + static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity. + + //! Chunk header for perpending to each chunk. + /*! Chunks are stored as a singly linked list. + */ + struct ChunkHeader { + size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself). + size_t size; //!< Current size of allocated memory in bytes. + ChunkHeader *next; //!< Next chunk in the linked list. + }; + + ChunkHeader *chunkHead_; //!< Head of the chunk linked-list. Only the head chunk serves allocation. + size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated. + void *userBuffer_; //!< User supplied buffer. + BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks. + BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object. +}; + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_ENCODINGS_H_ diff --git a/src/include/rapidjson/document.h b/src/include/rapidjson/document.h new file mode 100644 index 0000000..94d6e53 --- /dev/null +++ b/src/include/rapidjson/document.h @@ -0,0 +1,1932 @@ +// Copyright (C) 2011 Milo Yip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef RAPIDJSON_DOCUMENT_H_ +#define RAPIDJSON_DOCUMENT_H_ + +/*! \file document.h */ + +#include "reader.h" +#include "internal/meta.h" +#include "internal/strfunc.h" +#include // placement new + +#ifdef _MSC_VER +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant +#elif defined(__GNUC__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_HAS_STDSTRING + +#ifndef RAPIDJSON_HAS_STDSTRING +#ifdef RAPIDJSON_DOXYGEN_RUNNING +#define RAPIDJSON_HAS_STDSTRING 1 // force generation of documentation +#else +#define RAPIDJSON_HAS_STDSTRING 0 // no std::string support by default +#endif +/*! \def RAPIDJSON_HAS_STDSTRING + \ingroup RAPIDJSON_CONFIG + \brief Enable RapidJSON support for \c std::string + + By defining this preprocessor symbol to \c 1, several convenience functions for using + \ref rapidjson::GenericValue with \c std::string are enabled, especially + for construction and comparison. + + \hideinitializer +*/ +#include +#endif // RAPIDJSON_HAS_STDSTRING + +#ifndef RAPIDJSON_NOMEMBERITERATORCLASS +#include // std::iterator, std::random_access_iterator_tag +#endif + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS +#include // std::move +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +// Forward declaration. +template +class GenericValue; + +//! Name-value pair in a JSON object value. +/*! + This class was internal to GenericValue. It used to be a inner struct. + But a compiler (IBM XL C/C++ for AIX) have reported to have problem with that so it moved as a namespace scope struct. + https://code.google.com/p/rapidjson/issues/detail?id=64 +*/ +template +struct GenericMember { + GenericValue name; //!< name of member (must be a string) + GenericValue value; //!< value of member. +}; + +/////////////////////////////////////////////////////////////////////////////// +// GenericMemberIterator + +#ifndef RAPIDJSON_NOMEMBERITERATORCLASS + +//! (Constant) member iterator for a JSON object value +/*! + \tparam Const Is this a constant iterator? + \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document) + \tparam Allocator Allocator type for allocating memory of object, array and string. + + This class implements a Random Access Iterator for GenericMember elements + of a GenericValue, see ISO/IEC 14882:2003(E) C++ standard, 24.1 [lib.iterator.requirements]. + + \note This iterator implementation is mainly intended to avoid implicit + conversions from iterator values to \c NULL, + e.g. from GenericValue::FindMember. + + \note Define \c RAPIDJSON_NOMEMBERITERATORCLASS to fall back to a + pointer-based implementation, if your platform doesn't provide + the C++ header. + + \see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator + */ +template +class GenericMemberIterator + : public std::iterator >::Type> { + + friend class GenericValue; + template friend class GenericMemberIterator; + + typedef GenericMember PlainType; + typedef typename internal::MaybeAddConst::Type ValueType; + typedef std::iterator BaseType; + +public: + //! Iterator type itself + typedef GenericMemberIterator Iterator; + //! Constant iterator type + typedef GenericMemberIterator ConstIterator; + //! Non-constant iterator type + typedef GenericMemberIterator NonConstIterator; + + //! Pointer to (const) GenericMember + typedef typename BaseType::pointer Pointer; + //! Reference to (const) GenericMember + typedef typename BaseType::reference Reference; + //! Signed integer type (e.g. \c ptrdiff_t) + typedef typename BaseType::difference_type DifferenceType; + + //! Default constructor (singular value) + /*! Creates an iterator pointing to no element. + \note All operations, except for comparisons, are undefined on such values. + */ + GenericMemberIterator() : ptr_() {} + + //! Iterator conversions to more const + /*! + \param it (Non-const) iterator to copy from + + Allows the creation of an iterator from another GenericMemberIterator + that is "less const". Especially, creating a non-constant iterator + from a constant iterator are disabled: + \li const -> non-const (not ok) + \li const -> const (ok) + \li non-const -> const (ok) + \li non-const -> non-const (ok) + + \note If the \c Const template parameter is already \c false, this + constructor effectively defines a regular copy-constructor. + Otherwise, the copy constructor is implicitly defined. + */ + GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {} + + //! @name stepping + //@{ + Iterator& operator++(){ ++ptr_; return *this; } + Iterator& operator--(){ --ptr_; return *this; } + Iterator operator++(int){ Iterator old(*this); ++ptr_; return old; } + Iterator operator--(int){ Iterator old(*this); --ptr_; return old; } + //@} + + //! @name increment/decrement + //@{ + Iterator operator+(DifferenceType n) const { return Iterator(ptr_+n); } + Iterator operator-(DifferenceType n) const { return Iterator(ptr_-n); } + + Iterator& operator+=(DifferenceType n) { ptr_+=n; return *this; } + Iterator& operator-=(DifferenceType n) { ptr_-=n; return *this; } + //@} + + //! @name relations + //@{ + bool operator==(ConstIterator that) const { return ptr_ == that.ptr_; } + bool operator!=(ConstIterator that) const { return ptr_ != that.ptr_; } + bool operator<=(ConstIterator that) const { return ptr_ <= that.ptr_; } + bool operator>=(ConstIterator that) const { return ptr_ >= that.ptr_; } + bool operator< (ConstIterator that) const { return ptr_ < that.ptr_; } + bool operator> (ConstIterator that) const { return ptr_ > that.ptr_; } + //@} + + //! @name dereference + //@{ + Reference operator*() const { return *ptr_; } + Pointer operator->() const { return ptr_; } + Reference operator[](DifferenceType n) const { return ptr_[n]; } + //@} + + //! Distance + DifferenceType operator-(ConstIterator that) const { return ptr_-that.ptr_; } + +private: + //! Internal constructor from plain pointer + explicit GenericMemberIterator(Pointer p) : ptr_(p) {} + + Pointer ptr_; //!< raw pointer +}; + +#else // RAPIDJSON_NOMEMBERITERATORCLASS + +// class-based member iterator implementation disabled, use plain pointers + +template +struct GenericMemberIterator; + +//! non-const GenericMemberIterator +template +struct GenericMemberIterator { + //! use plain pointer as iterator type + typedef GenericMember* Iterator; +}; +//! const GenericMemberIterator +template +struct GenericMemberIterator { + //! use plain const pointer as iterator type + typedef const GenericMember* Iterator; +}; + +#endif // RAPIDJSON_NOMEMBERITERATORCLASS + +/////////////////////////////////////////////////////////////////////////////// +// GenericStringRef + +//! Reference to a constant string (not taking a copy) +/*! + \tparam CharType character type of the string + + This helper class is used to automatically infer constant string + references for string literals, especially from \c const \b (!) + character arrays. + + The main use is for creating JSON string values without copying the + source string via an \ref Allocator. This requires that the referenced + string pointers have a sufficient lifetime, which exceeds the lifetime + of the associated GenericValue. + + \b Example + \code + Value v("foo"); // ok, no need to copy & calculate length + const char foo[] = "foo"; + v.SetString(foo); // ok + + const char* bar = foo; + // Value x(bar); // not ok, can't rely on bar's lifetime + Value x(StringRef(bar)); // lifetime explicitly guaranteed by user + Value y(StringRef(bar, 3)); // ok, explicitly pass length + \endcode + + \see StringRef, GenericValue::SetString +*/ +template +struct GenericStringRef { + typedef CharType Ch; //!< character type of the string + + //! Create string reference from \c const character array + /*! + This constructor implicitly creates a constant string reference from + a \c const character array. It has better performance than + \ref StringRef(const CharType*) by inferring the string \ref length + from the array length, and also supports strings containing null + characters. + + \tparam N length of the string, automatically inferred + + \param str Constant character array, lifetime assumed to be longer + than the use of the string in e.g. a GenericValue + + \post \ref s == str + + \note Constant complexity. + \note There is a hidden, private overload to disallow references to + non-const character arrays to be created via this constructor. + By this, e.g. function-scope arrays used to be filled via + \c snprintf are excluded from consideration. + In such cases, the referenced string should be \b copied to the + GenericValue instead. + */ + template + GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT + : s(str), length(N-1) {} + + //! Explicitly create string reference from \c const character pointer + /*! + This constructor can be used to \b explicitly create a reference to + a constant string pointer. + + \see StringRef(const CharType*) + + \param str Constant character pointer, lifetime assumed to be longer + than the use of the string in e.g. a GenericValue + + \post \ref s == str + + \note There is a hidden, private overload to disallow references to + non-const character arrays to be created via this constructor. + By this, e.g. function-scope arrays used to be filled via + \c snprintf are excluded from consideration. + In such cases, the referenced string should be \b copied to the + GenericValue instead. + */ + explicit GenericStringRef(const CharType* str) + : s(str), length(internal::StrLen(str)){ RAPIDJSON_ASSERT(s != NULL); } + + //! Create constant string reference from pointer and length + /*! \param str constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \param len length of the string, excluding the trailing NULL terminator + + \post \ref s == str && \ref length == len + \note Constant complexity. + */ + GenericStringRef(const CharType* str, SizeType len) + : s(str), length(len) { RAPIDJSON_ASSERT(s != NULL); } + + //! implicit conversion to plain CharType pointer + operator const Ch *() const { return s; } + + const Ch* const s; //!< plain CharType pointer + const SizeType length; //!< length of the string (excluding the trailing NULL terminator) + +private: + //! Disallow copy-assignment + GenericStringRef operator=(const GenericStringRef&); + //! Disallow construction from non-const array + template + GenericStringRef(CharType (&str)[N]) /* = delete */; +}; + +//! Mark a character pointer as constant string +/*! Mark a plain character pointer as a "string literal". This function + can be used to avoid copying a character string to be referenced as a + value in a JSON GenericValue object, if the string's lifetime is known + to be valid long enough. + \tparam CharType Character type of the string + \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \return GenericStringRef string reference object + \relatesalso GenericStringRef + + \see GenericValue::GenericValue(StringRefType), GenericValue::operator=(StringRefType), GenericValue::SetString(StringRefType), GenericValue::PushBack(StringRefType, Allocator&), GenericValue::AddMember +*/ +template +inline GenericStringRef StringRef(const CharType* str) { + return GenericStringRef(str, internal::StrLen(str)); +} + +//! Mark a character pointer as constant string +/*! Mark a plain character pointer as a "string literal". This function + can be used to avoid copying a character string to be referenced as a + value in a JSON GenericValue object, if the string's lifetime is known + to be valid long enough. + + This version has better performance with supplied length, and also + supports string containing null characters. + + \tparam CharType character type of the string + \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \param length The length of source string. + \return GenericStringRef string reference object + \relatesalso GenericStringRef +*/ +template +inline GenericStringRef StringRef(const CharType* str, size_t length) { + return GenericStringRef(str, SizeType(length)); +} + +#if RAPIDJSON_HAS_STDSTRING +//! Mark a string object as constant string +/*! Mark a string object (e.g. \c std::string) as a "string literal". + This function can be used to avoid copying a string to be referenced as a + value in a JSON GenericValue object, if the string's lifetime is known + to be valid long enough. + + \tparam CharType character type of the string + \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \return GenericStringRef string reference object + \relatesalso GenericStringRef + \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. +*/ +template +inline GenericStringRef StringRef(const std::basic_string& str) { + return GenericStringRef(str.data(), SizeType(str.size())); +} +#endif + +/////////////////////////////////////////////////////////////////////////////// +// GenericValue type traits +namespace internal { + +template +struct IsGenericValueImpl : FalseType {}; + +// select candidates according to nested encoding and allocator types +template struct IsGenericValueImpl::Type, typename Void::Type> + : IsBaseOf, T>::Type {}; + +// helper to match arbitrary GenericValue instantiations, including derived classes +template struct IsGenericValue : IsGenericValueImpl::Type {}; + +} // namespace internal + +/////////////////////////////////////////////////////////////////////////////// +// GenericValue + +//! Represents a JSON value. Use Value for UTF8 encoding and default allocator. +/*! + A JSON value can be one of 7 types. This class is a variant type supporting + these types. + + Use the Value if UTF8 and default allocator + + \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document) + \tparam Allocator Allocator type for allocating memory of object, array and string. +*/ +template > +class GenericValue { +public: + //! Name-value pair in an object. + typedef GenericMember Member; + typedef Encoding EncodingType; //!< Encoding type from template parameter. + typedef Allocator AllocatorType; //!< Allocator type from template parameter. + typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. + typedef GenericStringRef StringRefType; //!< Reference to a constant string + typedef typename GenericMemberIterator::Iterator MemberIterator; //!< Member iterator for iterating in object. + typedef typename GenericMemberIterator::Iterator ConstMemberIterator; //!< Constant member iterator for iterating in object. + typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array. + typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array. + + //!@name Constructors and destructor. + //@{ + + //! Default constructor creates a null value. + GenericValue() RAPIDJSON_NOEXCEPT : data_(), flags_(kNullFlag) {} + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move constructor in C++11 + GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_), flags_(rhs.flags_) { + rhs.flags_ = kNullFlag; // give up contents + } +#endif + +private: + //! Copy constructor is not permitted. + GenericValue(const GenericValue& rhs); + +public: + + //! Constructor with JSON value type. + /*! This creates a Value of specified type with default content. + \param type Type of the value. + \note Default content for number is zero. + */ + explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_(), flags_() { + static const unsigned defaultFlags[7] = { + kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag, + kNumberAnyFlag + }; + RAPIDJSON_ASSERT(type <= kNumberType); + flags_ = defaultFlags[type]; + + // Use ShortString to store empty string. + if (type == kStringType) + data_.ss.SetLength(0); + } + + //! Explicit copy constructor (with allocator) + /*! Creates a copy of a Value by using the given Allocator + \tparam SourceAllocator allocator of \c rhs + \param rhs Value to copy from (read-only) + \param allocator Allocator for allocating copied elements and buffers. Commonly use GenericDocument::GetAllocator(). + \see CopyFrom() + */ + template< typename SourceAllocator > + GenericValue(const GenericValue& rhs, Allocator & allocator); + + //! Constructor for boolean value. + /*! \param b Boolean value + \note This constructor is limited to \em real boolean values and rejects + implicitly converted types like arbitrary pointers. Use an explicit cast + to \c bool, if you want to construct a boolean JSON value in such cases. + */ +#ifndef RAPIDJSON_DOXYGEN_RUNNING // hide SFINAE from Doxygen + template + explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame))) RAPIDJSON_NOEXCEPT +#else + explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT +#endif + : data_(), flags_(b ? kTrueFlag : kFalseFlag) { + // safe-guard against failing SFINAE + RAPIDJSON_STATIC_ASSERT((internal::IsSame::Value)); + } + + //! Constructor for int value. + explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberIntFlag) { + data_.n.i64 = i; + if (i >= 0) + flags_ |= kUintFlag | kUint64Flag; + } + + //! Constructor for unsigned value. + explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberUintFlag) { + data_.n.u64 = u; + if (!(u & 0x80000000)) + flags_ |= kIntFlag | kInt64Flag; + } + + //! Constructor for int64_t value. + explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberInt64Flag) { + data_.n.i64 = i64; + if (i64 >= 0) { + flags_ |= kNumberUint64Flag; + if (!(static_cast(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000))) + flags_ |= kUintFlag; + if (!(static_cast(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) + flags_ |= kIntFlag; + } + else if (i64 >= static_cast(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) + flags_ |= kIntFlag; + } + + //! Constructor for uint64_t value. + explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberUint64Flag) { + data_.n.u64 = u64; + if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000))) + flags_ |= kInt64Flag; + if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000))) + flags_ |= kUintFlag; + if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) + flags_ |= kIntFlag; + } + + //! Constructor for double value. + explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberDoubleFlag) { data_.n.d = d; } + + //! Constructor for constant string (i.e. do not make a copy of string) + GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_(), flags_() { SetStringRaw(StringRef(s, length)); } + + //! Constructor for constant string (i.e. do not make a copy of string) + explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_(), flags_() { SetStringRaw(s); } + + //! Constructor for copy-string (i.e. do make a copy of string) + GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s, length), allocator); } + + //! Constructor for copy-string (i.e. do make a copy of string) + GenericValue(const Ch*s, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s), allocator); } + +#if RAPIDJSON_HAS_STDSTRING + //! Constructor for copy-string from a string object (i.e. do make a copy of string) + /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + GenericValue(const std::basic_string& s, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s), allocator); } +#endif + + //! Destructor. + /*! Need to destruct elements of array, members of object, or copy-string. + */ + ~GenericValue() { + if (Allocator::kNeedFree) { // Shortcut by Allocator's trait + switch(flags_) { + case kArrayFlag: + for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v) + v->~GenericValue(); + Allocator::Free(data_.a.elements); + break; + + case kObjectFlag: + for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) + m->~Member(); + Allocator::Free(data_.o.members); + break; + + case kCopyStringFlag: + Allocator::Free(const_cast(data_.s.str)); + break; + + default: + break; // Do nothing for other types. + } + } + } + + //@} + + //!@name Assignment operators + //@{ + + //! Assignment with move semantics. + /*! \param rhs Source of the assignment. It will become a null value after assignment. + */ + GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT { + RAPIDJSON_ASSERT(this != &rhs); + this->~GenericValue(); + RawAssign(rhs); + return *this; + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move assignment in C++11 + GenericValue& operator=(GenericValue&& rhs) RAPIDJSON_NOEXCEPT { + return *this = rhs.Move(); + } +#endif + + //! Assignment of constant string reference (no copy) + /*! \param str Constant string reference to be assigned + \note This overload is needed to avoid clashes with the generic primitive type assignment overload below. + \see GenericStringRef, operator=(T) + */ + GenericValue& operator=(StringRefType str) RAPIDJSON_NOEXCEPT { + GenericValue s(str); + return *this = s; + } + + //! Assignment with primitive types. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param value The value to be assigned. + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref SetString(const Ch*, Allocator&) (for copying) or + \ref StringRef() (to explicitly mark the pointer as constant) instead. + All other pointer types would implicitly convert to \c bool, + use \ref SetBool() instead. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::IsPointer), (GenericValue&)) + operator=(T value) { + GenericValue v(value); + return *this = v; + } + + //! Deep-copy assignment from Value + /*! Assigns a \b copy of the Value to the current Value object + \tparam SourceAllocator Allocator type of \c rhs + \param rhs Value to copy from (read-only) + \param allocator Allocator to use for copying + */ + template + GenericValue& CopyFrom(const GenericValue& rhs, Allocator& allocator) { + RAPIDJSON_ASSERT((void*)this != (void const*)&rhs); + this->~GenericValue(); + new (this) GenericValue(rhs, allocator); + return *this; + } + + //! Exchange the contents of this value with those of other. + /*! + \param other Another value. + \note Constant complexity. + */ + GenericValue& Swap(GenericValue& other) RAPIDJSON_NOEXCEPT { + GenericValue temp; + temp.RawAssign(*this); + RawAssign(other); + other.RawAssign(temp); + return *this; + } + + //! Prepare Value for move semantics + /*! \return *this */ + GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; } + //@} + + //!@name Equal-to and not-equal-to operators + //@{ + //! Equal-to operator + /*! + \note If an object contains duplicated named member, comparing equality with any object is always \c false. + \note Linear time complexity (number of all values in the subtree and total lengths of all strings). + */ + template + bool operator==(const GenericValue& rhs) const { + typedef GenericValue RhsType; + if (GetType() != rhs.GetType()) + return false; + + switch (GetType()) { + case kObjectType: // Warning: O(n^2) inner-loop + if (data_.o.size != rhs.data_.o.size) + return false; + for (ConstMemberIterator lhsMemberItr = MemberBegin(); lhsMemberItr != MemberEnd(); ++lhsMemberItr) { + typename RhsType::ConstMemberIterator rhsMemberItr = rhs.FindMember(lhsMemberItr->name); + if (rhsMemberItr == rhs.MemberEnd() || lhsMemberItr->value != rhsMemberItr->value) + return false; + } + return true; + + case kArrayType: + if (data_.a.size != rhs.data_.a.size) + return false; + for (SizeType i = 0; i < data_.a.size; i++) + if ((*this)[i] != rhs[i]) + return false; + return true; + + case kStringType: + return StringEqual(rhs); + + case kNumberType: + if (IsDouble() || rhs.IsDouble()) + return GetDouble() == rhs.GetDouble(); // May convert one operand from integer to double. + else + return data_.n.u64 == rhs.data_.n.u64; + + default: // kTrueType, kFalseType, kNullType + return true; + } + } + + //! Equal-to operator with const C-string pointer + bool operator==(const Ch* rhs) const { return *this == GenericValue(StringRef(rhs)); } + +#if RAPIDJSON_HAS_STDSTRING + //! Equal-to operator with string object + /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + bool operator==(const std::basic_string& rhs) const { return *this == GenericValue(StringRef(rhs)); } +#endif + + //! Equal-to operator with primitive types + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c true, \c false + */ + template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr,internal::IsGenericValue >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); } + + //! Not-equal-to operator + /*! \return !(*this == rhs) + */ + template + bool operator!=(const GenericValue& rhs) const { return !(*this == rhs); } + + //! Not-equal-to operator with const C-string pointer + bool operator!=(const Ch* rhs) const { return !(*this == rhs); } + + //! Not-equal-to operator with arbitrary types + /*! \return !(*this == rhs) + */ + template RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue), (bool)) operator!=(const T& rhs) const { return !(*this == rhs); } + + //! Equal-to operator with arbitrary types (symmetric version) + /*! \return (rhs == lhs) + */ + template friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue), (bool)) operator==(const T& lhs, const GenericValue& rhs) { return rhs == lhs; } + + //! Not-Equal-to operator with arbitrary types (symmetric version) + /*! \return !(rhs == lhs) + */ + template friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); } + //@} + + //!@name Type + //@{ + + Type GetType() const { return static_cast(flags_ & kTypeMask); } + bool IsNull() const { return flags_ == kNullFlag; } + bool IsFalse() const { return flags_ == kFalseFlag; } + bool IsTrue() const { return flags_ == kTrueFlag; } + bool IsBool() const { return (flags_ & kBoolFlag) != 0; } + bool IsObject() const { return flags_ == kObjectFlag; } + bool IsArray() const { return flags_ == kArrayFlag; } + bool IsNumber() const { return (flags_ & kNumberFlag) != 0; } + bool IsInt() const { return (flags_ & kIntFlag) != 0; } + bool IsUint() const { return (flags_ & kUintFlag) != 0; } + bool IsInt64() const { return (flags_ & kInt64Flag) != 0; } + bool IsUint64() const { return (flags_ & kUint64Flag) != 0; } + bool IsDouble() const { return (flags_ & kDoubleFlag) != 0; } + bool IsString() const { return (flags_ & kStringFlag) != 0; } + + //@} + + //!@name Null + //@{ + + GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; } + + //@} + + //!@name Bool + //@{ + + bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return flags_ == kTrueFlag; } + //!< Set boolean value + /*! \post IsBool() == true */ + GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; } + + //@} + + //!@name Object + //@{ + + //! Set this value as an empty object. + /*! \post IsObject() == true */ + GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; } + + //! Get the number of members in the object. + SizeType MemberCount() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size; } + + //! Check whether the object is empty. + bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; } + + //! Get a value from an object associated with the name. + /*! \pre IsObject() == true + \tparam T Either \c Ch or \c const \c Ch (template used for disambiguation with \ref operator[](SizeType)) + \note In version 0.1x, if the member is not found, this function returns a null value. This makes issue 7. + Since 0.2, if the name is not correct, it will assert. + If user is unsure whether a member exists, user should use HasMember() first. + A better approach is to use FindMember(). + \note Linear time complexity. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr::Type, Ch> >),(GenericValue&)) operator[](T* name) { + GenericValue n(StringRef(name)); + return (*this)[n]; + } + template + RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr::Type, Ch> >),(const GenericValue&)) operator[](T* name) const { return const_cast(*this)[name]; } + + //! Get a value from an object associated with the name. + /*! \pre IsObject() == true + \tparam SourceAllocator Allocator of the \c name value + + \note Compared to \ref operator[](T*), this version is faster because it does not need a StrLen(). + And it can also handle strings with embedded null characters. + + \note Linear time complexity. + */ + template + GenericValue& operator[](const GenericValue& name) { + MemberIterator member = FindMember(name); + if (member != MemberEnd()) + return member->value; + else { + RAPIDJSON_ASSERT(false); // see above note + static GenericValue NullValue; + return NullValue; + } + } + template + const GenericValue& operator[](const GenericValue& name) const { return const_cast(*this)[name]; } + + //! Const member iterator + /*! \pre IsObject() == true */ + ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(data_.o.members); } + //! Const \em past-the-end member iterator + /*! \pre IsObject() == true */ + ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(data_.o.members + data_.o.size); } + //! Member iterator + /*! \pre IsObject() == true */ + MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(data_.o.members); } + //! \em Past-the-end member iterator + /*! \pre IsObject() == true */ + MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(data_.o.members + data_.o.size); } + + //! Check whether a member exists in the object. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Whether a member with that name exists. + \note It is better to use FindMember() directly if you need the obtain the value as well. + \note Linear time complexity. + */ + bool HasMember(const Ch* name) const { return FindMember(name) != MemberEnd(); } + + //! Check whether a member exists in the object with GenericValue name. + /*! + This version is faster because it does not need a StrLen(). It can also handle string with null character. + \param name Member name to be searched. + \pre IsObject() == true + \return Whether a member with that name exists. + \note It is better to use FindMember() directly if you need the obtain the value as well. + \note Linear time complexity. + */ + template + bool HasMember(const GenericValue& name) const { return FindMember(name) != MemberEnd(); } + + //! Find member by name. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Iterator to member, if it exists. + Otherwise returns \ref MemberEnd(). + + \note Earlier versions of Rapidjson returned a \c NULL pointer, in case + the requested member doesn't exist. For consistency with e.g. + \c std::map, this has been changed to MemberEnd() now. + \note Linear time complexity. + */ + MemberIterator FindMember(const Ch* name) { + GenericValue n(StringRef(name)); + return FindMember(n); + } + + ConstMemberIterator FindMember(const Ch* name) const { return const_cast(*this).FindMember(name); } + + //! Find member by name. + /*! + This version is faster because it does not need a StrLen(). It can also handle string with null character. + \param name Member name to be searched. + \pre IsObject() == true + \return Iterator to member, if it exists. + Otherwise returns \ref MemberEnd(). + + \note Earlier versions of Rapidjson returned a \c NULL pointer, in case + the requested member doesn't exist. For consistency with e.g. + \c std::map, this has been changed to MemberEnd() now. + \note Linear time complexity. + */ + template + MemberIterator FindMember(const GenericValue& name) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(name.IsString()); + MemberIterator member = MemberBegin(); + for ( ; member != MemberEnd(); ++member) + if (name.StringEqual(member->name)) + break; + return member; + } + template ConstMemberIterator FindMember(const GenericValue& name) const { return const_cast(*this).FindMember(name); } + + //! Add a member (name-value pair) to the object. + /*! \param name A string value as name of member. + \param value Value of any type. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \note The ownership of \c name and \c value will be transferred to this object on success. + \pre IsObject() && name.IsString() + \post name.IsNull() && value.IsNull() + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(name.IsString()); + + Object& o = data_.o; + if (o.size >= o.capacity) { + if (o.capacity == 0) { + o.capacity = kDefaultObjectCapacity; + o.members = reinterpret_cast(allocator.Malloc(o.capacity * sizeof(Member))); + } + else { + SizeType oldCapacity = o.capacity; + o.capacity += (oldCapacity + 1) / 2; // grow by factor 1.5 + o.members = reinterpret_cast(allocator.Realloc(o.members, oldCapacity * sizeof(Member), o.capacity * sizeof(Member))); + } + } + o.members[o.size].name.RawAssign(name); + o.members[o.size].value.RawAssign(value); + o.size++; + return *this; + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericValue& AddMember(GenericValue&& name, GenericValue&& value, Allocator& allocator) { + return AddMember(name, value, allocator); + } + GenericValue& AddMember(GenericValue&& name, GenericValue& value, Allocator& allocator) { + return AddMember(name, value, allocator); + } + GenericValue& AddMember(GenericValue& name, GenericValue&& value, Allocator& allocator) { + return AddMember(name, value, allocator); + } + GenericValue& AddMember(StringRefType name, GenericValue&& value, Allocator& allocator) { + GenericValue n(name); + return AddMember(n, value, allocator); + } +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + + + //! Add a member (name-value pair) to the object. + /*! \param name A constant string reference as name of member. + \param value Value of any type. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \note The ownership of \c value will be transferred to this object on success. + \pre IsObject() + \post value.IsNull() + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(StringRefType name, GenericValue& value, Allocator& allocator) { + GenericValue n(name); + return AddMember(n, value, allocator); + } + + //! Add a constant string value as member (name-value pair) to the object. + /*! \param name A constant string reference as name of member. + \param value constant string reference as value of member. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + \note This overload is needed to avoid clashes with the generic primitive type AddMember(StringRefType,T,Allocator&) overload below. + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(StringRefType name, StringRefType value, Allocator& allocator) { + GenericValue v(value); + return AddMember(name, v, allocator); + } + + //! Add any primitive value as member (name-value pair) to the object. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param name A constant string reference as name of member. + \param value Value of primitive type \c T as value of member + \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref + AddMember(StringRefType, StringRefType, Allocator&). + All other pointer types would implicitly convert to \c bool, + use an explicit cast instead, if needed. + \note Amortized Constant time complexity. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (GenericValue&)) + AddMember(StringRefType name, T value, Allocator& allocator) { + GenericValue n(name); + GenericValue v(value); + return AddMember(n, v, allocator); + } + + //! Remove all members in the object. + /*! This function do not deallocate memory in the object, i.e. the capacity is unchanged. + \note Linear time complexity. + */ + void RemoveAllMembers() { + RAPIDJSON_ASSERT(IsObject()); + for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) + m->~Member(); + data_.o.size = 0; + } + + //! Remove a member in object by its name. + /*! \param name Name of member to be removed. + \return Whether the member existed. + \note This function may reorder the object members. Use \ref + EraseMember(ConstMemberIterator) if you need to preserve the + relative order of the remaining members. + \note Linear time complexity. + */ + bool RemoveMember(const Ch* name) { + GenericValue n(StringRef(name)); + return RemoveMember(n); + } + + template + bool RemoveMember(const GenericValue& name) { + MemberIterator m = FindMember(name); + if (m != MemberEnd()) { + RemoveMember(m); + return true; + } + else + return false; + } + + //! Remove a member in object by iterator. + /*! \param m member iterator (obtained by FindMember() or MemberBegin()). + \return the new iterator after removal. + \note This function may reorder the object members. Use \ref + EraseMember(ConstMemberIterator) if you need to preserve the + relative order of the remaining members. + \note Constant time complexity. + */ + MemberIterator RemoveMember(MemberIterator m) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(data_.o.size > 0); + RAPIDJSON_ASSERT(data_.o.members != 0); + RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd()); + + MemberIterator last(data_.o.members + (data_.o.size - 1)); + if (data_.o.size > 1 && m != last) { + // Move the last one to this place + *m = *last; + } + else { + // Only one left, just destroy + m->~Member(); + } + --data_.o.size; + return m; + } + + //! Remove a member from an object by iterator. + /*! \param pos iterator to the member to remove + \pre IsObject() == true && \ref MemberBegin() <= \c pos < \ref MemberEnd() + \return Iterator following the removed element. + If the iterator \c pos refers to the last element, the \ref MemberEnd() iterator is returned. + \note This function preserves the relative order of the remaining object + members. If you do not need this, use the more efficient \ref RemoveMember(MemberIterator). + \note Linear time complexity. + */ + MemberIterator EraseMember(ConstMemberIterator pos) { + return EraseMember(pos, pos +1); + } + + //! Remove members in the range [first, last) from an object. + /*! \param first iterator to the first member to remove + \param last iterator following the last member to remove + \pre IsObject() == true && \ref MemberBegin() <= \c first <= \c last <= \ref MemberEnd() + \return Iterator following the last removed element. + \note This function preserves the relative order of the remaining object + members. + \note Linear time complexity. + */ + MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(data_.o.size > 0); + RAPIDJSON_ASSERT(data_.o.members != 0); + RAPIDJSON_ASSERT(first >= MemberBegin()); + RAPIDJSON_ASSERT(first <= last); + RAPIDJSON_ASSERT(last <= MemberEnd()); + + MemberIterator pos = MemberBegin() + (first - MemberBegin()); + for (MemberIterator itr = pos; itr != last; ++itr) + itr->~Member(); + std::memmove(&*pos, &*last, (MemberEnd() - last) * sizeof(Member)); + data_.o.size -= (last - first); + return pos; + } + + //@} + + //!@name Array + //@{ + + //! Set this value as an empty array. + /*! \post IsArray == true */ + GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; } + + //! Get the number of elements in array. + SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; } + + //! Get the capacity of array. + SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; } + + //! Check whether the array is empty. + bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; } + + //! Remove all elements in the array. + /*! This function do not deallocate memory in the array, i.e. the capacity is unchanged. + \note Linear time complexity. + */ + void Clear() { + RAPIDJSON_ASSERT(IsArray()); + for (SizeType i = 0; i < data_.a.size; ++i) + data_.a.elements[i].~GenericValue(); + data_.a.size = 0; + } + + //! Get an element from array by index. + /*! \pre IsArray() == true + \param index Zero-based index of element. + \see operator[](T*) + */ + GenericValue& operator[](SizeType index) { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(index < data_.a.size); + return data_.a.elements[index]; + } + const GenericValue& operator[](SizeType index) const { return const_cast(*this)[index]; } + + //! Element iterator + /*! \pre IsArray() == true */ + ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements; } + //! \em Past-the-end element iterator + /*! \pre IsArray() == true */ + ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements + data_.a.size; } + //! Constant element iterator + /*! \pre IsArray() == true */ + ConstValueIterator Begin() const { return const_cast(*this).Begin(); } + //! Constant \em past-the-end element iterator + /*! \pre IsArray() == true */ + ConstValueIterator End() const { return const_cast(*this).End(); } + + //! Request the array to have enough capacity to store elements. + /*! \param newCapacity The capacity that the array at least need to have. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \note Linear time complexity. + */ + GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) { + RAPIDJSON_ASSERT(IsArray()); + if (newCapacity > data_.a.capacity) { + data_.a.elements = (GenericValue*)allocator.Realloc(data_.a.elements, data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue)); + data_.a.capacity = newCapacity; + } + return *this; + } + + //! Append a GenericValue at the end of the array. + /*! \param value Value to be appended. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \pre IsArray() == true + \post value.IsNull() == true + \return The value itself for fluent API. + \note The ownership of \c value will be transferred to this array on success. + \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. + \note Amortized constant time complexity. + */ + GenericValue& PushBack(GenericValue& value, Allocator& allocator) { + RAPIDJSON_ASSERT(IsArray()); + if (data_.a.size >= data_.a.capacity) + Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : (data_.a.capacity + (data_.a.capacity + 1) / 2), allocator); + data_.a.elements[data_.a.size++].RawAssign(value); + return *this; + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericValue& PushBack(GenericValue&& value, Allocator& allocator) { + return PushBack(value, allocator); + } +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + + //! Append a constant string reference at the end of the array. + /*! \param value Constant string reference to be appended. + \param allocator Allocator for reallocating memory. It must be the same one used previously. Commonly use GenericDocument::GetAllocator(). + \pre IsArray() == true + \return The value itself for fluent API. + \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. + \note Amortized constant time complexity. + \see GenericStringRef + */ + GenericValue& PushBack(StringRefType value, Allocator& allocator) { + return (*this).template PushBack(value, allocator); + } + + //! Append a primitive value at the end of the array. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param value Value of primitive type T to be appended. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \pre IsArray() == true + \return The value itself for fluent API. + \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref PushBack(GenericValue&, Allocator&) or \ref + PushBack(StringRefType, Allocator&). + All other pointer types would implicitly convert to \c bool, + use an explicit cast instead, if needed. + \note Amortized constant time complexity. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (GenericValue&)) + PushBack(T value, Allocator& allocator) { + GenericValue v(value); + return PushBack(v, allocator); + } + + //! Remove the last element in the array. + /*! + \note Constant time complexity. + */ + GenericValue& PopBack() { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(!Empty()); + data_.a.elements[--data_.a.size].~GenericValue(); + return *this; + } + + //! Remove an element of array by iterator. + /*! + \param pos iterator to the element to remove + \pre IsArray() == true && \ref Begin() <= \c pos < \ref End() + \return Iterator following the removed element. If the iterator pos refers to the last element, the End() iterator is returned. + \note Linear time complexity. + */ + ValueIterator Erase(ConstValueIterator pos) { + return Erase(pos, pos + 1); + } + + //! Remove elements in the range [first, last) of the array. + /*! + \param first iterator to the first element to remove + \param last iterator following the last element to remove + \pre IsArray() == true && \ref Begin() <= \c first <= \c last <= \ref End() + \return Iterator following the last removed element. + \note Linear time complexity. + */ + ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(data_.a.size > 0); + RAPIDJSON_ASSERT(data_.a.elements != 0); + RAPIDJSON_ASSERT(first >= Begin()); + RAPIDJSON_ASSERT(first <= last); + RAPIDJSON_ASSERT(last <= End()); + ValueIterator pos = Begin() + (first - Begin()); + for (ValueIterator itr = pos; itr != last; ++itr) + itr->~GenericValue(); + std::memmove(pos, last, (End() - last) * sizeof(GenericValue)); + data_.a.size -= (last - first); + return pos; + } + + //@} + + //!@name Number + //@{ + + int GetInt() const { RAPIDJSON_ASSERT(flags_ & kIntFlag); return data_.n.i.i; } + unsigned GetUint() const { RAPIDJSON_ASSERT(flags_ & kUintFlag); return data_.n.u.u; } + int64_t GetInt64() const { RAPIDJSON_ASSERT(flags_ & kInt64Flag); return data_.n.i64; } + uint64_t GetUint64() const { RAPIDJSON_ASSERT(flags_ & kUint64Flag); return data_.n.u64; } + + double GetDouble() const { + RAPIDJSON_ASSERT(IsNumber()); + if ((flags_ & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion. + if ((flags_ & kIntFlag) != 0) return data_.n.i.i; // int -> double + if ((flags_ & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double + if ((flags_ & kInt64Flag) != 0) return (double)data_.n.i64; // int64_t -> double (may lose precision) + RAPIDJSON_ASSERT((flags_ & kUint64Flag) != 0); return (double)data_.n.u64; // uint64_t -> double (may lose precision) + } + + GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; } + GenericValue& SetUint(unsigned u) { this->~GenericValue(); new (this) GenericValue(u); return *this; } + GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; } + GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; } + GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; } + + //@} + + //!@name String + //@{ + + const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return ((flags_ & kInlineStrFlag) ? data_.ss.str : data_.s.str); } + + //! Get the length of string. + /*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength(). + */ + SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return ((flags_ & kInlineStrFlag) ? (data_.ss.GetLength()) : data_.s.length); } + + //! Set this value as a string without copying source string. + /*! This version has better performance with supplied length, and also support string containing null character. + \param s source string pointer. + \param length The length of source string, excluding the trailing null terminator. + \return The value itself for fluent API. + \post IsString() == true && GetString() == s && GetStringLength() == length + \see SetString(StringRefType) + */ + GenericValue& SetString(const Ch* s, SizeType length) { return SetString(StringRef(s, length)); } + + //! Set this value as a string without copying source string. + /*! \param s source string reference + \return The value itself for fluent API. + \post IsString() == true && GetString() == s && GetStringLength() == s.length + */ + GenericValue& SetString(StringRefType s) { this->~GenericValue(); SetStringRaw(s); return *this; } + + //! Set this value as a string by copying from source string. + /*! This version has better performance with supplied length, and also support string containing null character. + \param s source string. + \param length The length of source string, excluding the trailing null terminator. + \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length + */ + GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { this->~GenericValue(); SetStringRaw(StringRef(s, length), allocator); return *this; } + + //! Set this value as a string by copying from source string. + /*! \param s source string. + \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length + */ + GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(s, internal::StrLen(s), allocator); } + +#if RAPIDJSON_HAS_STDSTRING + //! Set this value as a string by copying from source string. + /*! \param s source string. + \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size() + \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + GenericValue& SetString(const std::basic_string& s, Allocator& allocator) { return SetString(s.data(), s.size(), allocator); } +#endif + + //@} + + //! Generate events of this value to a Handler. + /*! This function adopts the GoF visitor pattern. + Typical usage is to output this JSON value as JSON text via Writer, which is a Handler. + It can also be used to deep clone this value via GenericDocument, which is also a Handler. + \tparam Handler type of handler. + \param handler An object implementing concept Handler. + */ + template + bool Accept(Handler& handler) const { + switch(GetType()) { + case kNullType: return handler.Null(); + case kFalseType: return handler.Bool(false); + case kTrueType: return handler.Bool(true); + + case kObjectType: + if (!handler.StartObject()) + return false; + for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) { + RAPIDJSON_ASSERT(m->name.IsString()); // User may change the type of name by MemberIterator. + if (!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.flags_ & kCopyFlag) != 0)) + return false; + if (!m->value.Accept(handler)) + return false; + } + return handler.EndObject(data_.o.size); + + case kArrayType: + if (!handler.StartArray()) + return false; + for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v) + if (!v->Accept(handler)) + return false; + return handler.EndArray(data_.a.size); + + case kStringType: + return handler.String(GetString(), GetStringLength(), (flags_ & kCopyFlag) != 0); + + case kNumberType: + if (IsInt()) return handler.Int(data_.n.i.i); + else if (IsUint()) return handler.Uint(data_.n.u.u); + else if (IsInt64()) return handler.Int64(data_.n.i64); + else if (IsUint64()) return handler.Uint64(data_.n.u64); + else return handler.Double(data_.n.d); + + default: + RAPIDJSON_ASSERT(false); + } + return false; + } + +private: + template friend class GenericValue; + template friend class GenericDocument; + + enum { + kBoolFlag = 0x100, + kNumberFlag = 0x200, + kIntFlag = 0x400, + kUintFlag = 0x800, + kInt64Flag = 0x1000, + kUint64Flag = 0x2000, + kDoubleFlag = 0x4000, + kStringFlag = 0x100000, + kCopyFlag = 0x200000, + kInlineStrFlag = 0x400000, + + // Initial flags of different types. + kNullFlag = kNullType, + kTrueFlag = kTrueType | kBoolFlag, + kFalseFlag = kFalseType | kBoolFlag, + kNumberIntFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag, + kNumberUintFlag = kNumberType | kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag, + kNumberInt64Flag = kNumberType | kNumberFlag | kInt64Flag, + kNumberUint64Flag = kNumberType | kNumberFlag | kUint64Flag, + kNumberDoubleFlag = kNumberType | kNumberFlag | kDoubleFlag, + kNumberAnyFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag | kUintFlag | kUint64Flag | kDoubleFlag, + kConstStringFlag = kStringType | kStringFlag, + kCopyStringFlag = kStringType | kStringFlag | kCopyFlag, + kShortStringFlag = kStringType | kStringFlag | kCopyFlag | kInlineStrFlag, + kObjectFlag = kObjectType, + kArrayFlag = kArrayType, + + kTypeMask = 0xFF // bitwise-and with mask of 0xFF can be optimized by compiler + }; + + static const SizeType kDefaultArrayCapacity = 16; + static const SizeType kDefaultObjectCapacity = 16; + + struct String { + const Ch* str; + SizeType length; + unsigned hashcode; //!< reserved + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + // implementation detail: ShortString can represent zero-terminated strings up to MaxSize chars + // (excluding the terminating zero) and store a value to determine the length of the contained + // string in the last character str[LenPos] by storing "MaxSize - length" there. If the string + // to store has the maximal length of MaxSize then str[LenPos] will be 0 and therefore act as + // the string terminator as well. For getting the string length back from that value just use + // "MaxSize - str[LenPos]". + // This allows to store 11-chars strings in 32-bit mode and 15-chars strings in 64-bit mode + // inline (for `UTF8`-encoded strings). + struct ShortString { + enum { MaxChars = sizeof(String) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize }; + Ch str[MaxChars]; + + inline static bool Usable(SizeType len) { return (MaxSize >= len); } + inline void SetLength(SizeType len) { str[LenPos] = (Ch)(MaxSize - len); } + inline SizeType GetLength() const { return (SizeType)(MaxSize - str[LenPos]); } + }; // at most as many bytes as "String" above => 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + // By using proper binary layout, retrieval of different integer types do not need conversions. + union Number { +#if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN + struct I { + int i; + char padding[4]; + }i; + struct U { + unsigned u; + char padding2[4]; + }u; +#else + struct I { + char padding[4]; + int i; + }i; + struct U { + char padding2[4]; + unsigned u; + }u; +#endif + int64_t i64; + uint64_t u64; + double d; + }; // 8 bytes + + struct Object { + Member* members; + SizeType size; + SizeType capacity; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + struct Array { + GenericValue* elements; + SizeType size; + SizeType capacity; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + union Data { + String s; + ShortString ss; + Number n; + Object o; + Array a; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + // Initialize this value as array with initial data, without calling destructor. + void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) { + flags_ = kArrayFlag; + data_.a.elements = (GenericValue*)allocator.Malloc(count * sizeof(GenericValue)); + std::memcpy(data_.a.elements, values, count * sizeof(GenericValue)); + data_.a.size = data_.a.capacity = count; + } + + //! Initialize this value as object with initial data, without calling destructor. + void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) { + flags_ = kObjectFlag; + data_.o.members = (Member*)allocator.Malloc(count * sizeof(Member)); + std::memcpy(data_.o.members, members, count * sizeof(Member)); + data_.o.size = data_.o.capacity = count; + } + + //! Initialize this value as constant string, without calling destructor. + void SetStringRaw(StringRefType s) RAPIDJSON_NOEXCEPT { + flags_ = kConstStringFlag; + data_.s.str = s; + data_.s.length = s.length; + } + + //! Initialize this value as copy string with initial data, without calling destructor. + void SetStringRaw(StringRefType s, Allocator& allocator) { + Ch* str = NULL; + if(ShortString::Usable(s.length)) { + flags_ = kShortStringFlag; + data_.ss.SetLength(s.length); + str = data_.ss.str; + } else { + flags_ = kCopyStringFlag; + data_.s.length = s.length; + str = (Ch *)allocator.Malloc((s.length + 1) * sizeof(Ch)); + data_.s.str = str; + } + std::memcpy(str, s, s.length * sizeof(Ch)); + str[s.length] = '\0'; + } + + //! Assignment without calling destructor + void RawAssign(GenericValue& rhs) RAPIDJSON_NOEXCEPT { + data_ = rhs.data_; + flags_ = rhs.flags_; + rhs.flags_ = kNullFlag; + } + + template + bool StringEqual(const GenericValue& rhs) const { + RAPIDJSON_ASSERT(IsString()); + RAPIDJSON_ASSERT(rhs.IsString()); + + const SizeType len1 = GetStringLength(); + const SizeType len2 = rhs.GetStringLength(); + if(len1 != len2) { return false; } + + const Ch* const str1 = GetString(); + const Ch* const str2 = rhs.GetString(); + if(str1 == str2) { return true; } // fast path for constant string + + return (std::memcmp(str1, str2, sizeof(Ch) * len1) == 0); + } + + Data data_; + unsigned flags_; +}; + +//! GenericValue with UTF8 encoding +typedef GenericValue > Value; + +/////////////////////////////////////////////////////////////////////////////// +// GenericDocument + +//! A document for parsing JSON text as DOM. +/*! + \note implements Handler concept + \tparam Encoding Encoding for both parsing and string storage. + \tparam Allocator Allocator for allocating memory for the DOM + \tparam StackAllocator Allocator for allocating memory for stack during parsing. + \warning Although GenericDocument inherits from GenericValue, the API does \b not provide any virtual functions, especially no virtual destructor. To avoid memory leaks, do not \c delete a GenericDocument object via a pointer to a GenericValue. +*/ +template , typename StackAllocator = CrtAllocator> +class GenericDocument : public GenericValue { +public: + typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. + typedef GenericValue ValueType; //!< Value type of the document. + typedef Allocator AllocatorType; //!< Allocator type from template parameter. + + //! Constructor + /*! \param allocator Optional allocator for allocating memory. + \param stackCapacity Optional initial capacity of stack in bytes. + \param stackAllocator Optional allocator for allocating memory for stack. + */ + GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) : + allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_() + { + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move constructor in C++11 + GenericDocument(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT + : ValueType(std::move(rhs)), + allocator_(rhs.allocator_), + ownAllocator_(rhs.ownAllocator_), + stack_(std::move(rhs.stack_)), + parseResult_(rhs.parseResult_) + { + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.parseResult_ = ParseResult(); + } +#endif + + ~GenericDocument() { + Destroy(); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move assignment in C++11 + GenericDocument& operator=(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT + { + // The cast to ValueType is necessary here, because otherwise it would + // attempt to call GenericValue's templated assignment operator. + ValueType::operator=(std::forward(rhs)); + + // Calling the destructor here would prematurely call stack_'s destructor + Destroy(); + + allocator_ = rhs.allocator_; + ownAllocator_ = rhs.ownAllocator_; + stack_ = std::move(rhs.stack_); + parseResult_ = rhs.parseResult_; + + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.parseResult_ = ParseResult(); + + return *this; + } +#endif + + //!@name Parse from stream + //!@{ + + //! Parse JSON text from an input stream (with Encoding conversion) + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam SourceEncoding Encoding of input stream + \tparam InputStream Type of input stream, implementing Stream concept + \param is Input stream to be parsed. + \return The document itself for fluent API. + */ + template + GenericDocument& ParseStream(InputStream& is) { + ValueType::SetNull(); // Remove existing root if exist + GenericReader reader(&GetAllocator()); + ClearStackOnExit scope(*this); + parseResult_ = reader.template Parse(is, *this); + if (parseResult_) { + RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object + this->RawAssign(*stack_.template Pop(1)); // Add this-> to prevent issue 13. + } + return *this; + } + + //! Parse JSON text from an input stream + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam InputStream Type of input stream, implementing Stream concept + \param is Input stream to be parsed. + \return The document itself for fluent API. + */ + template + GenericDocument& ParseStream(InputStream& is) { + return ParseStream(is); + } + + //! Parse JSON text from an input stream (with \ref kParseDefaultFlags) + /*! \tparam InputStream Type of input stream, implementing Stream concept + \param is Input stream to be parsed. + \return The document itself for fluent API. + */ + template + GenericDocument& ParseStream(InputStream& is) { + return ParseStream(is); + } + //!@} + + //!@name Parse in-place from mutable string + //!@{ + + //! Parse JSON text from a mutable string (with Encoding conversion) + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam SourceEncoding Transcoding from input Encoding + \param str Mutable zero-terminated string to be parsed. + \return The document itself for fluent API. + */ + template + GenericDocument& ParseInsitu(Ch* str) { + GenericInsituStringStream s(str); + return ParseStream(s); + } + + //! Parse JSON text from a mutable string + /*! \tparam parseFlags Combination of \ref ParseFlag. + \param str Mutable zero-terminated string to be parsed. + \return The document itself for fluent API. + */ + template + GenericDocument& ParseInsitu(Ch* str) { + return ParseInsitu(str); + } + + //! Parse JSON text from a mutable string (with \ref kParseDefaultFlags) + /*! \param str Mutable zero-terminated string to be parsed. + \return The document itself for fluent API. + */ + GenericDocument& ParseInsitu(Ch* str) { + return ParseInsitu(str); + } + //!@} + + //!@name Parse from read-only string + //!@{ + + //! Parse JSON text from a read-only string (with Encoding conversion) + /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag). + \tparam SourceEncoding Transcoding from input Encoding + \param str Read-only zero-terminated string to be parsed. + */ + template + GenericDocument& Parse(const Ch* str) { + RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); + GenericStringStream s(str); + return ParseStream(s); + } + + //! Parse JSON text from a read-only string + /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag). + \param str Read-only zero-terminated string to be parsed. + */ + template + GenericDocument& Parse(const Ch* str) { + return Parse(str); + } + + //! Parse JSON text from a read-only string (with \ref kParseDefaultFlags) + /*! \param str Read-only zero-terminated string to be parsed. + */ + GenericDocument& Parse(const Ch* str) { + return Parse(str); + } + //!@} + + //!@name Handling parse errors + //!@{ + + //! Whether a parse error has occured in the last parsing. + bool HasParseError() const { return parseResult_.IsError(); } + + //! Get the \ref ParseErrorCode of last parsing. + ParseErrorCode GetParseError() const { return parseResult_.Code(); } + + //! Get the position of last parsing error in input, 0 otherwise. + size_t GetErrorOffset() const { return parseResult_.Offset(); } + + //!@} + + //! Get the allocator of this document. + Allocator& GetAllocator() { return *allocator_; } + + //! Get the capacity of stack in bytes. + size_t GetStackCapacity() const { return stack_.GetCapacity(); } + +private: + // clear stack on any exit from ParseStream, e.g. due to exception + struct ClearStackOnExit { + explicit ClearStackOnExit(GenericDocument& d) : d_(d) {} + ~ClearStackOnExit() { d_.ClearStack(); } + private: + ClearStackOnExit(const ClearStackOnExit&); + ClearStackOnExit& operator=(const ClearStackOnExit&); + GenericDocument& d_; + }; + + // callers of the following private Handler functions + template friend class GenericReader; // for parsing + template friend class GenericValue; // for deep copying + + // Implementation of Handler + bool Null() { new (stack_.template Push()) ValueType(); return true; } + bool Bool(bool b) { new (stack_.template Push()) ValueType(b); return true; } + bool Int(int i) { new (stack_.template Push()) ValueType(i); return true; } + bool Uint(unsigned i) { new (stack_.template Push()) ValueType(i); return true; } + bool Int64(int64_t i) { new (stack_.template Push()) ValueType(i); return true; } + bool Uint64(uint64_t i) { new (stack_.template Push()) ValueType(i); return true; } + bool Double(double d) { new (stack_.template Push()) ValueType(d); return true; } + + bool String(const Ch* str, SizeType length, bool copy) { + if (copy) + new (stack_.template Push()) ValueType(str, length, GetAllocator()); + else + new (stack_.template Push()) ValueType(str, length); + return true; + } + + bool StartObject() { new (stack_.template Push()) ValueType(kObjectType); return true; } + + bool Key(const Ch* str, SizeType length, bool copy) { return String(str, length, copy); } + + bool EndObject(SizeType memberCount) { + typename ValueType::Member* members = stack_.template Pop(memberCount); + stack_.template Top()->SetObjectRaw(members, (SizeType)memberCount, GetAllocator()); + return true; + } + + bool StartArray() { new (stack_.template Push()) ValueType(kArrayType); return true; } + + bool EndArray(SizeType elementCount) { + ValueType* elements = stack_.template Pop(elementCount); + stack_.template Top()->SetArrayRaw(elements, elementCount, GetAllocator()); + return true; + } + +private: + //! Prohibit copying + GenericDocument(const GenericDocument&); + //! Prohibit assignment + GenericDocument& operator=(const GenericDocument&); + + void ClearStack() { + if (Allocator::kNeedFree) + while (stack_.GetSize() > 0) // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects) + (stack_.template Pop(1))->~ValueType(); + else + stack_.Clear(); + stack_.ShrinkToFit(); + } + + void Destroy() { + RAPIDJSON_DELETE(ownAllocator_); + } + + static const size_t kDefaultStackCapacity = 1024; + Allocator* allocator_; + Allocator* ownAllocator_; + internal::Stack stack_; + ParseResult parseResult_; +}; + +//! GenericDocument with UTF8 encoding +typedef GenericDocument > Document; + +// defined here due to the dependency on GenericDocument +template +template +inline +GenericValue::GenericValue(const GenericValue& rhs, Allocator& allocator) +{ + switch (rhs.GetType()) { + case kObjectType: + case kArrayType: { // perform deep copy via SAX Handler + GenericDocument d(&allocator); + rhs.Accept(d); + RawAssign(*d.stack_.template Pop(1)); + } + break; + case kStringType: + if (rhs.flags_ == kConstStringFlag) { + flags_ = rhs.flags_; + data_ = *reinterpret_cast(&rhs.data_); + } else { + SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator); + } + break; + default: // kNumberType, kTrueType, kFalseType, kNullType + flags_ = rhs.flags_; + data_ = *reinterpret_cast(&rhs.data_); + } +} + +RAPIDJSON_NAMESPACE_END + +#if defined(_MSC_VER) || defined(__GNUC__) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_DOCUMENT_H_ diff --git a/src/include/rapidjson/encodedstream.h b/src/include/rapidjson/encodedstream.h new file mode 100644 index 0000000..ee8caa0 --- /dev/null +++ b/src/include/rapidjson/encodedstream.h @@ -0,0 +1,290 @@ +// Copyright (C) 2011 Milo Yip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef RAPIDJSON_ENCODEDSTREAM_H_ +#define RAPIDJSON_ENCODEDSTREAM_H_ + +#include "rapidjson.h" + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Input byte stream wrapper with a statically bound encoding. +/*! + \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE. + \tparam InputByteStream Type of input byte stream. For example, FileReadStream. +*/ +template +class EncodedInputStream { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); +public: + typedef typename Encoding::Ch Ch; + + EncodedInputStream(InputByteStream& is) : is_(is) { + current_ = Encoding::TakeBOM(is_); + } + + Ch Peek() const { return current_; } + Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; } + size_t Tell() const { return is_.Tell(); } + + // Not implemented + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + EncodedInputStream(const EncodedInputStream&); + EncodedInputStream& operator=(const EncodedInputStream&); + + InputByteStream& is_; + Ch current_; +}; + +//! Output byte stream wrapper with statically bound encoding. +/*! + \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE. + \tparam InputByteStream Type of input byte stream. For example, FileWriteStream. +*/ +template +class EncodedOutputStream { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); +public: + typedef typename Encoding::Ch Ch; + + EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) { + if (putBOM) + Encoding::PutBOM(os_); + } + + void Put(Ch c) { Encoding::Put(os_, c); } + void Flush() { os_.Flush(); } + + // Not implemented + Ch Peek() const { RAPIDJSON_ASSERT(false); } + Ch Take() { RAPIDJSON_ASSERT(false); } + size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + EncodedOutputStream(const EncodedOutputStream&); + EncodedOutputStream& operator=(const EncodedOutputStream&); + + OutputByteStream& os_; +}; + +#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8::x, UTF16LE::x, UTF16BE::x, UTF32LE::x, UTF32BE::x + +//! Input stream wrapper with dynamically bound encoding and automatic encoding detection. +/*! + \tparam CharType Type of character for reading. + \tparam InputByteStream type of input byte stream to be wrapped. +*/ +template +class AutoUTFInputStream { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); +public: + typedef CharType Ch; + + //! Constructor. + /*! + \param is input stream to be wrapped. + \param type UTF encoding type if it is not detected from the stream. + */ + AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) { + DetectType(); + static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) }; + takeFunc_ = f[type_]; + current_ = takeFunc_(*is_); + } + + UTFType GetType() const { return type_; } + bool HasBOM() const { return hasBOM_; } + + Ch Peek() const { return current_; } + Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; } + size_t Tell() const { return is_->Tell(); } + + // Not implemented + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + AutoUTFInputStream(const AutoUTFInputStream&); + AutoUTFInputStream& operator=(const AutoUTFInputStream&); + + // Detect encoding type with BOM or RFC 4627 + void DetectType() { + // BOM (Byte Order Mark): + // 00 00 FE FF UTF-32BE + // FF FE 00 00 UTF-32LE + // FE FF UTF-16BE + // FF FE UTF-16LE + // EF BB BF UTF-8 + + const unsigned char* c = (const unsigned char *)is_->Peek4(); + if (!c) + return; + + unsigned bom = c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24); + hasBOM_ = false; + if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } + else if (bom == 0x0000FEFF) { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } + else if ((bom & 0xFFFF) == 0xFFFE) { type_ = kUTF16BE; hasBOM_ = true; is_->Take(); is_->Take(); } + else if ((bom & 0xFFFF) == 0xFEFF) { type_ = kUTF16LE; hasBOM_ = true; is_->Take(); is_->Take(); } + else if ((bom & 0xFFFFFF) == 0xBFBBEF) { type_ = kUTF8; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); } + + // RFC 4627: Section 3 + // "Since the first two characters of a JSON text will always be ASCII + // characters [RFC0020], it is possible to determine whether an octet + // stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking + // at the pattern of nulls in the first four octets." + // 00 00 00 xx UTF-32BE + // 00 xx 00 xx UTF-16BE + // xx 00 00 00 UTF-32LE + // xx 00 xx 00 UTF-16LE + // xx xx xx xx UTF-8 + + if (!hasBOM_) { + unsigned pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0); + switch (pattern) { + case 0x08: type_ = kUTF32BE; break; + case 0x0A: type_ = kUTF16BE; break; + case 0x01: type_ = kUTF32LE; break; + case 0x05: type_ = kUTF16LE; break; + case 0x0F: type_ = kUTF8; break; + default: break; // Use type defined by user. + } + } + + // Runtime check whether the size of character type is sufficient. It only perform checks with assertion. + switch (type_) { + case kUTF8: + // Do nothing + break; + case kUTF16LE: + case kUTF16BE: + RAPIDJSON_ASSERT(sizeof(Ch) >= 2); + break; + case kUTF32LE: + case kUTF32BE: + RAPIDJSON_ASSERT(sizeof(Ch) >= 4); + break; + default: + RAPIDJSON_ASSERT(false); // Invalid type + } + } + + typedef Ch (*TakeFunc)(InputByteStream& is); + InputByteStream* is_; + UTFType type_; + Ch current_; + TakeFunc takeFunc_; + bool hasBOM_; +}; + +//! Output stream wrapper with dynamically bound encoding and automatic encoding detection. +/*! + \tparam CharType Type of character for writing. + \tparam InputByteStream type of output byte stream to be wrapped. +*/ +template +class AutoUTFOutputStream { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); +public: + typedef CharType Ch; + + //! Constructor. + /*! + \param os output stream to be wrapped. + \param type UTF encoding type. + \param putBOM Whether to write BOM at the beginning of the stream. + */ + AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) { + // RUntime check whether the size of character type is sufficient. It only perform checks with assertion. + switch (type_) { + case kUTF16LE: + case kUTF16BE: + RAPIDJSON_ASSERT(sizeof(Ch) >= 2); + break; + case kUTF32LE: + case kUTF32BE: + RAPIDJSON_ASSERT(sizeof(Ch) >= 4); + break; + case kUTF8: + // Do nothing + break; + default: + RAPIDJSON_ASSERT(false); // Invalid UTFType + } + + static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) }; + putFunc_ = f[type_]; + + if (putBOM) + PutBOM(); + } + + UTFType GetType() const { return type_; } + + void Put(Ch c) { putFunc_(*os_, c); } + void Flush() { os_->Flush(); } + + // Not implemented + Ch Peek() const { RAPIDJSON_ASSERT(false); } + Ch Take() { RAPIDJSON_ASSERT(false); } + size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + AutoUTFOutputStream(const AutoUTFOutputStream&); + AutoUTFOutputStream& operator=(const AutoUTFOutputStream&); + + void PutBOM() { + typedef void (*PutBOMFunc)(OutputByteStream&); + static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) }; + f[type_](*os_); + } + + typedef void (*PutFunc)(OutputByteStream&, Ch); + + OutputByteStream* os_; + UTFType type_; + PutFunc putFunc_; +}; + +#undef RAPIDJSON_ENCODINGS_FUNC + +RAPIDJSON_NAMESPACE_END + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_FILESTREAM_H_ diff --git a/src/include/rapidjson/encodings.h b/src/include/rapidjson/encodings.h new file mode 100644 index 0000000..71595f7 --- /dev/null +++ b/src/include/rapidjson/encodings.h @@ -0,0 +1,630 @@ +// Copyright (C) 2011 Milo Yip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef RAPIDJSON_ENCODINGS_H_ +#define RAPIDJSON_ENCODINGS_H_ + +#include "rapidjson.h" + +#ifdef _MSC_VER +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data +RAPIDJSON_DIAG_OFF(4702) // unreachable code +#elif defined(__GNUC__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// Encoding + +/*! \class rapidjson::Encoding + \brief Concept for encoding of Unicode characters. + +\code +concept Encoding { + typename Ch; //! Type of character. A "character" is actually a code unit in unicode's definition. + + enum { supportUnicode = 1 }; // or 0 if not supporting unicode + + //! \brief Encode a Unicode codepoint to an output stream. + //! \param os Output stream. + //! \param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively. + template + static void Encode(OutputStream& os, unsigned codepoint); + + //! \brief Decode a Unicode codepoint from an input stream. + //! \param is Input stream. + //! \param codepoint Output of the unicode codepoint. + //! \return true if a valid codepoint can be decoded from the stream. + template + static bool Decode(InputStream& is, unsigned* codepoint); + + //! \brief Validate one Unicode codepoint from an encoded stream. + //! \param is Input stream to obtain codepoint. + //! \param os Output for copying one codepoint. + //! \return true if it is valid. + //! \note This function just validating and copying the codepoint without actually decode it. + template + static bool Validate(InputStream& is, OutputStream& os); + + // The following functions are deal with byte streams. + + //! Take a character from input byte stream, skip BOM if exist. + template + static CharType TakeBOM(InputByteStream& is); + + //! Take a character from input byte stream. + template + static Ch Take(InputByteStream& is); + + //! Put BOM to output byte stream. + template + static void PutBOM(OutputByteStream& os); + + //! Put a character to output byte stream. + template + static void Put(OutputByteStream& os, Ch c); +}; +\endcode +*/ + +/////////////////////////////////////////////////////////////////////////////// +// UTF8 + +//! UTF-8 encoding. +/*! http://en.wikipedia.org/wiki/UTF-8 + http://tools.ietf.org/html/rfc3629 + \tparam CharType Code unit for storing 8-bit UTF-8 data. Default is char. + \note implements Encoding concept +*/ +template +struct UTF8 { + typedef CharType Ch; + + enum { supportUnicode = 1 }; + + template + static void Encode(OutputStream& os, unsigned codepoint) { + if (codepoint <= 0x7F) + os.Put(static_cast(codepoint & 0xFF)); + else if (codepoint <= 0x7FF) { + os.Put(static_cast(0xC0 | ((codepoint >> 6) & 0xFF))); + os.Put(static_cast(0x80 | ((codepoint & 0x3F)))); + } + else if (codepoint <= 0xFFFF) { + os.Put(static_cast(0xE0 | ((codepoint >> 12) & 0xFF))); + os.Put(static_cast(0x80 | ((codepoint >> 6) & 0x3F))); + os.Put(static_cast(0x80 | (codepoint & 0x3F))); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + os.Put(static_cast(0xF0 | ((codepoint >> 18) & 0xFF))); + os.Put(static_cast(0x80 | ((codepoint >> 12) & 0x3F))); + os.Put(static_cast(0x80 | ((codepoint >> 6) & 0x3F))); + os.Put(static_cast(0x80 | (codepoint & 0x3F))); + } + } + + template + static bool Decode(InputStream& is, unsigned* codepoint) { +#define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | ((unsigned char)c & 0x3Fu) +#define TRANS(mask) result &= ((GetRange((unsigned char)c) & mask) != 0) +#define TAIL() COPY(); TRANS(0x70) + Ch c = is.Take(); + if (!(c & 0x80)) { + *codepoint = (unsigned char)c; + return true; + } + + unsigned char type = GetRange((unsigned char)c); + *codepoint = (0xFF >> type) & (unsigned char)c; + bool result = true; + switch (type) { + case 2: TAIL(); return result; + case 3: TAIL(); TAIL(); return result; + case 4: COPY(); TRANS(0x50); TAIL(); return result; + case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result; + case 6: TAIL(); TAIL(); TAIL(); return result; + case 10: COPY(); TRANS(0x20); TAIL(); return result; + case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result; + default: return false; + } +#undef COPY +#undef TRANS +#undef TAIL + } + + template + static bool Validate(InputStream& is, OutputStream& os) { +#define COPY() os.Put(c = is.Take()) +#define TRANS(mask) result &= ((GetRange((unsigned char)c) & mask) != 0) +#define TAIL() COPY(); TRANS(0x70) + Ch c; + COPY(); + if (!(c & 0x80)) + return true; + + bool result = true; + switch (GetRange((unsigned char)c)) { + case 2: TAIL(); return result; + case 3: TAIL(); TAIL(); return result; + case 4: COPY(); TRANS(0x50); TAIL(); return result; + case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result; + case 6: TAIL(); TAIL(); TAIL(); return result; + case 10: COPY(); TRANS(0x20); TAIL(); return result; + case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result; + default: return false; + } +#undef COPY +#undef TRANS +#undef TAIL + } + + static unsigned char GetRange(unsigned char c) { + // Referring to DFA of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ + // With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types. + static const unsigned char type[] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8, + }; + return type[c]; + } + + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + Ch c = Take(is); + if ((unsigned char)c != 0xEFu) return c; + c = is.Take(); + if ((unsigned char)c != 0xBBu) return c; + c = is.Take(); + if ((unsigned char)c != 0xBFu) return c; + c = is.Take(); + return c; + } + + template + static Ch Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + return is.Take(); + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(0xEFu); os.Put(0xBBu); os.Put(0xBFu); + } + + template + static void Put(OutputByteStream& os, Ch c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(c)); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// UTF16 + +//! UTF-16 encoding. +/*! http://en.wikipedia.org/wiki/UTF-16 + http://tools.ietf.org/html/rfc2781 + \tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead. + \note implements Encoding concept + + \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness. + For streaming, use UTF16LE and UTF16BE, which handle endianness. +*/ +template +struct UTF16 { + typedef CharType Ch; + RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2); + + enum { supportUnicode = 1 }; + + template + static void Encode(OutputStream& os, unsigned codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); + if (codepoint <= 0xFFFF) { + RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair + os.Put(static_cast(codepoint)); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + unsigned v = codepoint - 0x10000; + os.Put(static_cast((v >> 10) | 0xD800)); + os.Put((v & 0x3FF) | 0xDC00); + } + } + + template + static bool Decode(InputStream& is, unsigned* codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2); + Ch c = is.Take(); + if (c < 0xD800 || c > 0xDFFF) { + *codepoint = c; + return true; + } + else if (c <= 0xDBFF) { + *codepoint = (c & 0x3FF) << 10; + c = is.Take(); + *codepoint |= (c & 0x3FF); + *codepoint += 0x10000; + return c >= 0xDC00 && c <= 0xDFFF; + } + return false; + } + + template + static bool Validate(InputStream& is, OutputStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2); + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); + Ch c; + os.Put(c = is.Take()); + if (c < 0xD800 || c > 0xDFFF) + return true; + else if (c <= 0xDBFF) { + os.Put(c = is.Take()); + return c >= 0xDC00 && c <= 0xDFFF; + } + return false; + } +}; + +//! UTF-16 little endian encoding. +template +struct UTF16LE : UTF16 { + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return (unsigned short)c == 0xFEFFu ? Take(is) : c; + } + + template + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = (unsigned char)is.Take(); + c |= (unsigned char)is.Take() << 8; + return c; + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(0xFFu); os.Put(0xFEu); + } + + template + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(c & 0xFFu); + os.Put((c >> 8) & 0xFFu); + } +}; + +//! UTF-16 big endian encoding. +template +struct UTF16BE : UTF16 { + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return (unsigned short)c == 0xFEFFu ? Take(is) : c; + } + + template + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = (unsigned char)is.Take() << 8; + c |= (unsigned char)is.Take(); + return c; + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(0xFEu); os.Put(0xFFu); + } + + template + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put((c >> 8) & 0xFFu); + os.Put(c & 0xFFu); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// UTF32 + +//! UTF-32 encoding. +/*! http://en.wikipedia.org/wiki/UTF-32 + \tparam CharType Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead. + \note implements Encoding concept + + \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness. + For streaming, use UTF32LE and UTF32BE, which handle endianness. +*/ +template +struct UTF32 { + typedef CharType Ch; + RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4); + + enum { supportUnicode = 1 }; + + template + static void Encode(OutputStream& os, unsigned codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4); + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + os.Put(codepoint); + } + + template + static bool Decode(InputStream& is, unsigned* codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4); + Ch c = is.Take(); + *codepoint = c; + return c <= 0x10FFFF; + } + + template + static bool Validate(InputStream& is, OutputStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4); + Ch c; + os.Put(c = is.Take()); + return c <= 0x10FFFF; + } +}; + +//! UTF-32 little endian enocoding. +template +struct UTF32LE : UTF32 { + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return (unsigned)c == 0x0000FEFFu ? Take(is) : c; + } + + template + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = (unsigned char)is.Take(); + c |= (unsigned char)is.Take() << 8; + c |= (unsigned char)is.Take() << 16; + c |= (unsigned char)is.Take() << 24; + return c; + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(0xFFu); os.Put(0xFEu); os.Put(0x00u); os.Put(0x00u); + } + + template + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(c & 0xFFu); + os.Put((c >> 8) & 0xFFu); + os.Put((c >> 16) & 0xFFu); + os.Put((c >> 24) & 0xFFu); + } +}; + +//! UTF-32 big endian encoding. +template +struct UTF32BE : UTF32 { + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return (unsigned)c == 0x0000FEFFu ? Take(is) : c; + } + + template + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = (unsigned char)is.Take() << 24; + c |= (unsigned char)is.Take() << 16; + c |= (unsigned char)is.Take() << 8; + c |= (unsigned char)is.Take(); + return c; + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(0x00u); os.Put(0x00u); os.Put(0xFEu); os.Put(0xFFu); + } + + template + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put((c >> 24) & 0xFFu); + os.Put((c >> 16) & 0xFFu); + os.Put((c >> 8) & 0xFFu); + os.Put(c & 0xFFu); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// ASCII + +//! ASCII encoding. +/*! http://en.wikipedia.org/wiki/ASCII + \tparam CharType Code unit for storing 7-bit ASCII data. Default is char. + \note implements Encoding concept +*/ +template +struct ASCII { + typedef CharType Ch; + + enum { supportUnicode = 0 }; + + template + static void Encode(OutputStream& os, unsigned codepoint) { + RAPIDJSON_ASSERT(codepoint <= 0x7F); + os.Put(static_cast(codepoint & 0xFF)); + } + + template + static bool Decode(InputStream& is, unsigned* codepoint) { + unsigned char c = static_cast(is.Take()); + *codepoint = c; + return c <= 0X7F; + } + + template + static bool Validate(InputStream& is, OutputStream& os) { + unsigned char c = is.Take(); + os.Put(c); + return c <= 0x7F; + } + + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + Ch c = Take(is); + return c; + } + + template + static Ch Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + return is.Take(); + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + (void)os; + } + + template + static void Put(OutputByteStream& os, Ch c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(c)); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// AutoUTF + +//! Runtime-specified UTF encoding type of a stream. +enum UTFType { + kUTF8 = 0, //!< UTF-8. + kUTF16LE = 1, //!< UTF-16 little endian. + kUTF16BE = 2, //!< UTF-16 big endian. + kUTF32LE = 3, //!< UTF-32 little endian. + kUTF32BE = 4 //!< UTF-32 big endian. +}; + +//! Dynamically select encoding according to stream's runtime-specified UTF encoding type. +/*! \note This class can be used with AutoUTFInputtStream and AutoUTFOutputStream, which provides GetType(). +*/ +template +struct AutoUTF { + typedef CharType Ch; + + enum { supportUnicode = 1 }; + +#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8::x, UTF16LE::x, UTF16BE::x, UTF32LE::x, UTF32BE::x + + template + RAPIDJSON_FORCEINLINE static void Encode(OutputStream& os, unsigned codepoint) { + typedef void (*EncodeFunc)(OutputStream&, unsigned); + static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) }; + (*f[os.GetType()])(os, codepoint); + } + + template + RAPIDJSON_FORCEINLINE static bool Decode(InputStream& is, unsigned* codepoint) { + typedef bool (*DecodeFunc)(InputStream&, unsigned*); + static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) }; + return (*f[is.GetType()])(is, codepoint); + } + + template + RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) { + typedef bool (*ValidateFunc)(InputStream&, OutputStream&); + static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) }; + return (*f[is.GetType()])(is, os); + } + +#undef RAPIDJSON_ENCODINGS_FUNC +}; + +/////////////////////////////////////////////////////////////////////////////// +// Transcoder + +//! Encoding conversion. +template +struct Transcoder { + //! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream. + template + RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) { + unsigned codepoint; + if (!SourceEncoding::Decode(is, &codepoint)) + return false; + TargetEncoding::Encode(os, codepoint); + return true; + } + + //! Validate one Unicode codepoint from an encoded stream. + template + RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) { + return Transcode(is, os); // Since source/target encoding is different, must transcode. + } +}; + +//! Specialization of Transcoder with same source and target encoding. +template +struct Transcoder { + template + RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) { + os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class. + return true; + } + + template + RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) { + return Encoding::Validate(is, os); // source/target encoding are the same + } +}; + +RAPIDJSON_NAMESPACE_END + +#if defined(__GNUC__) || defined(_MSV_VER) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_ENCODINGS_H_ diff --git a/src/include/rapidjson/error/en.h b/src/include/rapidjson/error/en.h new file mode 100644 index 0000000..0171183 --- /dev/null +++ b/src/include/rapidjson/error/en.h @@ -0,0 +1,71 @@ +// Copyright (C) 2011 Milo Yip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef RAPIDJSON_ERROR_EN_H__ +#define RAPIDJSON_ERROR_EN_H__ + +#include "error.h" + +RAPIDJSON_NAMESPACE_BEGIN + +//! Maps error code of parsing into error message. +/*! + \ingroup RAPIDJSON_ERRORS + \param parseErrorCode Error code obtained in parsing. + \return the error message. + \note User can make a copy of this function for localization. + Using switch-case is safer for future modification of error codes. +*/ +inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) { + switch (parseErrorCode) { + case kParseErrorNone: return RAPIDJSON_ERROR_STRING("No error."); + + case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty."); + case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not follow by other values."); + + case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value."); + + case kParseErrorObjectMissName: return RAPIDJSON_ERROR_STRING("Missing a name for object member."); + case kParseErrorObjectMissColon: return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member."); + case kParseErrorObjectMissCommaOrCurlyBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member."); + + case kParseErrorArrayMissCommaOrSquareBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element."); + + case kParseErrorStringUnicodeEscapeInvalidHex: return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string."); + case kParseErrorStringUnicodeSurrogateInvalid: return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid."); + case kParseErrorStringEscapeInvalid: return RAPIDJSON_ERROR_STRING("Invalid escape character in string."); + case kParseErrorStringMissQuotationMark: return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string."); + case kParseErrorStringInvalidEncoding: return RAPIDJSON_ERROR_STRING("Invalid encoding in string."); + + case kParseErrorNumberTooBig: return RAPIDJSON_ERROR_STRING("Number too big to be stored in double."); + case kParseErrorNumberMissFraction: return RAPIDJSON_ERROR_STRING("Miss fraction part in number."); + case kParseErrorNumberMissExponent: return RAPIDJSON_ERROR_STRING("Miss exponent in number."); + + case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error."); + case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error."); + + default: + return RAPIDJSON_ERROR_STRING("Unknown error."); + } +} + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_ERROR_EN_H__ diff --git a/src/include/rapidjson/error/error.h b/src/include/rapidjson/error/error.h new file mode 100644 index 0000000..729142a --- /dev/null +++ b/src/include/rapidjson/error/error.h @@ -0,0 +1,150 @@ +// Copyright (C) 2011 Milo Yip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef RAPIDJSON_ERROR_ERROR_H__ +#define RAPIDJSON_ERROR_ERROR_H__ + +/*! \file error.h */ + +/*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */ + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ERROR_CHARTYPE + +//! Character type of error messages. +/*! \ingroup RAPIDJSON_ERRORS + The default character type is \c char. + On Windows, user can define this macro as \c TCHAR for supporting both + unicode/non-unicode settings. +*/ +#ifndef RAPIDJSON_ERROR_CHARTYPE +#define RAPIDJSON_ERROR_CHARTYPE char +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ERROR_STRING + +//! Macro for converting string literial to \ref RAPIDJSON_ERROR_CHARTYPE[]. +/*! \ingroup RAPIDJSON_ERRORS + By default this conversion macro does nothing. + On Windows, user can define this macro as \c _T(x) for supporting both + unicode/non-unicode settings. +*/ +#ifndef RAPIDJSON_ERROR_STRING +#define RAPIDJSON_ERROR_STRING(x) x +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// ParseErrorCode + +//! Error code of parsing. +/*! \ingroup RAPIDJSON_ERRORS + \see GenericReader::Parse, GenericReader::GetParseErrorCode +*/ +enum ParseErrorCode { + kParseErrorNone = 0, //!< No error. + + kParseErrorDocumentEmpty, //!< The document is empty. + kParseErrorDocumentRootNotSingular, //!< The document root must not follow by other values. + + kParseErrorValueInvalid, //!< Invalid value. + + kParseErrorObjectMissName, //!< Missing a name for object member. + kParseErrorObjectMissColon, //!< Missing a colon after a name of object member. + kParseErrorObjectMissCommaOrCurlyBracket, //!< Missing a comma or '}' after an object member. + + kParseErrorArrayMissCommaOrSquareBracket, //!< Missing a comma or ']' after an array element. + + kParseErrorStringUnicodeEscapeInvalidHex, //!< Incorrect hex digit after \\u escape in string. + kParseErrorStringUnicodeSurrogateInvalid, //!< The surrogate pair in string is invalid. + kParseErrorStringEscapeInvalid, //!< Invalid escape character in string. + kParseErrorStringMissQuotationMark, //!< Missing a closing quotation mark in string. + kParseErrorStringInvalidEncoding, //!< Invalid encoding in string. + + kParseErrorNumberTooBig, //!< Number too big to be stored in double. + kParseErrorNumberMissFraction, //!< Miss fraction part in number. + kParseErrorNumberMissExponent, //!< Miss exponent in number. + + kParseErrorTermination, //!< Parsing was terminated. + kParseErrorUnspecificSyntaxError //!< Unspecific syntax error. +}; + +//! Result of parsing (wraps ParseErrorCode) +/*! + \ingroup RAPIDJSON_ERRORS + \code + Document doc; + ParseResult ok = doc.Parse("[42]"); + if (!ok) { + fprintf(stderr, "JSON parse error: %s (%u)", + GetParseError_En(ok.Code()), ok.Offset()); + exit(EXIT_FAILURE); + } + \endcode + \see GenericReader::Parse, GenericDocument::Parse +*/ +struct ParseResult { + + //! Default constructor, no error. + ParseResult() : code_(kParseErrorNone), offset_(0) {} + //! Constructor to set an error. + ParseResult(ParseErrorCode code, size_t offset) : code_(code), offset_(offset) {} + + //! Get the error code. + ParseErrorCode Code() const { return code_; } + //! Get the error offset, if \ref IsError(), 0 otherwise. + size_t Offset() const { return offset_; } + + //! Conversion to \c bool, returns \c true, iff !\ref IsError(). + operator bool() const { return !IsError(); } + //! Whether the result is an error. + bool IsError() const { return code_ != kParseErrorNone; } + + bool operator==(const ParseResult& that) const { return code_ == that.code_; } + bool operator==(ParseErrorCode code) const { return code_ == code; } + friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; } + + //! Reset error code. + void Clear() { Set(kParseErrorNone); } + //! Update error code and offset. + void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; } + +private: + ParseErrorCode code_; + size_t offset_; +}; + +//! Function pointer type of GetParseError(). +/*! \ingroup RAPIDJSON_ERRORS + + This is the prototype for \c GetParseError_X(), where \c X is a locale. + User can dynamically change locale in runtime, e.g.: +\code + GetParseErrorFunc GetParseError = GetParseError_En; // or whatever + const RAPIDJSON_ERROR_CHARTYPE* s = GetParseError(document.GetParseErrorCode()); +\endcode +*/ +typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode); + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_ERROR_ERROR_H__ diff --git a/src/include/rapidjson/filereadstream.h b/src/include/rapidjson/filereadstream.h new file mode 100644 index 0000000..5af9be5 --- /dev/null +++ b/src/include/rapidjson/filereadstream.h @@ -0,0 +1,94 @@ +// Copyright (C) 2011 Milo Yip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef RAPIDJSON_FILEREADSTREAM_H_ +#define RAPIDJSON_FILEREADSTREAM_H_ + +#include "rapidjson.h" +#include + +RAPIDJSON_NAMESPACE_BEGIN + +//! File byte stream for input using fread(). +/*! + \note implements Stream concept +*/ +class FileReadStream { +public: + typedef char Ch; //!< Character type (byte). + + //! Constructor. + /*! + \param fp File pointer opened for read. + \param buffer user-supplied buffer. + \param bufferSize size of buffer in bytes. Must >=4 bytes. + */ + FileReadStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { + RAPIDJSON_ASSERT(fp_ != 0); + RAPIDJSON_ASSERT(bufferSize >= 4); + Read(); + } + + Ch Peek() const { return *current_; } + Ch Take() { Ch c = *current_; Read(); return c; } + size_t Tell() const { return count_ + static_cast(current_ - buffer_); } + + // Not implemented + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + + // For encoding detection only. + const Ch* Peek4() const { + return (current_ + 4 <= bufferLast_) ? current_ : 0; + } + +private: + void Read() { + if (current_ < bufferLast_) + ++current_; + else if (!eof_) { + count_ += readCount_; + readCount_ = fread(buffer_, 1, bufferSize_, fp_); + bufferLast_ = buffer_ + readCount_ - 1; + current_ = buffer_; + + if (readCount_ < bufferSize_) { + buffer_[readCount_] = '\0'; + ++bufferLast_; + eof_ = true; + } + } + } + + std::FILE* fp_; + Ch *buffer_; + size_t bufferSize_; + Ch *bufferLast_; + Ch *current_; + size_t readCount_; + size_t count_; //!< Number of characters read + bool eof_; +}; + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_FILESTREAM_H_ diff --git a/src/include/rapidjson/filestream.h b/src/include/rapidjson/filestream.h new file mode 100644 index 0000000..a370c60 --- /dev/null +++ b/src/include/rapidjson/filestream.h @@ -0,0 +1,73 @@ +// Copyright (C) 2011 Milo Yip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef RAPIDJSON_FILESTREAM_H_ +#define RAPIDJSON_FILESTREAM_H_ + +#include "rapidjson.h" +#include + +RAPIDJSON_NAMESPACE_BEGIN + +//! (Deprecated) Wrapper of C file stream for input or output. +/*! + This simple wrapper does not check the validity of the stream. + \note implements Stream concept + \note deprecated: This was only for basic testing in version 0.1, it is found that the performance is very low by using fgetc(). Use FileReadStream instead. +*/ +class FileStream { +public: + typedef char Ch; //!< Character type. Only support char. + + FileStream(std::FILE* fp) : fp_(fp), current_('\0'), count_(0) { Read(); } + char Peek() const { return current_; } + char Take() { char c = current_; Read(); return c; } + size_t Tell() const { return count_; } + void Put(char c) { fputc(c, fp_); } + void Flush() { fflush(fp_); } + + // Not implemented + char* PutBegin() { return 0; } + size_t PutEnd(char*) { return 0; } + +private: + // Prohibit copy constructor & assignment operator. + FileStream(const FileStream&); + FileStream& operator=(const FileStream&); + + void Read() { + RAPIDJSON_ASSERT(fp_ != 0); + int c = fgetc(fp_); + if (c != EOF) { + current_ = (char)c; + count_++; + } + else if (current_ != '\0') + current_ = '\0'; + } + + std::FILE* fp_; + char current_; + size_t count_; +}; + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_FILESTREAM_H_ diff --git a/src/include/rapidjson/filewritestream.h b/src/include/rapidjson/filewritestream.h new file mode 100644 index 0000000..4352c8f --- /dev/null +++ b/src/include/rapidjson/filewritestream.h @@ -0,0 +1,97 @@ +// Copyright (C) 2011 Milo Yip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef RAPIDJSON_FILEWRITESTREAM_H_ +#define RAPIDJSON_FILEWRITESTREAM_H_ + +#include "rapidjson.h" +#include + +RAPIDJSON_NAMESPACE_BEGIN + +//! Wrapper of C file stream for input using fread(). +/*! + \note implements Stream concept +*/ +class FileWriteStream { +public: + typedef char Ch; //!< Character type. Only support char. + + FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) { + RAPIDJSON_ASSERT(fp_ != 0); + } + + void Put(char c) { + if (current_ >= bufferEnd_) + Flush(); + + *current_++ = c; + } + + void PutN(char c, size_t n) { + size_t avail = static_cast(bufferEnd_ - current_); + while (n > avail) { + std::memset(current_, c, avail); + current_ += avail; + Flush(); + n -= avail; + avail = static_cast(bufferEnd_ - current_); + } + + if (n > 0) { + std::memset(current_, c, n); + current_ += n; + } + } + + void Flush() { + if (current_ != buffer_) { + fwrite(buffer_, 1, static_cast(current_ - buffer_), fp_); + current_ = buffer_; + } + } + + // Not implemented + char Peek() const { RAPIDJSON_ASSERT(false); return 0; } + char Take() { RAPIDJSON_ASSERT(false); return 0; } + size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } + char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + // Prohibit copy constructor & assignment operator. + FileWriteStream(const FileWriteStream&); + FileWriteStream& operator=(const FileWriteStream&); + + std::FILE* fp_; + char *buffer_; + char *bufferEnd_; + char *current_; +}; + +//! Implement specialized version of PutN() with memset() for better performance. +template<> +inline void PutN(FileWriteStream& stream, char c, size_t n) { + stream.PutN(c, n); +} + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_FILESTREAM_H_ diff --git a/src/include/rapidjson/internal/biginteger.h b/src/include/rapidjson/internal/biginteger.h new file mode 100644 index 0000000..3e97920 --- /dev/null +++ b/src/include/rapidjson/internal/biginteger.h @@ -0,0 +1,294 @@ +// Copyright (C) 2011 Milo Yip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef RAPIDJSON_BIGINTEGER_H_ +#define RAPIDJSON_BIGINTEGER_H_ + +#include "../rapidjson.h" + +#if defined(_MSC_VER) && defined(_M_AMD64) +#include // for _umul128 +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +class BigInteger { +public: + typedef uint64_t Type; + + BigInteger(const BigInteger& rhs) : count_(rhs.count_) { + std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type)); + } + + explicit BigInteger(uint64_t u) : count_(1) { + digits_[0] = u; + } + + BigInteger(const char* decimals, size_t length) : count_(1) { + RAPIDJSON_ASSERT(length > 0); + digits_[0] = 0; + size_t i = 0; + const size_t kMaxDigitPerIteration = 19; // 2^64 = 18446744073709551616 > 10^19 + while (length >= kMaxDigitPerIteration) { + AppendDecimal64(decimals + i, decimals + i + kMaxDigitPerIteration); + length -= kMaxDigitPerIteration; + i += kMaxDigitPerIteration; + } + + if (length > 0) + AppendDecimal64(decimals + i, decimals + i + length); + } + + BigInteger& operator=(uint64_t u) { + digits_[0] = u; + count_ = 1; + return *this; + } + + BigInteger& operator+=(uint64_t u) { + Type backup = digits_[0]; + digits_[0] += u; + for (size_t i = 0; i < count_ - 1; i++) { + if (digits_[i] >= backup) + return *this; // no carry + backup = digits_[i + 1]; + digits_[i + 1] += 1; + } + + // Last carry + if (digits_[count_ - 1] < backup) + PushBack(1); + + return *this; + } + + BigInteger& operator*=(uint64_t u) { + if (u == 0) return *this = 0; + if (u == 1) return *this; + if (*this == 1) return *this = u; + + uint64_t k = 0; + for (size_t i = 0; i < count_; i++) { + uint64_t hi; + digits_[i] = MulAdd64(digits_[i], u, k, &hi); + k = hi; + } + + if (k > 0) + PushBack(k); + + return *this; + } + + BigInteger& operator*=(uint32_t u) { + if (u == 0) return *this = 0; + if (u == 1) return *this; + if (*this == 1) return *this = u; + + uint32_t k = 0; + for (size_t i = 0; i < count_; i++) { + const uint64_t c = digits_[i] >> 32; + const uint64_t d = digits_[i] & 0xFFFFFFFF; + const uint64_t uc = u * c; + const uint64_t ud = u * d; + const uint64_t p0 = ud + k; + const uint64_t p1 = uc + (p0 >> 32); + digits_[i] = (p0 & 0xFFFFFFFF) | (p1 << 32); + k = p1 >> 32; + } + + if (k > 0) + PushBack(k); + + return *this; + } + + BigInteger& operator<<=(size_t shift) { + if (IsZero() || shift == 0) return *this; + + size_t offset = shift / kTypeBit; + size_t interShift = shift % kTypeBit; + RAPIDJSON_ASSERT(count_ + offset <= kCapacity); + + if (interShift == 0) { + std::memmove(&digits_[count_ - 1 + offset], &digits_[count_ - 1], count_ * sizeof(Type)); + count_ += offset; + } + else { + digits_[count_] = 0; + for (size_t i = count_; i > 0; i--) + digits_[i + offset] = (digits_[i] << interShift) | (digits_[i - 1] >> (kTypeBit - interShift)); + digits_[offset] = digits_[0] << interShift; + count_ += offset; + if (digits_[count_]) + count_++; + } + + std::memset(digits_, 0, offset * sizeof(Type)); + + return *this; + } + + bool operator==(const BigInteger& rhs) const { + return count_ == rhs.count_ && std::memcmp(digits_, rhs.digits_, count_ * sizeof(Type)) == 0; + } + + bool operator==(const Type rhs) const { + return count_ == 1 && digits_[0] == rhs; + } + + BigInteger& MultiplyPow5(unsigned exp) { + static const uint32_t kPow5[12] = { + 5, + 5 * 5, + 5 * 5 * 5, + 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 + }; + if (exp == 0) return *this; + for (; exp >= 27; exp -= 27) *this *= RAPIDJSON_UINT64_C2(0X6765C793, 0XFA10079D); // 5^27 + for (; exp >= 13; exp -= 13) *this *= static_cast(1220703125u); // 5^13 + if (exp > 0) *this *= kPow5[exp - 1]; + return *this; + } + + // Compute absolute difference of this and rhs. + // Return false if this < rhs + bool Difference(const BigInteger& rhs, BigInteger* out) const { + int cmp = Compare(rhs); + if (cmp == 0) { + *out = BigInteger(0); + return false; + } + const BigInteger *a, *b; // Makes a > b + bool ret; + if (cmp < 0) { a = &rhs; b = this; ret = true; } + else { a = this; b = &rhs; ret = false; } + + Type borrow = 0; + for (size_t i = 0; i < a->count_; i++) { + Type d = a->digits_[i] - borrow; + if (i < b->count_) + d -= b->digits_[i]; + borrow = (d > a->digits_[i]) ? 1 : 0; + out->digits_[i] = d; + if (d != 0) + out->count_ = i + 1; + } + + return ret; + } + + int Compare(const BigInteger& rhs) const { + if (count_ != rhs.count_) + return count_ < rhs.count_ ? -1 : 1; + + for (size_t i = count_; i-- > 0;) + if (digits_[i] != rhs.digits_[i]) + return digits_[i] < rhs.digits_[i] ? -1 : 1; + + return 0; + } + + size_t GetCount() const { return count_; } + Type GetDigit(size_t index) const { RAPIDJSON_ASSERT(index < count_); return digits_[index]; } + bool IsZero() const { return count_ == 1 && digits_[0] == 0; } + +private: + void AppendDecimal64(const char* begin, const char* end) { + uint64_t u = ParseUint64(begin, end); + if (IsZero()) + *this = u; + else { + unsigned exp = static_cast(end - begin); + (MultiplyPow5(exp) <<= exp) += u; // *this = *this * 10^exp + u + } + } + + void PushBack(Type digit) { + RAPIDJSON_ASSERT(count_ < kCapacity); + digits_[count_++] = digit; + } + + static uint64_t ParseUint64(const char* begin, const char* end) { + uint64_t r = 0; + for (const char* p = begin; p != end; ++p) { + RAPIDJSON_ASSERT(*p >= '0' && *p <= '9'); + r = r * 10 + (*p - '0'); + } + return r; + } + + // Assume a * b + k < 2^128 + static uint64_t MulAdd64(uint64_t a, uint64_t b, uint64_t k, uint64_t* outHigh) { +#if defined(_MSC_VER) && defined(_M_AMD64) + uint64_t low = _umul128(a, b, outHigh) + k; + if (low < k) + (*outHigh)++; + return low; +#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__) + unsigned __int128 p = static_cast(a) * static_cast(b); + p += k; + *outHigh = p >> 64; + return static_cast(p); +#else + const uint64_t a0 = a & 0xFFFFFFFF, a1 = a >> 32, b0 = b & 0xFFFFFFFF, b1 = b >> 32; + uint64_t x0 = a0 * b0, x1 = a0 * b1, x2 = a1 * b0, x3 = a1 * b1; + x1 += (x0 >> 32); // can't give carry + x1 += x2; + if (x1 < x2) + x3 += (static_cast(1) << 32); + uint64_t lo = (x1 << 32) + (x0 & 0xFFFFFFFF); + uint64_t hi = x3 + (x1 >> 32); + + lo += k; + if (lo < k) + hi++; + *outHigh = hi; + return lo; +#endif + } + + static Type FullAdd(Type a, Type b, bool inCarry, bool* outCarry) { + Type c = a + b + (inCarry ? 1 : 0); + *outCarry = c < a; + return c; + } + + static const size_t kBitCount = 3328; // 64bit * 54 > 10^1000 + static const size_t kCapacity = kBitCount / sizeof(Type); + static const size_t kTypeBit = sizeof(Type) * 8; + + Type digits_[kCapacity]; + size_t count_; +}; + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_BIGINTEGER_H_ diff --git a/src/include/rapidjson/internal/diyfp.h b/src/include/rapidjson/internal/diyfp.h new file mode 100644 index 0000000..174b9fa --- /dev/null +++ b/src/include/rapidjson/internal/diyfp.h @@ -0,0 +1,268 @@ +// Copyright (C) 2011 Milo Yip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +// This is a C++ header-only implementation of Grisu2 algorithm from the publication: +// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with +// integers." ACM Sigplan Notices 45.6 (2010): 233-243. + +#ifndef RAPIDJSON_DIYFP_H_ +#define RAPIDJSON_DIYFP_H_ + +#if defined(_MSC_VER) +#include +#if defined(_M_AMD64) +#pragma intrinsic(_BitScanReverse64) +#endif +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +struct DiyFp { + DiyFp() {} + + DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {} + + explicit DiyFp(double d) { + union { + double d; + uint64_t u64; + } u = { d }; + + int biased_e = (u.u64 & kDpExponentMask) >> kDpSignificandSize; + uint64_t significand = (u.u64 & kDpSignificandMask); + if (biased_e != 0) { + f = significand + kDpHiddenBit; + e = biased_e - kDpExponentBias; + } + else { + f = significand; + e = kDpMinExponent + 1; + } + } + + DiyFp operator-(const DiyFp& rhs) const { + return DiyFp(f - rhs.f, e); + } + + DiyFp operator*(const DiyFp& rhs) const { +#if defined(_MSC_VER) && defined(_M_AMD64) + uint64_t h; + uint64_t l = _umul128(f, rhs.f, &h); + if (l & (uint64_t(1) << 63)) // rounding + h++; + return DiyFp(h, e + rhs.e + 64); +#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__) + unsigned __int128 p = static_cast(f) * static_cast(rhs.f); + uint64_t h = p >> 64; + uint64_t l = static_cast(p); + if (l & (uint64_t(1) << 63)) // rounding + h++; + return DiyFp(h, e + rhs.e + 64); +#else + const uint64_t M32 = 0xFFFFFFFF; + const uint64_t a = f >> 32; + const uint64_t b = f & M32; + const uint64_t c = rhs.f >> 32; + const uint64_t d = rhs.f & M32; + const uint64_t ac = a * c; + const uint64_t bc = b * c; + const uint64_t ad = a * d; + const uint64_t bd = b * d; + uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32); + tmp += 1U << 31; /// mult_round + return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64); +#endif + } + + DiyFp Normalize() const { +#if defined(_MSC_VER) && defined(_M_AMD64) + unsigned long index; + _BitScanReverse64(&index, f); + return DiyFp(f << (63 - index), e - (63 - index)); +#elif defined(__GNUC__) && __GNUC__ >= 4 + int s = __builtin_clzll(f); + return DiyFp(f << s, e - s); +#else + DiyFp res = *this; + while (!(res.f & (static_cast(1) << 63))) { + res.f <<= 1; + res.e--; + } + return res; +#endif + } + + DiyFp NormalizeBoundary() const { + DiyFp res = *this; + while (!(res.f & (kDpHiddenBit << 1))) { + res.f <<= 1; + res.e--; + } + res.f <<= (kDiySignificandSize - kDpSignificandSize - 2); + res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2); + return res; + } + + void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const { + DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary(); + DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1); + mi.f <<= mi.e - pl.e; + mi.e = pl.e; + *plus = pl; + *minus = mi; + } + + double ToDouble() const { + union { + double d; + uint64_t u64; + }u; + uint64_t significand = f; + int exponent = e; + while (significand > kDpHiddenBit + kDpSignificandMask) { + significand >>= 1; + exponent++; + } + while (exponent > kDpDenormalExponent && (significand & kDpHiddenBit) == 0) { + significand <<= 1; + exponent--; + } + if (exponent >= kDpMaxExponent) { + u.u64 = kDpExponentMask; // Infinity + return u.d; + } + else if (exponent < kDpDenormalExponent) + return 0.0; + const uint64_t be = (exponent == kDpDenormalExponent && (significand & kDpHiddenBit) == 0) ? 0 : + static_cast(exponent + kDpExponentBias); + u.u64 = (significand & kDpSignificandMask) | (be << kDpSignificandSize); + return u.d; + } + + static const int kDiySignificandSize = 64; + static const int kDpSignificandSize = 52; + static const int kDpExponentBias = 0x3FF + kDpSignificandSize; + static const int kDpMaxExponent = 0x7FF - kDpExponentBias; + static const int kDpMinExponent = -kDpExponentBias; + static const int kDpDenormalExponent = -kDpExponentBias + 1; + static const uint64_t kDpExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000); + static const uint64_t kDpSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF); + static const uint64_t kDpHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000); + + uint64_t f; + int e; +}; + +inline DiyFp GetCachedPowerByIndex(size_t index) { + // 10^-348, 10^-340, ..., 10^340 + static const uint64_t kCachedPowers_F[] = { + RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76), + RAPIDJSON_UINT64_C2(0x8b16fb20, 0x3055ac76), RAPIDJSON_UINT64_C2(0xcf42894a, 0x5dce35ea), + RAPIDJSON_UINT64_C2(0x9a6bb0aa, 0x55653b2d), RAPIDJSON_UINT64_C2(0xe61acf03, 0x3d1a45df), + RAPIDJSON_UINT64_C2(0xab70fe17, 0xc79ac6ca), RAPIDJSON_UINT64_C2(0xff77b1fc, 0xbebcdc4f), + RAPIDJSON_UINT64_C2(0xbe5691ef, 0x416bd60c), RAPIDJSON_UINT64_C2(0x8dd01fad, 0x907ffc3c), + RAPIDJSON_UINT64_C2(0xd3515c28, 0x31559a83), RAPIDJSON_UINT64_C2(0x9d71ac8f, 0xada6c9b5), + RAPIDJSON_UINT64_C2(0xea9c2277, 0x23ee8bcb), RAPIDJSON_UINT64_C2(0xaecc4991, 0x4078536d), + RAPIDJSON_UINT64_C2(0x823c1279, 0x5db6ce57), RAPIDJSON_UINT64_C2(0xc2109436, 0x4dfb5637), + RAPIDJSON_UINT64_C2(0x9096ea6f, 0x3848984f), RAPIDJSON_UINT64_C2(0xd77485cb, 0x25823ac7), + RAPIDJSON_UINT64_C2(0xa086cfcd, 0x97bf97f4), RAPIDJSON_UINT64_C2(0xef340a98, 0x172aace5), + RAPIDJSON_UINT64_C2(0xb23867fb, 0x2a35b28e), RAPIDJSON_UINT64_C2(0x84c8d4df, 0xd2c63f3b), + RAPIDJSON_UINT64_C2(0xc5dd4427, 0x1ad3cdba), RAPIDJSON_UINT64_C2(0x936b9fce, 0xbb25c996), + RAPIDJSON_UINT64_C2(0xdbac6c24, 0x7d62a584), RAPIDJSON_UINT64_C2(0xa3ab6658, 0x0d5fdaf6), + RAPIDJSON_UINT64_C2(0xf3e2f893, 0xdec3f126), RAPIDJSON_UINT64_C2(0xb5b5ada8, 0xaaff80b8), + RAPIDJSON_UINT64_C2(0x87625f05, 0x6c7c4a8b), RAPIDJSON_UINT64_C2(0xc9bcff60, 0x34c13053), + RAPIDJSON_UINT64_C2(0x964e858c, 0x91ba2655), RAPIDJSON_UINT64_C2(0xdff97724, 0x70297ebd), + RAPIDJSON_UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), RAPIDJSON_UINT64_C2(0xf8a95fcf, 0x88747d94), + RAPIDJSON_UINT64_C2(0xb9447093, 0x8fa89bcf), RAPIDJSON_UINT64_C2(0x8a08f0f8, 0xbf0f156b), + RAPIDJSON_UINT64_C2(0xcdb02555, 0x653131b6), RAPIDJSON_UINT64_C2(0x993fe2c6, 0xd07b7fac), + RAPIDJSON_UINT64_C2(0xe45c10c4, 0x2a2b3b06), RAPIDJSON_UINT64_C2(0xaa242499, 0x697392d3), + RAPIDJSON_UINT64_C2(0xfd87b5f2, 0x8300ca0e), RAPIDJSON_UINT64_C2(0xbce50864, 0x92111aeb), + RAPIDJSON_UINT64_C2(0x8cbccc09, 0x6f5088cc), RAPIDJSON_UINT64_C2(0xd1b71758, 0xe219652c), + RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), RAPIDJSON_UINT64_C2(0xe8d4a510, 0x00000000), + RAPIDJSON_UINT64_C2(0xad78ebc5, 0xac620000), RAPIDJSON_UINT64_C2(0x813f3978, 0xf8940984), + RAPIDJSON_UINT64_C2(0xc097ce7b, 0xc90715b3), RAPIDJSON_UINT64_C2(0x8f7e32ce, 0x7bea5c70), + RAPIDJSON_UINT64_C2(0xd5d238a4, 0xabe98068), RAPIDJSON_UINT64_C2(0x9f4f2726, 0x179a2245), + RAPIDJSON_UINT64_C2(0xed63a231, 0xd4c4fb27), RAPIDJSON_UINT64_C2(0xb0de6538, 0x8cc8ada8), + RAPIDJSON_UINT64_C2(0x83c7088e, 0x1aab65db), RAPIDJSON_UINT64_C2(0xc45d1df9, 0x42711d9a), + RAPIDJSON_UINT64_C2(0x924d692c, 0xa61be758), RAPIDJSON_UINT64_C2(0xda01ee64, 0x1a708dea), + RAPIDJSON_UINT64_C2(0xa26da399, 0x9aef774a), RAPIDJSON_UINT64_C2(0xf209787b, 0xb47d6b85), + RAPIDJSON_UINT64_C2(0xb454e4a1, 0x79dd1877), RAPIDJSON_UINT64_C2(0x865b8692, 0x5b9bc5c2), + RAPIDJSON_UINT64_C2(0xc83553c5, 0xc8965d3d), RAPIDJSON_UINT64_C2(0x952ab45c, 0xfa97a0b3), + RAPIDJSON_UINT64_C2(0xde469fbd, 0x99a05fe3), RAPIDJSON_UINT64_C2(0xa59bc234, 0xdb398c25), + RAPIDJSON_UINT64_C2(0xf6c69a72, 0xa3989f5c), RAPIDJSON_UINT64_C2(0xb7dcbf53, 0x54e9bece), + RAPIDJSON_UINT64_C2(0x88fcf317, 0xf22241e2), RAPIDJSON_UINT64_C2(0xcc20ce9b, 0xd35c78a5), + RAPIDJSON_UINT64_C2(0x98165af3, 0x7b2153df), RAPIDJSON_UINT64_C2(0xe2a0b5dc, 0x971f303a), + RAPIDJSON_UINT64_C2(0xa8d9d153, 0x5ce3b396), RAPIDJSON_UINT64_C2(0xfb9b7cd9, 0xa4a7443c), + RAPIDJSON_UINT64_C2(0xbb764c4c, 0xa7a44410), RAPIDJSON_UINT64_C2(0x8bab8eef, 0xb6409c1a), + RAPIDJSON_UINT64_C2(0xd01fef10, 0xa657842c), RAPIDJSON_UINT64_C2(0x9b10a4e5, 0xe9913129), + RAPIDJSON_UINT64_C2(0xe7109bfb, 0xa19c0c9d), RAPIDJSON_UINT64_C2(0xac2820d9, 0x623bf429), + RAPIDJSON_UINT64_C2(0x80444b5e, 0x7aa7cf85), RAPIDJSON_UINT64_C2(0xbf21e440, 0x03acdd2d), + RAPIDJSON_UINT64_C2(0x8e679c2f, 0x5e44ff8f), RAPIDJSON_UINT64_C2(0xd433179d, 0x9c8cb841), + RAPIDJSON_UINT64_C2(0x9e19db92, 0xb4e31ba9), RAPIDJSON_UINT64_C2(0xeb96bf6e, 0xbadf77d9), + RAPIDJSON_UINT64_C2(0xaf87023b, 0x9bf0ee6b) + }; + static const int16_t kCachedPowers_E[] = { + -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, + -954, -927, -901, -874, -847, -821, -794, -768, -741, -715, + -688, -661, -635, -608, -582, -555, -529, -502, -475, -449, + -422, -396, -369, -343, -316, -289, -263, -236, -210, -183, + -157, -130, -103, -77, -50, -24, 3, 30, 56, 83, + 109, 136, 162, 189, 216, 242, 269, 295, 322, 348, + 375, 402, 428, 455, 481, 508, 534, 561, 588, 614, + 641, 667, 694, 720, 747, 774, 800, 827, 853, 880, + 907, 933, 960, 986, 1013, 1039, 1066 + }; + return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]); +} + +inline DiyFp GetCachedPower(int e, int* K) { + + //int k = static_cast(ceil((-61 - e) * 0.30102999566398114)) + 374; + double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive + int k = static_cast(dk); + if (k != dk) + k++; + + unsigned index = static_cast((k >> 3) + 1); + *K = -(-348 + static_cast(index << 3)); // decimal exponent no need lookup table + + return GetCachedPowerByIndex(index); +} + +inline DiyFp GetCachedPower10(int exp, int *outExp) { + unsigned index = (exp + 348) / 8; + *outExp = -348 + index * 8; + return GetCachedPowerByIndex(index); + } + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_DIYFP_H_ diff --git a/src/include/rapidjson/internal/dtoa.h b/src/include/rapidjson/internal/dtoa.h new file mode 100644 index 0000000..c0fa2b8 --- /dev/null +++ b/src/include/rapidjson/internal/dtoa.h @@ -0,0 +1,225 @@ +// Copyright (C) 2011 Milo Yip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +// This is a C++ header-only implementation of Grisu2 algorithm from the publication: +// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with +// integers." ACM Sigplan Notices 45.6 (2010): 233-243. + +#ifndef RAPIDJSON_DTOA_ +#define RAPIDJSON_DTOA_ + +#include "itoa.h" // GetDigitsLut() +#include "diyfp.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) { + while (rest < wp_w && delta - rest >= ten_kappa && + (rest + ten_kappa < wp_w || /// closer + wp_w - rest > rest + ten_kappa - wp_w)) { + buffer[len - 1]--; + rest += ten_kappa; + } +} + +inline unsigned CountDecimalDigit32(uint32_t n) { + // Simple pure C++ implementation was faster than __builtin_clz version in this situation. + if (n < 10) return 1; + if (n < 100) return 2; + if (n < 1000) return 3; + if (n < 10000) return 4; + if (n < 100000) return 5; + if (n < 1000000) return 6; + if (n < 10000000) return 7; + if (n < 100000000) return 8; + if (n < 1000000000) return 9; + return 10; +} + +inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) { + static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; + const DiyFp one(uint64_t(1) << -Mp.e, Mp.e); + const DiyFp wp_w = Mp - W; + uint32_t p1 = static_cast(Mp.f >> -one.e); + uint64_t p2 = Mp.f & (one.f - 1); + int kappa = CountDecimalDigit32(p1); + *len = 0; + + while (kappa > 0) { + uint32_t d; + switch (kappa) { + case 10: d = p1 / 1000000000; p1 %= 1000000000; break; + case 9: d = p1 / 100000000; p1 %= 100000000; break; + case 8: d = p1 / 10000000; p1 %= 10000000; break; + case 7: d = p1 / 1000000; p1 %= 1000000; break; + case 6: d = p1 / 100000; p1 %= 100000; break; + case 5: d = p1 / 10000; p1 %= 10000; break; + case 4: d = p1 / 1000; p1 %= 1000; break; + case 3: d = p1 / 100; p1 %= 100; break; + case 2: d = p1 / 10; p1 %= 10; break; + case 1: d = p1; p1 = 0; break; + default: +#if defined(_MSC_VER) + __assume(0); +#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) + __builtin_unreachable(); +#else + d = 0; +#endif + } + if (d || *len) + buffer[(*len)++] = static_cast('0' + static_cast(d)); + kappa--; + uint64_t tmp = (static_cast(p1) << -one.e) + p2; + if (tmp <= delta) { + *K += kappa; + GrisuRound(buffer, *len, delta, tmp, static_cast(kPow10[kappa]) << -one.e, wp_w.f); + return; + } + } + + // kappa = 0 + for (;;) { + p2 *= 10; + delta *= 10; + char d = static_cast(p2 >> -one.e); + if (d || *len) + buffer[(*len)++] = static_cast('0' + d); + p2 &= one.f - 1; + kappa--; + if (p2 < delta) { + *K += kappa; + GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * kPow10[-kappa]); + return; + } + } +} + +inline void Grisu2(double value, char* buffer, int* length, int* K) { + const DiyFp v(value); + DiyFp w_m, w_p; + v.NormalizedBoundaries(&w_m, &w_p); + + const DiyFp c_mk = GetCachedPower(w_p.e, K); + const DiyFp W = v.Normalize() * c_mk; + DiyFp Wp = w_p * c_mk; + DiyFp Wm = w_m * c_mk; + Wm.f++; + Wp.f--; + DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K); +} + +inline char* WriteExponent(int K, char* buffer) { + if (K < 0) { + *buffer++ = '-'; + K = -K; + } + + if (K >= 100) { + *buffer++ = static_cast('0' + static_cast(K / 100)); + K %= 100; + const char* d = GetDigitsLut() + K * 2; + *buffer++ = d[0]; + *buffer++ = d[1]; + } + else if (K >= 10) { + const char* d = GetDigitsLut() + K * 2; + *buffer++ = d[0]; + *buffer++ = d[1]; + } + else + *buffer++ = static_cast('0' + static_cast(K)); + + return buffer; +} + +inline char* Prettify(char* buffer, int length, int k) { + const int kk = length + k; // 10^(kk-1) <= v < 10^kk + + if (length <= kk && kk <= 21) { + // 1234e7 -> 12340000000 + for (int i = length; i < kk; i++) + buffer[i] = '0'; + buffer[kk] = '.'; + buffer[kk + 1] = '0'; + return &buffer[kk + 2]; + } + else if (0 < kk && kk <= 21) { + // 1234e-2 -> 12.34 + std::memmove(&buffer[kk + 1], &buffer[kk], length - kk); + buffer[kk] = '.'; + return &buffer[length + 1]; + } + else if (-6 < kk && kk <= 0) { + // 1234e-6 -> 0.001234 + const int offset = 2 - kk; + std::memmove(&buffer[offset], &buffer[0], length); + buffer[0] = '0'; + buffer[1] = '.'; + for (int i = 2; i < offset; i++) + buffer[i] = '0'; + return &buffer[length + offset]; + } + else if (length == 1) { + // 1e30 + buffer[1] = 'e'; + return WriteExponent(kk - 1, &buffer[2]); + } + else { + // 1234e30 -> 1.234e33 + std::memmove(&buffer[2], &buffer[1], length - 1); + buffer[1] = '.'; + buffer[length + 1] = 'e'; + return WriteExponent(kk - 1, &buffer[0 + length + 2]); + } +} + +inline char* dtoa(double value, char* buffer) { + if (value == 0) { + buffer[0] = '0'; + buffer[1] = '.'; + buffer[2] = '0'; + return &buffer[3]; + } + else { + if (value < 0) { + *buffer++ = '-'; + value = -value; + } + int length, K; + Grisu2(value, buffer, &length, &K); + return Prettify(buffer, length, K); + } +} + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_DTOA_ diff --git a/src/include/rapidjson/internal/ieee754.h b/src/include/rapidjson/internal/ieee754.h new file mode 100644 index 0000000..ab65cc9 --- /dev/null +++ b/src/include/rapidjson/internal/ieee754.h @@ -0,0 +1,90 @@ +// Copyright (C) 2011 Milo Yip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef RAPIDJSON_IEEE754_ +#define RAPIDJSON_IEEE754_ + +#include "../rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +class Double { +public: + Double() {} + Double(double d) : d(d) {} + Double(uint64_t u) : u(u) {} + + double Value() const { return d; } + uint64_t Uint64Value() const { return u; } + + double NextPositiveDouble() const { + RAPIDJSON_ASSERT(!Sign()); + return Double(u + 1).Value(); + } + + double PreviousPositiveDouble() const { + RAPIDJSON_ASSERT(!Sign()); + if (d == 0.0) + return 0.0; + else + return Double(u - 1).Value(); + } + + bool Sign() const { return (u & kSignMask) != 0; } + uint64_t Significand() const { return u & kSignificandMask; } + int Exponent() const { return ((u & kExponentMask) >> kSignificandSize) - kExponentBias; } + + bool IsNan() const { return (u & kExponentMask) == kExponentMask && Significand() != 0; } + bool IsInf() const { return (u & kExponentMask) == kExponentMask && Significand() == 0; } + bool IsNormal() const { return (u & kExponentMask) != 0 || Significand() == 0; } + + uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); } + int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; } + uint64_t ToBias() const { return (u & kSignMask) ? ~u + 1 : u | kSignMask; } + + static unsigned EffectiveSignificandSize(int order) { + if (order >= -1021) + return 53; + else if (order <= -1074) + return 0; + else + return order + 1074; + } + +private: + static const int kSignificandSize = 52; + static const int kExponentBias = 0x3FF; + static const int kDenormalExponent = 1 - kExponentBias; + static const uint64_t kSignMask = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000); + static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000); + static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF); + static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000); + + union { + double d; + uint64_t u; + }; +}; + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_IEEE754_ diff --git a/src/include/rapidjson/internal/itoa.h b/src/include/rapidjson/internal/itoa.h new file mode 100644 index 0000000..3684f07 --- /dev/null +++ b/src/include/rapidjson/internal/itoa.h @@ -0,0 +1,306 @@ +// Copyright (C) 2011 Milo Yip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef RAPIDJSON_ITOA_ +#define RAPIDJSON_ITOA_ + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +inline const char* GetDigitsLut() { + static const char cDigitsLut[200] = { + '0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9', + '1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9', + '2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9', + '3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9', + '4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9', + '5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9', + '6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9', + '7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9', + '8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9', + '9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9' + }; + return cDigitsLut; +} + +inline char* u32toa(uint32_t value, char* buffer) { + const char* cDigitsLut = GetDigitsLut(); + + if (value < 10000) { + const uint32_t d1 = (value / 100) << 1; + const uint32_t d2 = (value % 100) << 1; + + if (value >= 1000) + *buffer++ = cDigitsLut[d1]; + if (value >= 100) + *buffer++ = cDigitsLut[d1 + 1]; + if (value >= 10) + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + } + else if (value < 100000000) { + // value = bbbbcccc + const uint32_t b = value / 10000; + const uint32_t c = value % 10000; + + const uint32_t d1 = (b / 100) << 1; + const uint32_t d2 = (b % 100) << 1; + + const uint32_t d3 = (c / 100) << 1; + const uint32_t d4 = (c % 100) << 1; + + if (value >= 10000000) + *buffer++ = cDigitsLut[d1]; + if (value >= 1000000) + *buffer++ = cDigitsLut[d1 + 1]; + if (value >= 100000) + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + + *buffer++ = cDigitsLut[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; + *buffer++ = cDigitsLut[d4 + 1]; + } + else { + // value = aabbbbcccc in decimal + + const uint32_t a = value / 100000000; // 1 to 42 + value %= 100000000; + + if (a >= 10) { + const unsigned i = a << 1; + *buffer++ = cDigitsLut[i]; + *buffer++ = cDigitsLut[i + 1]; + } + else + *buffer++ = static_cast('0' + static_cast(a)); + + const uint32_t b = value / 10000; // 0 to 9999 + const uint32_t c = value % 10000; // 0 to 9999 + + const uint32_t d1 = (b / 100) << 1; + const uint32_t d2 = (b % 100) << 1; + + const uint32_t d3 = (c / 100) << 1; + const uint32_t d4 = (c % 100) << 1; + + *buffer++ = cDigitsLut[d1]; + *buffer++ = cDigitsLut[d1 + 1]; + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + *buffer++ = cDigitsLut[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; + *buffer++ = cDigitsLut[d4 + 1]; + } + return buffer; +} + +inline char* i32toa(int32_t value, char* buffer) { + if (value < 0) { + *buffer++ = '-'; + value = -value; + } + + return u32toa(static_cast(value), buffer); +} + +inline char* u64toa(uint64_t value, char* buffer) { + const char* cDigitsLut = GetDigitsLut(); + const uint64_t kTen8 = 100000000; + const uint64_t kTen9 = kTen8 * 10; + const uint64_t kTen10 = kTen8 * 100; + const uint64_t kTen11 = kTen8 * 1000; + const uint64_t kTen12 = kTen8 * 10000; + const uint64_t kTen13 = kTen8 * 100000; + const uint64_t kTen14 = kTen8 * 1000000; + const uint64_t kTen15 = kTen8 * 10000000; + const uint64_t kTen16 = kTen8 * kTen8; + + if (value < kTen8) { + uint32_t v = static_cast(value); + if (v < 10000) { + const uint32_t d1 = (v / 100) << 1; + const uint32_t d2 = (v % 100) << 1; + + if (v >= 1000) + *buffer++ = cDigitsLut[d1]; + if (v >= 100) + *buffer++ = cDigitsLut[d1 + 1]; + if (v >= 10) + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + } + else { + // value = bbbbcccc + const uint32_t b = v / 10000; + const uint32_t c = v % 10000; + + const uint32_t d1 = (b / 100) << 1; + const uint32_t d2 = (b % 100) << 1; + + const uint32_t d3 = (c / 100) << 1; + const uint32_t d4 = (c % 100) << 1; + + if (value >= 10000000) + *buffer++ = cDigitsLut[d1]; + if (value >= 1000000) + *buffer++ = cDigitsLut[d1 + 1]; + if (value >= 100000) + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + + *buffer++ = cDigitsLut[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; + *buffer++ = cDigitsLut[d4 + 1]; + } + } + else if (value < kTen16) { + const uint32_t v0 = static_cast(value / kTen8); + const uint32_t v1 = static_cast(value % kTen8); + + const uint32_t b0 = v0 / 10000; + const uint32_t c0 = v0 % 10000; + + const uint32_t d1 = (b0 / 100) << 1; + const uint32_t d2 = (b0 % 100) << 1; + + const uint32_t d3 = (c0 / 100) << 1; + const uint32_t d4 = (c0 % 100) << 1; + + const uint32_t b1 = v1 / 10000; + const uint32_t c1 = v1 % 10000; + + const uint32_t d5 = (b1 / 100) << 1; + const uint32_t d6 = (b1 % 100) << 1; + + const uint32_t d7 = (c1 / 100) << 1; + const uint32_t d8 = (c1 % 100) << 1; + + if (value >= kTen15) + *buffer++ = cDigitsLut[d1]; + if (value >= kTen14) + *buffer++ = cDigitsLut[d1 + 1]; + if (value >= kTen13) + *buffer++ = cDigitsLut[d2]; + if (value >= kTen12) + *buffer++ = cDigitsLut[d2 + 1]; + if (value >= kTen11) + *buffer++ = cDigitsLut[d3]; + if (value >= kTen10) + *buffer++ = cDigitsLut[d3 + 1]; + if (value >= kTen9) + *buffer++ = cDigitsLut[d4]; + if (value >= kTen8) + *buffer++ = cDigitsLut[d4 + 1]; + + *buffer++ = cDigitsLut[d5]; + *buffer++ = cDigitsLut[d5 + 1]; + *buffer++ = cDigitsLut[d6]; + *buffer++ = cDigitsLut[d6 + 1]; + *buffer++ = cDigitsLut[d7]; + *buffer++ = cDigitsLut[d7 + 1]; + *buffer++ = cDigitsLut[d8]; + *buffer++ = cDigitsLut[d8 + 1]; + } + else { + const uint32_t a = static_cast(value / kTen16); // 1 to 1844 + value %= kTen16; + + if (a < 10) + *buffer++ = static_cast('0' + static_cast(a)); + else if (a < 100) { + const uint32_t i = a << 1; + *buffer++ = cDigitsLut[i]; + *buffer++ = cDigitsLut[i + 1]; + } + else if (a < 1000) { + *buffer++ = static_cast('0' + static_cast(a / 100)); + + const uint32_t i = (a % 100) << 1; + *buffer++ = cDigitsLut[i]; + *buffer++ = cDigitsLut[i + 1]; + } + else { + const uint32_t i = (a / 100) << 1; + const uint32_t j = (a % 100) << 1; + *buffer++ = cDigitsLut[i]; + *buffer++ = cDigitsLut[i + 1]; + *buffer++ = cDigitsLut[j]; + *buffer++ = cDigitsLut[j + 1]; + } + + const uint32_t v0 = static_cast(value / kTen8); + const uint32_t v1 = static_cast(value % kTen8); + + const uint32_t b0 = v0 / 10000; + const uint32_t c0 = v0 % 10000; + + const uint32_t d1 = (b0 / 100) << 1; + const uint32_t d2 = (b0 % 100) << 1; + + const uint32_t d3 = (c0 / 100) << 1; + const uint32_t d4 = (c0 % 100) << 1; + + const uint32_t b1 = v1 / 10000; + const uint32_t c1 = v1 % 10000; + + const uint32_t d5 = (b1 / 100) << 1; + const uint32_t d6 = (b1 % 100) << 1; + + const uint32_t d7 = (c1 / 100) << 1; + const uint32_t d8 = (c1 % 100) << 1; + + *buffer++ = cDigitsLut[d1]; + *buffer++ = cDigitsLut[d1 + 1]; + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + *buffer++ = cDigitsLut[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; + *buffer++ = cDigitsLut[d4 + 1]; + *buffer++ = cDigitsLut[d5]; + *buffer++ = cDigitsLut[d5 + 1]; + *buffer++ = cDigitsLut[d6]; + *buffer++ = cDigitsLut[d6 + 1]; + *buffer++ = cDigitsLut[d7]; + *buffer++ = cDigitsLut[d7 + 1]; + *buffer++ = cDigitsLut[d8]; + *buffer++ = cDigitsLut[d8 + 1]; + } + + return buffer; +} + +inline char* i64toa(int64_t value, char* buffer) { + if (value < 0) { + *buffer++ = '-'; + value = -value; + } + + return u64toa(static_cast(value), buffer); +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_ITOA_ diff --git a/src/include/rapidjson/internal/meta.h b/src/include/rapidjson/internal/meta.h new file mode 100644 index 0000000..c33f607 --- /dev/null +++ b/src/include/rapidjson/internal/meta.h @@ -0,0 +1,189 @@ +// Copyright (C) 2011 Milo Yip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef RAPIDJSON_INTERNAL_META_H_ +#define RAPIDJSON_INTERNAL_META_H_ + +#ifndef RAPIDJSON_RAPIDJSON_H_ +#error not yet included. Do not include this file directly. +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif +#if defined(_MSC_VER) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(6334) +#endif + +#if RAPIDJSON_HAS_CXX11_TYPETRAITS +#include +#endif + +//@cond RAPIDJSON_INTERNAL +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching +template struct Void { typedef void Type; }; + +/////////////////////////////////////////////////////////////////////////////// +// BoolType, TrueType, FalseType +// +template struct BoolType { + static const bool Value = Cond; + typedef BoolType Type; +}; +typedef BoolType TrueType; +typedef BoolType FalseType; + + +/////////////////////////////////////////////////////////////////////////////// +// SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr +// + +template struct SelectIfImpl { template struct Apply { typedef T1 Type; }; }; +template <> struct SelectIfImpl { template struct Apply { typedef T2 Type; }; }; +template struct SelectIfCond : SelectIfImpl::template Apply {}; +template struct SelectIf : SelectIfCond {}; + +template struct AndExprCond : FalseType {}; +template <> struct AndExprCond : TrueType {}; +template struct OrExprCond : TrueType {}; +template <> struct OrExprCond : FalseType {}; + +template struct BoolExpr : SelectIf::Type {}; +template struct NotExpr : SelectIf::Type {}; +template struct AndExpr : AndExprCond::Type {}; +template struct OrExpr : OrExprCond::Type {}; + + +/////////////////////////////////////////////////////////////////////////////// +// AddConst, MaybeAddConst, RemoveConst +template struct AddConst { typedef const T Type; }; +template struct MaybeAddConst : SelectIfCond {}; +template struct RemoveConst { typedef T Type; }; +template struct RemoveConst { typedef T Type; }; + + +/////////////////////////////////////////////////////////////////////////////// +// IsSame, IsConst, IsMoreConst, IsPointer +// +template struct IsSame : FalseType {}; +template struct IsSame : TrueType {}; + +template struct IsConst : FalseType {}; +template struct IsConst : TrueType {}; + +template +struct IsMoreConst + : AndExpr::Type, typename RemoveConst::Type>, + BoolType::Value >= IsConst::Value> >::Type {}; + +template struct IsPointer : FalseType {}; +template struct IsPointer : TrueType {}; + +/////////////////////////////////////////////////////////////////////////////// +// IsBaseOf +// +#if RAPIDJSON_HAS_CXX11_TYPETRAITS + +template struct IsBaseOf + : BoolType< ::std::is_base_of::value> {}; + +#else // simplified version adopted from Boost + +template struct IsBaseOfImpl { + RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0); + RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0); + + typedef char (&Yes)[1]; + typedef char (&No) [2]; + + template + static Yes Check(const D*, T); + static No Check(const B*, int); + + struct Host { + operator const B*() const; + operator const D*(); + }; + + enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) }; +}; + +template struct IsBaseOf + : OrExpr, BoolExpr > >::Type {}; + +#endif // RAPIDJSON_HAS_CXX11_TYPETRAITS + + +////////////////////////////////////////////////////////////////////////// +// EnableIf / DisableIf +// +template struct EnableIfCond { typedef T Type; }; +template struct EnableIfCond { /* empty */ }; + +template struct DisableIfCond { typedef T Type; }; +template struct DisableIfCond { /* empty */ }; + +template +struct EnableIf : EnableIfCond {}; + +template +struct DisableIf : DisableIfCond {}; + +// SFINAE helpers +struct SfinaeTag {}; +template struct RemoveSfinaeTag; +template struct RemoveSfinaeTag { typedef T Type; }; + +#define RAPIDJSON_REMOVEFPTR_(type) \ + typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \ + < ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type + +#define RAPIDJSON_ENABLEIF(cond) \ + typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ + ::Type * = NULL + +#define RAPIDJSON_DISABLEIF(cond) \ + typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ + ::Type * = NULL + +#define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \ + typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ + ::Type + +#define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \ + typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ + ::Type + +} // namespace internal +RAPIDJSON_NAMESPACE_END +//@endcond + +#if defined(__GNUC__) || defined(_MSC_VER) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_INTERNAL_META_H_ diff --git a/src/include/rapidjson/internal/pow10.h b/src/include/rapidjson/internal/pow10.h new file mode 100644 index 0000000..91cf647 --- /dev/null +++ b/src/include/rapidjson/internal/pow10.h @@ -0,0 +1,59 @@ +// Copyright (C) 2011 Milo Yip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef RAPIDJSON_POW10_ +#define RAPIDJSON_POW10_ + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +//! Computes integer powers of 10 in double (10.0^n). +/*! This function uses lookup table for fast and accurate results. + \param n non-negative exponent. Must <= 308. + \return 10.0^n +*/ +inline double Pow10(int n) { + static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes + 1e+0, + 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20, + 1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40, + 1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60, + 1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80, + 1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100, + 1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120, + 1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140, + 1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160, + 1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180, + 1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200, + 1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220, + 1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240, + 1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260, + 1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280, + 1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300, + 1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308 + }; + RAPIDJSON_ASSERT(n >= 0 && n <= 308); + return e[n]; +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_POW10_ diff --git a/src/include/rapidjson/internal/stack.h b/src/include/rapidjson/internal/stack.h new file mode 100644 index 0000000..62ae7aa --- /dev/null +++ b/src/include/rapidjson/internal/stack.h @@ -0,0 +1,183 @@ +// Copyright (C) 2011 Milo Yip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef RAPIDJSON_INTERNAL_STACK_H_ +#define RAPIDJSON_INTERNAL_STACK_H_ + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +/////////////////////////////////////////////////////////////////////////////// +// Stack + +//! A type-unsafe stack for storing different types of data. +/*! \tparam Allocator Allocator for allocating stack memory. +*/ +template +class Stack { +public: + // Optimization note: Do not allocate memory for stack_ in constructor. + // Do it lazily when first Push() -> Expand() -> Resize(). + Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) { + RAPIDJSON_ASSERT(stackCapacity > 0); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + Stack(Stack&& rhs) + : allocator_(rhs.allocator_), + ownAllocator_(rhs.ownAllocator_), + stack_(rhs.stack_), + stackTop_(rhs.stackTop_), + stackEnd_(rhs.stackEnd_), + initialCapacity_(rhs.initialCapacity_) + { + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.stack_ = 0; + rhs.stackTop_ = 0; + rhs.stackEnd_ = 0; + rhs.initialCapacity_ = 0; + } +#endif + + ~Stack() { + Destroy(); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + Stack& operator=(Stack&& rhs) { + if (&rhs != this) + { + Destroy(); + + allocator_ = rhs.allocator_; + ownAllocator_ = rhs.ownAllocator_; + stack_ = rhs.stack_; + stackTop_ = rhs.stackTop_; + stackEnd_ = rhs.stackEnd_; + initialCapacity_ = rhs.initialCapacity_; + + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.stack_ = 0; + rhs.stackTop_ = 0; + rhs.stackEnd_ = 0; + rhs.initialCapacity_ = 0; + } + return *this; + } +#endif + + void Clear() { stackTop_ = stack_; } + + void ShrinkToFit() { + if (Empty()) { + // If the stack is empty, completely deallocate the memory. + Allocator::Free(stack_); + stack_ = 0; + stackTop_ = 0; + stackEnd_ = 0; + } + else + Resize(GetSize()); + } + + // Optimization note: try to minimize the size of this function for force inline. + // Expansion is run very infrequently, so it is moved to another (probably non-inline) function. + template + RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) { + // Expand the stack if needed + if (stackTop_ + sizeof(T) * count >= stackEnd_) + Expand(count); + + T* ret = reinterpret_cast(stackTop_); + stackTop_ += sizeof(T) * count; + return ret; + } + + template + T* Pop(size_t count) { + RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T)); + stackTop_ -= count * sizeof(T); + return reinterpret_cast(stackTop_); + } + + template + T* Top() { + RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); + return reinterpret_cast(stackTop_ - sizeof(T)); + } + + template + T* Bottom() { return (T*)stack_; } + + Allocator& GetAllocator() { return *allocator_; } + bool Empty() const { return stackTop_ == stack_; } + size_t GetSize() const { return static_cast(stackTop_ - stack_); } + size_t GetCapacity() const { return static_cast(stackEnd_ - stack_); } + +private: + template + void Expand(size_t count) { + // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity. + size_t newCapacity; + if (stack_ == 0) { + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + newCapacity = initialCapacity_; + } else { + newCapacity = GetCapacity(); + newCapacity += (newCapacity + 1) / 2; + } + size_t newSize = GetSize() + sizeof(T) * count; + if (newCapacity < newSize) + newCapacity = newSize; + + Resize(newCapacity); + } + + void Resize(size_t newCapacity) { + const size_t size = GetSize(); // Backup the current size + stack_ = (char*)allocator_->Realloc(stack_, GetCapacity(), newCapacity); + stackTop_ = stack_ + size; + stackEnd_ = stack_ + newCapacity; + } + + void Destroy() { + Allocator::Free(stack_); + RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack + } + + // Prohibit copy constructor & assignment operator. + Stack(const Stack&); + Stack& operator=(const Stack&); + + Allocator* allocator_; + Allocator* ownAllocator_; + char *stack_; + char *stackTop_; + char *stackEnd_; + size_t initialCapacity_; +}; + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_STACK_H_ diff --git a/src/include/rapidjson/internal/strfunc.h b/src/include/rapidjson/internal/strfunc.h new file mode 100644 index 0000000..734adc3 --- /dev/null +++ b/src/include/rapidjson/internal/strfunc.h @@ -0,0 +1,43 @@ +// Copyright (C) 2011 Milo Yip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef RAPIDJSON_INTERNAL_STRFUNC_H_ +#define RAPIDJSON_INTERNAL_STRFUNC_H_ + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +//! Custom strlen() which works on different character types. +/*! \tparam Ch Character type (e.g. char, wchar_t, short) + \param s Null-terminated input string. + \return Number of characters in the string. + \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints. +*/ +template +inline SizeType StrLen(const Ch* s) { + const Ch* p = s; + while (*p) ++p; + return SizeType(p - s); +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_INTERNAL_STRFUNC_H_ diff --git a/src/include/rapidjson/internal/strtod.h b/src/include/rapidjson/internal/strtod.h new file mode 100644 index 0000000..1fc6050 --- /dev/null +++ b/src/include/rapidjson/internal/strtod.h @@ -0,0 +1,285 @@ +// Copyright (C) 2011 Milo Yip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef RAPIDJSON_STRTOD_ +#define RAPIDJSON_STRTOD_ + +#include "../rapidjson.h" +#include "ieee754.h" +#include "biginteger.h" +#include "diyfp.h" +#include "pow10.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +inline double FastPath(double significand, int exp) { + if (exp < -308) + return 0.0; + else if (exp >= 0) + return significand * internal::Pow10(exp); + else + return significand / internal::Pow10(-exp); +} + +inline double StrtodNormalPrecision(double d, int p) { + if (p < -308) { + // Prevent expSum < -308, making Pow10(p) = 0 + d = FastPath(d, -308); + d = FastPath(d, p + 308); + } + else + d = FastPath(d, p); + return d; +} + +template +inline T Min3(T a, T b, T c) { + T m = a; + if (m > b) m = b; + if (m > c) m = c; + return m; +} + +inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp, bool* adjustToNegative) { + const Double db(b); + const uint64_t bInt = db.IntegerSignificand(); + const int bExp = db.IntegerExponent(); + const int hExp = bExp - 1; + + int dS_Exp2 = 0, dS_Exp5 = 0, bS_Exp2 = 0, bS_Exp5 = 0, hS_Exp2 = 0, hS_Exp5 = 0; + + // Adjust for decimal exponent + if (dExp >= 0) { + dS_Exp2 += dExp; + dS_Exp5 += dExp; + } + else { + bS_Exp2 -= dExp; + bS_Exp5 -= dExp; + hS_Exp2 -= dExp; + hS_Exp5 -= dExp; + } + + // Adjust for binary exponent + if (bExp >= 0) + bS_Exp2 += bExp; + else { + dS_Exp2 -= bExp; + hS_Exp2 -= bExp; + } + + // Adjust for half ulp exponent + if (hExp >= 0) + hS_Exp2 += hExp; + else { + dS_Exp2 -= hExp; + bS_Exp2 -= hExp; + } + + // Remove common power of two factor from all three scaled values + int common_Exp2 = Min3(dS_Exp2, bS_Exp2, hS_Exp2); + dS_Exp2 -= common_Exp2; + bS_Exp2 -= common_Exp2; + hS_Exp2 -= common_Exp2; + + BigInteger dS = d; + dS.MultiplyPow5(dS_Exp5) <<= dS_Exp2; + + BigInteger bS(bInt); + bS.MultiplyPow5(bS_Exp5) <<= bS_Exp2; + + BigInteger hS(1); + hS.MultiplyPow5(hS_Exp5) <<= hS_Exp2; + + BigInteger delta(0); + *adjustToNegative = dS.Difference(bS, &delta); + + int cmp = delta.Compare(hS); + // If delta is within 1/2 ULP, check for special case when significand is power of two. + // In this case, need to compare with 1/2h in the lower bound. + if (cmp < 0 && *adjustToNegative && // within and dS < bS + db.IsNormal() && (bInt & (bInt - 1)) == 0 && // Power of 2 + db.Uint64Value() != RAPIDJSON_UINT64_C2(0x00100000, 0x00000000)) // minimum normal number must not do this + { + delta <<= 1; + return delta.Compare(hS); + } + return cmp; +} + +inline bool StrtodFast(double d, int p, double* result) { + // Use fast path for string-to-double conversion if possible + // see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/ + if (p > 22 && p < 22 + 16) { + // Fast Path Cases In Disguise + d *= internal::Pow10(p - 22); + p = 22; + } + + if (p >= -22 && p <= 22 && d <= 9007199254740991.0) { // 2^53 - 1 + *result = FastPath(d, p); + return true; + } + else + return false; +} + +// Compute an approximation and see if it is within 1/2 ULP +inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosition, int exp, double* result) { + uint64_t significand = 0; + size_t i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999 + for (; i < length; i++) { + if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || + (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5')) + break; + significand = significand * 10 + (decimals[i] - '0'); + } + + if (i < length && decimals[i] >= '5') // Rounding + significand++; + + size_t remaining = length - i; + const unsigned kUlpShift = 3; + const unsigned kUlp = 1 << kUlpShift; + int error = (remaining == 0) ? 0 : kUlp / 2; + + DiyFp v(significand, 0); + v = v.Normalize(); + error <<= -v.e; + + const int dExp = (int)decimalPosition - (int)i + exp; + + int actualExp; + DiyFp cachedPower = GetCachedPower10(dExp, &actualExp); + if (actualExp != dExp) { + static const DiyFp kPow10[] = { + DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 00000000), -60), // 10^1 + DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 00000000), -57), // 10^2 + DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 00000000), -54), // 10^3 + DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 00000000), -50), // 10^4 + DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 00000000), -47), // 10^5 + DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 00000000), -44), // 10^6 + DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 00000000), -40) // 10^7 + }; + int adjustment = dExp - actualExp - 1; + RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7); + v = v * kPow10[adjustment]; + if (length + adjustment > 19) // has more digits than decimal digits in 64-bit + error += kUlp / 2; + } + + v = v * cachedPower; + + error += kUlp + (error == 0 ? 0 : 1); + + const int oldExp = v.e; + v = v.Normalize(); + error <<= oldExp - v.e; + + const unsigned effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e); + unsigned precisionSize = 64 - effectiveSignificandSize; + if (precisionSize + kUlpShift >= 64) { + unsigned scaleExp = (precisionSize + kUlpShift) - 63; + v.f >>= scaleExp; + v.e += scaleExp; + error = (error >> scaleExp) + 1 + kUlp; + precisionSize -= scaleExp; + } + + DiyFp rounded(v.f >> precisionSize, v.e + precisionSize); + const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp; + const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp; + if (precisionBits >= halfWay + error) + rounded.f++; + + *result = rounded.ToDouble(); + + return halfWay - error >= precisionBits || precisionBits >= halfWay + error; +} + +inline double StrtodBigInteger(double approx, const char* decimals, size_t length, size_t decimalPosition, int exp) { + const BigInteger dInt(decimals, length); + const int dExp = (int)decimalPosition - (int)length + exp; + Double a(approx); + for (int i = 0; i < 10; i++) { + bool adjustToNegative; + int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp, &adjustToNegative); + if (cmp < 0) + return a.Value(); // within half ULP + else if (cmp == 0) { + // Round towards even + if (a.Significand() & 1) + return adjustToNegative ? a.PreviousPositiveDouble() : a.NextPositiveDouble(); + else + return a.Value(); + } + else // adjustment + a = adjustToNegative ? a.PreviousPositiveDouble() : a.NextPositiveDouble(); + } + + // This should not happen, but in case there is really a bug, break the infinite-loop + return a.Value(); +} + +inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) { + RAPIDJSON_ASSERT(d >= 0.0); + RAPIDJSON_ASSERT(length >= 1); + + double result; + if (StrtodFast(d, p, &result)) + return result; + + // Trim leading zeros + while (*decimals == '0' && length > 1) { + length--; + decimals++; + decimalPosition--; + } + + // Trim trailing zeros + while (decimals[length - 1] == '0' && length > 1) { + length--; + decimalPosition--; + exp++; + } + + // Trim right-most digits + const int kMaxDecimalDigit = 780; + if ((int)length > kMaxDecimalDigit) { + exp += (int(length) - kMaxDecimalDigit); + length = kMaxDecimalDigit; + } + + // If too small, underflow to zero + if (int(length) + exp < -324) + return 0.0; + + if (StrtodDiyFp(decimals, length, decimalPosition, exp, &result)) + return result; + + // Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison + return StrtodBigInteger(result, decimals, length, decimalPosition, exp); +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_STRTOD_ diff --git a/src/include/rapidjson/memorybuffer.h b/src/include/rapidjson/memorybuffer.h new file mode 100644 index 0000000..95c68a3 --- /dev/null +++ b/src/include/rapidjson/memorybuffer.h @@ -0,0 +1,76 @@ +// Copyright (C) 2011 Milo Yip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef RAPIDJSON_MEMORYBUFFER_H_ +#define RAPIDJSON_MEMORYBUFFER_H_ + +#include "rapidjson.h" +#include "internal/stack.h" + +RAPIDJSON_NAMESPACE_BEGIN + +//! Represents an in-memory output byte stream. +/*! + This class is mainly for being wrapped by EncodedOutputStream or AutoUTFOutputStream. + + It is similar to FileWriteBuffer but the destination is an in-memory buffer instead of a file. + + Differences between MemoryBuffer and StringBuffer: + 1. StringBuffer has Encoding but MemoryBuffer is only a byte buffer. + 2. StringBuffer::GetString() returns a null-terminated string. MemoryBuffer::GetBuffer() returns a buffer without terminator. + + \tparam Allocator type for allocating memory buffer. + \note implements Stream concept +*/ +template +struct GenericMemoryBuffer { + typedef char Ch; // byte + + GenericMemoryBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} + + void Put(Ch c) { *stack_.template Push() = c; } + void Flush() {} + + void Clear() { stack_.Clear(); } + void ShrinkToFit() { stack_.ShrinkToFit(); } + Ch* Push(size_t count) { return stack_.template Push(count); } + void Pop(size_t count) { stack_.template Pop(count); } + + const Ch* GetBuffer() const { + return stack_.template Bottom(); + } + + size_t GetSize() const { return stack_.GetSize(); } + + static const size_t kDefaultCapacity = 256; + mutable internal::Stack stack_; +}; + +typedef GenericMemoryBuffer<> MemoryBuffer; + +//! Implement specialized version of PutN() with memset() for better performance. +template<> +inline void PutN(MemoryBuffer& memoryBuffer, char c, size_t n) { + std::memset(memoryBuffer.stack_.Push(n), c, n * sizeof(c)); +} + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_MEMORYBUFFER_H_ diff --git a/src/include/rapidjson/memorystream.h b/src/include/rapidjson/memorystream.h new file mode 100644 index 0000000..f994a12 --- /dev/null +++ b/src/include/rapidjson/memorystream.h @@ -0,0 +1,67 @@ +// Copyright (C) 2011 Milo Yip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef RAPIDJSON_MEMORYSTREAM_H_ +#define RAPIDJSON_MEMORYSTREAM_H_ + +#include "rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN + +//! Represents an in-memory input byte stream. +/*! + This class is mainly for being wrapped by EncodedInputStream or AutoUTFInputStream. + + It is similar to FileReadBuffer but the source is an in-memory buffer instead of a file. + + Differences between MemoryStream and StringStream: + 1. StringStream has encoding but MemoryStream is a byte stream. + 2. MemoryStream needs size of the source buffer and the buffer don't need to be null terminated. StringStream assume null-terminated string as source. + 3. MemoryStream supports Peek4() for encoding detection. StringStream is specified with an encoding so it should not have Peek4(). + \note implements Stream concept +*/ +struct MemoryStream { + typedef char Ch; // byte + + MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {} + + Ch Peek() const { return (src_ == end_) ? '\0' : *src_; } + Ch Take() { return (src_ == end_) ? '\0' : *src_++; } + size_t Tell() const { return static_cast(src_ - begin_); } + + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + + // For encoding detection only. + const Ch* Peek4() const { + return Tell() + 4 <= size_ ? src_ : 0; + } + + const Ch* src_; //!< Current read position. + const Ch* begin_; //!< Original head of the string. + const Ch* end_; //!< End of stream. + size_t size_; //!< Size of the stream. +}; + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_MEMORYBUFFER_H_ diff --git a/src/include/rapidjson/msinttypes/inttypes.h b/src/include/rapidjson/msinttypes/inttypes.h new file mode 100644 index 0000000..af713c9 --- /dev/null +++ b/src/include/rapidjson/msinttypes/inttypes.h @@ -0,0 +1,312 @@ +// ISO C9x compliant inttypes.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2013 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the product nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_INTTYPES_H_ // [ +#define _MSC_INTTYPES_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include "stdint.h" + +// miloyip: VC supports inttypes.h since VC2013 +#if _MSC_VER >= 1800 +#include +#else + +// 7.8 Format conversion of integer types + +typedef struct { + intmax_t quot; + intmax_t rem; +} imaxdiv_t; + +// 7.8.1 Macros for format specifiers + +#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198 + +// The fprintf macros for signed integers are: +#define PRId8 "d" +#define PRIi8 "i" +#define PRIdLEAST8 "d" +#define PRIiLEAST8 "i" +#define PRIdFAST8 "d" +#define PRIiFAST8 "i" + +#define PRId16 "hd" +#define PRIi16 "hi" +#define PRIdLEAST16 "hd" +#define PRIiLEAST16 "hi" +#define PRIdFAST16 "hd" +#define PRIiFAST16 "hi" + +#define PRId32 "I32d" +#define PRIi32 "I32i" +#define PRIdLEAST32 "I32d" +#define PRIiLEAST32 "I32i" +#define PRIdFAST32 "I32d" +#define PRIiFAST32 "I32i" + +#define PRId64 "I64d" +#define PRIi64 "I64i" +#define PRIdLEAST64 "I64d" +#define PRIiLEAST64 "I64i" +#define PRIdFAST64 "I64d" +#define PRIiFAST64 "I64i" + +#define PRIdMAX "I64d" +#define PRIiMAX "I64i" + +#define PRIdPTR "Id" +#define PRIiPTR "Ii" + +// The fprintf macros for unsigned integers are: +#define PRIo8 "o" +#define PRIu8 "u" +#define PRIx8 "x" +#define PRIX8 "X" +#define PRIoLEAST8 "o" +#define PRIuLEAST8 "u" +#define PRIxLEAST8 "x" +#define PRIXLEAST8 "X" +#define PRIoFAST8 "o" +#define PRIuFAST8 "u" +#define PRIxFAST8 "x" +#define PRIXFAST8 "X" + +#define PRIo16 "ho" +#define PRIu16 "hu" +#define PRIx16 "hx" +#define PRIX16 "hX" +#define PRIoLEAST16 "ho" +#define PRIuLEAST16 "hu" +#define PRIxLEAST16 "hx" +#define PRIXLEAST16 "hX" +#define PRIoFAST16 "ho" +#define PRIuFAST16 "hu" +#define PRIxFAST16 "hx" +#define PRIXFAST16 "hX" + +#define PRIo32 "I32o" +#define PRIu32 "I32u" +#define PRIx32 "I32x" +#define PRIX32 "I32X" +#define PRIoLEAST32 "I32o" +#define PRIuLEAST32 "I32u" +#define PRIxLEAST32 "I32x" +#define PRIXLEAST32 "I32X" +#define PRIoFAST32 "I32o" +#define PRIuFAST32 "I32u" +#define PRIxFAST32 "I32x" +#define PRIXFAST32 "I32X" + +#define PRIo64 "I64o" +#define PRIu64 "I64u" +#define PRIx64 "I64x" +#define PRIX64 "I64X" +#define PRIoLEAST64 "I64o" +#define PRIuLEAST64 "I64u" +#define PRIxLEAST64 "I64x" +#define PRIXLEAST64 "I64X" +#define PRIoFAST64 "I64o" +#define PRIuFAST64 "I64u" +#define PRIxFAST64 "I64x" +#define PRIXFAST64 "I64X" + +#define PRIoMAX "I64o" +#define PRIuMAX "I64u" +#define PRIxMAX "I64x" +#define PRIXMAX "I64X" + +#define PRIoPTR "Io" +#define PRIuPTR "Iu" +#define PRIxPTR "Ix" +#define PRIXPTR "IX" + +// The fscanf macros for signed integers are: +#define SCNd8 "d" +#define SCNi8 "i" +#define SCNdLEAST8 "d" +#define SCNiLEAST8 "i" +#define SCNdFAST8 "d" +#define SCNiFAST8 "i" + +#define SCNd16 "hd" +#define SCNi16 "hi" +#define SCNdLEAST16 "hd" +#define SCNiLEAST16 "hi" +#define SCNdFAST16 "hd" +#define SCNiFAST16 "hi" + +#define SCNd32 "ld" +#define SCNi32 "li" +#define SCNdLEAST32 "ld" +#define SCNiLEAST32 "li" +#define SCNdFAST32 "ld" +#define SCNiFAST32 "li" + +#define SCNd64 "I64d" +#define SCNi64 "I64i" +#define SCNdLEAST64 "I64d" +#define SCNiLEAST64 "I64i" +#define SCNdFAST64 "I64d" +#define SCNiFAST64 "I64i" + +#define SCNdMAX "I64d" +#define SCNiMAX "I64i" + +#ifdef _WIN64 // [ +# define SCNdPTR "I64d" +# define SCNiPTR "I64i" +#else // _WIN64 ][ +# define SCNdPTR "ld" +# define SCNiPTR "li" +#endif // _WIN64 ] + +// The fscanf macros for unsigned integers are: +#define SCNo8 "o" +#define SCNu8 "u" +#define SCNx8 "x" +#define SCNX8 "X" +#define SCNoLEAST8 "o" +#define SCNuLEAST8 "u" +#define SCNxLEAST8 "x" +#define SCNXLEAST8 "X" +#define SCNoFAST8 "o" +#define SCNuFAST8 "u" +#define SCNxFAST8 "x" +#define SCNXFAST8 "X" + +#define SCNo16 "ho" +#define SCNu16 "hu" +#define SCNx16 "hx" +#define SCNX16 "hX" +#define SCNoLEAST16 "ho" +#define SCNuLEAST16 "hu" +#define SCNxLEAST16 "hx" +#define SCNXLEAST16 "hX" +#define SCNoFAST16 "ho" +#define SCNuFAST16 "hu" +#define SCNxFAST16 "hx" +#define SCNXFAST16 "hX" + +#define SCNo32 "lo" +#define SCNu32 "lu" +#define SCNx32 "lx" +#define SCNX32 "lX" +#define SCNoLEAST32 "lo" +#define SCNuLEAST32 "lu" +#define SCNxLEAST32 "lx" +#define SCNXLEAST32 "lX" +#define SCNoFAST32 "lo" +#define SCNuFAST32 "lu" +#define SCNxFAST32 "lx" +#define SCNXFAST32 "lX" + +#define SCNo64 "I64o" +#define SCNu64 "I64u" +#define SCNx64 "I64x" +#define SCNX64 "I64X" +#define SCNoLEAST64 "I64o" +#define SCNuLEAST64 "I64u" +#define SCNxLEAST64 "I64x" +#define SCNXLEAST64 "I64X" +#define SCNoFAST64 "I64o" +#define SCNuFAST64 "I64u" +#define SCNxFAST64 "I64x" +#define SCNXFAST64 "I64X" + +#define SCNoMAX "I64o" +#define SCNuMAX "I64u" +#define SCNxMAX "I64x" +#define SCNXMAX "I64X" + +#ifdef _WIN64 // [ +# define SCNoPTR "I64o" +# define SCNuPTR "I64u" +# define SCNxPTR "I64x" +# define SCNXPTR "I64X" +#else // _WIN64 ][ +# define SCNoPTR "lo" +# define SCNuPTR "lu" +# define SCNxPTR "lx" +# define SCNXPTR "lX" +#endif // _WIN64 ] + +#endif // __STDC_FORMAT_MACROS ] + +// 7.8.2 Functions for greatest-width integer types + +// 7.8.2.1 The imaxabs function +#define imaxabs _abs64 + +// 7.8.2.2 The imaxdiv function + +// This is modified version of div() function from Microsoft's div.c found +// in %MSVC.NET%\crt\src\div.c +#ifdef STATIC_IMAXDIV // [ +static +#else // STATIC_IMAXDIV ][ +_inline +#endif // STATIC_IMAXDIV ] +imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) +{ + imaxdiv_t result; + + result.quot = numer / denom; + result.rem = numer % denom; + + if (numer < 0 && result.rem > 0) { + // did division wrong; must fix up + ++result.quot; + result.rem -= denom; + } + + return result; +} + +// 7.8.2.3 The strtoimax and strtoumax functions +#define strtoimax _strtoi64 +#define strtoumax _strtoui64 + +// 7.8.2.4 The wcstoimax and wcstoumax functions +#define wcstoimax _wcstoi64 +#define wcstoumax _wcstoui64 + +#endif // _MSC_VER >= 1800 + +#endif // _MSC_INTTYPES_H_ ] diff --git a/src/include/rapidjson/msinttypes/stdint.h b/src/include/rapidjson/msinttypes/stdint.h new file mode 100644 index 0000000..bbad95a --- /dev/null +++ b/src/include/rapidjson/msinttypes/stdint.h @@ -0,0 +1,296 @@ +// ISO C9x compliant stdint.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2013 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the product nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_STDINT_H_ // [ +#define _MSC_STDINT_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +// miloyip: Originally Visual Studio 2010 uses its own stdint.h. However it generates warning with INT64_C(), so change to use this file for vs2010. +#if _MSC_VER >= 1600 // [ +#include + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +#undef INT8_C +#undef INT16_C +#undef INT32_C +#undef INT64_C +#undef UINT8_C +#undef UINT16_C +#undef UINT32_C +#undef UINT64_C + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +// These #ifndef's are needed to prevent collisions with . +// Check out Issue 9 for the details. +#ifndef INTMAX_C // [ +# define INTMAX_C INT64_C +#endif // INTMAX_C ] +#ifndef UINTMAX_C // [ +# define UINTMAX_C UINT64_C +#endif // UINTMAX_C ] + +#endif // __STDC_CONSTANT_MACROS ] + +#else // ] _MSC_VER >= 1700 [ + +#include + +// For Visual Studio 6 in C++ mode and for many Visual Studio versions when +// compiling for ARM we should wrap include with 'extern "C++" {}' +// or compiler give many errors like this: +// error C2733: second C linkage of overloaded function 'wmemchr' not allowed +#ifdef __cplusplus +extern "C" { +#endif +# include +#ifdef __cplusplus +} +#endif + +// Define _W64 macros to mark types changing their size, like intptr_t. +#ifndef _W64 +# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +# define _W64 __w64 +# else +# define _W64 +# endif +#endif + + +// 7.18.1 Integer types + +// 7.18.1.1 Exact-width integer types + +// Visual Studio 6 and Embedded Visual C++ 4 doesn't +// realize that, e.g. char has the same size as __int8 +// so we give up on __intX for them. +#if (_MSC_VER < 1300) + typedef signed char int8_t; + typedef signed short int16_t; + typedef signed int int32_t; + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; +#else + typedef signed __int8 int8_t; + typedef signed __int16 int16_t; + typedef signed __int32 int32_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; +#endif +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; + + +// 7.18.1.2 Minimum-width integer types +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +// 7.18.1.3 Fastest minimum-width integer types +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; + +// 7.18.1.4 Integer types capable of holding object pointers +#ifdef _WIN64 // [ + typedef signed __int64 intptr_t; + typedef unsigned __int64 uintptr_t; +#else // _WIN64 ][ + typedef _W64 signed int intptr_t; + typedef _W64 unsigned int uintptr_t; +#endif // _WIN64 ] + +// 7.18.1.5 Greatest-width integer types +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + + +// 7.18.2 Limits of specified-width integer types + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 + +// 7.18.2.1 Limits of exact-width integer types +#define INT8_MIN ((int8_t)_I8_MIN) +#define INT8_MAX _I8_MAX +#define INT16_MIN ((int16_t)_I16_MIN) +#define INT16_MAX _I16_MAX +#define INT32_MIN ((int32_t)_I32_MIN) +#define INT32_MAX _I32_MAX +#define INT64_MIN ((int64_t)_I64_MIN) +#define INT64_MAX _I64_MAX +#define UINT8_MAX _UI8_MAX +#define UINT16_MAX _UI16_MAX +#define UINT32_MAX _UI32_MAX +#define UINT64_MAX _UI64_MAX + +// 7.18.2.2 Limits of minimum-width integer types +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +// 7.18.2.3 Limits of fastest minimum-width integer types +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +// 7.18.2.4 Limits of integer types capable of holding object pointers +#ifdef _WIN64 // [ +# define INTPTR_MIN INT64_MIN +# define INTPTR_MAX INT64_MAX +# define UINTPTR_MAX UINT64_MAX +#else // _WIN64 ][ +# define INTPTR_MIN INT32_MIN +# define INTPTR_MAX INT32_MAX +# define UINTPTR_MAX UINT32_MAX +#endif // _WIN64 ] + +// 7.18.2.5 Limits of greatest-width integer types +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +// 7.18.3 Limits of other integer types + +#ifdef _WIN64 // [ +# define PTRDIFF_MIN _I64_MIN +# define PTRDIFF_MAX _I64_MAX +#else // _WIN64 ][ +# define PTRDIFF_MIN _I32_MIN +# define PTRDIFF_MAX _I32_MAX +#endif // _WIN64 ] + +#define SIG_ATOMIC_MIN INT_MIN +#define SIG_ATOMIC_MAX INT_MAX + +#ifndef SIZE_MAX // [ +# ifdef _WIN64 // [ +# define SIZE_MAX _UI64_MAX +# else // _WIN64 ][ +# define SIZE_MAX _UI32_MAX +# endif // _WIN64 ] +#endif // SIZE_MAX ] + +// WCHAR_MIN and WCHAR_MAX are also defined in +#ifndef WCHAR_MIN // [ +# define WCHAR_MIN 0 +#endif // WCHAR_MIN ] +#ifndef WCHAR_MAX // [ +# define WCHAR_MAX _UI16_MAX +#endif // WCHAR_MAX ] + +#define WINT_MIN 0 +#define WINT_MAX _UI16_MAX + +#endif // __STDC_LIMIT_MACROS ] + + +// 7.18.4 Limits of other integer types + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +// These #ifndef's are needed to prevent collisions with . +// Check out Issue 9 for the details. +#ifndef INTMAX_C // [ +# define INTMAX_C INT64_C +#endif // INTMAX_C ] +#ifndef UINTMAX_C // [ +# define UINTMAX_C UINT64_C +#endif // UINTMAX_C ] + +#endif // __STDC_CONSTANT_MACROS ] + +#endif // _MSC_VER >= 1600 ] + +#endif // _MSC_STDINT_H_ ] diff --git a/src/include/rapidjson/prettywriter.h b/src/include/rapidjson/prettywriter.h new file mode 100644 index 0000000..47a4efd --- /dev/null +++ b/src/include/rapidjson/prettywriter.h @@ -0,0 +1,211 @@ +// Copyright (C) 2011 Milo Yip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef RAPIDJSON_PRETTYWRITER_H_ +#define RAPIDJSON_PRETTYWRITER_H_ + +#include "writer.h" + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Writer with indentation and spacing. +/*! + \tparam OutputStream Type of ouptut os. + \tparam SourceEncoding Encoding of source string. + \tparam TargetEncoding Encoding of output stream. + \tparam StackAllocator Type of allocator for allocating memory of stack. +*/ +template, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator> +class PrettyWriter : public Writer { +public: + typedef Writer Base; + typedef typename Base::Ch Ch; + + //! Constructor + /*! \param os Output stream. + \param allocator User supplied allocator. If it is null, it will create a private one. + \param levelDepth Initial capacity of stack. + */ + PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : + Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {} + + //! Set custom indentation. + /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r'). + \param indentCharCount Number of indent characters for each indentation level. + \note The default indentation is 4 spaces. + */ + PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) { + RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r'); + indentChar_ = indentChar; + indentCharCount_ = indentCharCount; + return *this; + } + + /*! @name Implementation of Handler + \see Handler + */ + //@{ + + bool Null() { PrettyPrefix(kNullType); return Base::WriteNull(); } + bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::WriteBool(b); } + bool Int(int i) { PrettyPrefix(kNumberType); return Base::WriteInt(i); } + bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::WriteUint(u); } + bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::WriteInt64(i64); } + bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::WriteUint64(u64); } + bool Double(double d) { PrettyPrefix(kNumberType); return Base::WriteDouble(d); } + + bool String(const Ch* str, SizeType length, bool copy = false) { + (void)copy; + PrettyPrefix(kStringType); + return Base::WriteString(str, length); + } + +#if RAPIDJSON_HAS_STDSTRING + bool String(const std::basic_string& str) { + return String(str.data(), SizeType(str.size())); + } +#endif + + bool StartObject() { + PrettyPrefix(kObjectType); + new (Base::level_stack_.template Push()) typename Base::Level(false); + return Base::WriteStartObject(); + } + + bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } + + bool EndObject(SizeType memberCount = 0) { + (void)memberCount; + RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); + RAPIDJSON_ASSERT(!Base::level_stack_.template Top()->inArray); + bool empty = Base::level_stack_.template Pop(1)->valueCount == 0; + + if (!empty) { + Base::os_->Put('\n'); + WriteIndent(); + } + if (!Base::WriteEndObject()) + return false; + if (Base::level_stack_.Empty()) // end of json text + Base::os_->Flush(); + return true; + } + + bool StartArray() { + PrettyPrefix(kArrayType); + new (Base::level_stack_.template Push()) typename Base::Level(true); + return Base::WriteStartArray(); + } + + bool EndArray(SizeType memberCount = 0) { + (void)memberCount; + RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); + RAPIDJSON_ASSERT(Base::level_stack_.template Top()->inArray); + bool empty = Base::level_stack_.template Pop(1)->valueCount == 0; + + if (!empty) { + Base::os_->Put('\n'); + WriteIndent(); + } + if (!Base::WriteEndArray()) + return false; + if (Base::level_stack_.Empty()) // end of json text + Base::os_->Flush(); + return true; + } + + //@} + + /*! @name Convenience extensions */ + //@{ + + //! Simpler but slower overload. + bool String(const Ch* str) { return String(str, internal::StrLen(str)); } + bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); } + + //@} +protected: + void PrettyPrefix(Type type) { + (void)type; + if (Base::level_stack_.GetSize() != 0) { // this value is not at root + typename Base::Level* level = Base::level_stack_.template Top(); + + if (level->inArray) { + if (level->valueCount > 0) { + Base::os_->Put(','); // add comma if it is not the first element in array + Base::os_->Put('\n'); + } + else + Base::os_->Put('\n'); + WriteIndent(); + } + else { // in object + if (level->valueCount > 0) { + if (level->valueCount % 2 == 0) { + Base::os_->Put(','); + Base::os_->Put('\n'); + } + else { + Base::os_->Put(':'); + Base::os_->Put(' '); + } + } + else + Base::os_->Put('\n'); + + if (level->valueCount % 2 == 0) + WriteIndent(); + } + if (!level->inArray && level->valueCount % 2 == 0) + RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name + level->valueCount++; + } + else { + RAPIDJSON_ASSERT(!Base::hasRoot_); // Should only has one and only one root. + Base::hasRoot_ = true; + } + } + + void WriteIndent() { + size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_; + PutN(*Base::os_, indentChar_, count); + } + + Ch indentChar_; + unsigned indentCharCount_; + +private: + // Prohibit copy constructor & assignment operator. + PrettyWriter(const PrettyWriter&); + PrettyWriter& operator=(const PrettyWriter&); +}; + +RAPIDJSON_NAMESPACE_END + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/src/include/rapidjson/rapidjson.h b/src/include/rapidjson/rapidjson.h new file mode 100644 index 0000000..e9bfdba --- /dev/null +++ b/src/include/rapidjson/rapidjson.h @@ -0,0 +1,628 @@ +// Copyright (C) 2011 Milo Yip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef RAPIDJSON_RAPIDJSON_H_ +#define RAPIDJSON_RAPIDJSON_H_ + +// Copyright (c) 2011 Milo Yip (miloyip@gmail.com) +// Version 0.1 + +/*!\file rapidjson.h + \brief common definitions and configuration + + \see RAPIDJSON_CONFIG + */ + +/*! \defgroup RAPIDJSON_CONFIG RapidJSON configuration + \brief Configuration macros for library features + + Some RapidJSON features are configurable to adapt the library to a wide + variety of platforms, environments and usage scenarios. Most of the + features can be configured in terms of overriden or predefined + preprocessor macros at compile-time. + + Some additional customization is available in the \ref RAPIDJSON_ERRORS APIs. + + \note These macros should be given on the compiler command-line + (where applicable) to avoid inconsistent values when compiling + different translation units of a single application. + */ + +#include // malloc(), realloc(), free(), size_t +#include // memset(), memcpy(), memmove(), memcmp() + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_NAMESPACE_(BEGIN|END) +/*! \def RAPIDJSON_NAMESPACE + \ingroup RAPIDJSON_CONFIG + \brief provide custom rapidjson namespace + + In order to avoid symbol clashes and/or "One Definition Rule" errors + between multiple inclusions of (different versions of) RapidJSON in + a single binary, users can customize the name of the main RapidJSON + namespace. + + In case of a single nesting level, defining \c RAPIDJSON_NAMESPACE + to a custom name (e.g. \c MyRapidJSON) is sufficient. If multiple + levels are needed, both \ref RAPIDJSON_NAMESPACE_BEGIN and \ref + RAPIDJSON_NAMESPACE_END need to be defined as well: + + \code + // in some .cpp file + #define RAPIDJSON_NAMESPACE my::rapidjson + #define RAPIDJSON_NAMESPACE_BEGIN namespace my { namespace rapidjson { + #define RAPIDJSON_NAMESPACE_END } } + #include "rapidjson/..." + \endcode + + \see rapidjson + */ +/*! \def RAPIDJSON_NAMESPACE_BEGIN + \ingroup RAPIDJSON_CONFIG + \brief provide custom rapidjson namespace (opening expression) + \see RAPIDJSON_NAMESPACE +*/ +/*! \def RAPIDJSON_NAMESPACE_END + \ingroup RAPIDJSON_CONFIG + \brief provide custom rapidjson namespace (closing expression) + \see RAPIDJSON_NAMESPACE +*/ +#ifndef RAPIDJSON_NAMESPACE +#define RAPIDJSON_NAMESPACE rapidjson +#endif +#ifndef RAPIDJSON_NAMESPACE_BEGIN +#define RAPIDJSON_NAMESPACE_BEGIN namespace RAPIDJSON_NAMESPACE { +#endif +#ifndef RAPIDJSON_NAMESPACE_END +#define RAPIDJSON_NAMESPACE_END } +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_NO_INT64DEFINE + +/*! \def RAPIDJSON_NO_INT64DEFINE + \ingroup RAPIDJSON_CONFIG + \brief Use external 64-bit integer types. + + RapidJSON requires the 64-bit integer types \c int64_t and \c uint64_t types + to be available at global scope. + + If users have their own definition, define RAPIDJSON_NO_INT64DEFINE to + prevent RapidJSON from defining its own types. +*/ +#ifndef RAPIDJSON_NO_INT64DEFINE +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#ifdef _MSC_VER +#include "msinttypes/stdint.h" +#include "msinttypes/inttypes.h" +#else +// Other compilers should have this. +#include +#include +#endif +//!@endcond +#ifdef RAPIDJSON_DOXYGEN_RUNNING +#define RAPIDJSON_NO_INT64DEFINE +#endif +#endif // RAPIDJSON_NO_INT64TYPEDEF + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_FORCEINLINE + +#ifndef RAPIDJSON_FORCEINLINE +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#ifdef _MSC_VER +#define RAPIDJSON_FORCEINLINE __forceinline +#elif defined(__GNUC__) && __GNUC__ >= 4 +#define RAPIDJSON_FORCEINLINE __attribute__((always_inline)) +#else +#define RAPIDJSON_FORCEINLINE +#endif +//!@endcond +#endif // RAPIDJSON_FORCEINLINE + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ENDIAN +#define RAPIDJSON_LITTLEENDIAN 0 //!< Little endian machine +#define RAPIDJSON_BIGENDIAN 1 //!< Big endian machine + +//! Endianness of the machine. +/*! + \def RAPIDJSON_ENDIAN + \ingroup RAPIDJSON_CONFIG + + GCC 4.6 provided macro for detecting endianness of the target machine. But other + compilers may not have this. User can define RAPIDJSON_ENDIAN to either + \ref RAPIDJSON_LITTLEENDIAN or \ref RAPIDJSON_BIGENDIAN. + + Default detection implemented with reference to + \li https://gcc.gnu.org/onlinedocs/gcc-4.6.0/cpp/Common-Predefined-Macros.html + \li http://www.boost.org/doc/libs/1_42_0/boost/detail/endian.hpp +*/ +#ifndef RAPIDJSON_ENDIAN +// Detect with GCC 4.6's macro +# ifdef __BYTE_ORDER__ +# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +# else +# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN. +# endif // __BYTE_ORDER__ +// Detect with GLIBC's endian.h +# elif defined(__GLIBC__) +# include +# if (__BYTE_ORDER == __LITTLE_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif (__BYTE_ORDER == __BIG_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +# else +# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN. +# endif // __GLIBC__ +// Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro +# elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +// Detect with architecture macros +# elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__) +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +# elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__bfin__) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif defined(RAPIDJSON_DOXYGEN_RUNNING) +# define RAPIDJSON_ENDIAN +# else +# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN. +# endif +#endif // RAPIDJSON_ENDIAN + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_64BIT + +//! Whether using 64-bit architecture +#ifndef RAPIDJSON_64BIT +#if defined(__LP64__) || defined(_WIN64) +#define RAPIDJSON_64BIT 1 +#else +#define RAPIDJSON_64BIT 0 +#endif +#endif // RAPIDJSON_64BIT + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ALIGN + +//! Data alignment of the machine. +/*! \ingroup RAPIDJSON_CONFIG + \param x pointer to align + + Some machines require strict data alignment. Currently the default uses 4 bytes + alignment. User can customize by defining the RAPIDJSON_ALIGN function macro., +*/ +#ifndef RAPIDJSON_ALIGN +#define RAPIDJSON_ALIGN(x) ((x + 3u) & ~3u) +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_UINT64_C2 + +//! Construct a 64-bit literal by a pair of 32-bit integer. +/*! + 64-bit literal with or without ULL suffix is prone to compiler warnings. + UINT64_C() is C macro which cause compilation problems. + Use this macro to define 64-bit constants by a pair of 32-bit integer. +*/ +#ifndef RAPIDJSON_UINT64_C2 +#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast(high32) << 32) | static_cast(low32)) +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_SIMD + +/*! \def RAPIDJSON_SIMD + \ingroup RAPIDJSON_CONFIG + \brief Enable SSE2/SSE4.2 optimization. + + RapidJSON supports optimized implementations for some parsing operations + based on the SSE2 or SSE4.2 SIMD extensions on modern Intel-compatible + processors. + + To enable these optimizations, two different symbols can be defined; + \code + // Enable SSE2 optimization. + #define RAPIDJSON_SSE2 + + // Enable SSE4.2 optimization. + #define RAPIDJSON_SSE42 + \endcode + + \c RAPIDJSON_SSE42 takes precedence, if both are defined. + + If any of these symbols is defined, RapidJSON defines the macro + \c RAPIDJSON_SIMD to indicate the availability of the optimized code. +*/ +#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) \ + || defined(RAPIDJSON_DOXYGEN_RUNNING) +#define RAPIDJSON_SIMD +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_NO_SIZETYPEDEFINE + +#ifndef RAPIDJSON_NO_SIZETYPEDEFINE +/*! \def RAPIDJSON_NO_SIZETYPEDEFINE + \ingroup RAPIDJSON_CONFIG + \brief User-provided \c SizeType definition. + + In order to avoid using 32-bit size types for indexing strings and arrays, + define this preprocessor symbol and provide the type rapidjson::SizeType + before including RapidJSON: + \code + #define RAPIDJSON_NO_SIZETYPEDEFINE + namespace rapidjson { typedef ::std::size_t SizeType; } + #include "rapidjson/..." + \endcode + + \see rapidjson::SizeType +*/ +#ifdef RAPIDJSON_DOXYGEN_RUNNING +#define RAPIDJSON_NO_SIZETYPEDEFINE +#endif +RAPIDJSON_NAMESPACE_BEGIN +//! Size type (for string lengths, array sizes, etc.) +/*! RapidJSON uses 32-bit array/string indices even on 64-bit platforms, + instead of using \c size_t. Users may override the SizeType by defining + \ref RAPIDJSON_NO_SIZETYPEDEFINE. +*/ +typedef unsigned SizeType; +RAPIDJSON_NAMESPACE_END +#endif + +// always import std::size_t to rapidjson namespace +RAPIDJSON_NAMESPACE_BEGIN +using std::size_t; +RAPIDJSON_NAMESPACE_END + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ASSERT + +//! Assertion. +/*! \ingroup RAPIDJSON_CONFIG + By default, rapidjson uses C \c assert() for internal assertions. + User can override it by defining RAPIDJSON_ASSERT(x) macro. + + \note Parsing errors are handled and can be customized by the + \ref RAPIDJSON_ERRORS APIs. +*/ +#ifndef RAPIDJSON_ASSERT +#include +#define RAPIDJSON_ASSERT(x) assert(x) +#endif // RAPIDJSON_ASSERT + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_STATIC_ASSERT + +// Adopt from boost +#ifndef RAPIDJSON_STATIC_ASSERT +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +RAPIDJSON_NAMESPACE_BEGIN +template struct STATIC_ASSERTION_FAILURE; +template <> struct STATIC_ASSERTION_FAILURE { enum { value = 1 }; }; +template struct StaticAssertTest {}; +RAPIDJSON_NAMESPACE_END + +#define RAPIDJSON_JOIN(X, Y) RAPIDJSON_DO_JOIN(X, Y) +#define RAPIDJSON_DO_JOIN(X, Y) RAPIDJSON_DO_JOIN2(X, Y) +#define RAPIDJSON_DO_JOIN2(X, Y) X##Y + +#if defined(__GNUC__) +#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused)) +#else +#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE +#endif +//!@endcond + +/*! \def RAPIDJSON_STATIC_ASSERT + \brief (Internal) macro to check for conditions at compile-time + \param x compile-time condition + \hideinitializer + */ +#define RAPIDJSON_STATIC_ASSERT(x) \ + typedef ::RAPIDJSON_NAMESPACE::StaticAssertTest< \ + sizeof(::RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE)> \ + RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Helpers + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN + +#define RAPIDJSON_MULTILINEMACRO_BEGIN do { +#define RAPIDJSON_MULTILINEMACRO_END \ +} while((void)0, 0) + +// adopted from Boost +#define RAPIDJSON_VERSION_CODE(x,y,z) \ + (((x)*100000) + ((y)*100) + (z)) + +// token stringification +#define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x) +#define RAPIDJSON_DO_STRINGIFY(x) #x + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF + +#if defined(__GNUC__) +#define RAPIDJSON_GNUC \ + RAPIDJSON_VERSION_CODE(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__) +#endif + +#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,2,0)) + +#define RAPIDJSON_PRAGMA(x) _Pragma(RAPIDJSON_STRINGIFY(x)) +#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(GCC diagnostic x) +#define RAPIDJSON_DIAG_OFF(x) \ + RAPIDJSON_DIAG_PRAGMA(ignored RAPIDJSON_STRINGIFY(RAPIDJSON_JOIN(-W,x))) + +// push/pop support in Clang and GCC>=4.6 +#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) +#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push) +#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop) +#else // GCC >= 4.2, < 4.6 +#define RAPIDJSON_DIAG_PUSH /* ignored */ +#define RAPIDJSON_DIAG_POP /* ignored */ +#endif + +#elif defined(_MSC_VER) + +// pragma (MSVC specific) +#define RAPIDJSON_PRAGMA(x) __pragma(x) +#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(warning(x)) + +#define RAPIDJSON_DIAG_OFF(x) RAPIDJSON_DIAG_PRAGMA(disable: x) +#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push) +#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop) + +#else + +#define RAPIDJSON_DIAG_OFF(x) /* ignored */ +#define RAPIDJSON_DIAG_PUSH /* ignored */ +#define RAPIDJSON_DIAG_POP /* ignored */ + +#endif // RAPIDJSON_DIAG_* + +/////////////////////////////////////////////////////////////////////////////// +// C++11 features + +#ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS +#if defined(__clang__) +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS __has_feature(cxx_rvalue_references) +#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ + (defined(_MSC_VER) && _MSC_VER >= 1600) + +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1 +#else +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0 +#endif +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + +#ifndef RAPIDJSON_HAS_CXX11_NOEXCEPT +#if defined(__clang__) +#define RAPIDJSON_HAS_CXX11_NOEXCEPT __has_feature(cxx_noexcept) +#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) +// (defined(_MSC_VER) && _MSC_VER >= ????) // not yet supported +#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1 +#else +#define RAPIDJSON_HAS_CXX11_NOEXCEPT 0 +#endif +#endif +#if RAPIDJSON_HAS_CXX11_NOEXCEPT +#define RAPIDJSON_NOEXCEPT noexcept +#else +#define RAPIDJSON_NOEXCEPT /* noexcept */ +#endif // RAPIDJSON_HAS_CXX11_NOEXCEPT + +// no automatic detection, yet +#ifndef RAPIDJSON_HAS_CXX11_TYPETRAITS +#define RAPIDJSON_HAS_CXX11_TYPETRAITS 0 +#endif + +//!@endcond + +/////////////////////////////////////////////////////////////////////////////// +// new/delete + +#ifndef RAPIDJSON_NEW +///! customization point for global \c new +#define RAPIDJSON_NEW(x) new x +#endif +#ifndef RAPIDJSON_DELETE +///! customization point for global \c delete +#define RAPIDJSON_DELETE(x) delete x +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Allocators and Encodings + +#include "allocators.h" +#include "encodings.h" + +/*! \namespace rapidjson + \brief main RapidJSON namespace + \see RAPIDJSON_NAMESPACE +*/ +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// Stream + +/*! \class rapidjson::Stream + \brief Concept for reading and writing characters. + + For read-only stream, no need to implement PutBegin(), Put(), Flush() and PutEnd(). + + For write-only stream, only need to implement Put() and Flush(). + +\code +concept Stream { + typename Ch; //!< Character type of the stream. + + //! Read the current character from stream without moving the read cursor. + Ch Peek() const; + + //! Read the current character from stream and moving the read cursor to next character. + Ch Take(); + + //! Get the current read cursor. + //! \return Number of characters read from start. + size_t Tell(); + + //! Begin writing operation at the current read pointer. + //! \return The begin writer pointer. + Ch* PutBegin(); + + //! Write a character. + void Put(Ch c); + + //! Flush the buffer. + void Flush(); + + //! End the writing operation. + //! \param begin The begin write pointer returned by PutBegin(). + //! \return Number of characters written. + size_t PutEnd(Ch* begin); +} +\endcode +*/ + +//! Provides additional information for stream. +/*! + By using traits pattern, this type provides a default configuration for stream. + For custom stream, this type can be specialized for other configuration. + See TEST(Reader, CustomStringStream) in readertest.cpp for example. +*/ +template +struct StreamTraits { + //! Whether to make local copy of stream for optimization during parsing. + /*! + By default, for safety, streams do not use local copy optimization. + Stream that can be copied fast should specialize this, like StreamTraits. + */ + enum { copyOptimization = 0 }; +}; + +//! Put N copies of a character to a stream. +template +inline void PutN(Stream& stream, Ch c, size_t n) { + for (size_t i = 0; i < n; i++) + stream.Put(c); +} + +/////////////////////////////////////////////////////////////////////////////// +// StringStream + +//! Read-only string stream. +/*! \note implements Stream concept +*/ +template +struct GenericStringStream { + typedef typename Encoding::Ch Ch; + + GenericStringStream(const Ch *src) : src_(src), head_(src) {} + + Ch Peek() const { return *src_; } + Ch Take() { return *src_++; } + size_t Tell() const { return static_cast(src_ - head_); } + + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + + const Ch* src_; //!< Current read position. + const Ch* head_; //!< Original head of the string. +}; + +template +struct StreamTraits > { + enum { copyOptimization = 1 }; +}; + +//! String stream with UTF8 encoding. +typedef GenericStringStream > StringStream; + +/////////////////////////////////////////////////////////////////////////////// +// InsituStringStream + +//! A read-write string stream. +/*! This string stream is particularly designed for in-situ parsing. + \note implements Stream concept +*/ +template +struct GenericInsituStringStream { + typedef typename Encoding::Ch Ch; + + GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {} + + // Read + Ch Peek() { return *src_; } + Ch Take() { return *src_++; } + size_t Tell() { return static_cast(src_ - head_); } + + // Write + void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; } + + Ch* PutBegin() { return dst_ = src_; } + size_t PutEnd(Ch* begin) { return static_cast(dst_ - begin); } + void Flush() {} + + Ch* Push(size_t count) { Ch* begin = dst_; dst_ += count; return begin; } + void Pop(size_t count) { dst_ -= count; } + + Ch* src_; + Ch* dst_; + Ch* head_; +}; + +template +struct StreamTraits > { + enum { copyOptimization = 1 }; +}; + +//! Insitu string stream with UTF8 encoding. +typedef GenericInsituStringStream > InsituStringStream; + +/////////////////////////////////////////////////////////////////////////////// +// Type + +//! Type of JSON value +enum Type { + kNullType = 0, //!< null + kFalseType = 1, //!< false + kTrueType = 2, //!< true + kObjectType = 3, //!< object + kArrayType = 4, //!< array + kStringType = 5, //!< string + kNumberType = 6 //!< number +}; + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/src/include/rapidjson/reader.h b/src/include/rapidjson/reader.h new file mode 100644 index 0000000..c5cda8f --- /dev/null +++ b/src/include/rapidjson/reader.h @@ -0,0 +1,1444 @@ +// Copyright (C) 2011 Milo Yip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef RAPIDJSON_READER_H_ +#define RAPIDJSON_READER_H_ + +/*! \file reader.h */ + +#include "rapidjson.h" +#include "encodings.h" +#include "internal/meta.h" +#include "internal/stack.h" +#include "internal/strtod.h" + +#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER) +#include +#pragma intrinsic(_BitScanForward) +#endif +#ifdef RAPIDJSON_SSE42 +#include +#elif defined(RAPIDJSON_SSE2) +#include +#endif + +#ifdef _MSC_VER +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant +RAPIDJSON_DIAG_OFF(4702) // unreachable code +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#define RAPIDJSON_NOTHING /* deliberately empty */ +#ifndef RAPIDJSON_PARSE_ERROR_EARLY_RETURN +#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN(value) \ + RAPIDJSON_MULTILINEMACRO_BEGIN \ + if (HasParseError()) { return value; } \ + RAPIDJSON_MULTILINEMACRO_END +#endif +#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID \ + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING) +//!@endcond + +/*! \def RAPIDJSON_PARSE_ERROR_NORETURN + \ingroup RAPIDJSON_ERRORS + \brief Macro to indicate a parse error. + \param parseErrorCode \ref rapidjson::ParseErrorCode of the error + \param offset position of the error in JSON input (\c size_t) + + This macros can be used as a customization point for the internal + error handling mechanism of RapidJSON. + + A common usage model is to throw an exception instead of requiring the + caller to explicitly check the \ref rapidjson::GenericReader::Parse's + return value: + + \code + #define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode,offset) \ + throw ParseException(parseErrorCode, #parseErrorCode, offset) + + #include // std::runtime_error + #include "rapidjson/error/error.h" // rapidjson::ParseResult + + struct ParseException : std::runtime_error, rapidjson::ParseResult { + ParseException(rapidjson::ParseErrorCode code, const char* msg, size_t offset) + : std::runtime_error(msg), ParseResult(code, offset) {} + }; + + #include "rapidjson/reader.h" + \endcode + + \see RAPIDJSON_PARSE_ERROR, rapidjson::GenericReader::Parse + */ +#ifndef RAPIDJSON_PARSE_ERROR_NORETURN +#define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset) \ + RAPIDJSON_MULTILINEMACRO_BEGIN \ + RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \ + SetParseError(parseErrorCode, offset); \ + RAPIDJSON_MULTILINEMACRO_END +#endif + +/*! \def RAPIDJSON_PARSE_ERROR + \ingroup RAPIDJSON_ERRORS + \brief (Internal) macro to indicate and handle a parse error. + \param parseErrorCode \ref rapidjson::ParseErrorCode of the error + \param offset position of the error in JSON input (\c size_t) + + Invokes RAPIDJSON_PARSE_ERROR_NORETURN and stops the parsing. + + \see RAPIDJSON_PARSE_ERROR_NORETURN + \hideinitializer + */ +#ifndef RAPIDJSON_PARSE_ERROR +#define RAPIDJSON_PARSE_ERROR(parseErrorCode, offset) \ + RAPIDJSON_MULTILINEMACRO_BEGIN \ + RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \ + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \ + RAPIDJSON_MULTILINEMACRO_END +#endif + +#include "error/error.h" // ParseErrorCode, ParseResult + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// ParseFlag + +/*! \def RAPIDJSON_PARSE_DEFAULT_FLAGS + \ingroup RAPIDJSON_CONFIG + \brief User-defined kParseDefaultFlags definition. + + User can define this as any \c ParseFlag combinations. +*/ +#ifndef RAPIDJSON_PARSE_DEFAULT_FLAGS +#define RAPIDJSON_PARSE_DEFAULT_FLAGS kParseNoFlags +#endif + +//! Combination of parseFlags +/*! \see Reader::Parse, Document::Parse, Document::ParseInsitu, Document::ParseStream + */ +enum ParseFlag { + kParseNoFlags = 0, //!< No flags are set. + kParseInsituFlag = 1, //!< In-situ(destructive) parsing. + kParseValidateEncodingFlag = 2, //!< Validate encoding of JSON strings. + kParseIterativeFlag = 4, //!< Iterative(constant complexity in terms of function call stack size) parsing. + kParseStopWhenDoneFlag = 8, //!< After parsing a complete JSON root from stream, stop further processing the rest of stream. When this flag is used, parser will not generate kParseErrorDocumentRootNotSingular error. + kParseFullPrecisionFlag = 16, //!< Parse number in full precision (but slower). + kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS +}; + +/////////////////////////////////////////////////////////////////////////////// +// Handler + +/*! \class rapidjson::Handler + \brief Concept for receiving events from GenericReader upon parsing. + The functions return true if no error occurs. If they return false, + the event publisher should terminate the process. +\code +concept Handler { + typename Ch; + + bool Null(); + bool Bool(bool b); + bool Int(int i); + bool Uint(unsigned i); + bool Int64(int64_t i); + bool Uint64(uint64_t i); + bool Double(double d); + bool String(const Ch* str, SizeType length, bool copy); + bool StartObject(); + bool Key(const Ch* str, SizeType length, bool copy); + bool EndObject(SizeType memberCount); + bool StartArray(); + bool EndArray(SizeType elementCount); +}; +\endcode +*/ +/////////////////////////////////////////////////////////////////////////////// +// BaseReaderHandler + +//! Default implementation of Handler. +/*! This can be used as base class of any reader handler. + \note implements Handler concept +*/ +template, typename Derived = void> +struct BaseReaderHandler { + typedef typename Encoding::Ch Ch; + + typedef typename internal::SelectIf, BaseReaderHandler, Derived>::Type Override; + + bool Default() { return true; } + bool Null() { return static_cast(*this).Default(); } + bool Bool(bool) { return static_cast(*this).Default(); } + bool Int(int) { return static_cast(*this).Default(); } + bool Uint(unsigned) { return static_cast(*this).Default(); } + bool Int64(int64_t) { return static_cast(*this).Default(); } + bool Uint64(uint64_t) { return static_cast(*this).Default(); } + bool Double(double) { return static_cast(*this).Default(); } + bool String(const Ch*, SizeType, bool) { return static_cast(*this).Default(); } + bool StartObject() { return static_cast(*this).Default(); } + bool Key(const Ch* str, SizeType len, bool copy) { return static_cast(*this).String(str, len, copy); } + bool EndObject(SizeType) { return static_cast(*this).Default(); } + bool StartArray() { return static_cast(*this).Default(); } + bool EndArray(SizeType) { return static_cast(*this).Default(); } +}; + +/////////////////////////////////////////////////////////////////////////////// +// StreamLocalCopy + +namespace internal { + +template::copyOptimization> +class StreamLocalCopy; + +//! Do copy optimization. +template +class StreamLocalCopy { +public: + StreamLocalCopy(Stream& original) : s(original), original_(original) {} + ~StreamLocalCopy() { original_ = s; } + + Stream s; + +private: + StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */; + + Stream& original_; +}; + +//! Keep reference. +template +class StreamLocalCopy { +public: + StreamLocalCopy(Stream& original) : s(original) {} + + Stream& s; + +private: + StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */; +}; + +} // namespace internal + +/////////////////////////////////////////////////////////////////////////////// +// SkipWhitespace + +//! Skip the JSON white spaces in a stream. +/*! \param is A input stream for skipping white spaces. + \note This function has SSE2/SSE4.2 specialization. +*/ +template +void SkipWhitespace(InputStream& is) { + internal::StreamLocalCopy copy(is); + InputStream& s(copy.s); + + while (s.Peek() == ' ' || s.Peek() == '\n' || s.Peek() == '\r' || s.Peek() == '\t') + s.Take(); +} + +#ifdef RAPIDJSON_SSE42 +//! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once. +inline const char *SkipWhitespace_SIMD(const char* p) { + // Fast return for single non-whitespace + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // 16-byte align to the next boundary + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & ~15); + while (p != nextAligned) + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // The rest of string using SIMD + static const char whitespace[16] = " \n\r\t"; + const __m128i w = _mm_load_si128((const __m128i *)&whitespace[0]); + + for (;; p += 16) { + const __m128i s = _mm_load_si128((const __m128i *)p); + const unsigned r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY)); + if (r != 0) { // some of characters is non-whitespace +#ifdef _MSC_VER // Find the index of first non-whitespace + unsigned long offset; + _BitScanForward(&offset, r); + return p + offset; +#else + return p + __builtin_ffs(r) - 1; +#endif + } + } +} + +#elif defined(RAPIDJSON_SSE2) + +//! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once. +inline const char *SkipWhitespace_SIMD(const char* p) { + // Fast return for single non-whitespace + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // 16-byte align to the next boundary + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & ~15); + while (p != nextAligned) + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // The rest of string + static const char whitespaces[4][17] = { + " ", + "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", + "\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r", + "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"}; + + const __m128i w0 = _mm_loadu_si128((const __m128i *)&whitespaces[0][0]); + const __m128i w1 = _mm_loadu_si128((const __m128i *)&whitespaces[1][0]); + const __m128i w2 = _mm_loadu_si128((const __m128i *)&whitespaces[2][0]); + const __m128i w3 = _mm_loadu_si128((const __m128i *)&whitespaces[3][0]); + + for (;; p += 16) { + const __m128i s = _mm_load_si128((const __m128i *)p); + __m128i x = _mm_cmpeq_epi8(s, w0); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3)); + unsigned short r = (unsigned short)~_mm_movemask_epi8(x); + if (r != 0) { // some of characters may be non-whitespace +#ifdef _MSC_VER // Find the index of first non-whitespace + unsigned long offset; + _BitScanForward(&offset, r); + return p + offset; +#else + return p + __builtin_ffs(r) - 1; +#endif + } + } +} + +#endif // RAPIDJSON_SSE2 + +#ifdef RAPIDJSON_SIMD +//! Template function specialization for InsituStringStream +template<> inline void SkipWhitespace(InsituStringStream& is) { + is.src_ = const_cast(SkipWhitespace_SIMD(is.src_)); +} + +//! Template function specialization for StringStream +template<> inline void SkipWhitespace(StringStream& is) { + is.src_ = SkipWhitespace_SIMD(is.src_); +} +#endif // RAPIDJSON_SIMD + +/////////////////////////////////////////////////////////////////////////////// +// GenericReader + +//! SAX-style JSON parser. Use \ref Reader for UTF8 encoding and default allocator. +/*! GenericReader parses JSON text from a stream, and send events synchronously to an + object implementing Handler concept. + + It needs to allocate a stack for storing a single decoded string during + non-destructive parsing. + + For in-situ parsing, the decoded string is directly written to the source + text string, no temporary buffer is required. + + A GenericReader object can be reused for parsing multiple JSON text. + + \tparam SourceEncoding Encoding of the input stream. + \tparam TargetEncoding Encoding of the parse output. + \tparam StackAllocator Allocator type for stack. +*/ +template +class GenericReader { +public: + typedef typename SourceEncoding::Ch Ch; //!< SourceEncoding character type + + //! Constructor. + /*! \param stackAllocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing) + \param stackCapacity stack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing) + */ + GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(stackAllocator, stackCapacity), parseResult_() {} + + //! Parse JSON text. + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam InputStream Type of input stream, implementing Stream concept. + \tparam Handler Type of handler, implementing Handler concept. + \param is Input stream to be parsed. + \param handler The handler to receive events. + \return Whether the parsing is successful. + */ + template + ParseResult Parse(InputStream& is, Handler& handler) { + if (parseFlags & kParseIterativeFlag) + return IterativeParse(is, handler); + + parseResult_.Clear(); + + ClearStackOnExit scope(*this); + + SkipWhitespace(is); + + if (is.Peek() == '\0') { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentEmpty, is.Tell()); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + } + else { + ParseValue(is, handler); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + + if (!(parseFlags & kParseStopWhenDoneFlag)) { + SkipWhitespace(is); + + if (is.Peek() != '\0') { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell()); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + } + } + } + + return parseResult_; + } + + //! Parse JSON text (with \ref kParseDefaultFlags) + /*! \tparam InputStream Type of input stream, implementing Stream concept + \tparam Handler Type of handler, implementing Handler concept. + \param is Input stream to be parsed. + \param handler The handler to receive events. + \return Whether the parsing is successful. + */ + template + ParseResult Parse(InputStream& is, Handler& handler) { + return Parse(is, handler); + } + + //! Whether a parse error has occured in the last parsing. + bool HasParseError() const { return parseResult_.IsError(); } + + //! Get the \ref ParseErrorCode of last parsing. + ParseErrorCode GetParseErrorCode() const { return parseResult_.Code(); } + + //! Get the position of last parsing error in input, 0 otherwise. + size_t GetErrorOffset() const { return parseResult_.Offset(); } + +protected: + void SetParseError(ParseErrorCode code, size_t offset) { parseResult_.Set(code, offset); } + +private: + // Prohibit copy constructor & assignment operator. + GenericReader(const GenericReader&); + GenericReader& operator=(const GenericReader&); + + void ClearStack() { stack_.Clear(); } + + // clear stack on any exit from ParseStream, e.g. due to exception + struct ClearStackOnExit { + explicit ClearStackOnExit(GenericReader& r) : r_(r) {} + ~ClearStackOnExit() { r_.ClearStack(); } + private: + GenericReader& r_; + ClearStackOnExit(const ClearStackOnExit&); + ClearStackOnExit& operator=(const ClearStackOnExit&); + }; + + // Parse object: { string : value, ... } + template + void ParseObject(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == '{'); + is.Take(); // Skip '{' + + if (!handler.StartObject()) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + + SkipWhitespace(is); + + if (is.Peek() == '}') { + is.Take(); + if (!handler.EndObject(0)) // empty object + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + } + + for (SizeType memberCount = 0;;) { + if (is.Peek() != '"') + RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); + + ParseString(is, handler, true); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + SkipWhitespace(is); + + if (is.Take() != ':') + RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); + + SkipWhitespace(is); + + ParseValue(is, handler); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + SkipWhitespace(is); + + ++memberCount; + + switch (is.Take()) { + case ',': SkipWhitespace(is); break; + case '}': + if (!handler.EndObject(memberCount)) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + default: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); + } + } + } + + // Parse array: [ value, ... ] + template + void ParseArray(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == '['); + is.Take(); // Skip '[' + + if (!handler.StartArray()) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + + SkipWhitespace(is); + + if (is.Peek() == ']') { + is.Take(); + if (!handler.EndArray(0)) // empty array + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + } + + for (SizeType elementCount = 0;;) { + ParseValue(is, handler); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + ++elementCount; + SkipWhitespace(is); + + switch (is.Take()) { + case ',': SkipWhitespace(is); break; + case ']': + if (!handler.EndArray(elementCount)) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + default: RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); + } + } + } + + template + void ParseNull(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == 'n'); + is.Take(); + + if (is.Take() == 'u' && is.Take() == 'l' && is.Take() == 'l') { + if (!handler.Null()) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1); + } + + template + void ParseTrue(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == 't'); + is.Take(); + + if (is.Take() == 'r' && is.Take() == 'u' && is.Take() == 'e') { + if (!handler.Bool(true)) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1); + } + + template + void ParseFalse(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == 'f'); + is.Take(); + + if (is.Take() == 'a' && is.Take() == 'l' && is.Take() == 's' && is.Take() == 'e') { + if (!handler.Bool(false)) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1); + } + + // Helper function to parse four hexidecimal digits in \uXXXX in ParseString(). + template + unsigned ParseHex4(InputStream& is) { + unsigned codepoint = 0; + for (int i = 0; i < 4; i++) { + Ch c = is.Take(); + codepoint <<= 4; + codepoint += static_cast(c); + if (c >= '0' && c <= '9') + codepoint -= '0'; + else if (c >= 'A' && c <= 'F') + codepoint -= 'A' - 10; + else if (c >= 'a' && c <= 'f') + codepoint -= 'a' - 10; + else { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorStringUnicodeEscapeInvalidHex, is.Tell() - 1); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(0); + } + } + return codepoint; + } + + template + class StackStream { + public: + typedef CharType Ch; + + StackStream(internal::Stack& stack) : stack_(stack), length_(0) {} + RAPIDJSON_FORCEINLINE void Put(Ch c) { + *stack_.template Push() = c; + ++length_; + } + size_t Length() const { return length_; } + Ch* Pop() { + return stack_.template Pop(length_); + } + + private: + StackStream(const StackStream&); + StackStream& operator=(const StackStream&); + + internal::Stack& stack_; + SizeType length_; + }; + + // Parse string and generate String event. Different code paths for kParseInsituFlag. + template + void ParseString(InputStream& is, Handler& handler, bool isKey = false) { + internal::StreamLocalCopy copy(is); + InputStream& s(copy.s); + + bool success = false; + if (parseFlags & kParseInsituFlag) { + typename InputStream::Ch *head = s.PutBegin(); + ParseStringToStream(s, s); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + size_t length = s.PutEnd(head) - 1; + RAPIDJSON_ASSERT(length <= 0xFFFFFFFF); + const typename TargetEncoding::Ch* const str = (typename TargetEncoding::Ch*)head; + success = (isKey ? handler.Key(str, SizeType(length), false) : handler.String(str, SizeType(length), false)); + } + else { + StackStream stackStream(stack_); + ParseStringToStream(s, stackStream); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + SizeType length = static_cast(stackStream.Length()) - 1; + const typename TargetEncoding::Ch* const str = stackStream.Pop(); + success = (isKey ? handler.Key(str, length, true) : handler.String(str, length, true)); + } + if (!success) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell()); + } + + // Parse string to an output is + // This function handles the prefix/suffix double quotes, escaping, and optional encoding validation. + template + RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream& is, OutputStream& os) { +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + static const char escape[256] = { + Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/', + Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, + 0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0, + 0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 + }; +#undef Z16 +//!@endcond + + RAPIDJSON_ASSERT(is.Peek() == '\"'); + is.Take(); // Skip '\"' + + for (;;) { + Ch c = is.Peek(); + if (c == '\\') { // Escape + is.Take(); + Ch e = is.Take(); + if ((sizeof(Ch) == 1 || unsigned(e) < 256) && escape[(unsigned char)e]) { + os.Put(escape[(unsigned char)e]); + } + else if (e == 'u') { // Unicode + unsigned codepoint = ParseHex4(is); + if (codepoint >= 0xD800 && codepoint <= 0xDBFF) { + // Handle UTF-16 surrogate pair + if (is.Take() != '\\' || is.Take() != 'u') + RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, is.Tell() - 2); + unsigned codepoint2 = ParseHex4(is); + if (codepoint2 < 0xDC00 || codepoint2 > 0xDFFF) + RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, is.Tell() - 2); + codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000; + } + TEncoding::Encode(os, codepoint); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, is.Tell() - 1); + } + else if (c == '"') { // Closing double quote + is.Take(); + os.Put('\0'); // null-terminate the string + return; + } + else if (c == '\0') + RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell() - 1); + else if ((unsigned)c < 0x20) // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF + RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, is.Tell() - 1); + else { + if (parseFlags & kParseValidateEncodingFlag ? + !Transcoder::Validate(is, os) : + !Transcoder::Transcode(is, os)) + RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, is.Tell()); + } + } + } + + template + class NumberStream; + + template + class NumberStream { + public: + NumberStream(GenericReader& reader, InputStream& s) : is(s) { (void)reader; } + ~NumberStream() {} + + RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); } + RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); } + RAPIDJSON_FORCEINLINE Ch Take() { return is.Take(); } + size_t Tell() { return is.Tell(); } + size_t Length() { return 0; } + const char* Pop() { return 0; } + + protected: + NumberStream& operator=(const NumberStream&); + + InputStream& is; + }; + + template + class NumberStream : public NumberStream { + typedef NumberStream Base; + public: + NumberStream(GenericReader& reader, InputStream& is) : NumberStream(reader, is), stackStream(reader.stack_) {} + ~NumberStream() {} + + RAPIDJSON_FORCEINLINE Ch TakePush() { + stackStream.Put((char)Base::is.Peek()); + return Base::is.Take(); + } + + size_t Length() { return stackStream.Length(); } + + const char* Pop() { + stackStream.Put('\0'); + return stackStream.Pop(); + } + + private: + StackStream stackStream; + }; + + template + void ParseNumber(InputStream& is, Handler& handler) { + internal::StreamLocalCopy copy(is); + NumberStream s(*this, copy.s); + + // Parse minus + bool minus = false; + if (s.Peek() == '-') { + minus = true; + s.Take(); + } + + // Parse int: zero / ( digit1-9 *DIGIT ) + unsigned i = 0; + uint64_t i64 = 0; + bool use64bit = false; + int significandDigit = 0; + if (s.Peek() == '0') { + i = 0; + s.TakePush(); + } + else if (s.Peek() >= '1' && s.Peek() <= '9') { + i = static_cast(s.TakePush() - '0'); + + if (minus) + while (s.Peek() >= '0' && s.Peek() <= '9') { + if (i >= 214748364) { // 2^31 = 2147483648 + if (i != 214748364 || s.Peek() > '8') { + i64 = i; + use64bit = true; + break; + } + } + i = i * 10 + static_cast(s.TakePush() - '0'); + significandDigit++; + } + else + while (s.Peek() >= '0' && s.Peek() <= '9') { + if (i >= 429496729) { // 2^32 - 1 = 4294967295 + if (i != 429496729 || s.Peek() > '5') { + i64 = i; + use64bit = true; + break; + } + } + i = i * 10 + static_cast(s.TakePush() - '0'); + significandDigit++; + } + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); + + // Parse 64bit int + bool useDouble = false; + double d = 0.0; + if (use64bit) { + if (minus) + while (s.Peek() >= '0' && s.Peek() <= '9') { + if (i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC)) // 2^63 = 9223372036854775808 + if (i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8') { + d = i64; + useDouble = true; + break; + } + i64 = i64 * 10 + static_cast(s.TakePush() - '0'); + significandDigit++; + } + else + while (s.Peek() >= '0' && s.Peek() <= '9') { + if (i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999)) // 2^64 - 1 = 18446744073709551615 + if (i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5') { + d = i64; + useDouble = true; + break; + } + i64 = i64 * 10 + static_cast(s.TakePush() - '0'); + significandDigit++; + } + } + + // Force double for big integer + if (useDouble) { + while (s.Peek() >= '0' && s.Peek() <= '9') { + if (d >= 1.7976931348623157e307) // DBL_MAX / 10.0 + RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, s.Tell()); + d = d * 10 + (s.TakePush() - '0'); + } + } + + // Parse frac = decimal-point 1*DIGIT + int expFrac = 0; + size_t decimalPosition; + if (s.Peek() == '.') { + s.Take(); + decimalPosition = s.Length(); + + if (!(s.Peek() >= '0' && s.Peek() <= '9')) + RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissFraction, s.Tell()); + + if (!useDouble) { +#if RAPIDJSON_64BIT + // Use i64 to store significand in 64-bit architecture + if (!use64bit) + i64 = i; + + while (s.Peek() >= '0' && s.Peek() <= '9') { + if (i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) // 2^53 - 1 for fast path + break; + else { + i64 = i64 * 10 + static_cast(s.TakePush() - '0'); + --expFrac; + if (i64 != 0) + significandDigit++; + } + } + + d = (double)i64; +#else + // Use double to store significand in 32-bit architecture + d = use64bit ? (double)i64 : (double)i; +#endif + useDouble = true; + } + + while (s.Peek() >= '0' && s.Peek() <= '9') { + if (significandDigit < 17) { + d = d * 10.0 + (s.TakePush() - '0'); + --expFrac; + if (d != 0.0) + significandDigit++; + } + else + s.TakePush(); + } + } + else + decimalPosition = s.Length(); // decimal position at the end of integer. + + // Parse exp = e [ minus / plus ] 1*DIGIT + int exp = 0; + if (s.Peek() == 'e' || s.Peek() == 'E') { + if (!useDouble) { + d = use64bit ? i64 : i; + useDouble = true; + } + s.Take(); + + bool expMinus = false; + if (s.Peek() == '+') + s.Take(); + else if (s.Peek() == '-') { + s.Take(); + expMinus = true; + } + + if (s.Peek() >= '0' && s.Peek() <= '9') { + exp = s.Take() - '0'; + while (s.Peek() >= '0' && s.Peek() <= '9') { + exp = exp * 10 + (s.Take() - '0'); + if (exp > 308 && !expMinus) // exp > 308 should be rare, so it should be checked first. + RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, s.Tell()); + } + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissExponent, s.Tell()); + + if (expMinus) + exp = -exp; + } + + // Finish parsing, call event according to the type of number. + bool cont = true; + size_t length = s.Length(); + const char* decimal = s.Pop(); // Pop stack no matter if it will be used or not. + + if (useDouble) { + int p = exp + expFrac; + if (parseFlags & kParseFullPrecisionFlag) + d = internal::StrtodFullPrecision(d, p, decimal, length, decimalPosition, exp); + else + d = internal::StrtodNormalPrecision(d, p); + + cont = handler.Double(minus ? -d : d); + } + else { + if (use64bit) { + if (minus) + cont = handler.Int64(-(int64_t)i64); + else + cont = handler.Uint64(i64); + } + else { + if (minus) + cont = handler.Int(-(int)i); + else + cont = handler.Uint(i); + } + } + if (!cont) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell()); + } + + // Parse any JSON value + template + void ParseValue(InputStream& is, Handler& handler) { + switch (is.Peek()) { + case 'n': ParseNull (is, handler); break; + case 't': ParseTrue (is, handler); break; + case 'f': ParseFalse (is, handler); break; + case '"': ParseString(is, handler); break; + case '{': ParseObject(is, handler); break; + case '[': ParseArray (is, handler); break; + default : ParseNumber(is, handler); + } + } + + // Iterative Parsing + + // States + enum IterativeParsingState { + IterativeParsingStartState = 0, + IterativeParsingFinishState, + IterativeParsingErrorState, + + // Object states + IterativeParsingObjectInitialState, + IterativeParsingMemberKeyState, + IterativeParsingKeyValueDelimiterState, + IterativeParsingMemberValueState, + IterativeParsingMemberDelimiterState, + IterativeParsingObjectFinishState, + + // Array states + IterativeParsingArrayInitialState, + IterativeParsingElementState, + IterativeParsingElementDelimiterState, + IterativeParsingArrayFinishState, + + // Single value state + IterativeParsingValueState, + + cIterativeParsingStateCount + }; + + // Tokens + enum Token { + LeftBracketToken = 0, + RightBracketToken, + + LeftCurlyBracketToken, + RightCurlyBracketToken, + + CommaToken, + ColonToken, + + StringToken, + FalseToken, + TrueToken, + NullToken, + NumberToken, + + kTokenCount + }; + + RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) { + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#define N NumberToken +#define N16 N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N + // Maps from ASCII to Token + static const unsigned char tokenMap[256] = { + N16, // 00~0F + N16, // 10~1F + N, N, StringToken, N, N, N, N, N, N, N, N, N, CommaToken, N, N, N, // 20~2F + N, N, N, N, N, N, N, N, N, N, ColonToken, N, N, N, N, N, // 30~3F + N16, // 40~4F + N, N, N, N, N, N, N, N, N, N, N, LeftBracketToken, N, RightBracketToken, N, N, // 50~5F + N, N, N, N, N, N, FalseToken, N, N, N, N, N, N, N, NullToken, N, // 60~6F + N, N, N, N, TrueToken, N, N, N, N, N, N, LeftCurlyBracketToken, N, RightCurlyBracketToken, N, N, // 70~7F + N16, N16, N16, N16, N16, N16, N16, N16 // 80~FF + }; +#undef N +#undef N16 +//!@endcond + + if (sizeof(Ch) == 1 || unsigned(c) < 256) + return (Token)tokenMap[(unsigned char)c]; + else + return NumberToken; + } + + RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) { + // current state x one lookahead token -> new state + static const char G[cIterativeParsingStateCount][kTokenCount] = { + // Start + { + IterativeParsingArrayInitialState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingValueState, // String + IterativeParsingValueState, // False + IterativeParsingValueState, // True + IterativeParsingValueState, // Null + IterativeParsingValueState // Number + }, + // Finish(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // Error(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // ObjectInitial + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingObjectFinishState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingMemberKeyState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // MemberKey + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingKeyValueDelimiterState, // Colon + IterativeParsingErrorState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // KeyValueDelimiter + { + IterativeParsingArrayInitialState, // Left bracket(push MemberValue state) + IterativeParsingErrorState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket(push MemberValue state) + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingMemberValueState, // String + IterativeParsingMemberValueState, // False + IterativeParsingMemberValueState, // True + IterativeParsingMemberValueState, // Null + IterativeParsingMemberValueState // Number + }, + // MemberValue + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingObjectFinishState, // Right curly bracket + IterativeParsingMemberDelimiterState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingErrorState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // MemberDelimiter + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingMemberKeyState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // ObjectFinish(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // ArrayInitial + { + IterativeParsingArrayInitialState, // Left bracket(push Element state) + IterativeParsingArrayFinishState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket(push Element state) + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingElementState, // String + IterativeParsingElementState, // False + IterativeParsingElementState, // True + IterativeParsingElementState, // Null + IterativeParsingElementState // Number + }, + // Element + { + IterativeParsingErrorState, // Left bracket + IterativeParsingArrayFinishState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingErrorState, // Right curly bracket + IterativeParsingElementDelimiterState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingErrorState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // ElementDelimiter + { + IterativeParsingArrayInitialState, // Left bracket(push Element state) + IterativeParsingErrorState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket(push Element state) + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingElementState, // String + IterativeParsingElementState, // False + IterativeParsingElementState, // True + IterativeParsingElementState, // Null + IterativeParsingElementState // Number + }, + // ArrayFinish(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // Single Value (sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + } + }; // End of G + + return (IterativeParsingState)G[state][token]; + } + + // Make an advance in the token stream and state based on the candidate destination state which was returned by Transit(). + // May return a new state on state pop. + template + RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream& is, Handler& handler) { + switch (dst) { + case IterativeParsingStartState: + RAPIDJSON_ASSERT(false); + return IterativeParsingErrorState; + + case IterativeParsingFinishState: + return dst; + + case IterativeParsingErrorState: + return dst; + + case IterativeParsingObjectInitialState: + case IterativeParsingArrayInitialState: + { + // Push the state(Element or MemeberValue) if we are nested in another array or value of member. + // In this way we can get the correct state on ObjectFinish or ArrayFinish by frame pop. + IterativeParsingState n = src; + if (src == IterativeParsingArrayInitialState || src == IterativeParsingElementDelimiterState) + n = IterativeParsingElementState; + else if (src == IterativeParsingKeyValueDelimiterState) + n = IterativeParsingMemberValueState; + // Push current state. + *stack_.template Push(1) = n; + // Initialize and push the member/element count. + *stack_.template Push(1) = 0; + // Call handler + bool hr = (dst == IterativeParsingObjectInitialState) ? handler.StartObject() : handler.StartArray(); + // On handler short circuits the parsing. + if (!hr) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); + return IterativeParsingErrorState; + } + else { + is.Take(); + return dst; + } + } + + case IterativeParsingMemberKeyState: + ParseString(is, handler, true); + if (HasParseError()) + return IterativeParsingErrorState; + else + return dst; + + case IterativeParsingKeyValueDelimiterState: + if (token == ColonToken) { + is.Take(); + return dst; + } + else + return IterativeParsingErrorState; + + case IterativeParsingMemberValueState: + // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. + ParseValue(is, handler); + if (HasParseError()) { + return IterativeParsingErrorState; + } + return dst; + + case IterativeParsingElementState: + // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. + ParseValue(is, handler); + if (HasParseError()) { + return IterativeParsingErrorState; + } + return dst; + + case IterativeParsingMemberDelimiterState: + case IterativeParsingElementDelimiterState: + is.Take(); + // Update member/element count. + *stack_.template Top() = *stack_.template Top() + 1; + return dst; + + case IterativeParsingObjectFinishState: + { + // Get member count. + SizeType c = *stack_.template Pop(1); + // If the object is not empty, count the last member. + if (src == IterativeParsingMemberValueState) + ++c; + // Restore the state. + IterativeParsingState n = static_cast(*stack_.template Pop(1)); + // Transit to Finish state if this is the topmost scope. + if (n == IterativeParsingStartState) + n = IterativeParsingFinishState; + // Call handler + bool hr = handler.EndObject(c); + // On handler short circuits the parsing. + if (!hr) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); + return IterativeParsingErrorState; + } + else { + is.Take(); + return n; + } + } + + case IterativeParsingArrayFinishState: + { + // Get element count. + SizeType c = *stack_.template Pop(1); + // If the array is not empty, count the last element. + if (src == IterativeParsingElementState) + ++c; + // Restore the state. + IterativeParsingState n = static_cast(*stack_.template Pop(1)); + // Transit to Finish state if this is the topmost scope. + if (n == IterativeParsingStartState) + n = IterativeParsingFinishState; + // Call handler + bool hr = handler.EndArray(c); + // On handler short circuits the parsing. + if (!hr) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); + return IterativeParsingErrorState; + } + else { + is.Take(); + return n; + } + } + + case IterativeParsingValueState: + // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. + ParseValue(is, handler); + if (HasParseError()) { + return IterativeParsingErrorState; + } + return IterativeParsingFinishState; + + default: + RAPIDJSON_ASSERT(false); + return IterativeParsingErrorState; + } + } + + template + void HandleError(IterativeParsingState src, InputStream& is) { + if (HasParseError()) { + // Error flag has been set. + return; + } + + switch (src) { + case IterativeParsingStartState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell()); + case IterativeParsingFinishState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell()); + case IterativeParsingObjectInitialState: + case IterativeParsingMemberDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); + case IterativeParsingMemberKeyState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); + case IterativeParsingMemberValueState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); + case IterativeParsingElementState: RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); + default: RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); + } + } + + template + ParseResult IterativeParse(InputStream& is, Handler& handler) { + parseResult_.Clear(); + ClearStackOnExit scope(*this); + IterativeParsingState state = IterativeParsingStartState; + + SkipWhitespace(is); + while (is.Peek() != '\0') { + Token t = Tokenize(is.Peek()); + IterativeParsingState n = Predict(state, t); + IterativeParsingState d = Transit(state, t, n, is, handler); + + if (d == IterativeParsingErrorState) { + HandleError(state, is); + break; + } + + state = d; + + // Do not further consume streams if a root JSON has been parsed. + if ((parseFlags & kParseStopWhenDoneFlag) && state == IterativeParsingFinishState) + break; + + SkipWhitespace(is); + } + + // Handle the end of file. + if (state != IterativeParsingFinishState) + HandleError(state, is); + + return parseResult_; + } + + static const size_t kDefaultStackCapacity = 256; //!< Default stack capacity in bytes for storing a single decoded string. + internal::Stack stack_; //!< A stack for storing decoded string temporarily during non-destructive parsing. + ParseResult parseResult_; +}; // class GenericReader + +//! Reader with UTF8 encoding and default allocator. +typedef GenericReader, UTF8<> > Reader; + +RAPIDJSON_NAMESPACE_END + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#ifdef _MSC_VER +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_READER_H_ diff --git a/src/include/rapidjson/stringbuffer.h b/src/include/rapidjson/stringbuffer.h new file mode 100644 index 0000000..009a518 --- /dev/null +++ b/src/include/rapidjson/stringbuffer.h @@ -0,0 +1,99 @@ +// Copyright (C) 2011 Milo Yip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef RAPIDJSON_STRINGBUFFER_H_ +#define RAPIDJSON_STRINGBUFFER_H_ + +#include "rapidjson.h" + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS +#include // std::move +#endif + +#include "internal/stack.h" + +RAPIDJSON_NAMESPACE_BEGIN + +//! Represents an in-memory output stream. +/*! + \tparam Encoding Encoding of the stream. + \tparam Allocator type for allocating memory buffer. + \note implements Stream concept +*/ +template +class GenericStringBuffer { +public: + typedef typename Encoding::Ch Ch; + + GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericStringBuffer(GenericStringBuffer&& rhs) : stack_(std::move(rhs.stack_)) {} + GenericStringBuffer& operator=(GenericStringBuffer&& rhs) { + if (&rhs != this) + stack_ = std::move(rhs.stack_); + return *this; + } +#endif + + void Put(Ch c) { *stack_.template Push() = c; } + void Flush() {} + + void Clear() { stack_.Clear(); } + void ShrinkToFit() { + // Push and pop a null terminator. This is safe. + *stack_.template Push() = '\0'; + stack_.ShrinkToFit(); + stack_.template Pop(1); + } + Ch* Push(size_t count) { return stack_.template Push(count); } + void Pop(size_t count) { stack_.template Pop(count); } + + const Ch* GetString() const { + // Push and pop a null terminator. This is safe. + *stack_.template Push() = '\0'; + stack_.template Pop(1); + + return stack_.template Bottom(); + } + + size_t GetSize() const { return stack_.GetSize(); } + + static const size_t kDefaultCapacity = 256; + mutable internal::Stack stack_; + +private: + // Prohibit copy constructor & assignment operator. + GenericStringBuffer(const GenericStringBuffer&); + GenericStringBuffer& operator=(const GenericStringBuffer&); +}; + +//! String buffer with UTF8 encoding +typedef GenericStringBuffer > StringBuffer; + +//! Implement specialized version of PutN() with memset() for better performance. +template<> +inline void PutN(GenericStringBuffer >& stream, char c, size_t n) { + std::memset(stream.stack_.Push(n), c, n * sizeof(c)); +} + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_STRINGBUFFER_H_ diff --git a/src/include/rapidjson/writer.h b/src/include/rapidjson/writer.h new file mode 100644 index 0000000..c646f0f --- /dev/null +++ b/src/include/rapidjson/writer.h @@ -0,0 +1,401 @@ +// Copyright (C) 2011 Milo Yip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef RAPIDJSON_WRITER_H_ +#define RAPIDJSON_WRITER_H_ + +#include "rapidjson.h" +#include "internal/stack.h" +#include "internal/strfunc.h" +#include "internal/dtoa.h" +#include "internal/itoa.h" +#include "stringbuffer.h" +#include // placement new + +#if RAPIDJSON_HAS_STDSTRING +#include +#endif + +#ifdef _MSC_VER +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! JSON writer +/*! Writer implements the concept Handler. + It generates JSON text by events to an output os. + + User may programmatically calls the functions of a writer to generate JSON text. + + On the other side, a writer can also be passed to objects that generates events, + + for example Reader::Parse() and Document::Accept(). + + \tparam OutputStream Type of output stream. + \tparam SourceEncoding Encoding of source string. + \tparam TargetEncoding Encoding of output stream. + \tparam StackAllocator Type of allocator for allocating memory of stack. + \note implements Handler concept +*/ +template, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator> +class Writer { +public: + typedef typename SourceEncoding::Ch Ch; + + //! Constructor + /*! \param os Output stream. + \param stackAllocator User supplied allocator. If it is null, it will create a private one. + \param levelDepth Initial capacity of stack. + */ + explicit + Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) : + os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), hasRoot_(false) {} + + explicit + Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) : + os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), hasRoot_(false) {} + + //! Reset the writer with a new stream. + /*! + This function reset the writer with a new stream and default settings, + in order to make a Writer object reusable for output multiple JSONs. + + \param os New output stream. + \code + Writer writer(os1); + writer.StartObject(); + // ... + writer.EndObject(); + + writer.Reset(os2); + writer.StartObject(); + // ... + writer.EndObject(); + \endcode + */ + void Reset(OutputStream& os) { + os_ = &os; + hasRoot_ = false; + level_stack_.Clear(); + } + + //! Checks whether the output is a complete JSON. + /*! + A complete JSON has a complete root object or array. + */ + bool IsComplete() const { + return hasRoot_ && level_stack_.Empty(); + } + + /*!@name Implementation of Handler + \see Handler + */ + //@{ + + bool Null() { Prefix(kNullType); return WriteNull(); } + bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return WriteBool(b); } + bool Int(int i) { Prefix(kNumberType); return WriteInt(i); } + bool Uint(unsigned u) { Prefix(kNumberType); return WriteUint(u); } + bool Int64(int64_t i64) { Prefix(kNumberType); return WriteInt64(i64); } + bool Uint64(uint64_t u64) { Prefix(kNumberType); return WriteUint64(u64); } + + //! Writes the given \c double value to the stream + /*! + \param d The value to be written. + \return Whether it is succeed. + */ + bool Double(double d) { Prefix(kNumberType); return WriteDouble(d); } + + bool String(const Ch* str, SizeType length, bool copy = false) { + (void)copy; + Prefix(kStringType); + return WriteString(str, length); + } + +#if RAPIDJSON_HAS_STDSTRING + bool String(const std::basic_string& str) { + return String(str.data(), SizeType(str.size())); + } +#endif + + bool StartObject() { + Prefix(kObjectType); + new (level_stack_.template Push()) Level(false); + return WriteStartObject(); + } + + bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } + + bool EndObject(SizeType memberCount = 0) { + (void)memberCount; + RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); + RAPIDJSON_ASSERT(!level_stack_.template Top()->inArray); + level_stack_.template Pop(1); + bool ret = WriteEndObject(); + if (level_stack_.Empty()) // end of json text + os_->Flush(); + return ret; + } + + bool StartArray() { + Prefix(kArrayType); + new (level_stack_.template Push()) Level(true); + return WriteStartArray(); + } + + bool EndArray(SizeType elementCount = 0) { + (void)elementCount; + RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); + RAPIDJSON_ASSERT(level_stack_.template Top()->inArray); + level_stack_.template Pop(1); + bool ret = WriteEndArray(); + if (level_stack_.Empty()) // end of json text + os_->Flush(); + return ret; + } + //@} + + /*! @name Convenience extensions */ + //@{ + + //! Simpler but slower overload. + bool String(const Ch* str) { return String(str, internal::StrLen(str)); } + bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); } + + //@} + +protected: + //! Information for each nested level + struct Level { + Level(bool inArray_) : valueCount(0), inArray(inArray_) {} + size_t valueCount; //!< number of values in this level + bool inArray; //!< true if in array, otherwise in object + }; + + static const size_t kDefaultLevelDepth = 32; + + bool WriteNull() { + os_->Put('n'); os_->Put('u'); os_->Put('l'); os_->Put('l'); return true; + } + + bool WriteBool(bool b) { + if (b) { + os_->Put('t'); os_->Put('r'); os_->Put('u'); os_->Put('e'); + } + else { + os_->Put('f'); os_->Put('a'); os_->Put('l'); os_->Put('s'); os_->Put('e'); + } + return true; + } + + bool WriteInt(int i) { + char buffer[11]; + const char* end = internal::i32toa(i, buffer); + for (const char* p = buffer; p != end; ++p) + os_->Put(*p); + return true; + } + + bool WriteUint(unsigned u) { + char buffer[10]; + const char* end = internal::u32toa(u, buffer); + for (const char* p = buffer; p != end; ++p) + os_->Put(*p); + return true; + } + + bool WriteInt64(int64_t i64) { + char buffer[21]; + const char* end = internal::i64toa(i64, buffer); + for (const char* p = buffer; p != end; ++p) + os_->Put(*p); + return true; + } + + bool WriteUint64(uint64_t u64) { + char buffer[20]; + char* end = internal::u64toa(u64, buffer); + for (char* p = buffer; p != end; ++p) + os_->Put(*p); + return true; + } + + bool WriteDouble(double d) { + char buffer[25]; + char* end = internal::dtoa(d, buffer); + for (char* p = buffer; p != end; ++p) + os_->Put(*p); + return true; + } + + bool WriteString(const Ch* str, SizeType length) { + static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + static const char escape[256] = { +#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + //0 1 2 3 4 5 6 7 8 9 A B C D E F + 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00 + 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10 + 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20 + Z16, Z16, // 30~4F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50 + Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF +#undef Z16 + }; + + os_->Put('\"'); + GenericStringStream is(str); + while (is.Tell() < length) { + const Ch c = is.Peek(); + if (!TargetEncoding::supportUnicode && (unsigned)c >= 0x80) { + // Unicode escaping + unsigned codepoint; + if (!SourceEncoding::Decode(is, &codepoint)) + return false; + os_->Put('\\'); + os_->Put('u'); + if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) { + os_->Put(hexDigits[(codepoint >> 12) & 15]); + os_->Put(hexDigits[(codepoint >> 8) & 15]); + os_->Put(hexDigits[(codepoint >> 4) & 15]); + os_->Put(hexDigits[(codepoint ) & 15]); + } + else if (codepoint >= 0x010000 && codepoint <= 0x10FFFF) { + // Surrogate pair + unsigned s = codepoint - 0x010000; + unsigned lead = (s >> 10) + 0xD800; + unsigned trail = (s & 0x3FF) + 0xDC00; + os_->Put(hexDigits[(lead >> 12) & 15]); + os_->Put(hexDigits[(lead >> 8) & 15]); + os_->Put(hexDigits[(lead >> 4) & 15]); + os_->Put(hexDigits[(lead ) & 15]); + os_->Put('\\'); + os_->Put('u'); + os_->Put(hexDigits[(trail >> 12) & 15]); + os_->Put(hexDigits[(trail >> 8) & 15]); + os_->Put(hexDigits[(trail >> 4) & 15]); + os_->Put(hexDigits[(trail ) & 15]); + } + else + return false; // invalid code point + } + else if ((sizeof(Ch) == 1 || (unsigned)c < 256) && escape[(unsigned char)c]) { + is.Take(); + os_->Put('\\'); + os_->Put(escape[(unsigned char)c]); + if (escape[(unsigned char)c] == 'u') { + os_->Put('0'); + os_->Put('0'); + os_->Put(hexDigits[(unsigned char)c >> 4]); + os_->Put(hexDigits[(unsigned char)c & 0xF]); + } + } + else + Transcoder::Transcode(is, *os_); + } + os_->Put('\"'); + return true; + } + + bool WriteStartObject() { os_->Put('{'); return true; } + bool WriteEndObject() { os_->Put('}'); return true; } + bool WriteStartArray() { os_->Put('['); return true; } + bool WriteEndArray() { os_->Put(']'); return true; } + + void Prefix(Type type) { + (void)type; + if (level_stack_.GetSize() != 0) { // this value is not at root + Level* level = level_stack_.template Top(); + if (level->valueCount > 0) { + if (level->inArray) + os_->Put(','); // add comma if it is not the first element in array + else // in object + os_->Put((level->valueCount % 2 == 0) ? ',' : ':'); + } + if (!level->inArray && level->valueCount % 2 == 0) + RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name + level->valueCount++; + } + else { + RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root. + hasRoot_ = true; + } + } + + OutputStream* os_; + internal::Stack level_stack_; + bool hasRoot_; + +private: + // Prohibit copy constructor & assignment operator. + Writer(const Writer&); + Writer& operator=(const Writer&); +}; + +// Full specialization for StringStream to prevent memory copying + +template<> +inline bool Writer::WriteInt(int i) { + char *buffer = os_->Push(11); + const char* end = internal::i32toa(i, buffer); + os_->Pop(11 - (end - buffer)); + return true; +} + +template<> +inline bool Writer::WriteUint(unsigned u) { + char *buffer = os_->Push(10); + const char* end = internal::u32toa(u, buffer); + os_->Pop(10 - (end - buffer)); + return true; +} + +template<> +inline bool Writer::WriteInt64(int64_t i64) { + char *buffer = os_->Push(21); + const char* end = internal::i64toa(i64, buffer); + os_->Pop(21 - (end - buffer)); + return true; +} + +template<> +inline bool Writer::WriteUint64(uint64_t u) { + char *buffer = os_->Push(20); + const char* end = internal::u64toa(u, buffer); + os_->Pop(20 - (end - buffer)); + return true; +} + +template<> +inline bool Writer::WriteDouble(double d) { + char *buffer = os_->Push(25); + char* end = internal::dtoa(d, buffer); + os_->Pop(25 - (end - buffer)); + return true; +} + +RAPIDJSON_NAMESPACE_END + +#ifdef _MSC_VER +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/src/main.cpp b/src/main.cpp index 402aff2..b269330 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -46,7 +46,7 @@ int main() } } - window.clear(sf::Color(0, 0, 0)); + window.clear(sf::Color(72, 152, 72)); window.display(); timeElapsed = timer.getElapsedTime(); diff --git a/src/map/level1.json b/src/map/level1.json new file mode 100644 index 0000000..8d2c8e0 --- /dev/null +++ b/src/map/level1.json @@ -0,0 +1,53 @@ +{ "height":25, + "layers":[ + { + "data":[1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 0, 0, 0, 0, 0, 97, 98, 99, 100, 97, 98, 99, 100, 97, 98, 99, 100, 97, 98, 99, 100, 97, 98, 99, 100, 0, 0, 0, 0, 0, 193, 194, 195, 196, 193, 194, 195, 196, 193, 194, 195, 196, 193, 194, 195, 196, 193, 194, 195, 196, 0, 0, 0, 0, 0, 289, 290, 291, 292, 289, 290, 291, 292, 289, 290, 291, 292, 289, 290, 291, 292, 289, 290, 291, 292, 0, 0, 0, 0, 0, 385, 386, 387, 388, 385, 386, 387, 388, 385, 386, 387, 388, 385, 386, 387, 388, 385, 386, 387, 388, 0, 0, 0, 0, 0, 2153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2172, 0, 0, 0, 0, 0, 2249, 2250, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2268, 0, 0, 0, 0, 0, 2345, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2364, 0, 0, 0, 0, 0, 2441, 2442, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2460, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "height":25, + "name":"Layer 1", + "opacity":1, + "type":"tilelayer", + "visible":true, + "width":25, + "x":0, + "y":0 + }, + { + "data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 481, 482, 483, 484, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 577, 578, 579, 580, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 673, 674, 675, 676, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 769, 770, 771, 772, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 865, 866, 867, 868, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 481, 482, 483, 484, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 577, 578, 579, 580, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 673, 674, 675, 676, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 769, 770, 771, 772, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 865, 866, 867, 868, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "height":25, + "name":"Layer 2", + "opacity":1, + "type":"tilelayer", + "visible":true, + "width":25, + "x":0, + "y":0 + }], + "nextobjectid":1, + "orientation":"orthogonal", + "properties": + { + + }, + "renderorder":"right-down", + "tileheight":16, + "tilesets":[ + { + "firstgid":1, + "image":"..\/gfx\/Tilesheet.png", + "imageheight":930, + "imagewidth":1550, + "margin":0, + "name":"Tilesheet", + "properties": + { + + }, + "spacing":0, + "tileheight":16, + "tilewidth":16, + "transparentcolor":"#ffffff" + }], + "tilewidth":16, + "version":1, + "width":25 +} \ No newline at end of file diff --git a/src/map/level1.tmx b/src/map/level1.tmx new file mode 100644 index 0000000..5f8bd7a --- /dev/null +++ b/src/map/level1.tmx @@ -0,0 +1,16 @@ + + + + + + + + AQAAAAIAAAADAAAABAAAAAEAAAACAAAAAwAAAAQAAAABAAAAAgAAAAMAAAAEAAAAAQAAAAIAAAADAAAABAAAAAEAAAACAAAAAwAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGEAAABiAAAAYwAAAGQAAABhAAAAYgAAAGMAAABkAAAAYQAAAGIAAABjAAAAZAAAAGEAAABiAAAAYwAAAGQAAABhAAAAYgAAAGMAAABkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADBAAAAwgAAAMMAAADEAAAAwQAAAMIAAADDAAAAxAAAAMEAAADCAAAAwwAAAMQAAADBAAAAwgAAAMMAAADEAAAAwQAAAMIAAADDAAAAxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIQEAACIBAAAjAQAAJAEAACEBAAAiAQAAIwEAACQBAAAhAQAAIgEAACMBAAAkAQAAIQEAACIBAAAjAQAAJAEAACEBAAAiAQAAIwEAACQBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIEBAACCAQAAgwEAAIQBAACBAQAAggEAAIMBAACEAQAAgQEAAIIBAACDAQAAhAEAAIEBAACCAQAAgwEAAIQBAACBAQAAggEAAIMBAACEAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABpCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAyQgAAMoIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAACkJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8CQAAAAAAAAAAAAAAAAAAAAAAAAAAAACJCQAAigkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4QEAAOIBAADjAQAA5AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEECAABCAgAAQwIAAEQCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAChAgAAogIAAKMCAACkAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQMAAAIDAAADAwAABAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGEDAABiAwAAYwMAAGQDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADhAQAA4gEAAOMBAADkAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQQIAAEICAABDAgAARAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKECAACiAgAAowIAAKQCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAwAAAgMAAAMDAAAEAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYQMAAGIDAABjAwAAZAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== + + + diff --git a/src/maploader.cpp b/src/maploader.cpp new file mode 100644 index 0000000..4f582a4 --- /dev/null +++ b/src/maploader.cpp @@ -0,0 +1,12 @@ +#include "maploader.h" + +MapLoader::MapLoader() +{ + +} + +MapLoader::~MapLoader() +{ + +} + diff --git a/src/maploader.h b/src/maploader.h new file mode 100644 index 0000000..30e4193 --- /dev/null +++ b/src/maploader.h @@ -0,0 +1,12 @@ +#ifndef MAPLOADER_H +#define MAPLOADER_H + + +class MapLoader +{ +public: + MapLoader(); + ~MapLoader(); +}; + +#endif // MAPLOADER_H diff --git a/src/rpg.pro b/src/rpg.pro index 3b0c3f5..10c004e 100644 --- a/src/rpg.pro +++ b/src/rpg.pro @@ -6,15 +6,22 @@ CONFIG -= qt include(deployment.pri) qtcAddDeployment() -LIBS += -LC:/SFML/lib +LIBS += -L"$$PWD/include/SFML/lib" +LIBS += -L"$$PWD/include/rapidjson" CONFIG(release, debug|release): LIBS += -lsfml-audio -lsfml-graphics -lsfml-main -lsfml-network -lsfml-window -lsfml-system CONFIG(debug, debug|release): LIBS += -lsfml-audio-d -lsfml-graphics-d -lsfml-main-d -lsfml-network-d -lsfml-window-d -lsfml-system-d -INCLUDEPATH += C:/SFML/include -DEPENDPATH += C:/SFML/include +INCLUDEPATH += $$PWD/include/SFML/include +INCLUDEPATH += $$PWD/include/rapidjson +DEPENDPATH += $$PWD/include/SFML/include +DEPENDPATH += $$PWD/include/rapidjson TEMPLATE = app -SOURCES += main.cpp +SOURCES += main.cpp \ + maploader.cpp + +HEADERS += \ + maploader.h