Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 28b8659e16 | |||
| 0b9fc0520e | |||
| c54017c7be | |||
| bbfe341d23 | |||
| 14efe2cc39 | |||
| fcda12e321 | |||
| 1200a6e087 | |||
| 512fb23d0e | |||
| 5a547b6514 | |||
| ed45995645 | |||
| 0b6d826eba | |||
| 6d0c6be166 | |||
| 222b79b40a | |||
| 8f95b1a750 | |||
| 7d30017742 | |||
| 386ea5b6ad | |||
| 8949c37891 | |||
| 019174128c | |||
| 4e8b095e31 | |||
| 0e0368cada | |||
|
|
6e0923ac75 | ||
|
|
bba9ef8219 |
63
include/Defines.h
Normal file
63
include/Defines.h
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace td {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct Vec2 {
|
||||||
|
union {
|
||||||
|
T x;
|
||||||
|
T r;
|
||||||
|
};
|
||||||
|
|
||||||
|
union {
|
||||||
|
T y;
|
||||||
|
T g;
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr Vec2(T X = 0, T Y = 0) : x(X), y(Y) {}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline bool operator==(const Vec2<T>& vec2, const Vec2<T>& other) {
|
||||||
|
return vec2.x == other.x && vec2.y == other.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct Vec3 {
|
||||||
|
union {
|
||||||
|
T x;
|
||||||
|
T r;
|
||||||
|
};
|
||||||
|
|
||||||
|
union {
|
||||||
|
T y;
|
||||||
|
T g;
|
||||||
|
};
|
||||||
|
|
||||||
|
union {
|
||||||
|
T z;
|
||||||
|
T b;
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr Vec3(T X = 0, T Y = 0, T Z = 0) : x(X), y(Y), z(Z) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline bool operator==(const Vec3<T>& vec3, const Vec3<T>& other) {
|
||||||
|
return vec3.x == other.x && vec3.y == other.y && vec3.z == other.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
using Vec2i = Vec2<int>;
|
||||||
|
using Vec2u = Vec2<unsigned int>;
|
||||||
|
using Vec2f = Vec2<float>;
|
||||||
|
using Vec2d = Vec2<double>;
|
||||||
|
|
||||||
|
using Vec3i = Vec3<int>;
|
||||||
|
using Vec3u = Vec3<unsigned int>;
|
||||||
|
using Vec3f = Vec3<float>;
|
||||||
|
using Vec3d = Vec3<double>;
|
||||||
|
|
||||||
|
using Color = Vec3<unsigned char>;
|
||||||
|
|
||||||
|
} // namespace td
|
||||||
@@ -8,62 +8,62 @@ namespace td {
|
|||||||
namespace game {
|
namespace game {
|
||||||
|
|
||||||
enum class GameState : std::uint8_t {
|
enum class GameState : std::uint8_t {
|
||||||
Lobby,
|
Lobby,
|
||||||
Game,
|
Game,
|
||||||
EndGame,
|
EndGame,
|
||||||
Disconnected,
|
Disconnected,
|
||||||
Closed
|
Closed
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::map<std::uint8_t, Player> PlayerList;
|
typedef std::map<std::uint8_t, Player> PlayerList;
|
||||||
|
|
||||||
class GameListener {
|
class GameListener {
|
||||||
public:
|
public:
|
||||||
virtual void OnPlayerJoin(PlayerID player) {}
|
virtual void OnPlayerJoin(PlayerID player) {}
|
||||||
virtual void OnPlayerLeave(PlayerID player) {}
|
virtual void OnPlayerLeave(PlayerID player) {}
|
||||||
|
|
||||||
virtual void OnGameStateUpdate(GameState newState) {}
|
virtual void OnGameStateUpdate(GameState newState) {}
|
||||||
virtual void OnGameBegin() {}
|
virtual void OnGameBegin() {}
|
||||||
virtual void OnGameEnd() {}
|
virtual void OnGameEnd() {}
|
||||||
virtual void OnGameClose() {}
|
virtual void OnGameClose() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef utils::ObjectNotifier<GameListener> GameNotifier;
|
typedef utils::ObjectNotifier<GameListener> GameNotifier;
|
||||||
|
|
||||||
class Game : public GameNotifier {
|
class Game : public GameNotifier {
|
||||||
protected:
|
protected:
|
||||||
World* m_World;
|
World* m_World;
|
||||||
TeamList m_Teams = { Team{TeamColor::Red}, Team{TeamColor::Blue} };
|
TeamList m_Teams = { Team{TeamColor::Red}, Team{TeamColor::Blue} };
|
||||||
GameState m_GameState = GameState::Lobby;
|
GameState m_GameState = GameState::Lobby;
|
||||||
PlayerList m_Players;
|
PlayerList m_Players;
|
||||||
public:
|
public:
|
||||||
Game(World* world);
|
Game(World* world);
|
||||||
virtual ~Game();
|
virtual ~Game();
|
||||||
|
|
||||||
virtual void Tick(std::uint64_t delta);
|
virtual void Tick(std::uint64_t delta);
|
||||||
|
|
||||||
Team& GetRedTeam() { return m_Teams[static_cast<std::uint8_t>(TeamColor::Red)]; }
|
Team& GetRedTeam() { return m_Teams[static_cast<std::uint8_t>(TeamColor::Red)]; }
|
||||||
const Team& GetRedTeam() const { return m_Teams[static_cast<std::uint8_t>(TeamColor::Red)]; }
|
const Team& GetRedTeam() const { return m_Teams[static_cast<std::uint8_t>(TeamColor::Red)]; }
|
||||||
|
|
||||||
Team& GetBlueTeam() { return m_Teams[static_cast<std::uint8_t>(TeamColor::Blue)]; }
|
Team& GetBlueTeam() { return m_Teams[static_cast<std::uint8_t>(TeamColor::Blue)]; }
|
||||||
const Team& GetBlueTeam() const { return m_Teams[static_cast<std::uint8_t>(TeamColor::Red)]; }
|
const Team& GetBlueTeam() const { return m_Teams[static_cast<std::uint8_t>(TeamColor::Red)]; }
|
||||||
|
|
||||||
Team& GetTeam(TeamColor team) { return m_Teams[static_cast<std::uint8_t>(team)]; }
|
Team& GetTeam(TeamColor team) { return m_Teams[static_cast<std::uint8_t>(team)]; }
|
||||||
const Team& GetTeam(TeamColor team) const { return m_Teams[static_cast<std::uint8_t>(team)]; }
|
const Team& GetTeam(TeamColor team) const { return m_Teams[static_cast<std::uint8_t>(team)]; }
|
||||||
|
|
||||||
GameState GetGameState() const { return m_GameState; }
|
GameState GetGameState() const { return m_GameState; }
|
||||||
void SetGameState(GameState gameState) { m_GameState = gameState; };
|
virtual void SetGameState(GameState gameState) { m_GameState = gameState; };
|
||||||
|
|
||||||
const World* GetWorld() const { return m_World; }
|
const World* GetWorld() const { return m_World; }
|
||||||
World* GetWorld() { return m_World; }
|
World* GetWorld() { return m_World; }
|
||||||
|
|
||||||
const PlayerList& GetPlayers() const { return m_Players; }
|
const PlayerList& GetPlayers() const { return m_Players; }
|
||||||
PlayerList& GetPlayers() { return m_Players; }
|
PlayerList& GetPlayers() { return m_Players; }
|
||||||
|
|
||||||
const Player* GetPlayerById(PlayerID id) const;
|
const Player* GetPlayerById(PlayerID id) const;
|
||||||
Player* GetPlayerById(PlayerID id);
|
Player* GetPlayerById(PlayerID id);
|
||||||
|
|
||||||
const TeamList& GetTeams() const { return m_Teams; }
|
const TeamList& GetTeams() const { return m_Teams; }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -10,26 +10,26 @@ namespace protocol {
|
|||||||
|
|
||||||
class Connexion : public protocol::PacketHandler {
|
class Connexion : public protocol::PacketHandler {
|
||||||
protected:
|
protected:
|
||||||
protocol::PacketDispatcher m_Dispatcher;
|
protocol::PacketDispatcher m_Dispatcher;
|
||||||
private:
|
private:
|
||||||
network::TCPSocket m_Socket;
|
network::TCPSocket m_Socket;
|
||||||
public:
|
public:
|
||||||
Connexion();
|
Connexion();
|
||||||
Connexion(Connexion&& move);
|
Connexion(Connexion&& move);
|
||||||
Connexion(protocol::PacketDispatcher* dispatcher);
|
Connexion(protocol::PacketDispatcher* dispatcher);
|
||||||
Connexion(protocol::PacketDispatcher* dispatcher, network::TCPSocket& socket);
|
Connexion(protocol::PacketDispatcher* dispatcher, network::TCPSocket& socket);
|
||||||
virtual ~Connexion();
|
virtual ~Connexion();
|
||||||
|
|
||||||
virtual bool UpdateSocket();
|
virtual bool UpdateSocket();
|
||||||
void CloseConnection();
|
void CloseConnection();
|
||||||
|
|
||||||
bool Connect(const std::string& address, std::uint16_t port);
|
bool Connect(const std::string& address, std::uint16_t port);
|
||||||
|
|
||||||
network::Socket::Status GetSocketStatus() const { return m_Socket.GetStatus(); }
|
network::Socket::Status GetSocketStatus() const { return m_Socket.GetStatus(); }
|
||||||
|
|
||||||
void SendPacket(const protocol::Packet* packet);
|
void SendPacket(const protocol::Packet* packet);
|
||||||
|
|
||||||
REMOVE_COPY(Connexion);
|
REMOVE_COPY(Connexion);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace server
|
} // namespace server
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Defines.h"
|
||||||
#include "Towers.h"
|
#include "Towers.h"
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
#include "Team.h"
|
#include "Team.h"
|
||||||
@@ -9,34 +10,32 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
namespace game {
|
namespace game {
|
||||||
|
|
||||||
struct WalkableTile;
|
struct WalkableTile;
|
||||||
|
|
||||||
enum class EffectType : std::uint8_t {
|
enum class EffectType : std::uint8_t {
|
||||||
Slowness = 0,
|
Slowness = 0,
|
||||||
Stun,
|
Stun,
|
||||||
Fire,
|
Fire,
|
||||||
Poison,
|
Poison,
|
||||||
Heal,
|
Heal,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class MobType : std::uint8_t {
|
enum class MobType : std::uint8_t {
|
||||||
Zombie = 0,
|
Zombie = 0,
|
||||||
Spider,
|
Spider,
|
||||||
Skeleton,
|
Skeleton,
|
||||||
Pigman,
|
Pigman,
|
||||||
Creeper,
|
Creeper,
|
||||||
Silverfish,
|
Silverfish,
|
||||||
Blaze,
|
Blaze,
|
||||||
Witch,
|
Witch,
|
||||||
Slime,
|
Slime,
|
||||||
Giant,
|
Giant,
|
||||||
|
|
||||||
MOB_COUNT
|
MOB_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::uint32_t MobID;
|
typedef std::uint32_t MobID;
|
||||||
@@ -46,34 +45,34 @@ typedef std::vector<EffectType> EffectImmunities;
|
|||||||
|
|
||||||
class MobStats {
|
class MobStats {
|
||||||
private:
|
private:
|
||||||
float m_Damage;
|
float m_Damage;
|
||||||
float m_Speed;
|
float m_Speed;
|
||||||
glm::vec2 m_Size;
|
Vec2f m_Size;
|
||||||
std::uint16_t m_MoneyCost;
|
std::uint16_t m_MoneyCost;
|
||||||
std::uint16_t m_ExpCost;
|
std::uint16_t m_ExpCost;
|
||||||
std::uint16_t m_MaxLife;
|
std::uint16_t m_MaxLife;
|
||||||
std::uint16_t m_ExpReward;
|
std::uint16_t m_ExpReward;
|
||||||
public:
|
public:
|
||||||
MobStats(float damage, float speed, glm::vec2 size, std::uint16_t moneyCost,
|
MobStats(float damage, float speed, Vec2f size, std::uint16_t moneyCost,
|
||||||
std::uint16_t expCost, std::uint16_t expReward,
|
std::uint16_t expCost, std::uint16_t expReward,
|
||||||
std::uint16_t maxLife) : m_Damage(damage), m_Speed(speed),
|
std::uint16_t maxLife) : m_Damage(damage), m_Speed(speed),
|
||||||
m_Size(size), m_MoneyCost(moneyCost), m_ExpCost(expCost),
|
m_Size(size), m_MoneyCost(moneyCost), m_ExpCost(expCost),
|
||||||
m_MaxLife(maxLife), m_ExpReward(expReward) {
|
m_MaxLife(maxLife), m_ExpReward(expReward) {
|
||||||
}
|
}
|
||||||
|
|
||||||
float GetDamage() const { return m_Damage; }
|
float GetDamage() const { return m_Damage; }
|
||||||
float GetMovementSpeed() const { return m_Speed; }
|
float GetMovementSpeed() const { return m_Speed; }
|
||||||
const glm::vec2& GetSize() const { return m_Size; }
|
const Vec2f& GetSize() const { return m_Size; }
|
||||||
std::uint16_t GetMoneyCost() const { return m_MoneyCost; }
|
std::uint16_t GetMoneyCost() const { return m_MoneyCost; }
|
||||||
std::uint16_t GetExpCost() const { return m_ExpCost; }
|
std::uint16_t GetExpCost() const { return m_ExpCost; }
|
||||||
std::uint16_t GetExpReward() const { return m_ExpReward; }
|
std::uint16_t GetExpReward() const { return m_ExpReward; }
|
||||||
std::uint16_t GetMaxLife() const { return m_MaxLife; }
|
std::uint16_t GetMaxLife() const { return m_MaxLife; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EffectDuration {
|
struct EffectDuration {
|
||||||
EffectType type;
|
EffectType type;
|
||||||
float duration; // in seconds
|
float duration; // in seconds
|
||||||
Tower* tower; // the tower that gived the effect
|
Tower* tower; // the tower that gived the effect
|
||||||
};
|
};
|
||||||
|
|
||||||
const MobStats* GetMobStats(MobType type, std::uint8_t level);
|
const MobStats* GetMobStats(MobType type, std::uint8_t level);
|
||||||
@@ -82,149 +81,160 @@ const EffectImmunities& GetMobEffectImmunities(MobType type, std::uint8_t level)
|
|||||||
|
|
||||||
class Mob : public utils::shape::Rectangle {
|
class Mob : public utils::shape::Rectangle {
|
||||||
protected:
|
protected:
|
||||||
float m_Health;
|
float m_Health;
|
||||||
private:
|
private:
|
||||||
MobID m_ID;
|
MobID m_ID;
|
||||||
PlayerID m_Sender;
|
PlayerID m_Sender;
|
||||||
MobLevel m_Level;
|
MobLevel m_Level;
|
||||||
Direction m_Direction;
|
Direction m_Direction;
|
||||||
std::vector<EffectDuration> m_Effects;
|
std::vector<EffectDuration> m_Effects;
|
||||||
const Tower* m_LastDamage; // the last tower that damaged the mob
|
const Tower* m_LastDamage; // the last tower that damaged the mob
|
||||||
|
float m_HitCooldown;
|
||||||
|
|
||||||
utils::Timer m_EffectFireTimer;
|
utils::Timer m_EffectFireTimer;
|
||||||
utils::Timer m_EffectPoisonTimer;
|
utils::Timer m_EffectPoisonTimer;
|
||||||
utils::Timer m_EffectHealTimer;
|
utils::Timer m_EffectHealTimer;
|
||||||
|
|
||||||
TeamCastle* m_CastleTarget;
|
TeamCastle* m_CastleTarget;
|
||||||
utils::CooldownTimer m_AttackTimer;
|
utils::CooldownTimer m_AttackTimer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Mob(MobID id, MobLevel level, PlayerID sender) : m_Sender(sender), m_Level(level),
|
Mob(MobID id, MobLevel level, PlayerID sender) : m_Sender(sender), m_Level(level),
|
||||||
m_EffectFireTimer(1000), m_EffectPoisonTimer(1000),
|
m_HitCooldown(0), m_EffectFireTimer(1000), m_EffectPoisonTimer(1000),
|
||||||
m_EffectHealTimer(1000), m_CastleTarget(nullptr), m_AttackTimer(1000) {
|
m_EffectHealTimer(1000), m_CastleTarget(nullptr), m_AttackTimer(1000) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual MobType GetType() const = 0;
|
virtual MobType GetType() const = 0;
|
||||||
|
|
||||||
virtual void Tick(std::uint64_t delta, World* world);
|
virtual void Tick(std::uint64_t delta, World* world);
|
||||||
|
|
||||||
virtual bool OnDeath(World* world) { return true; }
|
virtual bool OnDeath(World* world) { return true; }
|
||||||
|
|
||||||
MobID GetMobID() const { return m_ID; }
|
MobID GetMobID() const { return m_ID; }
|
||||||
const TowerImmunities& GetTowerImmunities() const { return GetMobTowerImmunities(GetType(), m_Level); }
|
const TowerImmunities& GetTowerImmunities() const { return GetMobTowerImmunities(GetType(), m_Level); }
|
||||||
const EffectImmunities& GetEffectImmunities() const { return GetMobEffectImmunities(GetType(), m_Level); }
|
const EffectImmunities& GetEffectImmunities() const { return GetMobEffectImmunities(GetType(), m_Level); }
|
||||||
PlayerID GetSender() const { return m_Sender; }
|
PlayerID GetSender() const { return m_Sender; }
|
||||||
MobLevel GetLevel() const { return m_Level; }
|
MobLevel GetLevel() const { return m_Level; }
|
||||||
const MobStats* GetStats() const { return GetMobStats(GetType(), m_Level); }
|
const MobStats* GetStats() const { return GetMobStats(GetType(), m_Level); }
|
||||||
void SetHealth(float newHealth) { m_Health = newHealth; }
|
void SetHealth(float newHealth) { m_Health = newHealth; }
|
||||||
float GetHealth() const { return m_Health; }
|
float GetHealth() const { return m_Health; }
|
||||||
bool IsDead() const { return m_Health <= 0; }
|
bool IsDead() const { return m_Health <= 0; }
|
||||||
bool IsAlive() const { return m_Health > 0; }
|
bool IsAlive() const { return m_Health > 0; }
|
||||||
const Tower* GetLastDamageTower() { return m_LastDamage; }
|
const Tower* GetLastDamageTower() { return m_LastDamage; }
|
||||||
bool HasReachedEnemyCastle() { return m_CastleTarget != nullptr; }
|
bool HasReachedEnemyCastle() { return m_CastleTarget != nullptr; }
|
||||||
|
|
||||||
void Damage(float dmg, const Tower* damager) { m_Health = std::max(0.0f, m_Health - dmg); m_LastDamage = damager; }
|
void Damage(float dmg, const Tower* damager) {
|
||||||
void Heal(float heal) { m_Health = std::min(static_cast<float>(GetStats()->GetMaxLife()), m_Health + heal); }
|
m_Health = std::max(0.0f, m_Health - dmg);
|
||||||
void SetMobReachedCastle(TeamCastle* castle) { m_CastleTarget = castle; } // used when mob is in front of the castle
|
m_LastDamage = damager;
|
||||||
|
m_HitCooldown = 0.1;
|
||||||
|
}
|
||||||
|
|
||||||
bool IsImmuneTo(TowerType type);
|
void Heal(float heal) {
|
||||||
|
m_Health = std::min(static_cast<float>(GetStats()->GetMaxLife()), m_Health + heal);
|
||||||
|
}
|
||||||
|
|
||||||
bool IsImmuneTo(EffectType type);
|
void SetMobReachedCastle(TeamCastle* castle) { m_CastleTarget = castle; } // used when mob is in front of the castle
|
||||||
void AddEffect(EffectType type, float durationSec, Tower* tower);
|
|
||||||
bool HasEffect(EffectType type);
|
|
||||||
|
|
||||||
float GetTileX() { return GetCenterX() - static_cast<float>(static_cast<std::int32_t>(GetCenterX())); } // returns a float between 0 and 1 excluded
|
bool IsImmuneTo(TowerType type);
|
||||||
float GetTileY() { return GetCenterY() - static_cast<float>(static_cast<std::int32_t>(GetCenterY())); } // returns a float between 0 and 1 excluded
|
|
||||||
|
|
||||||
Direction GetDirection() const { return m_Direction; }
|
bool IsImmuneTo(EffectType type);
|
||||||
void SetDirection(Direction dir) { m_Direction = dir; }
|
void AddEffect(EffectType type, float durationSec, Tower* tower);
|
||||||
|
bool HasEffect(EffectType type);
|
||||||
|
|
||||||
|
bool HasTakenDamage() { return m_HitCooldown > 0; }
|
||||||
|
|
||||||
|
float GetTileX() { return GetCenterX() - static_cast<float>(static_cast<std::int32_t>(GetCenterX())); } // returns a float between 0 and 1 excluded
|
||||||
|
float GetTileY() { return GetCenterY() - static_cast<float>(static_cast<std::int32_t>(GetCenterY())); } // returns a float between 0 and 1 excluded
|
||||||
|
|
||||||
|
Direction GetDirection() const { return m_Direction; }
|
||||||
|
void SetDirection(Direction dir) { m_Direction = dir; }
|
||||||
protected:
|
protected:
|
||||||
void InitMob() {
|
void InitMob() {
|
||||||
m_Health = static_cast<float>(GetStats()->GetMaxLife());
|
m_Health = static_cast<float>(GetStats()->GetMaxLife());
|
||||||
SetSize(GetStats()->GetSize().x, GetStats()->GetSize().y);
|
SetSize(GetStats()->GetSize().x, GetStats()->GetSize().y);
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
void UpdateEffects(std::uint64_t delta, World* world);
|
void UpdateEffects(std::uint64_t delta, World* world);
|
||||||
void AttackCastle(std::uint64_t delta, World* world);
|
void AttackCastle(std::uint64_t delta, World* world);
|
||||||
void Move(std::uint64_t delta, World* world);
|
void Move(std::uint64_t delta, World* world);
|
||||||
void Walk(std::uint64_t delta, World* world);
|
void Walk(std::uint64_t delta, World* world);
|
||||||
void MoveBack(const TeamCastle& castle, World* world);
|
void MoveBack(const TeamCastle& castle, World* world);
|
||||||
void ChangeDirection(const WalkableTile& tile, World* world);
|
void ChangeDirection(const WalkableTile& tile, World* world);
|
||||||
bool IsTouchingCastle(const TeamCastle& castle) const;
|
bool IsTouchingCastle(const TeamCastle& castle) const;
|
||||||
EffectDuration& GetEffect(EffectType type);
|
EffectDuration& GetEffect(EffectType type);
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr<Mob> MobPtr;
|
typedef std::shared_ptr<Mob> MobPtr;
|
||||||
|
|
||||||
class Zombie : public Mob {
|
class Zombie : public Mob {
|
||||||
public:
|
public:
|
||||||
Zombie(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); }
|
Zombie(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); }
|
||||||
|
|
||||||
virtual MobType GetType() const { return MobType::Zombie; }
|
virtual MobType GetType() const { return MobType::Zombie; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class Spider : public Mob {
|
class Spider : public Mob {
|
||||||
public:
|
public:
|
||||||
Spider(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); }
|
Spider(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); }
|
||||||
|
|
||||||
virtual MobType GetType() const { return MobType::Spider; }
|
virtual MobType GetType() const { return MobType::Spider; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class Skeleton : public Mob {
|
class Skeleton : public Mob {
|
||||||
public:
|
public:
|
||||||
Skeleton(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); }
|
Skeleton(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); }
|
||||||
|
|
||||||
virtual MobType GetType() const { return MobType::Skeleton; }
|
virtual MobType GetType() const { return MobType::Skeleton; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class PigMan : public Mob {
|
class PigMan : public Mob {
|
||||||
public:
|
public:
|
||||||
PigMan(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); }
|
PigMan(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); }
|
||||||
|
|
||||||
virtual MobType GetType() const { return MobType::Pigman; }
|
virtual MobType GetType() const { return MobType::Pigman; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class Creeper : public Mob {
|
class Creeper : public Mob {
|
||||||
public:
|
public:
|
||||||
Creeper(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); }
|
Creeper(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); }
|
||||||
|
|
||||||
virtual MobType GetType() const { return MobType::Creeper; }
|
virtual MobType GetType() const { return MobType::Creeper; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class Silverfish : public Mob {
|
class Silverfish : public Mob {
|
||||||
public:
|
public:
|
||||||
Silverfish(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); }
|
Silverfish(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); }
|
||||||
|
|
||||||
virtual MobType GetType() const { return MobType::Silverfish; }
|
virtual MobType GetType() const { return MobType::Silverfish; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class Blaze : public Mob {
|
class Blaze : public Mob {
|
||||||
public:
|
public:
|
||||||
Blaze(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); }
|
Blaze(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); }
|
||||||
|
|
||||||
virtual MobType GetType() const { return MobType::Blaze; }
|
virtual MobType GetType() const { return MobType::Blaze; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class Witch : public Mob {
|
class Witch : public Mob {
|
||||||
public:
|
public:
|
||||||
Witch(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); }
|
Witch(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); }
|
||||||
|
|
||||||
virtual MobType GetType() const { return MobType::Witch; }
|
virtual MobType GetType() const { return MobType::Witch; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class Slime : public Mob {
|
class Slime : public Mob {
|
||||||
public:
|
public:
|
||||||
Slime(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); }
|
Slime(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); }
|
||||||
|
|
||||||
virtual MobType GetType() const { return MobType::Slime; }
|
virtual MobType GetType() const { return MobType::Slime; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class Giant : public Mob {
|
class Giant : public Mob {
|
||||||
public:
|
public:
|
||||||
Giant(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); }
|
Giant(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); }
|
||||||
|
|
||||||
virtual MobType GetType() const { return MobType::Giant; }
|
virtual MobType GetType() const { return MobType::Giant; }
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace MobFactory {
|
namespace MobFactory {
|
||||||
@@ -236,13 +246,13 @@ std::string GetMobName(MobType type);
|
|||||||
|
|
||||||
class MobListener {
|
class MobListener {
|
||||||
public:
|
public:
|
||||||
virtual void OnMobSpawn(Mob* mob) {}
|
virtual void OnMobSpawn(Mob* mob) {}
|
||||||
virtual void OnMobDie(Mob* mob) {}
|
virtual void OnMobDie(Mob* mob) {}
|
||||||
|
|
||||||
virtual void OnMobDamage(Mob* target, float damage, Tower* damager) {}
|
virtual void OnMobDamage(Mob* target, float damage, Tower* damager) {}
|
||||||
|
|
||||||
virtual void OnMobTouchCastle(Mob* damager, TeamCastle* enemyCastle) {}
|
virtual void OnMobTouchCastle(Mob* damager, TeamCastle* enemyCastle) {}
|
||||||
virtual void OnMobCastleDamage(Mob* damager, TeamCastle* enemyCastle, float damage) {}
|
virtual void OnMobCastleDamage(Mob* damager, TeamCastle* enemyCastle, float damage) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef utils::ObjectNotifier<MobListener> MobNotifier;
|
typedef utils::ObjectNotifier<MobListener> MobNotifier;
|
||||||
|
|||||||
@@ -10,41 +10,41 @@ namespace game {
|
|||||||
|
|
||||||
class Player {
|
class Player {
|
||||||
private:
|
private:
|
||||||
TeamColor m_TeamColor;
|
TeamColor m_TeamColor;
|
||||||
PlayerUpgrades m_Upgrades;
|
PlayerUpgrades m_Upgrades;
|
||||||
|
|
||||||
std::uint32_t m_Gold;
|
std::uint32_t m_Gold;
|
||||||
std::uint32_t m_Exp;
|
std::uint32_t m_Exp;
|
||||||
std::string m_Name;
|
std::string m_Name;
|
||||||
PlayerID m_ID;
|
PlayerID m_ID;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Player(std::uint8_t id = 0) : m_TeamColor(TeamColor::None), m_Gold(0), m_Exp(0), m_ID(id) {}
|
Player(std::uint8_t id = 0) : m_TeamColor(TeamColor::None), m_Gold(0), m_Exp(0), m_ID(id) {}
|
||||||
|
|
||||||
const std::string& GetName() const { return m_Name; }
|
const std::string& GetName() const { return m_Name; }
|
||||||
void SetName(const std::string& name) { m_Name = name; }
|
void SetName(const std::string& name) { m_Name = name; }
|
||||||
|
|
||||||
TeamColor GetTeamColor() const { return m_TeamColor; }
|
TeamColor GetTeamColor() const { return m_TeamColor; }
|
||||||
void SetTeamColor(TeamColor teamColor) { m_TeamColor = teamColor; }
|
void SetTeamColor(TeamColor teamColor) { m_TeamColor = teamColor; }
|
||||||
|
|
||||||
std::uint32_t GetGold() const { return m_Gold; }
|
std::uint32_t GetGold() const { return m_Gold; }
|
||||||
void SetGold(std::uint32_t gold) { m_Gold = gold; }
|
void SetGold(std::uint32_t gold) { m_Gold = gold; }
|
||||||
void AddGold(std::uint32_t gold) { m_Gold += gold; }
|
void AddGold(std::uint32_t gold) { m_Gold += gold; }
|
||||||
void RemoveGold(std::uint32_t gold) { m_Gold -= gold; }
|
void RemoveGold(std::uint32_t gold) { m_Gold -= gold; }
|
||||||
|
|
||||||
std::uint32_t GetExp() const { return m_Exp; }
|
std::uint32_t GetExp() const { return m_Exp; }
|
||||||
void SetExp(std::uint32_t exp) { m_Exp = exp; }
|
void SetExp(std::uint32_t exp) { m_Exp = exp; }
|
||||||
void AddExp(std::uint32_t exp) { m_Exp += exp; }
|
void AddExp(std::uint32_t exp) { m_Exp += exp; }
|
||||||
void RemoveExp(std::uint32_t exp) { m_Exp -= exp; }
|
void RemoveExp(std::uint32_t exp) { m_Exp -= exp; }
|
||||||
|
|
||||||
const PlayerUpgrades& getUpgrades() const { return m_Upgrades; }
|
const PlayerUpgrades& getUpgrades() const { return m_Upgrades; }
|
||||||
PlayerUpgrades& getUpgrades() { return m_Upgrades; }
|
PlayerUpgrades& getUpgrades() { return m_Upgrades; }
|
||||||
|
|
||||||
bool HasEnoughGold(std::uint32_t gold) const { return m_Gold >= gold; }
|
bool HasEnoughGold(std::uint32_t gold) const { return m_Gold >= gold; }
|
||||||
bool HasEnoughExp(std::uint32_t exp) const { return m_Exp >= exp; }
|
bool HasEnoughExp(std::uint32_t exp) const { return m_Exp >= exp; }
|
||||||
|
|
||||||
PlayerID GetID() const { return m_ID; }
|
PlayerID GetID() const { return m_ID; }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace game
|
} // namespace game
|
||||||
|
|||||||
@@ -7,27 +7,27 @@ namespace game {
|
|||||||
|
|
||||||
class PlayerUpgrades {
|
class PlayerUpgrades {
|
||||||
private:
|
private:
|
||||||
std::uint8_t m_ClickerLevel;
|
std::uint8_t m_ClickerLevel;
|
||||||
std::uint8_t m_GoldPerSecond;
|
std::uint8_t m_GoldPerSecond;
|
||||||
std::array<std::uint8_t, static_cast<std::size_t>(MobType::MOB_COUNT)> m_MobsUpgradeLevel;
|
std::array<std::uint8_t, static_cast<std::size_t>(MobType::MOB_COUNT)> m_MobsUpgradeLevel;
|
||||||
public:
|
public:
|
||||||
static const int MAX_MOB_LEVEL = 5;
|
static const int MAX_MOB_LEVEL = 5;
|
||||||
static const int MAX_CLICKER_LEVEL = 3;
|
static const int MAX_CLICKER_LEVEL = 3;
|
||||||
|
|
||||||
PlayerUpgrades() : m_ClickerLevel(1), m_GoldPerSecond(5) {}
|
PlayerUpgrades() : m_ClickerLevel(1), m_GoldPerSecond(5) {}
|
||||||
|
|
||||||
std::uint8_t GetClickerLevel() const { return m_ClickerLevel; }
|
std::uint8_t GetClickerLevel() const { return m_ClickerLevel; }
|
||||||
std::uint8_t GetMobUpgradeLevel(MobType mob) const { return m_MobsUpgradeLevel.at(static_cast<std::size_t>(mob)); }
|
std::uint8_t GetMobUpgradeLevel(MobType mob) const { return m_MobsUpgradeLevel.at(static_cast<std::size_t>(mob)); }
|
||||||
std::uint8_t GetGoldPerSecond() const { return m_GoldPerSecond; }
|
std::uint8_t GetGoldPerSecond() const { return m_GoldPerSecond; }
|
||||||
|
|
||||||
|
|
||||||
void UpgradeMob(MobType mob) {
|
void UpgradeMob(MobType mob) {
|
||||||
std::uint8_t& mobLevel = m_MobsUpgradeLevel.at(static_cast<std::size_t>(mob));
|
std::uint8_t& mobLevel = m_MobsUpgradeLevel.at(static_cast<std::size_t>(mob));
|
||||||
mobLevel = std::min(mobLevel + 1, MAX_MOB_LEVEL);
|
mobLevel = std::min(mobLevel + 1, MAX_MOB_LEVEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpgradeClicker() { m_ClickerLevel = std::min(m_ClickerLevel + 1, MAX_CLICKER_LEVEL); }
|
void UpgradeClicker() { m_ClickerLevel = std::min(m_ClickerLevel + 1, MAX_CLICKER_LEVEL); }
|
||||||
void SetGoldPerSecond(std::uint8_t goldPerSecond) { m_GoldPerSecond = goldPerSecond; }
|
void SetGoldPerSecond(std::uint8_t goldPerSecond) { m_GoldPerSecond = goldPerSecond; }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace game
|
} // namespace game
|
||||||
|
|||||||
@@ -14,76 +14,76 @@ namespace game {
|
|||||||
class Player;
|
class Player;
|
||||||
|
|
||||||
enum class TeamColor : std::int8_t {
|
enum class TeamColor : std::int8_t {
|
||||||
None = -1,
|
None = -1,
|
||||||
Red,
|
Red,
|
||||||
Blue
|
Blue
|
||||||
};
|
};
|
||||||
|
|
||||||
class Spawn : public utils::shape::Rectangle {
|
class Spawn : public utils::shape::Rectangle {
|
||||||
private:
|
private:
|
||||||
Direction m_Direction;
|
Direction m_Direction;
|
||||||
public:
|
public:
|
||||||
Spawn() {
|
Spawn() {
|
||||||
SetWidth(5);
|
SetWidth(5);
|
||||||
SetHeight(5);
|
SetHeight(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
Direction GetDirection() const { return m_Direction; }
|
Direction GetDirection() const { return m_Direction; }
|
||||||
|
|
||||||
void SetDirection(Direction direction) { m_Direction = direction; }
|
void SetDirection(Direction direction) { m_Direction = direction; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class Team;
|
class Team;
|
||||||
|
|
||||||
class TeamCastle : public utils::shape::Rectangle {
|
class TeamCastle : public utils::shape::Rectangle {
|
||||||
private:
|
private:
|
||||||
const Team* m_Team;
|
const Team* m_Team;
|
||||||
float m_Life;
|
float m_Life;
|
||||||
public:
|
public:
|
||||||
static constexpr int CastleMaxLife = 1000;
|
static constexpr int CastleMaxLife = 1000;
|
||||||
|
|
||||||
TeamCastle(const Team* team) : m_Team(team), m_Life(CastleMaxLife) {
|
TeamCastle(const Team* team) : m_Team(team), m_Life(CastleMaxLife) {
|
||||||
SetWidth(5);
|
SetWidth(5);
|
||||||
SetHeight(5);
|
SetHeight(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
TeamCastle() : TeamCastle(nullptr) {}
|
TeamCastle() : TeamCastle(nullptr) {}
|
||||||
|
|
||||||
float GetLife() const { return m_Life; }
|
float GetLife() const { return m_Life; }
|
||||||
|
|
||||||
const Team* GetTeam() const { return m_Team; }
|
const Team* GetTeam() const { return m_Team; }
|
||||||
void SetTeam(const Team* team) { m_Team = team; }
|
void SetTeam(const Team* team) { m_Team = team; }
|
||||||
|
|
||||||
void SetLife(float life) { m_Life = life; }
|
void SetLife(float life) { m_Life = life; }
|
||||||
void Damage(float damage) { m_Life = std::max(0.0f, m_Life - damage); }
|
void Damage(float damage) { m_Life = std::max(0.0f, m_Life - damage); }
|
||||||
|
|
||||||
void SetShape(utils::shape::Rectangle rect) {
|
void SetShape(utils::shape::Rectangle rect) {
|
||||||
SetCenter(rect.GetCenter());
|
SetCenter(rect.GetCenter());
|
||||||
SetSize(rect.GetSize());
|
SetSize(rect.GetSize());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Team {
|
class Team {
|
||||||
private:
|
private:
|
||||||
std::vector<Player*> m_Players;
|
std::vector<Player*> m_Players;
|
||||||
TeamColor m_Color;
|
TeamColor m_Color;
|
||||||
Spawn m_Spawn;
|
Spawn m_Spawn;
|
||||||
TeamCastle m_TeamCastle;
|
TeamCastle m_TeamCastle;
|
||||||
public:
|
public:
|
||||||
Team(TeamColor color);
|
Team(TeamColor color);
|
||||||
|
|
||||||
void AddPlayer(Player* newPlayer);
|
void AddPlayer(Player* newPlayer);
|
||||||
void RemovePlayer(const Player* player);
|
void RemovePlayer(const Player* player);
|
||||||
|
|
||||||
TeamColor GetColor() const;
|
TeamColor GetColor() const;
|
||||||
|
|
||||||
const Spawn& GetSpawn() const { return m_Spawn; }
|
const Spawn& GetSpawn() const { return m_Spawn; }
|
||||||
Spawn& GetSpawn() { return m_Spawn; }
|
Spawn& GetSpawn() { return m_Spawn; }
|
||||||
|
|
||||||
const TeamCastle& GetCastle() const { return m_TeamCastle; }
|
const TeamCastle& GetCastle() const { return m_TeamCastle; }
|
||||||
TeamCastle& GetCastle() { return m_TeamCastle; }
|
TeamCastle& GetCastle() { return m_TeamCastle; }
|
||||||
|
|
||||||
std::uint8_t GetPlayerCount() const;
|
std::uint8_t GetPlayerCount() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::array<Team, 2> TeamList;
|
typedef std::array<Team, 2> TeamList;
|
||||||
|
|||||||
@@ -17,69 +17,69 @@ class Mob;
|
|||||||
typedef std::shared_ptr<Mob> MobPtr;
|
typedef std::shared_ptr<Mob> MobPtr;
|
||||||
|
|
||||||
enum class TowerType : std::uint8_t {
|
enum class TowerType : std::uint8_t {
|
||||||
Archer = 0,
|
Archer = 0,
|
||||||
Ice,
|
Ice,
|
||||||
Sorcerer,
|
Sorcerer,
|
||||||
Zeus,
|
Zeus,
|
||||||
Mage,
|
Mage,
|
||||||
Artillery,
|
Artillery,
|
||||||
Quake,
|
Quake,
|
||||||
Poison,
|
Poison,
|
||||||
|
|
||||||
Leach,
|
Leach,
|
||||||
Turret,
|
Turret,
|
||||||
Necromancer,
|
Necromancer,
|
||||||
|
|
||||||
TowerCount
|
TowerCount
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class TowerSize : std::uint8_t {
|
enum class TowerSize : std::uint8_t {
|
||||||
Little = 3, // 3x3
|
Little = 3, // 3x3
|
||||||
Big = 5, // 5x5
|
Big = 5, // 5x5
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class TowerPath : std::uint8_t {
|
enum class TowerPath : std::uint8_t {
|
||||||
Top = 0,
|
Top = 0,
|
||||||
Base, // Base Path
|
Base, // Base Path
|
||||||
Bottom
|
Bottom
|
||||||
};
|
};
|
||||||
|
|
||||||
class TowerStats {
|
class TowerStats {
|
||||||
private:
|
private:
|
||||||
float m_Rate;
|
float m_Rate;
|
||||||
float m_Damage;
|
float m_Damage;
|
||||||
std::uint8_t m_Range;
|
std::uint8_t m_Range;
|
||||||
public:
|
public:
|
||||||
TowerStats(float rate, float damage, std::uint8_t range) : m_Rate(rate), m_Damage(damage),
|
TowerStats(float rate, float damage, std::uint8_t range) : m_Rate(rate), m_Damage(damage),
|
||||||
m_Range(range) {
|
m_Range(range) {
|
||||||
}
|
}
|
||||||
|
|
||||||
float GetDamageRate() const { return m_Rate; }
|
float GetDamageRate() const { return m_Rate; }
|
||||||
float GetDamage() const { return m_Damage; }
|
float GetDamage() const { return m_Damage; }
|
||||||
std::uint8_t GetRange() const { return m_Range; }
|
std::uint8_t GetRange() const { return m_Range; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class TowerLevel {
|
class TowerLevel {
|
||||||
private:
|
private:
|
||||||
// 1, 2, 3, 4
|
// 1, 2, 3, 4
|
||||||
std::uint8_t m_Level : 3;
|
std::uint8_t m_Level : 3;
|
||||||
// 0 : base path 1 : top path (if there is bottom path) 2 : bottom path (if there is top path)
|
// 0 : base path 1 : top path (if there is bottom path) 2 : bottom path (if there is top path)
|
||||||
TowerPath m_Path : 2;
|
TowerPath m_Path : 2;
|
||||||
public:
|
public:
|
||||||
TowerLevel() : m_Level(1), m_Path(TowerPath::Base) {}
|
TowerLevel() : m_Level(1), m_Path(TowerPath::Base) {}
|
||||||
TowerLevel(std::uint8_t level, TowerPath path) : m_Level(level), m_Path(path) {}
|
TowerLevel(std::uint8_t level, TowerPath path) : m_Level(level), m_Path(path) {}
|
||||||
|
|
||||||
std::uint8_t GetLevel() const { return m_Level; }
|
std::uint8_t GetLevel() const { return m_Level; }
|
||||||
TowerPath GetPath() const { return m_Path; }
|
TowerPath GetPath() const { return m_Path; }
|
||||||
|
|
||||||
void SetLevel(std::uint8_t level) { m_Level = level; }
|
void SetLevel(std::uint8_t level) { m_Level = level; }
|
||||||
void SetPath(TowerPath path) { m_Path = path; }
|
void SetPath(TowerPath path) { m_Path = path; }
|
||||||
|
|
||||||
// operator to sort maps
|
// operator to sort maps
|
||||||
friend bool operator<(const TowerLevel& level, const TowerLevel& other) {
|
friend bool operator<(const TowerLevel& level, const TowerLevel& other) {
|
||||||
return level.GetLevel() + static_cast<std::uint8_t>(level.GetPath()) * 4 <
|
return level.GetLevel() + static_cast<std::uint8_t>(level.GetPath()) * 4 <
|
||||||
other.GetLevel() + static_cast<std::uint8_t>(other.GetPath()) * 4;
|
other.GetLevel() + static_cast<std::uint8_t>(other.GetPath()) * 4;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const TowerStats* GetTowerStats(TowerType type, TowerLevel level);
|
const TowerStats* GetTowerStats(TowerType type, TowerLevel level);
|
||||||
@@ -88,36 +88,36 @@ typedef std::uint16_t TowerID;
|
|||||||
|
|
||||||
class Tower : public utils::shape::Circle {
|
class Tower : public utils::shape::Circle {
|
||||||
private:
|
private:
|
||||||
TowerID m_ID;
|
TowerID m_ID;
|
||||||
TowerType m_Type;
|
TowerType m_Type;
|
||||||
TowerLevel m_Level{};
|
TowerLevel m_Level{};
|
||||||
PlayerID m_Builder;
|
PlayerID m_Builder;
|
||||||
protected:
|
protected:
|
||||||
utils::CooldownTimer m_Timer;
|
utils::CooldownTimer m_Timer;
|
||||||
public:
|
public:
|
||||||
Tower(TowerID id, TowerType type, std::int32_t x, std::int32_t y, PlayerID builder) : utils::shape::Circle(x + 0.5f, y + 0.5f, 0), m_ID(id), m_Type(type), m_Builder(builder),
|
Tower(TowerID id, TowerType type, std::int32_t x, std::int32_t y, PlayerID builder) : utils::shape::Circle(x + 0.5f, y + 0.5f, 0), m_ID(id), m_Type(type), m_Builder(builder),
|
||||||
m_Timer(GetStats()->GetDamageRate() * 1000) { // converting seconds to millis
|
m_Timer(GetStats()->GetDamageRate() * 1000) { // converting seconds to millis
|
||||||
SetRadius(GetStats()->GetRange());
|
SetRadius(GetStats()->GetRange());
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual TowerType GetType() const = 0;
|
virtual TowerType GetType() const = 0;
|
||||||
virtual TowerSize GetSize() const = 0;
|
virtual TowerSize GetSize() const = 0;
|
||||||
virtual void Tick(std::uint64_t delta, World* world) = 0;
|
virtual void Tick(std::uint64_t delta, World* world) = 0;
|
||||||
|
|
||||||
void Upgrade(std::uint8_t level, TowerPath path) {
|
void Upgrade(std::uint8_t level, TowerPath path) {
|
||||||
m_Level.SetLevel(level);
|
m_Level.SetLevel(level);
|
||||||
m_Level.SetPath(path);
|
m_Level.SetPath(path);
|
||||||
m_Timer.SetCooldown(GetStats()->GetDamageRate() * 1000); // converting seconds to millis
|
m_Timer.SetCooldown(GetStats()->GetDamageRate() * 1000); // converting seconds to millis
|
||||||
m_Timer.Reset();
|
m_Timer.Reset();
|
||||||
SetRadius(GetStats()->GetRange());
|
SetRadius(GetStats()->GetRange());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::uint16_t GetID() const { return m_ID; }
|
std::uint16_t GetID() const { return m_ID; }
|
||||||
const TowerLevel& GetLevel() const { return m_Level; }
|
const TowerLevel& GetLevel() const { return m_Level; }
|
||||||
const TowerStats* GetStats() const { return GetTowerStats(m_Type, m_Level); }
|
const TowerStats* GetStats() const { return GetTowerStats(m_Type, m_Level); }
|
||||||
PlayerID GetBuilder() const { return m_Builder; }
|
PlayerID GetBuilder() const { return m_Builder; }
|
||||||
|
|
||||||
bool IsMobInRange(MobPtr mob);
|
bool IsMobInRange(MobPtr mob);
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr<Tower> TowerPtr;
|
typedef std::shared_ptr<Tower> TowerPtr;
|
||||||
@@ -132,16 +132,17 @@ std::string GetTowerName(TowerType type);
|
|||||||
|
|
||||||
class TowerInfo {
|
class TowerInfo {
|
||||||
private:
|
private:
|
||||||
std::string m_Name, m_Description;
|
std::string m_Name, m_Description;
|
||||||
bool m_IsBigTower;
|
bool m_IsBigTower;
|
||||||
public:
|
public:
|
||||||
TowerInfo(std::string&& name, std::string&& description, bool big) : m_Name(std::move(name)),
|
TowerInfo(std::string&& name, std::string&& description, bool big) : m_Name(std::move(name)),
|
||||||
m_Description(std::move(description)), m_IsBigTower(big) {}
|
m_Description(std::move(description)), m_IsBigTower(big) {
|
||||||
|
}
|
||||||
|
|
||||||
const std::string& GetName() const { return m_Name; }
|
const std::string& GetName() const { return m_Name; }
|
||||||
const std::string& GetDescription() const { return m_Description; }
|
const std::string& GetDescription() const { return m_Description; }
|
||||||
|
|
||||||
bool IsBigTower() const { return m_IsBigTower; }
|
bool IsBigTower() const { return m_IsBigTower; }
|
||||||
};
|
};
|
||||||
|
|
||||||
const TowerInfo& GetTowerInfo(TowerType type);
|
const TowerInfo& GetTowerInfo(TowerType type);
|
||||||
@@ -150,115 +151,115 @@ const TowerInfo& GetTowerInfo(TowerType type);
|
|||||||
|
|
||||||
class LittleTower : public Tower {
|
class LittleTower : public Tower {
|
||||||
public:
|
public:
|
||||||
LittleTower(TowerID id, TowerType type, std::uint16_t x, std::uint16_t y, PlayerID builder) : Tower(id, type, x, y, builder) {}
|
LittleTower(TowerID id, TowerType type, std::uint16_t x, std::uint16_t y, PlayerID builder) : Tower(id, type, x, y, builder) {}
|
||||||
|
|
||||||
virtual TowerSize GetSize() const { return TowerSize::Little; }
|
virtual TowerSize GetSize() const { return TowerSize::Little; }
|
||||||
|
|
||||||
virtual TowerType GetType() const = 0;
|
virtual TowerType GetType() const = 0;
|
||||||
virtual void Tick(std::uint64_t delta, World* world) = 0;
|
virtual void Tick(std::uint64_t delta, World* world) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ArcherTower : public LittleTower {
|
class ArcherTower : public LittleTower {
|
||||||
public:
|
public:
|
||||||
ArcherTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {}
|
ArcherTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {}
|
||||||
|
|
||||||
constexpr static float ExplosionRadius = 1.5f;
|
constexpr static float ExplosionRadius = 1.5f;
|
||||||
constexpr static float FireDurationSec = 10.0f;
|
constexpr static float FireDurationSec = 10.0f;
|
||||||
|
|
||||||
virtual TowerType GetType() const { return TowerType::Archer; }
|
virtual TowerType GetType() const { return TowerType::Archer; }
|
||||||
virtual void Tick(std::uint64_t delta, World* world);
|
virtual void Tick(std::uint64_t delta, World* world);
|
||||||
};
|
};
|
||||||
|
|
||||||
class IceTower : public LittleTower {
|
class IceTower : public LittleTower {
|
||||||
public:
|
public:
|
||||||
IceTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {}
|
IceTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {}
|
||||||
|
|
||||||
virtual TowerType GetType() const { return TowerType::Ice; }
|
virtual TowerType GetType() const { return TowerType::Ice; }
|
||||||
virtual void Tick(std::uint64_t delta, World* world);
|
virtual void Tick(std::uint64_t delta, World* world);
|
||||||
};
|
};
|
||||||
|
|
||||||
class MageTower : public LittleTower {
|
class MageTower : public LittleTower {
|
||||||
public:
|
public:
|
||||||
MageTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {}
|
MageTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {}
|
||||||
|
|
||||||
virtual TowerType GetType() const { return TowerType::Mage; }
|
virtual TowerType GetType() const { return TowerType::Mage; }
|
||||||
virtual void Tick(std::uint64_t delta, World* world);
|
virtual void Tick(std::uint64_t delta, World* world);
|
||||||
};
|
};
|
||||||
|
|
||||||
class PoisonTower : public LittleTower {
|
class PoisonTower : public LittleTower {
|
||||||
public:
|
public:
|
||||||
PoisonTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {}
|
PoisonTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {}
|
||||||
|
|
||||||
virtual TowerType GetType() const { return TowerType::Poison; }
|
virtual TowerType GetType() const { return TowerType::Poison; }
|
||||||
virtual void Tick(std::uint64_t delta, World* world);
|
virtual void Tick(std::uint64_t delta, World* world);
|
||||||
};
|
};
|
||||||
|
|
||||||
class QuakeTower : public LittleTower {
|
class QuakeTower : public LittleTower {
|
||||||
public:
|
public:
|
||||||
QuakeTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {}
|
QuakeTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {}
|
||||||
|
|
||||||
virtual TowerType GetType() const { return TowerType::Quake; }
|
virtual TowerType GetType() const { return TowerType::Quake; }
|
||||||
virtual void Tick(std::uint64_t delta, World* world);
|
virtual void Tick(std::uint64_t delta, World* world);
|
||||||
};
|
};
|
||||||
|
|
||||||
class ArtilleryTower : public LittleTower {
|
class ArtilleryTower : public LittleTower {
|
||||||
public:
|
public:
|
||||||
ArtilleryTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {}
|
ArtilleryTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {}
|
||||||
|
|
||||||
virtual TowerType GetType() const { return TowerType::Artillery; }
|
virtual TowerType GetType() const { return TowerType::Artillery; }
|
||||||
virtual void Tick(std::uint64_t delta, World* world);
|
virtual void Tick(std::uint64_t delta, World* world);
|
||||||
};
|
};
|
||||||
|
|
||||||
class SorcererTower : public LittleTower {
|
class SorcererTower : public LittleTower {
|
||||||
public:
|
public:
|
||||||
SorcererTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {}
|
SorcererTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {}
|
||||||
|
|
||||||
virtual TowerType GetType() const { return TowerType::Sorcerer; }
|
virtual TowerType GetType() const { return TowerType::Sorcerer; }
|
||||||
virtual void Tick(std::uint64_t delta, World* world);
|
virtual void Tick(std::uint64_t delta, World* world);
|
||||||
};
|
};
|
||||||
|
|
||||||
class ZeusTower : public LittleTower {
|
class ZeusTower : public LittleTower {
|
||||||
public:
|
public:
|
||||||
ZeusTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {}
|
ZeusTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, GetType(), x, y, builder) {}
|
||||||
|
|
||||||
virtual TowerType GetType() const { return TowerType::Zeus; }
|
virtual TowerType GetType() const { return TowerType::Zeus; }
|
||||||
virtual void Tick(std::uint64_t delta, World* world);
|
virtual void Tick(std::uint64_t delta, World* world);
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---------- Big Towers ----------
|
// ---------- Big Towers ----------
|
||||||
|
|
||||||
class BigTower : public Tower {
|
class BigTower : public Tower {
|
||||||
public:
|
public:
|
||||||
BigTower(TowerID id, TowerType type, std::uint16_t x, std::uint16_t y, PlayerID builder) : Tower(id, type, x, y, builder) {}
|
BigTower(TowerID id, TowerType type, std::uint16_t x, std::uint16_t y, PlayerID builder) : Tower(id, type, x, y, builder) {}
|
||||||
|
|
||||||
virtual TowerSize GetSize() const { return TowerSize::Big; }
|
virtual TowerSize GetSize() const { return TowerSize::Big; }
|
||||||
|
|
||||||
virtual TowerType GetType() const = 0;
|
virtual TowerType GetType() const = 0;
|
||||||
virtual void Tick(std::uint64_t delta, World* world) = 0;
|
virtual void Tick(std::uint64_t delta, World* world) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TurretTower : public BigTower {
|
class TurretTower : public BigTower {
|
||||||
public:
|
public:
|
||||||
TurretTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : BigTower(id, GetType(), x, y, builder) {}
|
TurretTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : BigTower(id, GetType(), x, y, builder) {}
|
||||||
|
|
||||||
virtual TowerType GetType() const { return TowerType::Turret; }
|
virtual TowerType GetType() const { return TowerType::Turret; }
|
||||||
virtual void Tick(std::uint64_t delta, World* world);
|
virtual void Tick(std::uint64_t delta, World* world);
|
||||||
};
|
};
|
||||||
|
|
||||||
class NecromancerTower : public BigTower {
|
class NecromancerTower : public BigTower {
|
||||||
public:
|
public:
|
||||||
NecromancerTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : BigTower(id, GetType(), x, y, builder) {}
|
NecromancerTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : BigTower(id, GetType(), x, y, builder) {}
|
||||||
|
|
||||||
virtual TowerType GetType() const { return TowerType::Necromancer; }
|
virtual TowerType GetType() const { return TowerType::Necromancer; }
|
||||||
virtual void Tick(std::uint64_t delta, World* world);
|
virtual void Tick(std::uint64_t delta, World* world);
|
||||||
};
|
};
|
||||||
|
|
||||||
class LeachTower : public BigTower {
|
class LeachTower : public BigTower {
|
||||||
public:
|
public:
|
||||||
LeachTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : BigTower(id, GetType(), x, y, builder) {}
|
LeachTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : BigTower(id, GetType(), x, y, builder) {}
|
||||||
|
|
||||||
virtual TowerType GetType() const { return TowerType::Leach; }
|
virtual TowerType GetType() const { return TowerType::Leach; }
|
||||||
virtual void Tick(std::uint64_t delta, World* world);
|
virtual void Tick(std::uint64_t delta, World* world);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace game
|
} // namespace game
|
||||||
|
|||||||
@@ -9,10 +9,10 @@ namespace td {
|
|||||||
namespace game {
|
namespace game {
|
||||||
|
|
||||||
enum class Direction : std::uint8_t {
|
enum class Direction : std::uint8_t {
|
||||||
PositiveX = 1 << 0,
|
PositiveX = 1 << 0,
|
||||||
NegativeX = 1 << 1,
|
NegativeX = 1 << 1,
|
||||||
PositiveY = 1 << 2,
|
PositiveY = 1 << 2,
|
||||||
NegativeY = 1 << 3,
|
NegativeY = 1 << 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::uint8_t PlayerID;
|
typedef std::uint8_t PlayerID;
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <glm/glm.hpp>
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
#include "Mobs.h"
|
#include "Mobs.h"
|
||||||
@@ -14,11 +13,11 @@ namespace td {
|
|||||||
namespace game {
|
namespace game {
|
||||||
|
|
||||||
struct ChunkCoord {
|
struct ChunkCoord {
|
||||||
std::int16_t x, y;
|
std::int16_t x, y;
|
||||||
|
|
||||||
friend bool operator==(const td::game::ChunkCoord& first, const td::game::ChunkCoord& other) {
|
friend bool operator==(const td::game::ChunkCoord& first, const td::game::ChunkCoord& other) {
|
||||||
return first.x == other.x && first.y == other.y;
|
return first.x == other.x && first.y == other.y;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -29,9 +28,9 @@ struct ChunkCoord {
|
|||||||
namespace std {
|
namespace std {
|
||||||
template <>
|
template <>
|
||||||
struct hash<td::game::ChunkCoord> {
|
struct hash<td::game::ChunkCoord> {
|
||||||
std::size_t operator()(const td::game::ChunkCoord& key) const noexcept{
|
std::size_t operator()(const td::game::ChunkCoord& key) const noexcept {
|
||||||
return std::hash<std::int16_t>()(key.x << 16 | key.y);
|
return std::hash<std::int16_t>()(key.x << 16 | key.y);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,19 +47,15 @@ namespace game {
|
|||||||
class Game;
|
class Game;
|
||||||
|
|
||||||
enum class TileType : std::uint8_t {
|
enum class TileType : std::uint8_t {
|
||||||
None = 0,
|
None = 0,
|
||||||
Tower,
|
Tower,
|
||||||
Walk,
|
Walk,
|
||||||
Decoration,
|
Decoration,
|
||||||
/*Heal,
|
/*Heal,
|
||||||
Lava,
|
Lava,
|
||||||
Bedrock,
|
Bedrock,
|
||||||
Freeze,
|
Freeze,
|
||||||
Ice,*/
|
Ice,*/
|
||||||
};
|
|
||||||
|
|
||||||
struct Color {
|
|
||||||
std::uint8_t r, g, b;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr Color BLACK{ 0, 0, 0 };
|
static constexpr Color BLACK{ 0, 0, 0 };
|
||||||
@@ -71,26 +66,26 @@ static constexpr Color GREEN{ 0, 255, 0 };
|
|||||||
static constexpr Color BLUE{ 0, 0, 255 };
|
static constexpr Color BLUE{ 0, 0, 255 };
|
||||||
|
|
||||||
struct Tile {
|
struct Tile {
|
||||||
virtual TileType GetType() const = 0;
|
virtual TileType GetType() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TowerTile : Tile {
|
struct TowerTile : Tile {
|
||||||
std::uint8_t color_palette_ref;
|
std::uint8_t color_palette_ref;
|
||||||
TeamColor team_owner;
|
TeamColor team_owner;
|
||||||
|
|
||||||
virtual TileType GetType() const { return TileType::Tower; }
|
virtual TileType GetType() const { return TileType::Tower; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WalkableTile : Tile {
|
struct WalkableTile : Tile {
|
||||||
Direction direction;
|
Direction direction;
|
||||||
|
|
||||||
virtual TileType GetType() const { return TileType::Walk; }
|
virtual TileType GetType() const { return TileType::Walk; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DecorationTile : Tile {
|
struct DecorationTile : Tile {
|
||||||
std::uint16_t color_palette_ref;
|
std::uint16_t color_palette_ref;
|
||||||
|
|
||||||
virtual TileType GetType() const { return TileType::Decoration; }
|
virtual TileType GetType() const { return TileType::Decoration; }
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr<Tile> TilePtr;
|
typedef std::shared_ptr<Tile> TilePtr;
|
||||||
@@ -102,19 +97,19 @@ typedef std::uint32_t TileIndex;
|
|||||||
|
|
||||||
//32 x 32 area
|
//32 x 32 area
|
||||||
struct Chunk {
|
struct Chunk {
|
||||||
enum { ChunkWidth = 32, ChunkHeight = 32, ChunkSize = ChunkWidth * ChunkHeight };
|
enum { ChunkWidth = 32, ChunkHeight = 32, ChunkSize = ChunkWidth * ChunkHeight };
|
||||||
typedef std::array<std::uint16_t, ChunkSize> ChunkData;
|
typedef std::array<std::uint16_t, ChunkSize> ChunkData;
|
||||||
|
|
||||||
// stores index of tile palette
|
// stores index of tile palette
|
||||||
ChunkData tiles{ 0 };
|
ChunkData tiles{ 0 };
|
||||||
ChunkPalette palette;
|
ChunkPalette palette;
|
||||||
|
|
||||||
TileIndex GetTileIndex(std::uint16_t tileNumber) const {
|
TileIndex GetTileIndex(std::uint16_t tileNumber) const {
|
||||||
TileIndex chunkPaletteIndex = tiles.at(tileNumber);
|
TileIndex chunkPaletteIndex = tiles.at(tileNumber);
|
||||||
if (chunkPaletteIndex == 0) // index 0 means empty tile index 1 = first tile
|
if (chunkPaletteIndex == 0) // index 0 means empty tile index 1 = first tile
|
||||||
return 0;
|
return 0;
|
||||||
return palette.at(chunkPaletteIndex);
|
return palette.at(chunkPaletteIndex);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr<Chunk> ChunkPtr;
|
typedef std::shared_ptr<Chunk> ChunkPtr;
|
||||||
@@ -131,119 +126,119 @@ typedef std::vector<TowerPtr> TowerList;
|
|||||||
|
|
||||||
class WorldListener {
|
class WorldListener {
|
||||||
public:
|
public:
|
||||||
WorldListener() {}
|
WorldListener() {}
|
||||||
|
|
||||||
virtual void OnTowerAdd(TowerPtr tower) {}
|
virtual void OnTowerAdd(TowerPtr tower) {}
|
||||||
virtual void OnTowerRemove(TowerPtr tower) {}
|
virtual void OnTowerRemove(TowerPtr tower) {}
|
||||||
|
|
||||||
virtual void OnArcherTowerShot(MobPtr target, ArcherTower* shooter) {}
|
virtual void OnArcherTowerShot(MobPtr target, ArcherTower* shooter) {}
|
||||||
|
|
||||||
virtual void OnArrowShot(MobPtr target, bool fire, Tower* shooter) {}
|
virtual void OnArrowShot(MobPtr target, bool fire, Tower* shooter) {}
|
||||||
virtual void OnExplosion(utils::shape::Circle explosion, float centerDamage, Tower* shooter) {}
|
virtual void OnExplosion(utils::shape::Circle explosion, float centerDamage, Tower* shooter) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef utils::ObjectNotifier<WorldListener> WorldNotifier;
|
typedef utils::ObjectNotifier<WorldListener> WorldNotifier;
|
||||||
|
|
||||||
class World : public WorldListener, public MobListener {
|
class World : public WorldListener, public MobListener {
|
||||||
protected:
|
protected:
|
||||||
TowerTileColorPalette m_TowerPlacePalette;
|
TowerTileColorPalette m_TowerPlacePalette;
|
||||||
Color m_WalkablePalette;
|
Color m_WalkablePalette;
|
||||||
std::vector<Color> m_DecorationPalette;
|
std::vector<Color> m_DecorationPalette;
|
||||||
Color m_Background;
|
Color m_Background;
|
||||||
|
|
||||||
std::unordered_map<ChunkCoord, ChunkPtr> m_Chunks;
|
std::unordered_map<ChunkCoord, ChunkPtr> m_Chunks;
|
||||||
|
|
||||||
SpawnColorPalette m_SpawnColorPalette;
|
SpawnColorPalette m_SpawnColorPalette;
|
||||||
|
|
||||||
TilePalette m_TilePalette;
|
TilePalette m_TilePalette;
|
||||||
|
|
||||||
MobList m_Mobs;
|
MobList m_Mobs;
|
||||||
|
|
||||||
TowerList m_Towers;
|
TowerList m_Towers;
|
||||||
|
|
||||||
Game* m_Game;
|
Game* m_Game;
|
||||||
|
|
||||||
WorldNotifier m_WorldNotifier;
|
WorldNotifier m_WorldNotifier;
|
||||||
MobNotifier m_MobNotifier;
|
MobNotifier m_MobNotifier;
|
||||||
public:
|
public:
|
||||||
World(Game* game);
|
World(Game* game);
|
||||||
|
|
||||||
bool LoadMap(const protocol::WorldBeginDataPacket* worldHeader);
|
bool LoadMap(const protocol::WorldBeginDataPacket* worldHeader);
|
||||||
bool LoadMap(const protocol::WorldDataPacket* worldData);
|
bool LoadMap(const protocol::WorldDataPacket* worldData);
|
||||||
|
|
||||||
bool LoadMapFromFile(const std::string& fileName);
|
bool LoadMapFromFile(const std::string& fileName);
|
||||||
bool SaveMap(const std::string& fileName) const;
|
bool SaveMap(const std::string& fileName) const;
|
||||||
|
|
||||||
void Tick(std::uint64_t delta);
|
void Tick(std::uint64_t delta);
|
||||||
|
|
||||||
void SpawnMobAt(MobID id, MobType type, std::uint8_t level, PlayerID sender, float x, float y, Direction dir);
|
void SpawnMobAt(MobID id, MobType type, std::uint8_t level, PlayerID sender, float x, float y, Direction dir);
|
||||||
|
|
||||||
TowerPtr PlaceTowerAt(TowerID id, TowerType type, std::int32_t x, std::int32_t y, PlayerID builder);
|
TowerPtr PlaceTowerAt(TowerID id, TowerType type, std::int32_t x, std::int32_t y, PlayerID builder);
|
||||||
TowerPtr RemoveTower(TowerID id);
|
TowerPtr RemoveTower(TowerID id);
|
||||||
|
|
||||||
TilePtr GetTile(std::int32_t x, std::int32_t y) const;
|
TilePtr GetTile(std::int32_t x, std::int32_t y) const;
|
||||||
|
|
||||||
const TowerTileColorPalette& GetTowerTileColorPalette() const { return m_TowerPlacePalette; }
|
const TowerTileColorPalette& GetTowerTileColorPalette() const { return m_TowerPlacePalette; }
|
||||||
const Color& GetWalkableTileColor() const { return m_WalkablePalette; }
|
const Color& GetWalkableTileColor() const { return m_WalkablePalette; }
|
||||||
const std::vector<Color>& GetDecorationPalette() const { return m_DecorationPalette; }
|
const std::vector<Color>& GetDecorationPalette() const { return m_DecorationPalette; }
|
||||||
const Color& GetBackgroundColor() const { return m_Background; }
|
const Color& GetBackgroundColor() const { return m_Background; }
|
||||||
|
|
||||||
const TilePalette& GetTilePalette() const { return m_TilePalette; }
|
const TilePalette& GetTilePalette() const { return m_TilePalette; }
|
||||||
|
|
||||||
TilePtr GetTilePtr(TileIndex index) const {
|
TilePtr GetTilePtr(TileIndex index) const {
|
||||||
if (index == 0)
|
if (index == 0)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return m_TilePalette.at(index - 1);
|
return m_TilePalette.at(index - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CanPlaceLittleTower(const glm::vec2& worldPos, PlayerID player) const;
|
bool CanPlaceLittleTower(const Vec2f& worldPos, PlayerID player) const;
|
||||||
bool CanPlaceBigTower(const glm::vec2& worldPos, PlayerID player) const;
|
bool CanPlaceBigTower(const Vec2f& worldPos, PlayerID player) const;
|
||||||
|
|
||||||
TowerPtr GetTower(const glm::vec2& position) const; // returns null if no tower is here
|
TowerPtr GetTower(const Vec2f& position) const; // returns null if no tower is here
|
||||||
|
|
||||||
const std::unordered_map<ChunkCoord, ChunkPtr>& GetChunks() const { return m_Chunks; }
|
const std::unordered_map<ChunkCoord, ChunkPtr>& GetChunks() const { return m_Chunks; }
|
||||||
|
|
||||||
const Color& GetSpawnColor(TeamColor color) const { return m_SpawnColorPalette[static_cast<std::size_t>(color)]; }
|
const Color& GetSpawnColor(TeamColor color) const { return m_SpawnColorPalette[static_cast<std::size_t>(color)]; }
|
||||||
const SpawnColorPalette& GetSpawnColors() const { return m_SpawnColorPalette; }
|
const SpawnColorPalette& GetSpawnColors() const { return m_SpawnColorPalette; }
|
||||||
|
|
||||||
const MobList& GetMobList() const { return m_Mobs; }
|
const MobList& GetMobList() const { return m_Mobs; }
|
||||||
MobList& GetMobList() { return m_Mobs; }
|
MobList& GetMobList() { return m_Mobs; }
|
||||||
|
|
||||||
const Color* GetTileColor(TilePtr tile) const;
|
const Color* GetTileColor(TilePtr tile) const;
|
||||||
|
|
||||||
Team& GetRedTeam();
|
Team& GetRedTeam();
|
||||||
const Team& GetRedTeam() const;
|
const Team& GetRedTeam() const;
|
||||||
|
|
||||||
Team& GetBlueTeam();
|
Team& GetBlueTeam();
|
||||||
const Team& GetBlueTeam() const;
|
const Team& GetBlueTeam() const;
|
||||||
|
|
||||||
Team& GetTeam(TeamColor team);
|
Team& GetTeam(TeamColor team);
|
||||||
const Team& GetTeam(TeamColor team) const;
|
const Team& GetTeam(TeamColor team) const;
|
||||||
|
|
||||||
const TeamList& GetTeams() const;
|
const TeamList& GetTeams() const;
|
||||||
|
|
||||||
const TowerList& GetTowers() const { return m_Towers; }
|
const TowerList& GetTowers() const { return m_Towers; }
|
||||||
TowerPtr GetTowerById(TowerID tower);
|
TowerPtr GetTowerById(TowerID tower);
|
||||||
|
|
||||||
const Player* GetPlayerById(PlayerID id) const;
|
const Player* GetPlayerById(PlayerID id) const;
|
||||||
|
|
||||||
WorldNotifier& GetWorldNotifier() { return m_WorldNotifier; }
|
WorldNotifier& GetWorldNotifier() { return m_WorldNotifier; }
|
||||||
MobNotifier& GetMobNotifier() { return m_MobNotifier; }
|
MobNotifier& GetMobNotifier() { return m_MobNotifier; }
|
||||||
|
|
||||||
// WorldListener
|
// WorldListener
|
||||||
|
|
||||||
virtual void OnArcherTowerShot(MobPtr target, ArcherTower* shooter) override;
|
virtual void OnArcherTowerShot(MobPtr target, ArcherTower* shooter) override;
|
||||||
virtual void OnArrowShot(MobPtr target, bool fire, Tower* shooter) override;
|
virtual void OnArrowShot(MobPtr target, bool fire, Tower* shooter) override;
|
||||||
virtual void OnExplosion(utils::shape::Circle explosion, float centerDamage, Tower* shooter) override;
|
virtual void OnExplosion(utils::shape::Circle explosion, float centerDamage, Tower* shooter) override;
|
||||||
|
|
||||||
// MobListener
|
// MobListener
|
||||||
|
|
||||||
virtual void OnMobDamage(Mob* target, float damage, Tower* source) override;
|
virtual void OnMobDamage(Mob* target, float damage, Tower* source) override;
|
||||||
virtual void OnMobCastleDamage(Mob* damager, TeamCastle* enemyCastle, float damage) override;
|
virtual void OnMobCastleDamage(Mob* damager, TeamCastle* enemyCastle, float damage) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void TickMobs(std::uint64_t delta);
|
void TickMobs(std::uint64_t delta);
|
||||||
void CleanDeadMobs();
|
void CleanDeadMobs();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace game
|
} // namespace game
|
||||||
|
|||||||
@@ -17,38 +17,38 @@ namespace client {
|
|||||||
|
|
||||||
class Client {
|
class Client {
|
||||||
private:
|
private:
|
||||||
render::Renderer* m_Renderer;
|
render::Renderer* m_Renderer;
|
||||||
ClientConnexion m_Connexion;
|
ClientConnexion m_Connexion;
|
||||||
std::unique_ptr<ClientGame> m_Game;
|
std::unique_ptr<ClientGame> m_Game;
|
||||||
bool m_Connected;
|
bool m_Connected;
|
||||||
public:
|
public:
|
||||||
Client(render::Renderer* renderer) : m_Renderer(renderer), m_Game(std::make_unique<ClientGame>(this)), m_Connected(false) {}
|
Client(render::Renderer* renderer) : m_Renderer(renderer), m_Game(std::make_unique<ClientGame>(this)), m_Connected(false) {}
|
||||||
|
|
||||||
const ClientGame& GetGame() const { return *m_Game; }
|
const ClientGame& GetGame() const { return *m_Game; }
|
||||||
const ClientConnexion& GetConnexion() const { return m_Connexion; }
|
const ClientConnexion& GetConnexion() const { return m_Connexion; }
|
||||||
render::Renderer* GetRenderer() const { return m_Renderer; }
|
render::Renderer* GetRenderer() const { return m_Renderer; }
|
||||||
|
|
||||||
ClientGame& GetGame() { return *m_Game; }
|
ClientGame& GetGame() { return *m_Game; }
|
||||||
ClientConnexion& GetConnexion() { return m_Connexion; }
|
ClientConnexion& GetConnexion() { return m_Connexion; }
|
||||||
|
|
||||||
const game::Player* GetPlayer() { return m_Game->GetPlayer(); }
|
const game::Player* GetPlayer() { return m_Game->GetPlayer(); }
|
||||||
|
|
||||||
void Tick(std::uint64_t delta);
|
void Tick(std::uint64_t delta);
|
||||||
|
|
||||||
void Render();
|
void Render();
|
||||||
|
|
||||||
bool Connect(const network::IPAddresses& addresses, std::uint16_t port);
|
bool Connect(const network::IPAddresses& addresses, std::uint16_t port);
|
||||||
void CloseConnection();
|
void CloseConnection();
|
||||||
|
|
||||||
bool IsConnected() const { return m_Connexion.GetSocketStatus() == network::Socket::Connected; }
|
bool IsConnected() const { return m_Connexion.GetSocketStatus() == network::Socket::Connected; }
|
||||||
|
|
||||||
void SelectTeam(game::TeamColor team);
|
void SelectTeam(game::TeamColor team);
|
||||||
void SendMobs(const std::vector<protocol::MobSend>& mobSends);
|
void SendMobs(const std::vector<protocol::MobSend>& mobSends);
|
||||||
void PlaceTower(game::TowerType type, const glm::vec2& position);
|
void PlaceTower(game::TowerType type, const Vec2f& position);
|
||||||
void UpgradeTower(game::TowerID tower, game::TowerLevel level);
|
void UpgradeTower(game::TowerID tower, game::TowerLevel level);
|
||||||
void RemoveTower(game::TowerID tower);
|
void RemoveTower(game::TowerID tower);
|
||||||
private:
|
private:
|
||||||
void Reset();
|
void Reset();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace client
|
} // namespace client
|
||||||
|
|||||||
@@ -9,28 +9,30 @@ namespace client {
|
|||||||
|
|
||||||
class ClientConnexion : public protocol::Connexion {
|
class ClientConnexion : public protocol::Connexion {
|
||||||
private:
|
private:
|
||||||
std::uint8_t m_ConnectionID;
|
std::uint8_t m_ConnectionID;
|
||||||
std::string m_DisconnectReason;
|
std::string m_DisconnectReason;
|
||||||
float m_ServerTPS;
|
float m_ServerTPS;
|
||||||
int m_Ping = 0;
|
float m_ServerMSPT;
|
||||||
|
int m_Ping = 0;
|
||||||
public:
|
public:
|
||||||
ClientConnexion();
|
ClientConnexion();
|
||||||
|
|
||||||
virtual bool UpdateSocket();
|
virtual bool UpdateSocket();
|
||||||
|
|
||||||
virtual void HandlePacket(const protocol::KeepAlivePacket* packet) override;
|
virtual void HandlePacket(const protocol::KeepAlivePacket* packet) override;
|
||||||
virtual void HandlePacket(const protocol::ConnexionInfoPacket* packet) override;
|
virtual void HandlePacket(const protocol::ConnexionInfoPacket* packet) override;
|
||||||
virtual void HandlePacket(const protocol::DisconnectPacket* packet) override;
|
virtual void HandlePacket(const protocol::DisconnectPacket* packet) override;
|
||||||
virtual void HandlePacket(const protocol::ServerTpsPacket* packet) override;
|
virtual void HandlePacket(const protocol::ServerTpsPacket* packet) override;
|
||||||
|
|
||||||
const std::string& GetDisconnectReason() const { return m_DisconnectReason; }
|
const std::string& GetDisconnectReason() const { return m_DisconnectReason; }
|
||||||
float GetServerTPS() const { return m_ServerTPS; }
|
float GetServerTPS() const { return m_ServerTPS; }
|
||||||
int GetServerPing() const { return m_Ping; }
|
float GetServerMSPT() const { return m_ServerMSPT; }
|
||||||
|
int GetServerPing() const { return m_Ping; }
|
||||||
|
|
||||||
REMOVE_COPY(ClientConnexion);
|
REMOVE_COPY(ClientConnexion);
|
||||||
private:
|
private:
|
||||||
void RegisterHandlers();
|
void RegisterHandlers();
|
||||||
void Login();
|
void Login();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace client
|
} // namespace client
|
||||||
|
|||||||
@@ -16,40 +16,42 @@ class Client;
|
|||||||
|
|
||||||
class ClientGame : public protocol::PacketHandler, public game::Game {
|
class ClientGame : public protocol::PacketHandler, public game::Game {
|
||||||
private:
|
private:
|
||||||
Client* m_Client;
|
Client* m_Client;
|
||||||
std::uint8_t m_ConnexionID;
|
std::uint8_t m_ConnexionID;
|
||||||
std::uint32_t m_LobbyTime = 0;
|
std::uint32_t m_LobbyTime = 0;
|
||||||
game::Player* m_Player = nullptr;
|
game::Player* m_Player = nullptr;
|
||||||
render::Renderer* m_Renderer;
|
render::Renderer* m_Renderer;
|
||||||
client::WorldClient m_WorldClient;
|
client::WorldClient m_WorldClient;
|
||||||
render::WorldRenderer m_WorldRenderer;
|
render::WorldRenderer m_WorldRenderer;
|
||||||
public:
|
public:
|
||||||
ClientGame(Client* client);
|
ClientGame(Client* client);
|
||||||
virtual ~ClientGame();
|
virtual ~ClientGame();
|
||||||
|
|
||||||
virtual void Tick(std::uint64_t delta);
|
virtual void Tick(std::uint64_t delta);
|
||||||
|
|
||||||
void RenderWorld();
|
void RenderWorld();
|
||||||
|
|
||||||
std::uint32_t GetLobbyTime() const { return m_LobbyTime; }
|
std::uint32_t GetLobbyTime() const { return m_LobbyTime; }
|
||||||
const game::Player* GetPlayer() const { return m_Player; }
|
const game::Player* GetPlayer() const { return m_Player; }
|
||||||
const WorldClient& GetWorld() const { return m_WorldClient; }
|
const WorldClient& GetWorld() const { return m_WorldClient; }
|
||||||
Client* GetClient() const { return m_Client; }
|
Client* GetClient() const { return m_Client; }
|
||||||
|
|
||||||
render::Renderer* GetRenderer() const { return m_Renderer; }
|
render::Renderer* GetRenderer() const { return m_Renderer; }
|
||||||
WorldClient& GetWorldClient() { return m_WorldClient; }
|
WorldClient& GetWorldClient() { return m_WorldClient; }
|
||||||
|
|
||||||
virtual void HandlePacket(const protocol::ConnexionInfoPacket* packet) override;
|
void SetGameState(game::GameState gameState) override;
|
||||||
virtual void HandlePacket(const protocol::PlayerJoinPacket* packet) override;
|
|
||||||
virtual void HandlePacket(const protocol::PlayerLeavePacket* packet) override;
|
virtual void HandlePacket(const protocol::ConnexionInfoPacket* packet) override;
|
||||||
virtual void HandlePacket(const protocol::PlayerListPacket* packet) override;
|
virtual void HandlePacket(const protocol::PlayerJoinPacket* packet) override;
|
||||||
virtual void HandlePacket(const protocol::UpdatePlayerTeamPacket* packet) override;
|
virtual void HandlePacket(const protocol::PlayerLeavePacket* packet) override;
|
||||||
virtual void HandlePacket(const protocol::UpdateGameStatePacket* packet) override;
|
virtual void HandlePacket(const protocol::PlayerListPacket* packet) override;
|
||||||
virtual void HandlePacket(const protocol::UpdateLobbyTimePacket* packet) override;
|
virtual void HandlePacket(const protocol::UpdatePlayerTeamPacket* packet) override;
|
||||||
virtual void HandlePacket(const protocol::UpdateMoneyPacket* packet) override;
|
virtual void HandlePacket(const protocol::UpdateGameStatePacket* packet) override;
|
||||||
virtual void HandlePacket(const protocol::UpdateExpPacket* packet) override;
|
virtual void HandlePacket(const protocol::UpdateLobbyTimePacket* packet) override;
|
||||||
virtual void HandlePacket(const protocol::DisconnectPacket* packet) override;
|
virtual void HandlePacket(const protocol::UpdateMoneyPacket* packet) override;
|
||||||
virtual void HandlePacket(const protocol::WorldDataPacket* packet) override;
|
virtual void HandlePacket(const protocol::UpdateExpPacket* packet) override;
|
||||||
|
virtual void HandlePacket(const protocol::DisconnectPacket* packet) override;
|
||||||
|
virtual void HandlePacket(const protocol::WorldDataPacket* packet) override;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -10,18 +10,18 @@ class ClientGame;
|
|||||||
|
|
||||||
class WorldClient : public game::World, public protocol::PacketHandler {
|
class WorldClient : public game::World, public protocol::PacketHandler {
|
||||||
private:
|
private:
|
||||||
ClientGame* m_Game;
|
ClientGame* m_Game;
|
||||||
public:
|
public:
|
||||||
WorldClient(ClientGame* game);
|
WorldClient(ClientGame* game);
|
||||||
|
|
||||||
virtual void HandlePacket(const protocol::WorldBeginDataPacket* packet) override;
|
virtual void HandlePacket(const protocol::WorldBeginDataPacket* packet) override;
|
||||||
virtual void HandlePacket(const protocol::WorldDataPacket* packet) override;
|
virtual void HandlePacket(const protocol::WorldDataPacket* packet) override;
|
||||||
virtual void HandlePacket(const protocol::SpawnMobPacket* packet) override;
|
virtual void HandlePacket(const protocol::SpawnMobPacket* packet) override;
|
||||||
virtual void HandlePacket(const protocol::UpgradeTowerPacket* packet) override;
|
virtual void HandlePacket(const protocol::UpgradeTowerPacket* packet) override;
|
||||||
virtual void HandlePacket(const protocol::WorldAddTowerPacket* packet) override;
|
virtual void HandlePacket(const protocol::WorldAddTowerPacket* packet) override;
|
||||||
virtual void HandlePacket(const protocol::RemoveTowerPacket* packet) override;
|
virtual void HandlePacket(const protocol::RemoveTowerPacket* packet) override;
|
||||||
virtual void HandlePacket(const protocol::UpdateMobStatesPacket* packet) override;
|
virtual void HandlePacket(const protocol::UpdateMobStatesPacket* packet) override;
|
||||||
virtual void HandlePacket(const protocol::UpdateCastleLifePacket* packet) override;
|
virtual void HandlePacket(const protocol::UpdateCastleLifePacket* packet) override;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -11,23 +11,23 @@ class Server;
|
|||||||
|
|
||||||
class Lobby {
|
class Lobby {
|
||||||
private:
|
private:
|
||||||
Server* m_Server;
|
Server* m_Server;
|
||||||
bool m_GameStarted = false;
|
bool m_GameStarted = false;
|
||||||
std::uint64_t m_StartTimerTime = 0;
|
std::uint64_t m_StartTimerTime = 0;
|
||||||
std::vector<std::uint8_t> m_Players;
|
std::vector<std::uint8_t> m_Players;
|
||||||
utils::AutoTimer m_Timer;
|
utils::AutoTimer m_Timer;
|
||||||
public:
|
public:
|
||||||
Lobby(Server* server);
|
Lobby(Server* server);
|
||||||
|
|
||||||
void OnPlayerJoin(std::uint8_t playerID);
|
void OnPlayerJoin(std::uint8_t playerID);
|
||||||
void OnPlayerLeave(std::uint8_t playerID);
|
void OnPlayerLeave(std::uint8_t playerID);
|
||||||
|
|
||||||
void SendTimeRemaining();
|
void SendTimeRemaining();
|
||||||
|
|
||||||
void Tick();
|
void Tick();
|
||||||
|
|
||||||
//static constexpr int LobbyWaitingTime = 2 * 60 * 1000; // in millis
|
//static constexpr int LobbyWaitingTime = 2 * 60 * 1000; // in millis
|
||||||
static constexpr int LobbyWaitingTime = 5 * 1000; // in millis
|
static constexpr int LobbyWaitingTime = 5 * 1000; // in millis
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace server
|
} // namespace server
|
||||||
|
|||||||
@@ -21,80 +21,84 @@ typedef std::map<std::uint8_t, ServerConnexion> ConnexionMap;
|
|||||||
|
|
||||||
class TickCounter {
|
class TickCounter {
|
||||||
private:
|
private:
|
||||||
float m_TPS;
|
float m_TPS;
|
||||||
std::uint64_t m_LastTPSTime;
|
float m_MSPT;
|
||||||
std::uint8_t m_TickCount;
|
std::uint64_t m_LastTPSTime;
|
||||||
|
std::uint8_t m_TickCount;
|
||||||
public:
|
public:
|
||||||
TickCounter() {}
|
TickCounter() {}
|
||||||
|
|
||||||
void Reset() {
|
void Reset() {
|
||||||
m_TPS = SERVER_TPS;
|
m_TPS = SERVER_TPS;
|
||||||
m_LastTPSTime = utils::GetTime();
|
m_LastTPSTime = utils::GetTime();
|
||||||
m_TickCount = 0;
|
m_TickCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Update() { // return true when tps is updated
|
bool Update() { // return true when tps is updated
|
||||||
m_TickCount++;
|
m_TickCount++;
|
||||||
if (m_TickCount >= SERVER_TPS) {
|
if (m_TickCount >= SERVER_TPS) {
|
||||||
std::uint64_t timeElapsedSinceLast20Ticks = td::utils::GetTime() - m_LastTPSTime;
|
std::uint64_t timeElapsedSinceLast20Ticks = td::utils::GetTime() - m_LastTPSTime;
|
||||||
m_TPS = static_cast<float>(SERVER_TPS) / static_cast<float>(timeElapsedSinceLast20Ticks / 1000.0f);
|
m_TPS = static_cast<float>(SERVER_TPS) / static_cast<float>(timeElapsedSinceLast20Ticks / 1000.0f);
|
||||||
m_TickCount = 0;
|
m_TickCount = 0;
|
||||||
m_LastTPSTime = td::utils::GetTime();
|
m_LastTPSTime = td::utils::GetTime();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
float GetTPS() const { return m_TPS; }
|
float GetTPS() const { return m_TPS; }
|
||||||
|
float GetMSPT() const { return m_MSPT; }
|
||||||
|
|
||||||
|
void SetMSPT(float mspt) { m_MSPT = mspt; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class Server {
|
class Server {
|
||||||
private:
|
private:
|
||||||
network::TCPListener m_Listener;
|
network::TCPListener m_Listener;
|
||||||
ConnexionMap m_Connections;
|
ConnexionMap m_Connections;
|
||||||
ServerGame m_Game{ this };
|
ServerGame m_Game{ this };
|
||||||
Lobby m_Lobby{ this };
|
Lobby m_Lobby{ this };
|
||||||
TickCounter m_TickCounter;
|
TickCounter m_TickCounter;
|
||||||
|
|
||||||
std::thread m_Thread;
|
std::thread m_Thread;
|
||||||
bool m_ServerRunning;
|
bool m_ServerRunning;
|
||||||
public:
|
public:
|
||||||
Server(const std::string& worldFilePath);
|
Server(const std::string& worldFilePath);
|
||||||
virtual ~Server();
|
virtual ~Server();
|
||||||
|
|
||||||
bool Start(std::uint16_t port);
|
bool Start(std::uint16_t port);
|
||||||
void Stop(); // force the server to stop
|
void Stop(); // force the server to stop
|
||||||
void Close(); // at the end of a game
|
void Close(); // at the end of a game
|
||||||
|
|
||||||
void RemoveConnexion(std::uint8_t connexionID);
|
void RemoveConnexion(std::uint8_t connexionID);
|
||||||
|
|
||||||
void BroadcastPacket(const protocol::Packet* packet);
|
void BroadcastPacket(const protocol::Packet* packet);
|
||||||
|
|
||||||
float GetTPS() const { return m_TickCounter.GetTPS(); }
|
float GetTPS() const { return m_TickCounter.GetTPS(); }
|
||||||
|
|
||||||
bool IsRunning() { return m_ServerRunning; }
|
bool IsRunning() { return m_ServerRunning; }
|
||||||
|
|
||||||
const ServerGame& GetGame() const { return m_Game; }
|
const ServerGame& GetGame() const { return m_Game; }
|
||||||
ServerGame& GetGame() { return m_Game; }
|
ServerGame& GetGame() { return m_Game; }
|
||||||
|
|
||||||
const Lobby& GetLobby() const { return m_Lobby; }
|
const Lobby& GetLobby() const { return m_Lobby; }
|
||||||
const ConnexionMap& GetConnexions() const { return m_Connections; }
|
const ConnexionMap& GetConnexions() const { return m_Connections; }
|
||||||
ConnexionMap& GetConnexions() { return m_Connections; }
|
ConnexionMap& GetConnexions() { return m_Connections; }
|
||||||
|
|
||||||
const game::PlayerList& GetPlayers() const { return m_Game.GetPlayers(); }
|
const game::PlayerList& GetPlayers() const { return m_Game.GetPlayers(); }
|
||||||
game::PlayerList& GetPlayers() { return m_Game.GetPlayers(); }
|
game::PlayerList& GetPlayers() { return m_Game.GetPlayers(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Accept();
|
void Accept();
|
||||||
void UpdateSockets();
|
void UpdateSockets();
|
||||||
|
|
||||||
void Clean();
|
void Clean();
|
||||||
void StartThread();
|
void StartThread();
|
||||||
void StopThread();
|
void StopThread();
|
||||||
void Tick(std::uint64_t delta);
|
void Tick(std::uint64_t delta);
|
||||||
|
|
||||||
void OnPlayerJoin(std::uint8_t id);
|
void OnPlayerJoin(std::uint8_t id);
|
||||||
void OnPlayerLeave(std::uint8_t id);
|
void OnPlayerLeave(std::uint8_t id);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace server
|
} // namespace server
|
||||||
|
|||||||
@@ -11,49 +11,48 @@ namespace server {
|
|||||||
|
|
||||||
class Server;
|
class Server;
|
||||||
|
|
||||||
struct KeepAlive
|
struct KeepAlive {
|
||||||
{
|
std::uint64_t keepAliveID = 0;
|
||||||
std::uint64_t keepAliveID = 0;
|
std::uint64_t sendTime;
|
||||||
std::uint64_t sendTime;
|
bool recievedResponse = false;
|
||||||
bool recievedResponse = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class ServerConnexion : public protocol::Connexion {
|
class ServerConnexion : public protocol::Connexion {
|
||||||
private:
|
private:
|
||||||
Server* m_Server = nullptr;
|
Server* m_Server = nullptr;
|
||||||
std::uint8_t m_ID;
|
std::uint8_t m_ID;
|
||||||
KeepAlive m_KeepAlive;
|
KeepAlive m_KeepAlive;
|
||||||
game::Player* m_Player;
|
game::Player* m_Player;
|
||||||
public:
|
public:
|
||||||
ServerConnexion();
|
ServerConnexion();
|
||||||
ServerConnexion(network::TCPSocket& socket, std::uint8_t id);
|
ServerConnexion(network::TCPSocket& socket, std::uint8_t id);
|
||||||
ServerConnexion(ServerConnexion&& move);
|
ServerConnexion(ServerConnexion&& move);
|
||||||
virtual ~ServerConnexion();
|
virtual ~ServerConnexion();
|
||||||
|
|
||||||
void SetServer(Server* server);
|
void SetServer(Server* server);
|
||||||
|
|
||||||
virtual void HandlePacket(const protocol::PlayerLoginPacket* packet) override;
|
virtual void HandlePacket(const protocol::PlayerLoginPacket* packet) override;
|
||||||
virtual void HandlePacket(const protocol::KeepAlivePacket* packet) override;
|
virtual void HandlePacket(const protocol::KeepAlivePacket* packet) override;
|
||||||
virtual void HandlePacket(const protocol::SelectTeamPacket* packet) override;
|
virtual void HandlePacket(const protocol::SelectTeamPacket* packet) override;
|
||||||
virtual void HandlePacket(const protocol::DisconnectPacket* packet) override;
|
virtual void HandlePacket(const protocol::DisconnectPacket* packet) override;
|
||||||
virtual void HandlePacket(const protocol::PlaceTowerPacket* packet) override;
|
virtual void HandlePacket(const protocol::PlaceTowerPacket* packet) override;
|
||||||
virtual void HandlePacket(const protocol::SendMobsPacket* packet) override;
|
virtual void HandlePacket(const protocol::SendMobsPacket* packet) override;
|
||||||
virtual void HandlePacket(const protocol::UpgradeTowerPacket* packet) override;
|
virtual void HandlePacket(const protocol::UpgradeTowerPacket* packet) override;
|
||||||
virtual void HandlePacket(const protocol::RemoveTowerPacket* packet) override;
|
virtual void HandlePacket(const protocol::RemoveTowerPacket* packet) override;
|
||||||
|
|
||||||
std::uint8_t GetID() const { return m_ID; }
|
std::uint8_t GetID() const { return m_ID; }
|
||||||
const game::Player* GetPlayer() const { return m_Player; }
|
const game::Player* GetPlayer() const { return m_Player; }
|
||||||
game::Player* GetPlayer() { return m_Player; }
|
game::Player* GetPlayer() { return m_Player; }
|
||||||
|
|
||||||
virtual bool UpdateSocket();
|
virtual bool UpdateSocket();
|
||||||
|
|
||||||
REMOVE_COPY(ServerConnexion);
|
REMOVE_COPY(ServerConnexion);
|
||||||
private:
|
private:
|
||||||
void RegisterHandlers();
|
void RegisterHandlers();
|
||||||
void CheckKeepAlive();
|
void CheckKeepAlive();
|
||||||
void SendKeepAlive();
|
void SendKeepAlive();
|
||||||
void InitConnection();
|
void InitConnection();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace server
|
} // namespace server
|
||||||
|
|||||||
@@ -11,32 +11,32 @@ class Server;
|
|||||||
|
|
||||||
class ServerGame : public game::Game, public game::GameListener {
|
class ServerGame : public game::Game, public game::GameListener {
|
||||||
private:
|
private:
|
||||||
Server* m_Server;
|
Server* m_Server;
|
||||||
ServerWorld m_ServerWorld;
|
ServerWorld m_ServerWorld;
|
||||||
utils::AutoTimer m_GoldMineTimer;
|
utils::AutoTimer m_GoldMineTimer;
|
||||||
utils::AutoTimer m_MobStatesTimer;
|
utils::AutoTimer m_MobStatesTimer;
|
||||||
utils::CooldownTimer m_EndGameCooldown;
|
utils::CooldownTimer m_EndGameCooldown;
|
||||||
public:
|
public:
|
||||||
ServerGame(Server* server);
|
ServerGame(Server* server);
|
||||||
~ServerGame() {}
|
~ServerGame() {}
|
||||||
|
|
||||||
ServerWorld* GetServerWorld() { return &m_ServerWorld; }
|
ServerWorld* GetServerWorld() { return &m_ServerWorld; }
|
||||||
|
|
||||||
virtual void Tick(std::uint64_t delta);
|
virtual void Tick(std::uint64_t delta);
|
||||||
void StartGame();
|
void StartGame();
|
||||||
|
|
||||||
// GameListener
|
// GameListener
|
||||||
|
|
||||||
virtual void OnGameStateUpdate(game::GameState newState) override;
|
virtual void OnGameStateUpdate(game::GameState newState) override;
|
||||||
virtual void OnGameBegin() override;
|
virtual void OnGameBegin() override;
|
||||||
virtual void OnGameEnd() override;
|
virtual void OnGameEnd() override;
|
||||||
virtual void OnGameClose() override;
|
virtual void OnGameClose() override;
|
||||||
private:
|
private:
|
||||||
void BalanceTeams();
|
void BalanceTeams();
|
||||||
void InitPlayerStats();
|
void InitPlayerStats();
|
||||||
void UpdateMobStates();
|
void UpdateMobStates();
|
||||||
void UpdateGoldMines();
|
void UpdateGoldMines();
|
||||||
void UpdatePlayerStats();
|
void UpdatePlayerStats();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace game
|
} // namespace game
|
||||||
|
|||||||
@@ -10,19 +10,19 @@ class ServerGame;
|
|||||||
|
|
||||||
class ServerWorld : public game::World {
|
class ServerWorld : public game::World {
|
||||||
private:
|
private:
|
||||||
game::MobID m_CurrentMobID;
|
game::MobID m_CurrentMobID;
|
||||||
game::TowerID m_CurrentTowerID;
|
game::TowerID m_CurrentTowerID;
|
||||||
Server* m_Server;
|
Server* m_Server;
|
||||||
public:
|
public:
|
||||||
static constexpr float MobSpawnBorder = 0.01f;
|
static constexpr float MobSpawnBorder = 0.01f;
|
||||||
|
|
||||||
ServerWorld(Server* server, ServerGame* game);
|
ServerWorld(Server* server, ServerGame* game);
|
||||||
|
|
||||||
void SpawnMobs(game::MobType type, std::uint8_t level, game::PlayerID sender, std::uint8_t count);
|
void SpawnMobs(game::MobType type, std::uint8_t level, game::PlayerID sender, std::uint8_t count);
|
||||||
game::TowerPtr PlaceTowerAt(game::TowerType type, std::int32_t x, std::int32_t y, game::PlayerID builder);
|
game::TowerPtr PlaceTowerAt(game::TowerType type, std::int32_t x, std::int32_t y, game::PlayerID builder);
|
||||||
|
|
||||||
virtual void OnMobDie(game::Mob* mob) override;
|
virtual void OnMobDie(game::Mob* mob) override;
|
||||||
virtual void OnMobCastleDamage(game::Mob* damager, game::TeamCastle* enemyCastle, float damage) override;
|
virtual void OnMobCastleDamage(game::Mob* damager, game::TeamCastle* enemyCastle, float damage) override;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -10,166 +10,166 @@ namespace td {
|
|||||||
|
|
||||||
class DataBuffer {
|
class DataBuffer {
|
||||||
private:
|
private:
|
||||||
typedef std::vector<std::uint8_t> Data;
|
typedef std::vector<std::uint8_t> Data;
|
||||||
Data m_Buffer;
|
Data m_Buffer;
|
||||||
std::size_t m_ReadOffset;
|
std::size_t m_ReadOffset;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef Data::iterator iterator;
|
typedef Data::iterator iterator;
|
||||||
typedef Data::const_iterator const_iterator;
|
typedef Data::const_iterator const_iterator;
|
||||||
typedef Data::reference reference;
|
typedef Data::reference reference;
|
||||||
typedef Data::const_reference const_reference;
|
typedef Data::const_reference const_reference;
|
||||||
|
|
||||||
DataBuffer();
|
DataBuffer();
|
||||||
DataBuffer(const DataBuffer& other);
|
DataBuffer(const DataBuffer& other);
|
||||||
DataBuffer(const DataBuffer& other, Data::difference_type offset);
|
DataBuffer(const DataBuffer& other, Data::difference_type offset);
|
||||||
DataBuffer(DataBuffer&& other);
|
DataBuffer(DataBuffer&& other);
|
||||||
DataBuffer(const std::string& str);
|
DataBuffer(const std::string& str);
|
||||||
|
|
||||||
DataBuffer& operator=(const DataBuffer& other);
|
DataBuffer& operator=(const DataBuffer& other);
|
||||||
DataBuffer& operator=(DataBuffer&& other);
|
DataBuffer& operator=(DataBuffer&& other);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void Append(T data) {
|
void Append(T data) {
|
||||||
std::size_t size = sizeof(data);
|
std::size_t size = sizeof(data);
|
||||||
std::size_t end_pos = m_Buffer.size();
|
std::size_t end_pos = m_Buffer.size();
|
||||||
m_Buffer.resize(m_Buffer.size() + size);
|
m_Buffer.resize(m_Buffer.size() + size);
|
||||||
memcpy(&m_Buffer[end_pos], &data, size);
|
memcpy(&m_Buffer[end_pos], &data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
DataBuffer& operator<<(T data) {
|
DataBuffer& operator<<(T data) {
|
||||||
// Switch to big endian
|
// Switch to big endian
|
||||||
//std::reverse((std::uint8_t*)&data, (std::uint8_t*)&data + sizeof(T));
|
//std::reverse((std::uint8_t*)&data, (std::uint8_t*)&data + sizeof(T));
|
||||||
Append(data);
|
Append(data);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
DataBuffer& operator<<(std::string str) {
|
DataBuffer& operator<<(std::string str) {
|
||||||
m_Buffer.insert(m_Buffer.end(), str.begin(), str.end());
|
m_Buffer.insert(m_Buffer.end(), str.begin(), str.end());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
DataBuffer& operator<<(DataBuffer& data) {
|
DataBuffer& operator<<(DataBuffer& data) {
|
||||||
m_Buffer.insert(m_Buffer.end(), data.begin(), data.end());
|
m_Buffer.insert(m_Buffer.end(), data.begin(), data.end());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
DataBuffer& operator<<(const DataBuffer& data) {
|
DataBuffer& operator<<(const DataBuffer& data) {
|
||||||
m_Buffer.insert(m_Buffer.end(), data.begin(), data.end());
|
m_Buffer.insert(m_Buffer.end(), data.begin(), data.end());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
DataBuffer& operator>>(T& data) {
|
DataBuffer& operator>>(T& data) {
|
||||||
assert(m_ReadOffset + sizeof(T) <= GetSize());
|
assert(m_ReadOffset + sizeof(T) <= GetSize());
|
||||||
data = *(reinterpret_cast<T*>(&m_Buffer[m_ReadOffset]));
|
data = *(reinterpret_cast<T*>(&m_Buffer[m_ReadOffset]));
|
||||||
//std::reverse((std::uint8_t*)&data, (std::uint8_t*)&data + sizeof(T));
|
//std::reverse((std::uint8_t*)&data, (std::uint8_t*)&data + sizeof(T));
|
||||||
m_ReadOffset += sizeof(T);
|
m_ReadOffset += sizeof(T);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
DataBuffer& operator>>(DataBuffer& data) {
|
DataBuffer& operator>>(DataBuffer& data) {
|
||||||
data.Resize(GetSize() - m_ReadOffset);
|
data.Resize(GetSize() - m_ReadOffset);
|
||||||
std::copy(m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset), m_Buffer.end(), data.begin());
|
std::copy(m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset), m_Buffer.end(), data.begin());
|
||||||
m_ReadOffset = m_Buffer.size();
|
m_ReadOffset = m_Buffer.size();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
DataBuffer& operator>>(std::string& str) {
|
DataBuffer& operator>>(std::string& str) {
|
||||||
std::size_t stringSize = strlen(reinterpret_cast<const char*>(m_Buffer.data()) + m_ReadOffset) + 1; // including null character
|
std::size_t stringSize = strlen(reinterpret_cast<const char*>(m_Buffer.data()) + m_ReadOffset) + 1; // including null character
|
||||||
str.resize(stringSize);
|
str.resize(stringSize);
|
||||||
std::copy(m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset),
|
std::copy(m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset),
|
||||||
m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset + stringSize), str.begin());
|
m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset + stringSize), str.begin());
|
||||||
m_ReadOffset += stringSize;
|
m_ReadOffset += stringSize;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteSome(const char* buffer, std::size_t amount) {
|
void WriteSome(const char* buffer, std::size_t amount) {
|
||||||
std::size_t end_pos = m_Buffer.size();
|
std::size_t end_pos = m_Buffer.size();
|
||||||
m_Buffer.resize(m_Buffer.size() + amount);
|
m_Buffer.resize(m_Buffer.size() + amount);
|
||||||
memcpy(m_Buffer.data() + end_pos, buffer, amount);
|
memcpy(m_Buffer.data() + end_pos, buffer, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteSome(const std::uint8_t* buffer, std::size_t amount) {
|
void WriteSome(const std::uint8_t* buffer, std::size_t amount) {
|
||||||
std::size_t end_pos = m_Buffer.size();
|
std::size_t end_pos = m_Buffer.size();
|
||||||
m_Buffer.resize(m_Buffer.size() + amount);
|
m_Buffer.resize(m_Buffer.size() + amount);
|
||||||
memcpy(m_Buffer.data() + end_pos, buffer, amount);
|
memcpy(m_Buffer.data() + end_pos, buffer, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadSome(char* buffer, std::size_t amount) {
|
void ReadSome(char* buffer, std::size_t amount) {
|
||||||
assert(m_ReadOffset + amount <= GetSize());
|
assert(m_ReadOffset + amount <= GetSize());
|
||||||
std::copy_n(m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset), amount, buffer);
|
std::copy_n(m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset), amount, buffer);
|
||||||
m_ReadOffset += amount;
|
m_ReadOffset += amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadSome(std::uint8_t* buffer, std::size_t amount) {
|
void ReadSome(std::uint8_t* buffer, std::size_t amount) {
|
||||||
assert(m_ReadOffset + amount <= GetSize());
|
assert(m_ReadOffset + amount <= GetSize());
|
||||||
std::copy_n(m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset), amount, buffer);
|
std::copy_n(m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset), amount, buffer);
|
||||||
m_ReadOffset += amount;
|
m_ReadOffset += amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadSome(DataBuffer& buffer, std::size_t amount) {
|
void ReadSome(DataBuffer& buffer, std::size_t amount) {
|
||||||
assert(m_ReadOffset + amount <= GetSize());
|
assert(m_ReadOffset + amount <= GetSize());
|
||||||
buffer.Resize(amount);
|
buffer.Resize(amount);
|
||||||
std::copy_n(m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset), amount, buffer.begin());
|
std::copy_n(m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset), amount, buffer.begin());
|
||||||
m_ReadOffset += amount;
|
m_ReadOffset += amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadSome(std::string& buffer, std::size_t amount) {
|
void ReadSome(std::string& buffer, std::size_t amount) {
|
||||||
assert(m_ReadOffset + amount <= GetSize());
|
assert(m_ReadOffset + amount <= GetSize());
|
||||||
buffer.resize(amount);
|
buffer.resize(amount);
|
||||||
std::copy_n(m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset), amount, buffer.begin());
|
std::copy_n(m_Buffer.begin() + static_cast<Data::difference_type>(m_ReadOffset), amount, buffer.begin());
|
||||||
m_ReadOffset += amount;
|
m_ReadOffset += amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Resize(std::size_t size) {
|
void Resize(std::size_t size) {
|
||||||
m_Buffer.resize(size);
|
m_Buffer.resize(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reserve(std::size_t amount) {
|
void Reserve(std::size_t amount) {
|
||||||
m_Buffer.reserve(amount);
|
m_Buffer.reserve(amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void erase(iterator it) {
|
void erase(iterator it) {
|
||||||
m_Buffer.erase(it);
|
m_Buffer.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Clear() {
|
void Clear() {
|
||||||
m_Buffer.clear();
|
m_Buffer.clear();
|
||||||
m_ReadOffset = 0;
|
m_ReadOffset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsFinished() const {
|
bool IsFinished() const {
|
||||||
return m_ReadOffset >= m_Buffer.size();
|
return m_ReadOffset >= m_Buffer.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::uint8_t* data() {
|
std::uint8_t* data() {
|
||||||
return m_Buffer.data();
|
return m_Buffer.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::uint8_t* data() const {
|
const std::uint8_t* data() const {
|
||||||
return m_Buffer.data();
|
return m_Buffer.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t GetReadOffset() const { return m_ReadOffset; }
|
std::size_t GetReadOffset() const { return m_ReadOffset; }
|
||||||
void SetReadOffset(std::size_t pos);
|
void SetReadOffset(std::size_t pos);
|
||||||
|
|
||||||
std::string ToString() const;
|
std::string ToString() const;
|
||||||
std::size_t GetSize() const;
|
std::size_t GetSize() const;
|
||||||
bool IsEmpty() const;
|
bool IsEmpty() const;
|
||||||
std::size_t GetRemaining() const;
|
std::size_t GetRemaining() const;
|
||||||
|
|
||||||
iterator begin();
|
iterator begin();
|
||||||
iterator end();
|
iterator end();
|
||||||
const_iterator begin() const;
|
const_iterator begin() const;
|
||||||
const_iterator end() const;
|
const_iterator end() const;
|
||||||
|
|
||||||
reference operator[](Data::size_type i) { return m_Buffer[i]; }
|
reference operator[](Data::size_type i) { return m_Buffer[i]; }
|
||||||
const_reference operator[](Data::size_type i) const { return m_Buffer[i]; }
|
const_reference operator[](Data::size_type i) const { return m_Buffer[i]; }
|
||||||
|
|
||||||
bool ReadFile(const std::string& fileName);
|
bool ReadFile(const std::string& fileName);
|
||||||
bool WriteFile(const std::string& fileName);
|
bool WriteFile(const std::string& fileName);
|
||||||
};
|
};
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& os, const DataBuffer& buffer);
|
std::ostream& operator<<(std::ostream& os, const DataBuffer& buffer);
|
||||||
|
|||||||
15
include/misc/DiscordRPC.h
Normal file
15
include/misc/DiscordRPC.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace td {
|
||||||
|
namespace utils {
|
||||||
|
|
||||||
|
void InitDiscordRPC();
|
||||||
|
void UpdateDiscordRPC();
|
||||||
|
void ShutdownDiscordRPC();
|
||||||
|
|
||||||
|
void UpdateDiscordPresence(const std::string& state, const std::string& details, bool resetTimer = false);
|
||||||
|
|
||||||
|
} // namespace utils
|
||||||
|
} // namespace td
|
||||||
@@ -6,15 +6,15 @@
|
|||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
namespace utils {
|
namespace utils {
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
std::string format(const std::string& format, Args... args){
|
std::string format(const std::string& format, Args... args) {
|
||||||
int size = snprintf(nullptr, 0, format.c_str(), args...) + 1; // Extra space for '\0'
|
int size = snprintf(nullptr, 0, format.c_str(), args...) + 1; // Extra space for '\0'
|
||||||
if (size <= 0){
|
if (size <= 0) {
|
||||||
throw std::runtime_error("Error during formatting.");
|
throw std::runtime_error("Error during formatting.");
|
||||||
}
|
}
|
||||||
std::unique_ptr<char[]> buf(new char[size]);
|
std::unique_ptr<char[]> buf(new char[size]);
|
||||||
snprintf(buf.get(), size, format.c_str(), args...);
|
snprintf(buf.get(), static_cast<std::size_t>(size), format.c_str(), args...);
|
||||||
return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside
|
return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,26 +10,26 @@ namespace utils {
|
|||||||
template <typename Listener>
|
template <typename Listener>
|
||||||
class ObjectNotifier {
|
class ObjectNotifier {
|
||||||
protected:
|
protected:
|
||||||
std::vector<Listener*> m_Listeners;
|
std::vector<Listener*> m_Listeners;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void BindListener(Listener* listener) {
|
void BindListener(Listener* listener) {
|
||||||
m_Listeners.push_back(listener);
|
m_Listeners.push_back(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnbindListener(Listener* listener) {
|
void UnbindListener(Listener* listener) {
|
||||||
auto iter = std::find(m_Listeners.begin(), m_Listeners.end(), listener);
|
auto iter = std::find(m_Listeners.begin(), m_Listeners.end(), listener);
|
||||||
|
|
||||||
if (iter == m_Listeners.end()) return;
|
if (iter == m_Listeners.end()) return;
|
||||||
|
|
||||||
m_Listeners.erase(iter);
|
m_Listeners.erase(iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Func, typename... Args>
|
template <typename Func, typename... Args>
|
||||||
void NotifyListeners(Func function, Args... args) {
|
void NotifyListeners(Func function, Args... args) {
|
||||||
for (Listener* listener : m_Listeners)
|
for (Listener* listener : m_Listeners)
|
||||||
std::bind(function, listener, args...)();
|
std::bind(function, listener, args...)();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace utils
|
} // namespace utils
|
||||||
|
|||||||
@@ -4,49 +4,49 @@ namespace td {
|
|||||||
namespace utils {
|
namespace utils {
|
||||||
|
|
||||||
enum class Os {
|
enum class Os {
|
||||||
Windows = 0,
|
Windows = 0,
|
||||||
Linux,
|
Linux,
|
||||||
Android,
|
Android,
|
||||||
Unknown,
|
Unknown,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Architecture {
|
enum class Architecture {
|
||||||
x86_64 = 0,
|
x86_64 = 0,
|
||||||
x86,
|
x86,
|
||||||
Arm64,
|
Arm64,
|
||||||
Armhf,
|
Armhf,
|
||||||
Unknown,
|
Unknown,
|
||||||
};
|
};
|
||||||
|
|
||||||
inline Os GetSystemOs() {
|
inline Os GetSystemOs() {
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
return Os::Windows;
|
return Os::Windows;
|
||||||
#elif defined(__ANDROID__)
|
#elif defined(__ANDROID__)
|
||||||
return Os::Android;
|
return Os::Android;
|
||||||
#elif defined(__unix__)
|
#elif defined(__unix__)
|
||||||
return Os::Linux;
|
return Os::Linux;
|
||||||
#else
|
#else
|
||||||
#pragma message ("Target OS unknown or unsupported !")
|
#pragma message ("Target OS unknown or unsupported !")
|
||||||
return Os::Unknown;
|
return Os::Unknown;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Architecture GetSystemArchitecture() {
|
inline Architecture GetSystemArchitecture() {
|
||||||
#if defined(_WIN64)
|
#if defined(_WIN64)
|
||||||
return Architecture::x86_64;
|
return Architecture::x86_64;
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
return Architecture::x86;
|
return Architecture::x86;
|
||||||
#elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
|
#elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
|
||||||
return Architecture::x86_64;
|
return Architecture::x86_64;
|
||||||
#elif defined(_M_IX86) || defined(_X86_) || defined(i386) || defined(__i386) || defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)
|
#elif defined(_M_IX86) || defined(_X86_) || defined(i386) || defined(__i386) || defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)
|
||||||
return Architecture::x86;
|
return Architecture::x86;
|
||||||
#elif defined(__aarch64__)
|
#elif defined(__aarch64__)
|
||||||
return Architecture::Arm64;
|
return Architecture::Arm64;
|
||||||
#elif defined(__arm__) || defined(_M_ARM)
|
#elif defined(__arm__) || defined(_M_ARM)
|
||||||
return Architecture::Armhf;
|
return Architecture::Armhf;
|
||||||
#else
|
#else
|
||||||
#pragma message ("Target CPU architecture unknown or unsupported !")
|
#pragma message ("Target CPU architecture unknown or unsupported !")
|
||||||
return Architecture::Unknown;
|
return Architecture::Unknown;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,18 +7,18 @@ namespace utils {
|
|||||||
|
|
||||||
template<typename NumberType>
|
template<typename NumberType>
|
||||||
NumberType GetRandomInt(NumberType min, NumberType max) {
|
NumberType GetRandomInt(NumberType min, NumberType max) {
|
||||||
std::random_device randomDevice;
|
std::random_device randomDevice;
|
||||||
std::mt19937 generator(randomDevice());
|
std::mt19937 generator(randomDevice());
|
||||||
std::uniform_int_distribution<NumberType> distrib(min, max);
|
std::uniform_int_distribution<NumberType> distrib(min, max);
|
||||||
return distrib(generator);
|
return distrib(generator);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename NumberType>
|
template<typename NumberType>
|
||||||
NumberType GetRandomReal(NumberType min, NumberType max) {
|
NumberType GetRandomReal(NumberType min, NumberType max) {
|
||||||
std::random_device randomDevice;
|
std::random_device randomDevice;
|
||||||
std::mt19937 generator(randomDevice());
|
std::mt19937 generator(randomDevice());
|
||||||
std::uniform_real_distribution<NumberType> distrib(min, max);
|
std::uniform_real_distribution<NumberType> distrib(min, max);
|
||||||
return distrib(generator);
|
return distrib(generator);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace utils
|
} // namespace utils
|
||||||
|
|||||||
@@ -8,87 +8,87 @@ namespace shape {
|
|||||||
|
|
||||||
class Point {
|
class Point {
|
||||||
private:
|
private:
|
||||||
float m_X, m_Y;
|
float m_X, m_Y;
|
||||||
public:
|
public:
|
||||||
Point() : m_X(0), m_Y(0) {}
|
Point() : m_X(0), m_Y(0) {}
|
||||||
Point(float x, float y) : m_X(x), m_Y(y) {}
|
Point(float x, float y) : m_X(x), m_Y(y) {}
|
||||||
|
|
||||||
float GetX() const { return m_X; }
|
float GetX() const { return m_X; }
|
||||||
float GetY() const { return m_Y; }
|
float GetY() const { return m_Y; }
|
||||||
|
|
||||||
void SetX(float x) { m_X = x; }
|
void SetX(float x) { m_X = x; }
|
||||||
void SetY(float y) { m_Y = y; }
|
void SetY(float y) { m_Y = y; }
|
||||||
|
|
||||||
float Distance(const Point& point) const;
|
float Distance(const Point& point) const;
|
||||||
float DistanceSquared(const Point& point) const;
|
float DistanceSquared(const Point& point) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Circle;
|
class Circle;
|
||||||
|
|
||||||
class Rectangle {
|
class Rectangle {
|
||||||
private:
|
private:
|
||||||
Point m_Center;
|
Point m_Center;
|
||||||
float m_Width, m_Height;
|
float m_Width, m_Height;
|
||||||
public:
|
public:
|
||||||
Rectangle() {}
|
Rectangle() {}
|
||||||
|
|
||||||
const Point& GetCenter() const { return m_Center; }
|
const Point& GetCenter() const { return m_Center; }
|
||||||
float GetCenterX() const { return m_Center.GetX(); }
|
float GetCenterX() const { return m_Center.GetX(); }
|
||||||
float GetCenterY() const { return m_Center.GetY(); }
|
float GetCenterY() const { return m_Center.GetY(); }
|
||||||
|
|
||||||
float GetWidth() const { return m_Width; }
|
float GetWidth() const { return m_Width; }
|
||||||
float GetHeight() const { return m_Height; }
|
float GetHeight() const { return m_Height; }
|
||||||
|
|
||||||
Point GetTopLeft() const { return { m_Center.GetX() - (m_Width / 2.0f), m_Center.GetY() - (m_Height / 2.0f) }; }
|
Point GetTopLeft() const { return { m_Center.GetX() - (m_Width / 2.0f), m_Center.GetY() - (m_Height / 2.0f) }; }
|
||||||
Point GetBottomRight() const { return { m_Center.GetX() + (m_Width / 2.0f), m_Center.GetY() + (m_Height / 2.0f) }; }
|
Point GetBottomRight() const { return { m_Center.GetX() + (m_Width / 2.0f), m_Center.GetY() + (m_Height / 2.0f) }; }
|
||||||
|
|
||||||
void SetCenter(const Point& center) { m_Center = center; }
|
void SetCenter(const Point& center) { m_Center = center; }
|
||||||
void SetCenterX(float x) { m_Center.SetX(x); }
|
void SetCenterX(float x) { m_Center.SetX(x); }
|
||||||
void SetCenterY(float y) { m_Center.SetY(y); }
|
void SetCenterY(float y) { m_Center.SetY(y); }
|
||||||
|
|
||||||
void SetSize(float width, float height) { SetWidth(width); SetHeight(height); }
|
void SetSize(float width, float height) { SetWidth(width); SetHeight(height); }
|
||||||
void SetSize(Point size) { SetSize(size.GetX(), size.GetY()); }
|
void SetSize(Point size) { SetSize(size.GetX(), size.GetY()); }
|
||||||
Point GetSize() { return { m_Width, m_Height }; }
|
Point GetSize() { return { m_Width, m_Height }; }
|
||||||
|
|
||||||
void SetWidth(float width) { m_Width = width; }
|
void SetWidth(float width) { m_Width = width; }
|
||||||
void SetHeight(float height) { m_Height = height; }
|
void SetHeight(float height) { m_Height = height; }
|
||||||
|
|
||||||
bool CollidesWith(const Point& point) const;
|
bool CollidesWith(const Point& point) const;
|
||||||
bool CollidesWith(const Rectangle& rect) const;
|
bool CollidesWith(const Rectangle& rect) const;
|
||||||
bool CollidesWith(const Circle& circle) const;
|
bool CollidesWith(const Circle& circle) const;
|
||||||
|
|
||||||
// distance from the closest side of the rectangle
|
// distance from the closest side of the rectangle
|
||||||
float Distance(const Circle& circle) const;
|
float Distance(const Circle& circle) const;
|
||||||
float DistanceSquared(const Circle& circle) const;
|
float DistanceSquared(const Circle& circle) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Circle {
|
class Circle {
|
||||||
private:
|
private:
|
||||||
Point m_Center;
|
Point m_Center;
|
||||||
float m_Radius;
|
float m_Radius;
|
||||||
public:
|
public:
|
||||||
Circle(float x, float y, float radius) : m_Center(x, y), m_Radius(radius) {}
|
Circle(float x, float y, float radius) : m_Center(x, y), m_Radius(radius) {}
|
||||||
Circle() : m_Radius(0) {}
|
Circle() : m_Radius(0) {}
|
||||||
|
|
||||||
const Point& GetCenter() const { return m_Center; }
|
const Point& GetCenter() const { return m_Center; }
|
||||||
float GetCenterX() const { return m_Center.GetX(); }
|
float GetCenterX() const { return m_Center.GetX(); }
|
||||||
float GetCenterY() const { return m_Center.GetY(); }
|
float GetCenterY() const { return m_Center.GetY(); }
|
||||||
|
|
||||||
float GetRadius() const { return m_Radius; }
|
float GetRadius() const { return m_Radius; }
|
||||||
|
|
||||||
void SetCenter(const Point& center) { m_Center = center; }
|
void SetCenter(const Point& center) { m_Center = center; }
|
||||||
void SetCenterX(float x) { m_Center.SetX(x); }
|
void SetCenterX(float x) { m_Center.SetX(x); }
|
||||||
void SetCenterY(float y) { m_Center.SetY(y); }
|
void SetCenterY(float y) { m_Center.SetY(y); }
|
||||||
|
|
||||||
void SetRadius(float radius) { m_Radius = radius; }
|
void SetRadius(float radius) { m_Radius = radius; }
|
||||||
|
|
||||||
bool CollidesWith(const Point& point) const;
|
bool CollidesWith(const Point& point) const;
|
||||||
bool CollidesWith(const Rectangle& rect) const;
|
bool CollidesWith(const Rectangle& rect) const;
|
||||||
bool CollidesWith(const Circle& circle) const;
|
bool CollidesWith(const Circle& circle) const;
|
||||||
|
|
||||||
// distance from the closest side of the rectangle
|
// distance from the closest side of the rectangle
|
||||||
float Distance(const Rectangle& rect) const;
|
float Distance(const Rectangle& rect) const;
|
||||||
float DistanceSquared(const Rectangle& rect) const;
|
float DistanceSquared(const Rectangle& rect) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace shape
|
} // namespace shape
|
||||||
|
|||||||
@@ -14,62 +14,62 @@ typedef std::function<void()> TimerExecFunction;
|
|||||||
// utililty class to call function at regular period of time
|
// utililty class to call function at regular period of time
|
||||||
class AutoTimer {
|
class AutoTimer {
|
||||||
private:
|
private:
|
||||||
std::uint64_t m_Interval;
|
std::uint64_t m_Interval;
|
||||||
TimerExecFunction m_Function;
|
TimerExecFunction m_Function;
|
||||||
|
|
||||||
std::uint64_t m_LastTime = GetTime();
|
std::uint64_t m_LastTime = GetTime();
|
||||||
std::uint64_t m_InternalTime = 0;
|
std::uint64_t m_InternalTime = 0;
|
||||||
public:
|
public:
|
||||||
AutoTimer() : m_Interval(0), m_Function(nullptr) {}
|
AutoTimer() : m_Interval(0), m_Function(nullptr) {}
|
||||||
AutoTimer(std::uint64_t interval) : m_Interval(interval), m_Function(nullptr) {}
|
AutoTimer(std::uint64_t interval) : m_Interval(interval), m_Function(nullptr) {}
|
||||||
AutoTimer(std::uint64_t interval, TimerExecFunction callback) : m_Interval(interval), m_Function(callback) {}
|
AutoTimer(std::uint64_t interval, TimerExecFunction callback) : m_Interval(interval), m_Function(callback) {}
|
||||||
|
|
||||||
void Update();
|
void Update();
|
||||||
void Update(std::uint64_t delta);
|
void Update(std::uint64_t delta);
|
||||||
|
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
void SetInterval(std::uint64_t newInterval) { m_Interval = newInterval; }
|
void SetInterval(std::uint64_t newInterval) { m_Interval = newInterval; }
|
||||||
std::uint64_t GetInterval() const { return m_Interval; }
|
std::uint64_t GetInterval() const { return m_Interval; }
|
||||||
|
|
||||||
void SetCallbackFunction(TimerExecFunction newCallback) { m_Function = newCallback; }
|
void SetCallbackFunction(TimerExecFunction newCallback) { m_Function = newCallback; }
|
||||||
TimerExecFunction GetCallbackFunction() const { return m_Function; }
|
TimerExecFunction GetCallbackFunction() const { return m_Function; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// utililty class to call function at regular period of time
|
// utililty class to call function at regular period of time
|
||||||
class Timer {
|
class Timer {
|
||||||
private:
|
private:
|
||||||
std::uint64_t m_Interval; // in millis
|
std::uint64_t m_Interval; // in millis
|
||||||
std::uint64_t m_InternalTime = 0;
|
std::uint64_t m_InternalTime = 0;
|
||||||
public:
|
public:
|
||||||
Timer() : m_Interval(0) {}
|
Timer() : m_Interval(0) {}
|
||||||
Timer(std::uint64_t interval) : m_Interval(interval) {}
|
Timer(std::uint64_t interval) : m_Interval(interval) {}
|
||||||
|
|
||||||
bool Update(std::uint64_t delta);
|
bool Update(std::uint64_t delta);
|
||||||
|
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
void SetInterval(std::uint64_t newInterval) { m_Interval = newInterval; }
|
void SetInterval(std::uint64_t newInterval) { m_Interval = newInterval; }
|
||||||
std::uint64_t GetInterval() const { return m_Interval; }
|
std::uint64_t GetInterval() const { return m_Interval; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// utililty class to call function at regular period of time with a cooldown (used for towers and mobs )
|
// utililty class to call function at regular period of time with a cooldown (used for towers and mobs )
|
||||||
class CooldownTimer {
|
class CooldownTimer {
|
||||||
private:
|
private:
|
||||||
std::uint64_t m_Cooldown; // in millis
|
std::uint64_t m_Cooldown; // in millis
|
||||||
std::uint64_t m_CooldownTime;
|
std::uint64_t m_CooldownTime;
|
||||||
public:
|
public:
|
||||||
CooldownTimer() : m_Cooldown(0), m_CooldownTime(0) {}
|
CooldownTimer() : m_Cooldown(0), m_CooldownTime(0) {}
|
||||||
CooldownTimer(std::uint64_t cooldown) : m_Cooldown(0), m_CooldownTime(cooldown) {}
|
CooldownTimer(std::uint64_t cooldown) : m_Cooldown(0), m_CooldownTime(cooldown) {}
|
||||||
|
|
||||||
bool Update(std::uint64_t delta);
|
bool Update(std::uint64_t delta);
|
||||||
|
|
||||||
void ApplyCooldown();
|
void ApplyCooldown();
|
||||||
|
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
void SetCooldown(std::uint64_t newCooldown) { m_CooldownTime = newCooldown; }
|
void SetCooldown(std::uint64_t newCooldown) { m_CooldownTime = newCooldown; }
|
||||||
std::uint64_t GetCooldown() const { return m_CooldownTime; }
|
std::uint64_t GetCooldown() const { return m_CooldownTime; }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace utils
|
} // namespace utils
|
||||||
|
|||||||
@@ -11,38 +11,38 @@ namespace network {
|
|||||||
/* IPv4 address */
|
/* IPv4 address */
|
||||||
class IPAddress {
|
class IPAddress {
|
||||||
private:
|
private:
|
||||||
std::uint32_t m_Address;
|
std::uint32_t m_Address;
|
||||||
bool m_Valid;
|
bool m_Valid;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/* Create an invalid address */
|
/* Create an invalid address */
|
||||||
IPAddress() noexcept;
|
IPAddress() noexcept;
|
||||||
|
|
||||||
/* Initialize by string IP */
|
/* Initialize by string IP */
|
||||||
IPAddress(const std::string& str);
|
IPAddress(const std::string& str);
|
||||||
|
|
||||||
/* Initialize by string IP */
|
/* Initialize by string IP */
|
||||||
IPAddress(const std::wstring& str);
|
IPAddress(const std::wstring& str);
|
||||||
|
|
||||||
/* Initialize by octets */
|
/* Initialize by octets */
|
||||||
IPAddress(std::uint8_t octet1, std::uint8_t octet2, std::uint8_t octet3, std::uint8_t octet4) noexcept;
|
IPAddress(std::uint8_t octet1, std::uint8_t octet2, std::uint8_t octet3, std::uint8_t octet4) noexcept;
|
||||||
|
|
||||||
/* Get the specific octet. 1-4 */
|
/* Get the specific octet. 1-4 */
|
||||||
std::uint8_t GetOctet(std::uint8_t num) const;
|
std::uint8_t GetOctet(std::uint8_t num) const;
|
||||||
|
|
||||||
/* Set the specific octet. 1-4 */
|
/* Set the specific octet. 1-4 */
|
||||||
void SetOctet(std::uint8_t num, std::uint8_t value);
|
void SetOctet(std::uint8_t num, std::uint8_t value);
|
||||||
|
|
||||||
/* Make sure the IP is valid. It will be invalid if the host wasn't found. */
|
/* Make sure the IP is valid. It will be invalid if the host wasn't found. */
|
||||||
bool IsValid() const noexcept { return m_Valid; }
|
bool IsValid() const noexcept { return m_Valid; }
|
||||||
|
|
||||||
std::string ToString() const;
|
std::string ToString() const;
|
||||||
|
|
||||||
static IPAddress LocalAddress();
|
static IPAddress LocalAddress();
|
||||||
|
|
||||||
bool operator==(const IPAddress& right);
|
bool operator==(const IPAddress& right);
|
||||||
bool operator!=(const IPAddress& right);
|
bool operator!=(const IPAddress& right);
|
||||||
bool operator==(bool b);
|
bool operator==(bool b);
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<IPAddress> IPAddresses;
|
typedef std::vector<IPAddress> IPAddresses;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ namespace network {
|
|||||||
|
|
||||||
class Dns {
|
class Dns {
|
||||||
public:
|
public:
|
||||||
static IPAddresses Resolve(const std::string& host);
|
static IPAddresses Resolve(const std::string& host);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // ns network
|
} // ns network
|
||||||
|
|||||||
@@ -40,45 +40,45 @@ typedef int SocketHandle;
|
|||||||
|
|
||||||
class Socket {
|
class Socket {
|
||||||
public:
|
public:
|
||||||
enum Status { Connected, Disconnected, Error };
|
enum Status { Connected, Disconnected, Error };
|
||||||
enum Type { TCP, UDP };
|
enum Type { TCP, UDP };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_Blocking;
|
bool m_Blocking;
|
||||||
Type m_Type;
|
Type m_Type;
|
||||||
Status m_Status;
|
Status m_Status;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
SocketHandle m_Handle;
|
SocketHandle m_Handle;
|
||||||
|
|
||||||
Socket(Type type);
|
Socket(Type type);
|
||||||
void SetStatus(Status status);
|
void SetStatus(Status status);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~Socket();
|
virtual ~Socket();
|
||||||
|
|
||||||
Socket(Socket&& rhs) = default;
|
Socket(Socket&& rhs) = default;
|
||||||
Socket& operator=(Socket&& rhs) = default;
|
Socket& operator=(Socket&& rhs) = default;
|
||||||
|
|
||||||
bool SetBlocking(bool block);
|
bool SetBlocking(bool block);
|
||||||
bool IsBlocking() const noexcept;
|
bool IsBlocking() const noexcept;
|
||||||
|
|
||||||
Type GetType() const noexcept;
|
Type GetType() const noexcept;
|
||||||
Status GetStatus() const noexcept;
|
Status GetStatus() const noexcept;
|
||||||
SocketHandle GetHandle() const noexcept;
|
SocketHandle GetHandle() const noexcept;
|
||||||
|
|
||||||
bool Connect(const std::string& ip, std::uint16_t port);
|
bool Connect(const std::string& ip, std::uint16_t port);
|
||||||
virtual bool Connect(const IPAddress& address, std::uint16_t port) = 0;
|
virtual bool Connect(const IPAddress& address, std::uint16_t port) = 0;
|
||||||
|
|
||||||
void Disconnect();
|
void Disconnect();
|
||||||
|
|
||||||
std::size_t Send(const std::string& data);
|
std::size_t Send(const std::string& data);
|
||||||
std::size_t Send(DataBuffer& buffer);
|
std::size_t Send(DataBuffer& buffer);
|
||||||
|
|
||||||
virtual std::size_t Send(const uint8_t* data, std::size_t size) = 0;
|
virtual std::size_t Send(const uint8_t* data, std::size_t size) = 0;
|
||||||
virtual DataBuffer Receive(std::size_t amount) = 0;
|
virtual DataBuffer Receive(std::size_t amount) = 0;
|
||||||
|
|
||||||
virtual std::size_t Receive(DataBuffer& buffer, std::size_t amount) = 0;
|
virtual std::size_t Receive(DataBuffer& buffer, std::size_t amount) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr<Socket> SocketPtr;
|
typedef std::shared_ptr<Socket> SocketPtr;
|
||||||
|
|||||||
@@ -5,30 +5,30 @@ namespace td {
|
|||||||
namespace network {
|
namespace network {
|
||||||
|
|
||||||
class TCPListener {
|
class TCPListener {
|
||||||
int m_Handle;
|
int m_Handle;
|
||||||
std::uint16_t m_Port;
|
std::uint16_t m_Port;
|
||||||
int m_MaxConnections;
|
int m_MaxConnections;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TCPListener();
|
TCPListener();
|
||||||
~TCPListener();
|
~TCPListener();
|
||||||
|
|
||||||
bool Listen(std::uint16_t port, int maxConnections);
|
bool Listen(std::uint16_t port, int maxConnections);
|
||||||
bool Accept(TCPSocket& newSocket);
|
bool Accept(TCPSocket& newSocket);
|
||||||
|
|
||||||
void Destroy();
|
void Destroy();
|
||||||
bool Close();
|
bool Close();
|
||||||
bool SetBlocking(bool blocking);
|
bool SetBlocking(bool blocking);
|
||||||
|
|
||||||
std::uint16_t GetListeningPort() const {
|
std::uint16_t GetListeningPort() const {
|
||||||
return m_Port;
|
return m_Port;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetMaximumConnections() const {
|
int GetMaximumConnections() const {
|
||||||
return m_MaxConnections;
|
return m_MaxConnections;
|
||||||
}
|
}
|
||||||
|
|
||||||
REMOVE_COPY(TCPListener);
|
REMOVE_COPY(TCPListener);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace network
|
} // namespace network
|
||||||
|
|||||||
@@ -13,22 +13,22 @@ class TCPListener;
|
|||||||
|
|
||||||
class TCPSocket : public Socket {
|
class TCPSocket : public Socket {
|
||||||
private:
|
private:
|
||||||
IPAddress m_RemoteIP;
|
IPAddress m_RemoteIP;
|
||||||
uint16_t m_Port;
|
uint16_t m_Port;
|
||||||
sockaddr m_RemoteAddr;
|
sockaddr m_RemoteAddr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TCPSocket();
|
TCPSocket();
|
||||||
TCPSocket(TCPSocket&& other);
|
TCPSocket(TCPSocket&& other);
|
||||||
|
|
||||||
virtual bool Connect(const IPAddress& address, std::uint16_t port);
|
virtual bool Connect(const IPAddress& address, std::uint16_t port);
|
||||||
virtual std::size_t Send(const std::uint8_t* data, std::size_t size);
|
virtual std::size_t Send(const std::uint8_t* data, std::size_t size);
|
||||||
virtual DataBuffer Receive(std::size_t amount);
|
virtual DataBuffer Receive(std::size_t amount);
|
||||||
virtual std::size_t Receive(DataBuffer& buffer, std::size_t amount);
|
virtual std::size_t Receive(DataBuffer& buffer, std::size_t amount);
|
||||||
|
|
||||||
REMOVE_COPY(TCPSocket);
|
REMOVE_COPY(TCPSocket);
|
||||||
|
|
||||||
friend class TCPListener;
|
friend class TCPListener;
|
||||||
};
|
};
|
||||||
|
|
||||||
void SendPacket(const DataBuffer& data, network::TCPSocket& socket);
|
void SendPacket(const DataBuffer& data, network::TCPSocket& socket);
|
||||||
|
|||||||
@@ -11,18 +11,18 @@ namespace network {
|
|||||||
|
|
||||||
class UDPSocket : public Socket {
|
class UDPSocket : public Socket {
|
||||||
private:
|
private:
|
||||||
IPAddress m_RemoteIP;
|
IPAddress m_RemoteIP;
|
||||||
uint16_t m_Port;
|
uint16_t m_Port;
|
||||||
sockaddr_in m_RemoteAddr;
|
sockaddr_in m_RemoteAddr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
UDPSocket();
|
UDPSocket();
|
||||||
|
|
||||||
bool Connect(const IPAddress& address, std::uint16_t port);
|
bool Connect(const IPAddress& address, std::uint16_t port);
|
||||||
std::size_t Send(const std::uint8_t* data, std::size_t size);
|
std::size_t Send(const std::uint8_t* data, std::size_t size);
|
||||||
|
|
||||||
virtual DataBuffer Receive(std::size_t amount);
|
virtual DataBuffer Receive(std::size_t amount);
|
||||||
virtual std::size_t Receive(DataBuffer& buffer, std::size_t amount);
|
virtual std::size_t Receive(DataBuffer& buffer, std::size_t amount);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // ns network
|
} // ns network
|
||||||
|
|||||||
@@ -12,21 +12,21 @@ class PacketHandler;
|
|||||||
|
|
||||||
class PacketDispatcher {
|
class PacketDispatcher {
|
||||||
private:
|
private:
|
||||||
std::map<PacketType, std::vector<PacketHandler*>> m_Handlers;
|
std::map<PacketType, std::vector<PacketHandler*>> m_Handlers;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PacketDispatcher() = default;
|
PacketDispatcher() = default;
|
||||||
|
|
||||||
PacketDispatcher(const PacketDispatcher& rhs) = delete;
|
PacketDispatcher(const PacketDispatcher& rhs) = delete;
|
||||||
PacketDispatcher& operator=(const PacketDispatcher& rhs) = delete;
|
PacketDispatcher& operator=(const PacketDispatcher& rhs) = delete;
|
||||||
PacketDispatcher(PacketDispatcher&& rhs) = delete;
|
PacketDispatcher(PacketDispatcher&& rhs) = delete;
|
||||||
PacketDispatcher& operator=(PacketDispatcher&& rhs) = delete;
|
PacketDispatcher& operator=(PacketDispatcher&& rhs) = delete;
|
||||||
|
|
||||||
void Dispatch(const PacketPtr& packet);
|
void Dispatch(const PacketPtr& packet);
|
||||||
|
|
||||||
void RegisterHandler(PacketType type, PacketHandler* handler);
|
void RegisterHandler(PacketType type, PacketHandler* handler);
|
||||||
void UnregisterHandler(PacketType type, PacketHandler* handler);
|
void UnregisterHandler(PacketType type, PacketHandler* handler);
|
||||||
void UnregisterHandler(PacketHandler* handler);
|
void UnregisterHandler(PacketHandler* handler);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace protocol
|
} // namespace protocol
|
||||||
|
|||||||
@@ -9,39 +9,39 @@ class PacketDispatcher;
|
|||||||
|
|
||||||
class PacketHandler {
|
class PacketHandler {
|
||||||
private:
|
private:
|
||||||
PacketDispatcher* m_Dispatcher;
|
PacketDispatcher* m_Dispatcher;
|
||||||
public:
|
public:
|
||||||
PacketHandler(PacketDispatcher* dispatcher) : m_Dispatcher(dispatcher) {}
|
PacketHandler(PacketDispatcher* dispatcher) : m_Dispatcher(dispatcher) {}
|
||||||
virtual ~PacketHandler() {}
|
virtual ~PacketHandler() {}
|
||||||
|
|
||||||
PacketDispatcher* GetDispatcher() { return m_Dispatcher; }
|
PacketDispatcher* GetDispatcher() { return m_Dispatcher; }
|
||||||
|
|
||||||
virtual void HandlePacket(const ConnexionInfoPacket* packet) {}
|
virtual void HandlePacket(const ConnexionInfoPacket* packet) {}
|
||||||
virtual void HandlePacket(const DisconnectPacket* packet) {}
|
virtual void HandlePacket(const DisconnectPacket* packet) {}
|
||||||
virtual void HandlePacket(const KeepAlivePacket* packet) {}
|
virtual void HandlePacket(const KeepAlivePacket* packet) {}
|
||||||
virtual void HandlePacket(const PlaceTowerPacket* packet) {}
|
virtual void HandlePacket(const PlaceTowerPacket* packet) {}
|
||||||
virtual void HandlePacket(const PlayerBuyItemPacket* packet) {}
|
virtual void HandlePacket(const PlayerBuyItemPacket* packet) {}
|
||||||
virtual void HandlePacket(const PlayerBuyMobUpgradePacket* packet) {}
|
virtual void HandlePacket(const PlayerBuyMobUpgradePacket* packet) {}
|
||||||
virtual void HandlePacket(const PlayerJoinPacket* packet) {}
|
virtual void HandlePacket(const PlayerJoinPacket* packet) {}
|
||||||
virtual void HandlePacket(const PlayerLeavePacket* packet) {}
|
virtual void HandlePacket(const PlayerLeavePacket* packet) {}
|
||||||
virtual void HandlePacket(const PlayerListPacket* packet) {}
|
virtual void HandlePacket(const PlayerListPacket* packet) {}
|
||||||
virtual void HandlePacket(const PlayerLoginPacket* packet) {}
|
virtual void HandlePacket(const PlayerLoginPacket* packet) {}
|
||||||
virtual void HandlePacket(const RemoveTowerPacket* packet) {}
|
virtual void HandlePacket(const RemoveTowerPacket* packet) {}
|
||||||
virtual void HandlePacket(const SelectTeamPacket* packet) {}
|
virtual void HandlePacket(const SelectTeamPacket* packet) {}
|
||||||
virtual void HandlePacket(const SendMobsPacket* packet) {}
|
virtual void HandlePacket(const SendMobsPacket* packet) {}
|
||||||
virtual void HandlePacket(const ServerTpsPacket* packet) {}
|
virtual void HandlePacket(const ServerTpsPacket* packet) {}
|
||||||
virtual void HandlePacket(const SpawnMobPacket* packet) {}
|
virtual void HandlePacket(const SpawnMobPacket* packet) {}
|
||||||
virtual void HandlePacket(const UpdateCastleLifePacket* packet) {}
|
virtual void HandlePacket(const UpdateCastleLifePacket* packet) {}
|
||||||
virtual void HandlePacket(const UpdateExpPacket* packet) {}
|
virtual void HandlePacket(const UpdateExpPacket* packet) {}
|
||||||
virtual void HandlePacket(const UpdateGameStatePacket* packet) {}
|
virtual void HandlePacket(const UpdateGameStatePacket* packet) {}
|
||||||
virtual void HandlePacket(const UpdateLobbyTimePacket* packet) {}
|
virtual void HandlePacket(const UpdateLobbyTimePacket* packet) {}
|
||||||
virtual void HandlePacket(const UpdateMobStatesPacket* packet) {}
|
virtual void HandlePacket(const UpdateMobStatesPacket* packet) {}
|
||||||
virtual void HandlePacket(const UpdateMoneyPacket* packet) {}
|
virtual void HandlePacket(const UpdateMoneyPacket* packet) {}
|
||||||
virtual void HandlePacket(const UpdatePlayerTeamPacket* packet) {}
|
virtual void HandlePacket(const UpdatePlayerTeamPacket* packet) {}
|
||||||
virtual void HandlePacket(const UpgradeTowerPacket* packet) {}
|
virtual void HandlePacket(const UpgradeTowerPacket* packet) {}
|
||||||
virtual void HandlePacket(const WorldAddTowerPacket* packet) {}
|
virtual void HandlePacket(const WorldAddTowerPacket* packet) {}
|
||||||
virtual void HandlePacket(const WorldBeginDataPacket* packet) {}
|
virtual void HandlePacket(const WorldBeginDataPacket* packet) {}
|
||||||
virtual void HandlePacket(const WorldDataPacket* packet) {}
|
virtual void HandlePacket(const WorldDataPacket* packet) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace protocol
|
} // namespace protocol
|
||||||
|
|||||||
@@ -12,621 +12,627 @@ namespace protocol {
|
|||||||
class PacketHandler;
|
class PacketHandler;
|
||||||
|
|
||||||
enum class PacketType : std::uint8_t {
|
enum class PacketType : std::uint8_t {
|
||||||
// client --> server
|
// client --> server
|
||||||
PlayerLogin = 0,
|
PlayerLogin = 0,
|
||||||
SelectTeam,
|
SelectTeam,
|
||||||
SpawnMob,
|
SpawnMob,
|
||||||
SendMobs,
|
SendMobs,
|
||||||
PlaceTower,
|
PlaceTower,
|
||||||
|
|
||||||
// client <-- server
|
// client <-- server
|
||||||
PlayerJoin,
|
PlayerJoin,
|
||||||
PlayerLeave,
|
PlayerLeave,
|
||||||
WorldBeginData,
|
WorldBeginData,
|
||||||
WorldData,
|
WorldData,
|
||||||
UpdateMoney,
|
UpdateMoney,
|
||||||
UpdateEXP,
|
UpdateEXP,
|
||||||
UpdateLobbyTime,
|
UpdateLobbyTime,
|
||||||
UpdateGameState,
|
UpdateGameState,
|
||||||
PlayerList,
|
PlayerList,
|
||||||
ConnectionInfo,
|
ConnectionInfo,
|
||||||
UpdatePlayerTeam,
|
UpdatePlayerTeam,
|
||||||
ServerTps,
|
ServerTps,
|
||||||
WorldAddTower,
|
WorldAddTower,
|
||||||
UpdateMobStates,
|
UpdateMobStates,
|
||||||
UpdateCastleLife,
|
UpdateCastleLife,
|
||||||
|
|
||||||
// client <--> server
|
// client <--> server
|
||||||
KeepAlive,
|
KeepAlive,
|
||||||
Disconnect,
|
Disconnect,
|
||||||
UpgradeTower,
|
UpgradeTower,
|
||||||
RemoveTower,
|
RemoveTower,
|
||||||
PlayerBuyItem,
|
PlayerBuyItem,
|
||||||
PlayerBuyMobUpgrade,
|
PlayerBuyMobUpgrade,
|
||||||
|
|
||||||
PACKET_COUNT
|
PACKET_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WorldHeader {
|
struct WorldHeader {
|
||||||
game::TowerTileColorPalette m_TowerPlacePalette;
|
game::TowerTileColorPalette m_TowerPlacePalette;
|
||||||
game::Color m_WalkablePalette;
|
Color m_WalkablePalette;
|
||||||
std::vector<game::Color> m_DecorationPalette;
|
std::vector<Color> m_DecorationPalette;
|
||||||
game::Color m_Background;
|
Color m_Background;
|
||||||
|
|
||||||
game::SpawnColorPalette m_SpawnColorPalette;
|
game::SpawnColorPalette m_SpawnColorPalette;
|
||||||
|
|
||||||
game::TilePalette m_TilePalette;
|
game::TilePalette m_TilePalette;
|
||||||
|
|
||||||
game::Spawn m_RedSpawn, m_BlueSpawn;
|
game::Spawn m_RedSpawn, m_BlueSpawn;
|
||||||
game::TeamCastle m_RedCastle, m_BlueCastle;
|
game::TeamCastle m_RedCastle, m_BlueCastle;
|
||||||
|
|
||||||
const game::World* m_World;
|
const game::World* m_World;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WorldData {
|
struct WorldData {
|
||||||
std::unordered_map<game::ChunkCoord, game::ChunkPtr> m_Chunks;
|
std::unordered_map<game::ChunkCoord, game::ChunkPtr> m_Chunks;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Packet {
|
class Packet {
|
||||||
public:
|
public:
|
||||||
Packet() {}
|
Packet() {}
|
||||||
virtual ~Packet() {}
|
virtual ~Packet() {}
|
||||||
|
|
||||||
virtual DataBuffer Serialize(bool packetID = true) const = 0;
|
virtual DataBuffer Serialize(bool packetID = true) const = 0;
|
||||||
virtual void Deserialize(DataBuffer& data) = 0;
|
virtual void Deserialize(DataBuffer& data) = 0;
|
||||||
virtual void Dispatch(PacketHandler* handler) const = 0;
|
virtual void Dispatch(PacketHandler* handler) const = 0;
|
||||||
|
|
||||||
void WritePacketID(DataBuffer& data, bool packetID) const;
|
void WritePacketID(DataBuffer& data, bool packetID) const;
|
||||||
|
|
||||||
virtual PacketType GetType() const = 0;
|
virtual PacketType GetType() const = 0;
|
||||||
std::uint8_t GetID() const { return static_cast<std::uint8_t>(GetType()); }
|
std::uint8_t GetID() const { return static_cast<std::uint8_t>(GetType()); }
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::unique_ptr<Packet> PacketPtr;
|
typedef std::unique_ptr<Packet> PacketPtr;
|
||||||
|
|
||||||
class KeepAlivePacket : public Packet {
|
class KeepAlivePacket : public Packet {
|
||||||
private:
|
private:
|
||||||
std::uint64_t m_AliveID;
|
std::uint64_t m_AliveID;
|
||||||
public:
|
public:
|
||||||
KeepAlivePacket() {}
|
KeepAlivePacket() {}
|
||||||
KeepAlivePacket(std::uint64_t aliveID) : m_AliveID(aliveID) {}
|
KeepAlivePacket(std::uint64_t aliveID) : m_AliveID(aliveID) {}
|
||||||
virtual ~KeepAlivePacket() {}
|
virtual ~KeepAlivePacket() {}
|
||||||
|
|
||||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||||
virtual void Deserialize(DataBuffer& data);
|
virtual void Deserialize(DataBuffer& data);
|
||||||
virtual void Dispatch(PacketHandler* handler) const;
|
virtual void Dispatch(PacketHandler* handler) const;
|
||||||
|
|
||||||
std::uint64_t GetAliveID() const { return m_AliveID; }
|
std::uint64_t GetAliveID() const { return m_AliveID; }
|
||||||
|
|
||||||
virtual PacketType GetType() const { return PacketType::KeepAlive; }
|
virtual PacketType GetType() const { return PacketType::KeepAlive; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class PlayerLoginPacket : public Packet {
|
class PlayerLoginPacket : public Packet {
|
||||||
private:
|
private:
|
||||||
std::string m_PlayerName;
|
std::string m_PlayerName;
|
||||||
public:
|
public:
|
||||||
PlayerLoginPacket() {}
|
PlayerLoginPacket() {}
|
||||||
PlayerLoginPacket(std::string playerName) : m_PlayerName(playerName) {}
|
PlayerLoginPacket(std::string playerName) : m_PlayerName(playerName) {}
|
||||||
virtual ~PlayerLoginPacket() {}
|
virtual ~PlayerLoginPacket() {}
|
||||||
|
|
||||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||||
virtual void Deserialize(DataBuffer& data);
|
virtual void Deserialize(DataBuffer& data);
|
||||||
virtual void Dispatch(PacketHandler* handler) const;
|
virtual void Dispatch(PacketHandler* handler) const;
|
||||||
|
|
||||||
virtual PacketType GetType() const { return PacketType::PlayerLogin; }
|
virtual PacketType GetType() const { return PacketType::PlayerLogin; }
|
||||||
|
|
||||||
const std::string& GetPlayerName() const { return m_PlayerName; }
|
const std::string& GetPlayerName() const { return m_PlayerName; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class WorldBeginDataPacket : public Packet {
|
class WorldBeginDataPacket : public Packet {
|
||||||
private:
|
private:
|
||||||
WorldHeader m_Header;
|
WorldHeader m_Header;
|
||||||
public:
|
public:
|
||||||
WorldBeginDataPacket() {}
|
WorldBeginDataPacket() {}
|
||||||
WorldBeginDataPacket(const game::World* world) {
|
WorldBeginDataPacket(const game::World* world) {
|
||||||
m_Header.m_World = world;
|
m_Header.m_World = world;
|
||||||
}
|
}
|
||||||
virtual ~WorldBeginDataPacket() {}
|
virtual ~WorldBeginDataPacket() {}
|
||||||
|
|
||||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||||
virtual void Deserialize(DataBuffer& data);
|
virtual void Deserialize(DataBuffer& data);
|
||||||
virtual void Dispatch(PacketHandler* handler) const;
|
virtual void Dispatch(PacketHandler* handler) const;
|
||||||
|
|
||||||
virtual PacketType GetType() const { return PacketType::WorldBeginData; }
|
virtual PacketType GetType() const { return PacketType::WorldBeginData; }
|
||||||
|
|
||||||
const game::TowerTileColorPalette& GetTowerTilePalette() const { return m_Header.m_TowerPlacePalette; }
|
const game::TowerTileColorPalette& GetTowerTilePalette() const { return m_Header.m_TowerPlacePalette; }
|
||||||
const game::Color& GetWalkableTileColor() const { return m_Header.m_WalkablePalette; }
|
const Color& GetWalkableTileColor() const { return m_Header.m_WalkablePalette; }
|
||||||
const std::vector<game::Color>& GetDecorationPalette() const { return m_Header.m_DecorationPalette; }
|
const std::vector<Color>& GetDecorationPalette() const { return m_Header.m_DecorationPalette; }
|
||||||
const game::Color& GetBackgroundColor() const { return m_Header.m_Background; }
|
const Color& GetBackgroundColor() const { return m_Header.m_Background; }
|
||||||
|
|
||||||
const game::Spawn& GetRedSpawn() const { return m_Header.m_RedSpawn; }
|
const game::Spawn& GetRedSpawn() const { return m_Header.m_RedSpawn; }
|
||||||
const game::Spawn& GetBlueSpawn() const { return m_Header.m_BlueSpawn; }
|
const game::Spawn& GetBlueSpawn() const { return m_Header.m_BlueSpawn; }
|
||||||
|
|
||||||
const game::SpawnColorPalette& GetSpawnPalette() const { return m_Header.m_SpawnColorPalette; }
|
const game::SpawnColorPalette& GetSpawnPalette() const { return m_Header.m_SpawnColorPalette; }
|
||||||
|
|
||||||
const game::TeamCastle& GetRedCastle() const { return m_Header.m_RedCastle; }
|
const game::TeamCastle& GetRedCastle() const { return m_Header.m_RedCastle; }
|
||||||
const game::TeamCastle& GetBlueCastle() const { return m_Header.m_BlueCastle; }
|
const game::TeamCastle& GetBlueCastle() const { return m_Header.m_BlueCastle; }
|
||||||
|
|
||||||
const game::TilePalette GetTilePalette() const { return m_Header.m_TilePalette; }
|
const game::TilePalette GetTilePalette() const { return m_Header.m_TilePalette; }
|
||||||
|
|
||||||
void setWorldHeader(const WorldHeader& header) { m_Header = header; }
|
void setWorldHeader(const WorldHeader& header) { m_Header = header; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class WorldDataPacket : public Packet {
|
class WorldDataPacket : public Packet {
|
||||||
private:
|
private:
|
||||||
WorldData m_WorldData;
|
WorldData m_WorldData;
|
||||||
|
|
||||||
const game::World* m_World;
|
const game::World* m_World;
|
||||||
public:
|
public:
|
||||||
WorldDataPacket() {}
|
WorldDataPacket() {}
|
||||||
WorldDataPacket(const game::World* world) : m_World(world) {}
|
WorldDataPacket(const game::World* world) : m_World(world) {}
|
||||||
virtual ~WorldDataPacket() {}
|
virtual ~WorldDataPacket() {}
|
||||||
|
|
||||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||||
virtual void Deserialize(DataBuffer& data);
|
virtual void Deserialize(DataBuffer& data);
|
||||||
virtual void Dispatch(PacketHandler* handler) const;
|
virtual void Dispatch(PacketHandler* handler) const;
|
||||||
|
|
||||||
virtual PacketType GetType() const { return PacketType::WorldData; }
|
virtual PacketType GetType() const { return PacketType::WorldData; }
|
||||||
|
|
||||||
const std::unordered_map<game::ChunkCoord, game::ChunkPtr>& GetChunks() const { return m_WorldData.m_Chunks; }
|
const std::unordered_map<game::ChunkCoord, game::ChunkPtr>& GetChunks() const { return m_WorldData.m_Chunks; }
|
||||||
|
|
||||||
DataBuffer SerializeCustom() const; // allow serialisation with invalid World member
|
DataBuffer SerializeCustom() const; // allow serialisation with invalid World member
|
||||||
void SetWorldData(const WorldData& worldData) { m_WorldData = worldData; }
|
void SetWorldData(const WorldData& worldData) { m_WorldData = worldData; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class UpdateMoneyPacket : public Packet {
|
class UpdateMoneyPacket : public Packet {
|
||||||
private:
|
private:
|
||||||
std::uint32_t m_NewAmount;
|
std::uint32_t m_NewAmount;
|
||||||
public:
|
public:
|
||||||
UpdateMoneyPacket() {}
|
UpdateMoneyPacket() {}
|
||||||
UpdateMoneyPacket(std::uint32_t newAmount) : m_NewAmount(newAmount) {}
|
UpdateMoneyPacket(std::uint32_t newAmount) : m_NewAmount(newAmount) {}
|
||||||
virtual ~UpdateMoneyPacket() {}
|
virtual ~UpdateMoneyPacket() {}
|
||||||
|
|
||||||
std::uint32_t GetGold() const { return m_NewAmount; }
|
std::uint32_t GetGold() const { return m_NewAmount; }
|
||||||
|
|
||||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||||
virtual void Deserialize(DataBuffer& data);
|
virtual void Deserialize(DataBuffer& data);
|
||||||
virtual void Dispatch(PacketHandler* handler) const;
|
virtual void Dispatch(PacketHandler* handler) const;
|
||||||
|
|
||||||
virtual PacketType GetType() const { return PacketType::UpdateMoney; }
|
virtual PacketType GetType() const { return PacketType::UpdateMoney; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class UpdateExpPacket : public Packet {
|
class UpdateExpPacket : public Packet {
|
||||||
private:
|
private:
|
||||||
std::uint32_t m_NewAmount;
|
std::uint32_t m_NewAmount;
|
||||||
public:
|
public:
|
||||||
UpdateExpPacket() {}
|
UpdateExpPacket() {}
|
||||||
UpdateExpPacket(std::uint32_t newAmount) : m_NewAmount(newAmount) {}
|
UpdateExpPacket(std::uint32_t newAmount) : m_NewAmount(newAmount) {}
|
||||||
virtual ~UpdateExpPacket() {}
|
virtual ~UpdateExpPacket() {}
|
||||||
|
|
||||||
std::uint32_t GetExp() const { return m_NewAmount; }
|
std::uint32_t GetExp() const { return m_NewAmount; }
|
||||||
|
|
||||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||||
virtual void Deserialize(DataBuffer& data);
|
virtual void Deserialize(DataBuffer& data);
|
||||||
virtual void Dispatch(PacketHandler* handler) const;
|
virtual void Dispatch(PacketHandler* handler) const;
|
||||||
|
|
||||||
virtual PacketType GetType() const { return PacketType::UpdateEXP; }
|
virtual PacketType GetType() const { return PacketType::UpdateEXP; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class UpdateLobbyTimePacket : public Packet {
|
class UpdateLobbyTimePacket : public Packet {
|
||||||
private:
|
private:
|
||||||
std::uint32_t m_RemainingTime;
|
std::uint32_t m_RemainingTime;
|
||||||
public:
|
public:
|
||||||
UpdateLobbyTimePacket() {}
|
UpdateLobbyTimePacket() {}
|
||||||
UpdateLobbyTimePacket(std::uint32_t remainingTime) : m_RemainingTime(remainingTime) {}
|
UpdateLobbyTimePacket(std::uint32_t remainingTime) : m_RemainingTime(remainingTime) {}
|
||||||
virtual ~UpdateLobbyTimePacket() {}
|
virtual ~UpdateLobbyTimePacket() {}
|
||||||
|
|
||||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||||
virtual void Deserialize(DataBuffer& data);
|
virtual void Deserialize(DataBuffer& data);
|
||||||
virtual void Dispatch(PacketHandler* handler) const;
|
virtual void Dispatch(PacketHandler* handler) const;
|
||||||
|
|
||||||
std::uint32_t GetRemainingTime() const { return m_RemainingTime; }
|
std::uint32_t GetRemainingTime() const { return m_RemainingTime; }
|
||||||
|
|
||||||
virtual PacketType GetType() const { return PacketType::UpdateLobbyTime; }
|
virtual PacketType GetType() const { return PacketType::UpdateLobbyTime; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class UpdateGameStatePacket : public Packet {
|
class UpdateGameStatePacket : public Packet {
|
||||||
private:
|
private:
|
||||||
game::GameState m_GameState;
|
game::GameState m_GameState;
|
||||||
public:
|
public:
|
||||||
UpdateGameStatePacket() {}
|
UpdateGameStatePacket() {}
|
||||||
UpdateGameStatePacket(game::GameState gameState) : m_GameState(gameState) {}
|
UpdateGameStatePacket(game::GameState gameState) : m_GameState(gameState) {}
|
||||||
virtual ~UpdateGameStatePacket() {}
|
virtual ~UpdateGameStatePacket() {}
|
||||||
|
|
||||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||||
virtual void Deserialize(DataBuffer& data);
|
virtual void Deserialize(DataBuffer& data);
|
||||||
virtual void Dispatch(PacketHandler* handler) const;
|
virtual void Dispatch(PacketHandler* handler) const;
|
||||||
|
|
||||||
game::GameState GetGameState() const { return m_GameState; }
|
game::GameState GetGameState() const { return m_GameState; }
|
||||||
|
|
||||||
virtual PacketType GetType() const { return PacketType::UpdateGameState; }
|
virtual PacketType GetType() const { return PacketType::UpdateGameState; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PlayerInfo {
|
struct PlayerInfo {
|
||||||
std::string name;
|
std::string name;
|
||||||
game::TeamColor team;
|
game::TeamColor team;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PlayerListPacket : public Packet {
|
class PlayerListPacket : public Packet {
|
||||||
private:
|
private:
|
||||||
std::map<std::uint8_t, PlayerInfo> m_Players;
|
std::map<std::uint8_t, PlayerInfo> m_Players;
|
||||||
public:
|
public:
|
||||||
PlayerListPacket() {}
|
PlayerListPacket() {}
|
||||||
PlayerListPacket(std::map<std::uint8_t, PlayerInfo> players) : m_Players(players) {}
|
PlayerListPacket(std::map<std::uint8_t, PlayerInfo> players) : m_Players(players) {}
|
||||||
virtual ~PlayerListPacket() {}
|
virtual ~PlayerListPacket() {}
|
||||||
|
|
||||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||||
virtual void Deserialize(DataBuffer& data);
|
virtual void Deserialize(DataBuffer& data);
|
||||||
virtual void Dispatch(PacketHandler* handler) const;
|
virtual void Dispatch(PacketHandler* handler) const;
|
||||||
|
|
||||||
const std::map<std::uint8_t, PlayerInfo>& GetPlayers() const { return m_Players; }
|
const std::map<std::uint8_t, PlayerInfo>& GetPlayers() const { return m_Players; }
|
||||||
|
|
||||||
virtual PacketType GetType() const { return PacketType::PlayerList; }
|
virtual PacketType GetType() const { return PacketType::PlayerList; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class PlayerJoinPacket : public Packet {
|
class PlayerJoinPacket : public Packet {
|
||||||
private:
|
private:
|
||||||
std::uint8_t m_PlayerID;
|
std::uint8_t m_PlayerID;
|
||||||
std::string m_PlayerName;
|
std::string m_PlayerName;
|
||||||
public:
|
public:
|
||||||
PlayerJoinPacket() {}
|
PlayerJoinPacket() {}
|
||||||
PlayerJoinPacket(std::uint8_t playerID, const std::string& playerName) : m_PlayerID(playerID), m_PlayerName(playerName) {}
|
PlayerJoinPacket(std::uint8_t playerID, const std::string& playerName) : m_PlayerID(playerID), m_PlayerName(playerName) {}
|
||||||
virtual ~PlayerJoinPacket() {}
|
virtual ~PlayerJoinPacket() {}
|
||||||
|
|
||||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||||
virtual void Deserialize(DataBuffer& data);
|
virtual void Deserialize(DataBuffer& data);
|
||||||
virtual void Dispatch(PacketHandler* handler) const;
|
virtual void Dispatch(PacketHandler* handler) const;
|
||||||
|
|
||||||
std::uint8_t GetPlayerID() const { return m_PlayerID; }
|
std::uint8_t GetPlayerID() const { return m_PlayerID; }
|
||||||
const std::string& GetPlayerName() const { return m_PlayerName; }
|
const std::string& GetPlayerName() const { return m_PlayerName; }
|
||||||
|
|
||||||
virtual PacketType GetType() const { return PacketType::PlayerJoin; }
|
virtual PacketType GetType() const { return PacketType::PlayerJoin; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class PlayerLeavePacket : public Packet {
|
class PlayerLeavePacket : public Packet {
|
||||||
private:
|
private:
|
||||||
std::uint8_t m_PlayerID;
|
std::uint8_t m_PlayerID;
|
||||||
public:
|
public:
|
||||||
PlayerLeavePacket() {}
|
PlayerLeavePacket() {}
|
||||||
PlayerLeavePacket(std::uint8_t playerID) : m_PlayerID(playerID) {}
|
PlayerLeavePacket(std::uint8_t playerID) : m_PlayerID(playerID) {}
|
||||||
virtual ~PlayerLeavePacket() {}
|
virtual ~PlayerLeavePacket() {}
|
||||||
|
|
||||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||||
virtual void Deserialize(DataBuffer& data);
|
virtual void Deserialize(DataBuffer& data);
|
||||||
virtual void Dispatch(PacketHandler* handler) const;
|
virtual void Dispatch(PacketHandler* handler) const;
|
||||||
|
|
||||||
std::uint8_t GetPlayerID() const { return m_PlayerID; }
|
std::uint8_t GetPlayerID() const { return m_PlayerID; }
|
||||||
|
|
||||||
virtual PacketType GetType() const { return PacketType::PlayerLeave; }
|
virtual PacketType GetType() const { return PacketType::PlayerLeave; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class ConnexionInfoPacket : public Packet {
|
class ConnexionInfoPacket : public Packet {
|
||||||
private:
|
private:
|
||||||
std::uint8_t m_ConnectionID;
|
std::uint8_t m_ConnectionID;
|
||||||
public:
|
public:
|
||||||
ConnexionInfoPacket() {}
|
ConnexionInfoPacket() {}
|
||||||
ConnexionInfoPacket(std::uint8_t connectionID) : m_ConnectionID(connectionID) {}
|
ConnexionInfoPacket(std::uint8_t connectionID) : m_ConnectionID(connectionID) {}
|
||||||
virtual ~ConnexionInfoPacket() {}
|
virtual ~ConnexionInfoPacket() {}
|
||||||
|
|
||||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||||
virtual void Deserialize(DataBuffer& data);
|
virtual void Deserialize(DataBuffer& data);
|
||||||
virtual void Dispatch(PacketHandler* handler) const;
|
virtual void Dispatch(PacketHandler* handler) const;
|
||||||
|
|
||||||
std::uint8_t GetConnectionID() const { return m_ConnectionID; }
|
std::uint8_t GetConnectionID() const { return m_ConnectionID; }
|
||||||
|
|
||||||
virtual PacketType GetType() const { return PacketType::ConnectionInfo; }
|
virtual PacketType GetType() const { return PacketType::ConnectionInfo; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class SelectTeamPacket : public Packet {
|
class SelectTeamPacket : public Packet {
|
||||||
private:
|
private:
|
||||||
game::TeamColor m_SelectedTeam;
|
game::TeamColor m_SelectedTeam;
|
||||||
public:
|
public:
|
||||||
SelectTeamPacket() {}
|
SelectTeamPacket() {}
|
||||||
SelectTeamPacket(game::TeamColor selectedTeam) : m_SelectedTeam(selectedTeam) {}
|
SelectTeamPacket(game::TeamColor selectedTeam) : m_SelectedTeam(selectedTeam) {}
|
||||||
virtual ~SelectTeamPacket() {}
|
virtual ~SelectTeamPacket() {}
|
||||||
|
|
||||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||||
virtual void Deserialize(DataBuffer& data);
|
virtual void Deserialize(DataBuffer& data);
|
||||||
virtual void Dispatch(PacketHandler* handler) const;
|
virtual void Dispatch(PacketHandler* handler) const;
|
||||||
|
|
||||||
game::TeamColor GetSelectedTeam() const { return m_SelectedTeam; }
|
game::TeamColor GetSelectedTeam() const { return m_SelectedTeam; }
|
||||||
|
|
||||||
virtual PacketType GetType() const { return PacketType::SelectTeam; }
|
virtual PacketType GetType() const { return PacketType::SelectTeam; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class UpdatePlayerTeamPacket : public Packet {
|
class UpdatePlayerTeamPacket : public Packet {
|
||||||
private:
|
private:
|
||||||
std::uint8_t m_PlayerID;
|
std::uint8_t m_PlayerID;
|
||||||
game::TeamColor m_SelectedTeam;
|
game::TeamColor m_SelectedTeam;
|
||||||
public:
|
public:
|
||||||
UpdatePlayerTeamPacket() {}
|
UpdatePlayerTeamPacket() {}
|
||||||
UpdatePlayerTeamPacket(std::uint8_t playerID, game::TeamColor selectedTeam) : m_PlayerID(playerID), m_SelectedTeam(selectedTeam) {}
|
UpdatePlayerTeamPacket(std::uint8_t playerID, game::TeamColor selectedTeam) : m_PlayerID(playerID), m_SelectedTeam(selectedTeam) {}
|
||||||
virtual ~UpdatePlayerTeamPacket() {}
|
virtual ~UpdatePlayerTeamPacket() {}
|
||||||
|
|
||||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||||
virtual void Deserialize(DataBuffer& data);
|
virtual void Deserialize(DataBuffer& data);
|
||||||
virtual void Dispatch(PacketHandler* handler) const;
|
virtual void Dispatch(PacketHandler* handler) const;
|
||||||
|
|
||||||
game::TeamColor GetSelectedTeam() const { return m_SelectedTeam; }
|
game::TeamColor GetSelectedTeam() const { return m_SelectedTeam; }
|
||||||
std::uint8_t GetPlayerID() const { return m_PlayerID; }
|
std::uint8_t GetPlayerID() const { return m_PlayerID; }
|
||||||
|
|
||||||
virtual PacketType GetType() const { return PacketType::UpdatePlayerTeam; }
|
virtual PacketType GetType() const { return PacketType::UpdatePlayerTeam; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class DisconnectPacket : public Packet {
|
class DisconnectPacket : public Packet {
|
||||||
private:
|
private:
|
||||||
std::string m_Reason; // only when sent from server
|
std::string m_Reason; // only when sent from server
|
||||||
public:
|
public:
|
||||||
DisconnectPacket() {}
|
DisconnectPacket() {}
|
||||||
DisconnectPacket(std::string reason) : m_Reason(reason) {}
|
DisconnectPacket(std::string reason) : m_Reason(reason) {}
|
||||||
virtual ~DisconnectPacket() {}
|
virtual ~DisconnectPacket() {}
|
||||||
|
|
||||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||||
virtual void Deserialize(DataBuffer& data);
|
virtual void Deserialize(DataBuffer& data);
|
||||||
virtual void Dispatch(PacketHandler* handler) const;
|
virtual void Dispatch(PacketHandler* handler) const;
|
||||||
|
|
||||||
const std::string& GetReason() const { return m_Reason; }
|
const std::string& GetReason() const { return m_Reason; }
|
||||||
|
|
||||||
virtual PacketType GetType() const { return PacketType::Disconnect; }
|
virtual PacketType GetType() const { return PacketType::Disconnect; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class ServerTpsPacket : public Packet {
|
class ServerTpsPacket : public Packet {
|
||||||
private:
|
private:
|
||||||
float m_TPS;
|
float m_TPS;
|
||||||
std::uint64_t m_PacketSendTime; // used to calculate ping
|
float m_MSPT;
|
||||||
|
std::uint64_t m_PacketSendTime; // used to calculate ping
|
||||||
public:
|
public:
|
||||||
ServerTpsPacket() {}
|
ServerTpsPacket() {}
|
||||||
ServerTpsPacket(float tps, std::uint64_t sendTime) : m_TPS(tps), m_PacketSendTime(sendTime) {}
|
ServerTpsPacket(float tps, float mspt, std::uint64_t sendTime) : m_TPS(tps), m_MSPT(mspt), m_PacketSendTime(sendTime) {}
|
||||||
virtual ~ServerTpsPacket() {}
|
virtual ~ServerTpsPacket() {}
|
||||||
|
|
||||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||||
virtual void Deserialize(DataBuffer& data);
|
virtual void Deserialize(DataBuffer& data);
|
||||||
virtual void Dispatch(PacketHandler* handler) const;
|
virtual void Dispatch(PacketHandler* handler) const;
|
||||||
|
|
||||||
float GetTPS() const { return m_TPS; }
|
float GetTPS() const { return m_TPS; }
|
||||||
std::uint64_t GetPacketSendTime() const { return m_PacketSendTime; }
|
float GetMSPT() const { return m_MSPT; }
|
||||||
|
std::uint64_t GetPacketSendTime() const { return m_PacketSendTime; }
|
||||||
|
|
||||||
virtual PacketType GetType() const { return PacketType::ServerTps; }
|
virtual PacketType GetType() const { return PacketType::ServerTps; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MobSend { // represents a mob send
|
struct MobSend { // represents a mob send
|
||||||
game::MobType mobType : 4;
|
game::MobType mobType : 4;
|
||||||
game::MobLevel mobLevel : 4;
|
game::MobLevel mobLevel : 4;
|
||||||
std::uint8_t mobCount; // the max is 12
|
std::uint8_t mobCount; // the max is 12
|
||||||
};
|
};
|
||||||
|
|
||||||
class SendMobsPacket : public Packet {
|
class SendMobsPacket : public Packet {
|
||||||
private:
|
private:
|
||||||
std::vector<MobSend> m_MobSends;
|
std::vector<MobSend> m_MobSends;
|
||||||
public:
|
public:
|
||||||
SendMobsPacket() {}
|
SendMobsPacket() {}
|
||||||
SendMobsPacket(const std::vector<MobSend>& mobSends) : m_MobSends(mobSends) {}
|
SendMobsPacket(const std::vector<MobSend>& mobSends) : m_MobSends(mobSends) {}
|
||||||
virtual ~SendMobsPacket() {}
|
virtual ~SendMobsPacket() {}
|
||||||
|
|
||||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||||
virtual void Deserialize(DataBuffer& data);
|
virtual void Deserialize(DataBuffer& data);
|
||||||
virtual void Dispatch(PacketHandler* handler) const;
|
virtual void Dispatch(PacketHandler* handler) const;
|
||||||
|
|
||||||
const std::vector<MobSend>& GetMobSends() const { return m_MobSends; }
|
const std::vector<MobSend>& GetMobSends() const { return m_MobSends; }
|
||||||
|
|
||||||
virtual PacketType GetType() const { return PacketType::SendMobs; }
|
virtual PacketType GetType() const { return PacketType::SendMobs; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class SpawnMobPacket : public Packet {
|
class SpawnMobPacket : public Packet {
|
||||||
private:
|
private:
|
||||||
game::MobID m_MobID;
|
game::MobID m_MobID;
|
||||||
game::MobType m_MobType;
|
game::MobType m_MobType;
|
||||||
game::MobLevel m_MobLevel;
|
game::MobLevel m_MobLevel;
|
||||||
game::Direction m_MobDirection;
|
game::Direction m_MobDirection;
|
||||||
game::PlayerID m_Sender;
|
game::PlayerID m_Sender;
|
||||||
float m_MobX, m_MobY;
|
float m_MobX, m_MobY;
|
||||||
public:
|
public:
|
||||||
SpawnMobPacket() {}
|
SpawnMobPacket() {}
|
||||||
SpawnMobPacket(game::MobID id, game::MobType type, std::uint8_t level, game::PlayerID sender,
|
SpawnMobPacket(game::MobID id, game::MobType type, std::uint8_t level, game::PlayerID sender,
|
||||||
float x, float y, game::Direction dir) : m_MobID(id), m_MobType(type), m_MobLevel(level),
|
float x, float y, game::Direction dir) : m_MobID(id), m_MobType(type), m_MobLevel(level),
|
||||||
m_MobDirection(dir), m_Sender(sender), m_MobX(x), m_MobY(y) {}
|
m_MobDirection(dir), m_Sender(sender), m_MobX(x), m_MobY(y) {
|
||||||
virtual ~SpawnMobPacket() {}
|
}
|
||||||
|
virtual ~SpawnMobPacket() {}
|
||||||
|
|
||||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||||
virtual void Deserialize(DataBuffer& data);
|
virtual void Deserialize(DataBuffer& data);
|
||||||
virtual void Dispatch(PacketHandler* handler) const;
|
virtual void Dispatch(PacketHandler* handler) const;
|
||||||
|
|
||||||
game::MobID GetMobID() const { return m_MobID; }
|
game::MobID GetMobID() const { return m_MobID; }
|
||||||
game::MobType GetMobType() const { return m_MobType; }
|
game::MobType GetMobType() const { return m_MobType; }
|
||||||
game::MobLevel GetMobLevel() const { return m_MobLevel; }
|
game::MobLevel GetMobLevel() const { return m_MobLevel; }
|
||||||
game::Direction GetMobDirection() const { return m_MobDirection; }
|
game::Direction GetMobDirection() const { return m_MobDirection; }
|
||||||
game::PlayerID GetSender() const { return m_Sender; }
|
game::PlayerID GetSender() const { return m_Sender; }
|
||||||
float GetMobX() const { return m_MobX; }
|
float GetMobX() const { return m_MobX; }
|
||||||
float GetMobY() const { return m_MobY; }
|
float GetMobY() const { return m_MobY; }
|
||||||
|
|
||||||
virtual PacketType GetType() const { return PacketType::SpawnMob; }
|
virtual PacketType GetType() const { return PacketType::SpawnMob; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class PlaceTowerPacket : public Packet {
|
class PlaceTowerPacket : public Packet {
|
||||||
private:
|
private:
|
||||||
std::int32_t m_TowerX, m_TowerY;
|
std::int32_t m_TowerX, m_TowerY;
|
||||||
game::TowerType m_TowerType;
|
game::TowerType m_TowerType;
|
||||||
public:
|
public:
|
||||||
PlaceTowerPacket() {}
|
PlaceTowerPacket() {}
|
||||||
PlaceTowerPacket(std::int32_t x, std::int32_t y, game::TowerType type) :
|
PlaceTowerPacket(std::int32_t x, std::int32_t y, game::TowerType type) :
|
||||||
m_TowerX(x), m_TowerY(y), m_TowerType(type) {}
|
m_TowerX(x), m_TowerY(y), m_TowerType(type) {
|
||||||
virtual ~PlaceTowerPacket() {}
|
}
|
||||||
|
virtual ~PlaceTowerPacket() {}
|
||||||
|
|
||||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||||
virtual void Deserialize(DataBuffer& data);
|
virtual void Deserialize(DataBuffer& data);
|
||||||
virtual void Dispatch(PacketHandler* handler) const;
|
virtual void Dispatch(PacketHandler* handler) const;
|
||||||
|
|
||||||
std::int32_t GetTowerX() const { return m_TowerX; }
|
std::int32_t GetTowerX() const { return m_TowerX; }
|
||||||
std::int32_t GetTowerY() const { return m_TowerY; }
|
std::int32_t GetTowerY() const { return m_TowerY; }
|
||||||
game::TowerType GetTowerType() const { return m_TowerType; }
|
game::TowerType GetTowerType() const { return m_TowerType; }
|
||||||
|
|
||||||
virtual PacketType GetType() const { return PacketType::PlaceTower; }
|
virtual PacketType GetType() const { return PacketType::PlaceTower; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class WorldAddTowerPacket : public Packet {
|
class WorldAddTowerPacket : public Packet {
|
||||||
private:
|
private:
|
||||||
game::TowerID m_TowerID;
|
game::TowerID m_TowerID;
|
||||||
std::int32_t m_TowerX, m_TowerY;
|
std::int32_t m_TowerX, m_TowerY;
|
||||||
game::TowerType m_TowerType;
|
game::TowerType m_TowerType;
|
||||||
game::PlayerID m_Builder;
|
game::PlayerID m_Builder;
|
||||||
public:
|
public:
|
||||||
WorldAddTowerPacket() {}
|
WorldAddTowerPacket() {}
|
||||||
WorldAddTowerPacket(game::TowerID id, std::int32_t x, std::int32_t y, game::TowerType type, game::PlayerID player) :
|
WorldAddTowerPacket(game::TowerID id, std::int32_t x, std::int32_t y, game::TowerType type, game::PlayerID player) :
|
||||||
m_TowerID(id), m_TowerX(x), m_TowerY(y), m_TowerType(type), m_Builder(player) {}
|
m_TowerID(id), m_TowerX(x), m_TowerY(y), m_TowerType(type), m_Builder(player) {
|
||||||
virtual ~WorldAddTowerPacket() {}
|
}
|
||||||
|
virtual ~WorldAddTowerPacket() {}
|
||||||
|
|
||||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||||
virtual void Deserialize(DataBuffer& data);
|
virtual void Deserialize(DataBuffer& data);
|
||||||
virtual void Dispatch(PacketHandler* handler) const;
|
virtual void Dispatch(PacketHandler* handler) const;
|
||||||
|
|
||||||
game::TowerID GetTowerID() const { return m_TowerID; }
|
game::TowerID GetTowerID() const { return m_TowerID; }
|
||||||
std::int32_t GetTowerX() const { return m_TowerX; }
|
std::int32_t GetTowerX() const { return m_TowerX; }
|
||||||
std::int32_t GetTowerY() const { return m_TowerY; }
|
std::int32_t GetTowerY() const { return m_TowerY; }
|
||||||
game::TowerType GetTowerType() const { return m_TowerType; }
|
game::TowerType GetTowerType() const { return m_TowerType; }
|
||||||
game::PlayerID GetBuilder() const { return m_Builder; }
|
game::PlayerID GetBuilder() const { return m_Builder; }
|
||||||
|
|
||||||
virtual PacketType GetType() const { return PacketType::WorldAddTower; }
|
virtual PacketType GetType() const { return PacketType::WorldAddTower; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class RemoveTowerPacket : public Packet {
|
class RemoveTowerPacket : public Packet {
|
||||||
private:
|
private:
|
||||||
game::TowerID m_TowerID;
|
game::TowerID m_TowerID;
|
||||||
public:
|
public:
|
||||||
RemoveTowerPacket() {}
|
RemoveTowerPacket() {}
|
||||||
RemoveTowerPacket(game::TowerID id) : m_TowerID(id) {}
|
RemoveTowerPacket(game::TowerID id) : m_TowerID(id) {}
|
||||||
virtual ~RemoveTowerPacket() {}
|
virtual ~RemoveTowerPacket() {}
|
||||||
|
|
||||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||||
virtual void Deserialize(DataBuffer& data);
|
virtual void Deserialize(DataBuffer& data);
|
||||||
virtual void Dispatch(PacketHandler* handler) const;
|
virtual void Dispatch(PacketHandler* handler) const;
|
||||||
|
|
||||||
game::TowerID GetTowerID() const { return m_TowerID; }
|
game::TowerID GetTowerID() const { return m_TowerID; }
|
||||||
|
|
||||||
virtual PacketType GetType() const { return PacketType::RemoveTower; }
|
virtual PacketType GetType() const { return PacketType::RemoveTower; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class UpgradeTowerPacket : public Packet {
|
class UpgradeTowerPacket : public Packet {
|
||||||
private:
|
private:
|
||||||
game::TowerID m_TowerID;
|
game::TowerID m_TowerID;
|
||||||
game::TowerLevel m_TowerLevel;
|
game::TowerLevel m_TowerLevel;
|
||||||
public:
|
public:
|
||||||
UpgradeTowerPacket() {}
|
UpgradeTowerPacket() {}
|
||||||
UpgradeTowerPacket(game::TowerID tower, game::TowerLevel level) : m_TowerID(tower), m_TowerLevel(level) {}
|
UpgradeTowerPacket(game::TowerID tower, game::TowerLevel level) : m_TowerID(tower), m_TowerLevel(level) {}
|
||||||
virtual ~UpgradeTowerPacket() {}
|
virtual ~UpgradeTowerPacket() {}
|
||||||
|
|
||||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||||
virtual void Deserialize(DataBuffer& data);
|
virtual void Deserialize(DataBuffer& data);
|
||||||
virtual void Dispatch(PacketHandler* handler) const;
|
virtual void Dispatch(PacketHandler* handler) const;
|
||||||
|
|
||||||
game::TowerID GetTowerID() const { return m_TowerID; }
|
game::TowerID GetTowerID() const { return m_TowerID; }
|
||||||
game::TowerLevel GetTowerLevel() const { return m_TowerLevel; }
|
game::TowerLevel GetTowerLevel() const { return m_TowerLevel; }
|
||||||
|
|
||||||
virtual PacketType GetType() const { return PacketType::UpgradeTower; }
|
virtual PacketType GetType() const { return PacketType::UpgradeTower; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class MobState {
|
class MobState {
|
||||||
using Point = utils::shape::Point;
|
using Point = utils::shape::Point;
|
||||||
private:
|
private:
|
||||||
game::MobID m_MobID;
|
game::MobID m_MobID;
|
||||||
Point m_MobPosition;
|
Point m_MobPosition;
|
||||||
float m_MobLife;
|
float m_MobLife;
|
||||||
game::Direction m_MobDirection;
|
game::Direction m_MobDirection;
|
||||||
public:
|
public:
|
||||||
MobState() {}
|
MobState() {}
|
||||||
MobState(game::MobID id, const Point& position, float life, game::Direction direction) :
|
MobState(game::MobID id, const Point& position, float life, game::Direction direction) :
|
||||||
m_MobID(id), m_MobPosition(position), m_MobLife(life), m_MobDirection(direction) {}
|
m_MobID(id), m_MobPosition(position), m_MobLife(life), m_MobDirection(direction) {
|
||||||
|
}
|
||||||
|
|
||||||
game::MobID GetMobId() const { return m_MobID; }
|
game::MobID GetMobId() const { return m_MobID; }
|
||||||
Point GetMobPosition() const { return m_MobPosition; }
|
Point GetMobPosition() const { return m_MobPosition; }
|
||||||
float GetMobLife() const { return m_MobLife; }
|
float GetMobLife() const { return m_MobLife; }
|
||||||
game::Direction GetMobDirection() const { return m_MobDirection; }
|
game::Direction GetMobDirection() const { return m_MobDirection; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class UpdateMobStatesPacket : public Packet {
|
class UpdateMobStatesPacket : public Packet {
|
||||||
private:
|
private:
|
||||||
std::vector<MobState> m_MobStates;
|
std::vector<MobState> m_MobStates;
|
||||||
public:
|
public:
|
||||||
UpdateMobStatesPacket() {}
|
UpdateMobStatesPacket() {}
|
||||||
virtual ~UpdateMobStatesPacket() {}
|
virtual ~UpdateMobStatesPacket() {}
|
||||||
|
|
||||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||||
virtual void Deserialize(DataBuffer& data);
|
virtual void Deserialize(DataBuffer& data);
|
||||||
virtual void Dispatch(PacketHandler* handler) const;
|
virtual void Dispatch(PacketHandler* handler) const;
|
||||||
|
|
||||||
void addMobState(MobState mobState) { m_MobStates.push_back(mobState); }
|
void addMobState(MobState mobState) { m_MobStates.push_back(mobState); }
|
||||||
|
|
||||||
const std::vector<MobState>& GetMobStates() const { return m_MobStates; }
|
const std::vector<MobState>& GetMobStates() const { return m_MobStates; }
|
||||||
|
|
||||||
virtual PacketType GetType() const { return PacketType::UpdateMobStates; }
|
virtual PacketType GetType() const { return PacketType::UpdateMobStates; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class UpdateCastleLifePacket : public Packet {
|
class UpdateCastleLifePacket : public Packet {
|
||||||
private:
|
private:
|
||||||
std::uint16_t m_CastleLife;
|
std::uint16_t m_CastleLife;
|
||||||
game::TeamColor m_Team;
|
game::TeamColor m_Team;
|
||||||
public:
|
public:
|
||||||
UpdateCastleLifePacket() {}
|
UpdateCastleLifePacket() {}
|
||||||
UpdateCastleLifePacket(std::uint16_t life, game::TeamColor team) : m_CastleLife(life), m_Team(team) {}
|
UpdateCastleLifePacket(std::uint16_t life, game::TeamColor team) : m_CastleLife(life), m_Team(team) {}
|
||||||
virtual ~UpdateCastleLifePacket() {}
|
virtual ~UpdateCastleLifePacket() {}
|
||||||
|
|
||||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||||
virtual void Deserialize(DataBuffer& data);
|
virtual void Deserialize(DataBuffer& data);
|
||||||
virtual void Dispatch(PacketHandler* handler) const;
|
virtual void Dispatch(PacketHandler* handler) const;
|
||||||
|
|
||||||
std::uint16_t GetCastleLife() const { return m_CastleLife; }
|
std::uint16_t GetCastleLife() const { return m_CastleLife; }
|
||||||
game::TeamColor GetTeamColor() const { return m_Team; }
|
game::TeamColor GetTeamColor() const { return m_Team; }
|
||||||
|
|
||||||
virtual PacketType GetType() const { return PacketType::UpdateCastleLife; }
|
virtual PacketType GetType() const { return PacketType::UpdateCastleLife; }
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ItemType : std::uint8_t {
|
enum class ItemType : std::uint8_t {
|
||||||
// Upgrades
|
// Upgrades
|
||||||
ClickerUpgrade,
|
ClickerUpgrade,
|
||||||
GoldPerSecUpgrade,
|
GoldPerSecUpgrade,
|
||||||
|
|
||||||
// Items
|
// Items
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Packet used by the client to buy items or upgrades
|
/** Packet used by the client to buy items or upgrades
|
||||||
Packet used by the server to confirm transaction */
|
Packet used by the server to confirm transaction */
|
||||||
class PlayerBuyItemPacket : public Packet {
|
class PlayerBuyItemPacket : public Packet {
|
||||||
private:
|
private:
|
||||||
ItemType m_ItemType;
|
ItemType m_ItemType;
|
||||||
std::uint8_t m_Count;
|
std::uint8_t m_Count;
|
||||||
public:
|
public:
|
||||||
PlayerBuyItemPacket() {}
|
PlayerBuyItemPacket() {}
|
||||||
PlayerBuyItemPacket(ItemType itemType, std::uint8_t count) : m_ItemType(itemType), m_Count(count) {}
|
PlayerBuyItemPacket(ItemType itemType, std::uint8_t count) : m_ItemType(itemType), m_Count(count) {}
|
||||||
virtual ~PlayerBuyItemPacket() {}
|
virtual ~PlayerBuyItemPacket() {}
|
||||||
|
|
||||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||||
virtual void Deserialize(DataBuffer& data);
|
virtual void Deserialize(DataBuffer& data);
|
||||||
virtual void Dispatch(PacketHandler* handler) const;
|
virtual void Dispatch(PacketHandler* handler) const;
|
||||||
|
|
||||||
ItemType GetItemType() const { return m_ItemType; }
|
ItemType GetItemType() const { return m_ItemType; }
|
||||||
std::uint8_t GetCount() const { return m_Count; }
|
std::uint8_t GetCount() const { return m_Count; }
|
||||||
|
|
||||||
virtual PacketType GetType() const { return PacketType::PlayerBuyItem; }
|
virtual PacketType GetType() const { return PacketType::PlayerBuyItem; }
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Packet used by the client to buy mob upgrades
|
/** Packet used by the client to buy mob upgrades
|
||||||
Packet used by the server to confirm transaction */
|
Packet used by the server to confirm transaction */
|
||||||
class PlayerBuyMobUpgradePacket : public Packet {
|
class PlayerBuyMobUpgradePacket : public Packet {
|
||||||
private:
|
private:
|
||||||
game::MobType m_MobType;
|
game::MobType m_MobType;
|
||||||
std::uint8_t m_MobLevel;
|
std::uint8_t m_MobLevel;
|
||||||
public:
|
public:
|
||||||
PlayerBuyMobUpgradePacket() {}
|
PlayerBuyMobUpgradePacket() {}
|
||||||
PlayerBuyMobUpgradePacket(game::MobType mobType, std::uint8_t level) : m_MobType(mobType), m_MobLevel(level) {}
|
PlayerBuyMobUpgradePacket(game::MobType mobType, std::uint8_t level) : m_MobType(mobType), m_MobLevel(level) {}
|
||||||
virtual ~PlayerBuyMobUpgradePacket() {}
|
virtual ~PlayerBuyMobUpgradePacket() {}
|
||||||
|
|
||||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||||
virtual void Deserialize(DataBuffer& data);
|
virtual void Deserialize(DataBuffer& data);
|
||||||
virtual void Dispatch(PacketHandler* handler) const;
|
virtual void Dispatch(PacketHandler* handler) const;
|
||||||
|
|
||||||
game::MobType GetMobType() const { return m_MobType; }
|
game::MobType GetMobType() const { return m_MobType; }
|
||||||
std::uint8_t GetLevel() const { return m_MobLevel; }
|
std::uint8_t GetLevel() const { return m_MobLevel; }
|
||||||
|
|
||||||
virtual PacketType GetType() const { return PacketType::PlayerBuyMobUpgrade; }
|
virtual PacketType GetType() const { return PacketType::PlayerBuyMobUpgrade; }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace protocol
|
} // namespace protocol
|
||||||
|
|||||||
@@ -13,17 +13,17 @@
|
|||||||
#if defined(__has_include)
|
#if defined(__has_include)
|
||||||
|
|
||||||
#if __has_include(<GL/glew.h>)
|
#if __has_include(<GL/glew.h>)
|
||||||
#define TD_IMPL_OPENGL_LOADER_GLEW
|
#define TD_IMPL_OPENGL_LOADER_GLEW
|
||||||
#elif __has_include(<glad/glad.h>)
|
#elif __has_include(<glad/glad.h>)
|
||||||
#define TD_IMPL_OPENGL_LOADER_GLAD
|
#define TD_IMPL_OPENGL_LOADER_GLAD
|
||||||
#elif __has_include(<GL/gl3w.h>)
|
#elif __has_include(<GL/gl3w.h>)
|
||||||
#define TD_IMPL_OPENGL_LOADER_GL3W
|
#define TD_IMPL_OPENGL_LOADER_GL3W
|
||||||
#elif __has_include(<glbinding/glbinding.h>)
|
#elif __has_include(<glbinding/glbinding.h>)
|
||||||
#define TD_IMPL_OPENGL_LOADER_GLBINDING3
|
#define TD_IMPL_OPENGL_LOADER_GLBINDING3
|
||||||
#elif __has_include(<glbinding/Binding.h>)
|
#elif __has_include(<glbinding/Binding.h>)
|
||||||
#define TD_IMPL_OPENGL_LOADER_GLBINDING2
|
#define TD_IMPL_OPENGL_LOADER_GLBINDING2
|
||||||
#else
|
#else
|
||||||
#error "Cannot detect OpenGL loader!"
|
#error "Cannot detect OpenGL loader!"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include "Defines.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "loader/GLLoader.h"
|
#include "loader/GLLoader.h"
|
||||||
#include "render/shaders/WorldShader.h"
|
#include "render/shaders/WorldShader.h"
|
||||||
@@ -11,45 +11,46 @@ namespace render {
|
|||||||
|
|
||||||
class Renderer {
|
class Renderer {
|
||||||
public:
|
public:
|
||||||
static constexpr float m_AnimationSpeed = 2.0f;
|
static constexpr float m_AnimationSpeed = 2.0f;
|
||||||
|
|
||||||
struct Model {
|
struct Model {
|
||||||
GL::VertexArray* vao;
|
GL::VertexArray* vao;
|
||||||
glm::vec2 positon;
|
Vec2f positon;
|
||||||
};
|
Vec3f color = { 1, 1, 1 };
|
||||||
|
};
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<shader::WorldShader> m_WorldShader;
|
std::unique_ptr<shader::WorldShader> m_WorldShader;
|
||||||
std::unique_ptr<shader::EntityShader> m_EntityShader;
|
std::unique_ptr<shader::EntityShader> m_EntityShader;
|
||||||
|
|
||||||
glm::vec3 m_BackgroundColor;
|
Vec3f m_BackgroundColor;
|
||||||
|
|
||||||
bool m_IsometricView = true;
|
bool m_IsometricView = true;
|
||||||
float m_IsometricShade = m_IsometricView;
|
float m_IsometricShade = m_IsometricView;
|
||||||
glm::vec2 m_CamPos{};
|
Vec2f m_CamPos{};
|
||||||
public:
|
public:
|
||||||
Renderer();
|
Renderer();
|
||||||
~Renderer();
|
~Renderer();
|
||||||
|
|
||||||
bool Init();
|
bool Init();
|
||||||
|
|
||||||
void Prepare();
|
void Prepare();
|
||||||
void Resize(const int width, const int height);
|
void Resize(const int width, const int height);
|
||||||
|
|
||||||
void RenderVAO(const GL::VertexArray& vao);
|
void RenderVAO(const GL::VertexArray& vao);
|
||||||
void RenderModel(const Model& model);
|
void RenderModel(const Model& model);
|
||||||
|
|
||||||
void SetZoom(float zoom);
|
void SetZoom(float zoom);
|
||||||
void SetCamMovement(const glm::vec2& mov);
|
void SetCamMovement(const Vec2f& mov);
|
||||||
void SetCamPos(const glm::vec2& newPos);
|
void SetCamPos(const Vec2f& newPos);
|
||||||
void SetIsometricView(bool isometric); // false = 2D true = Isometric
|
void SetIsometricView(bool isometric); // false = 2D true = Isometric
|
||||||
|
|
||||||
void SetBackgroundColor(const glm::vec3& color) { m_BackgroundColor = color; }
|
void SetBackgroundColor(const Vec3f& color) { m_BackgroundColor = color; }
|
||||||
|
|
||||||
glm::vec2 GetCursorWorldPos(const glm::vec2& cursorPos, float aspectRatio, float zoom, float windowWidth, float windowHeight);
|
Vec2f GetCursorWorldPos(const Vec2f& cursorPos, float aspectRatio, float zoom, float windowWidth, float windowHeight);
|
||||||
private:
|
private:
|
||||||
void UpdateIsometricView();
|
void UpdateIsometricView();
|
||||||
void UpdateIsometricFade();
|
void UpdateIsometricFade();
|
||||||
void InitShaders();
|
void InitShaders();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace render
|
} // namespace render
|
||||||
|
|||||||
@@ -11,27 +11,27 @@ namespace render {
|
|||||||
|
|
||||||
class VertexCache {
|
class VertexCache {
|
||||||
|
|
||||||
typedef std::vector<float> Vector;
|
typedef std::vector<float> Vector;
|
||||||
|
|
||||||
struct DataIndex {
|
struct DataIndex {
|
||||||
Vector position;
|
Vector position;
|
||||||
Vector color;
|
Vector color;
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::size_t m_VertexCount;
|
std::size_t m_VertexCount;
|
||||||
std::unordered_map<std::uint64_t, DataIndex> m_Indexes;
|
std::unordered_map<std::uint64_t, DataIndex> m_Indexes;
|
||||||
std::unique_ptr<GL::VertexArray> m_VertexArray;
|
std::unique_ptr<GL::VertexArray> m_VertexArray;
|
||||||
public:
|
public:
|
||||||
VertexCache() : m_VertexCount(0) {}
|
VertexCache() : m_VertexCount(0) {}
|
||||||
|
|
||||||
void AddData(std::uint64_t index, std::vector<float> positions, std::vector<float> colors);
|
void AddData(std::uint64_t index, std::vector<float> positions, std::vector<float> colors);
|
||||||
void RemoveData(std::uint64_t index);
|
void RemoveData(std::uint64_t index);
|
||||||
void Clear();
|
void Clear();
|
||||||
void UpdateVertexArray();
|
void UpdateVertexArray();
|
||||||
|
|
||||||
const GL::VertexArray& GetVertexArray() const { return *m_VertexArray; }
|
const GL::VertexArray& GetVertexArray() const { return *m_VertexArray; }
|
||||||
bool IsEmpty() const { return m_VertexArray == nullptr; }
|
bool IsEmpty() const { return m_VertexArray == nullptr; }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace render
|
} // namespace render
|
||||||
|
|||||||
@@ -6,13 +6,12 @@
|
|||||||
#include "render/VertexCache.h"
|
#include "render/VertexCache.h"
|
||||||
|
|
||||||
#include "render/gui/TowerPlacePopup.h"
|
#include "render/gui/TowerPlacePopup.h"
|
||||||
|
#include "render/gui/TowerUpgradePopup.h"
|
||||||
#include "render/gui/MobTooltip.h"
|
#include "render/gui/MobTooltip.h"
|
||||||
#include "render/gui/CastleTooltip.h"
|
#include "render/gui/CastleTooltip.h"
|
||||||
|
|
||||||
#include "render/gui/imgui/imgui.h"
|
#include "render/gui/imgui/imgui.h"
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
|
|
||||||
namespace client {
|
namespace client {
|
||||||
@@ -26,61 +25,61 @@ namespace render {
|
|||||||
|
|
||||||
class WorldRenderer : public game::WorldListener {
|
class WorldRenderer : public game::WorldListener {
|
||||||
private:
|
private:
|
||||||
client::ClientGame* m_Client;
|
client::ClientGame* m_Client;
|
||||||
Renderer* m_Renderer;
|
Renderer* m_Renderer;
|
||||||
game::World* m_World;
|
game::World* m_World;
|
||||||
std::unique_ptr<GL::VertexArray> m_WorldVao, m_MobVao, m_SelectTileVao;
|
std::unique_ptr<GL::VertexArray> m_WorldVao, m_MobVao, m_SelectTileVao;
|
||||||
glm::vec2 m_CamPos;
|
Vec2f m_CamPos;
|
||||||
glm::vec2 m_CursorPos;
|
Vec2f m_CursorPos;
|
||||||
glm::vec2 m_HoldCursorPos;
|
Vec2f m_HoldCursorPos;
|
||||||
glm::vec2 m_LastClicked;
|
Vec2f m_LastClicked;
|
||||||
float m_Zoom;
|
float m_Zoom;
|
||||||
float m_CamSensibility = 1;
|
float m_CamSensibility = 1;
|
||||||
bool m_PopupOpened = false;
|
bool m_PopupOpened = false;
|
||||||
VertexCache m_TowersCache;
|
VertexCache m_TowersCache;
|
||||||
|
|
||||||
std::unique_ptr<gui::TowerPlacePopup> m_TowerPlacePopup;
|
std::unique_ptr<gui::TowerPlacePopup> m_TowerPlacePopup;
|
||||||
std::unique_ptr<gui::MobTooltip> m_MobTooltip;
|
std::unique_ptr<gui::TowerUpgradePopup> m_TowerUpgradePopup;
|
||||||
std::unique_ptr<gui::CastleTooltip> m_CastleTooltip;
|
std::unique_ptr<gui::MobTooltip> m_MobTooltip;
|
||||||
|
std::unique_ptr<gui::CastleTooltip> m_CastleTooltip;
|
||||||
public:
|
public:
|
||||||
WorldRenderer(game::World* world, client::ClientGame* client);
|
WorldRenderer(game::World* world, client::ClientGame* client);
|
||||||
~WorldRenderer();
|
~WorldRenderer();
|
||||||
|
|
||||||
void LoadModels();
|
void LoadModels();
|
||||||
|
|
||||||
static ImVec4 GetImGuiTeamColor(game::TeamColor color);
|
static ImVec4 GetImGuiTeamColor(game::TeamColor color);
|
||||||
|
|
||||||
void Update();
|
void Update();
|
||||||
void Render();
|
void Render();
|
||||||
|
|
||||||
void SetCamPos(float camX, float camY);
|
void SetCamPos(float camX, float camY);
|
||||||
|
|
||||||
void MoveCam(float relativeX, float relativeY, float aspectRatio);
|
void MoveCam(float relativeX, float relativeY, float aspectRatio);
|
||||||
void ChangeZoom(float zoom);
|
void ChangeZoom(float zoom);
|
||||||
|
|
||||||
// WorldListener
|
// WorldListener
|
||||||
|
|
||||||
virtual void OnTowerAdd(game::TowerPtr tower);
|
virtual void OnTowerAdd(game::TowerPtr tower);
|
||||||
virtual void OnTowerRemove(game::TowerPtr tower);
|
virtual void OnTowerRemove(game::TowerPtr tower);
|
||||||
private:
|
private:
|
||||||
void Click();
|
void Click();
|
||||||
void RenderWorld() const;
|
void RenderWorld() const;
|
||||||
void RenderTowers() const;
|
void RenderTowers() const;
|
||||||
void RenderMobs() const;
|
void RenderMobs() const;
|
||||||
void RenderTileSelect() const;
|
void RenderTileSelect() const;
|
||||||
void RenderPopups();
|
void RenderPopups();
|
||||||
void RenderTowerUpgradePopup();
|
void RenderMobTooltip() const;
|
||||||
void RenderMobTooltip() const;
|
void RenderCastleTooltip() const;
|
||||||
void RenderCastleTooltip() const;
|
void DetectClick();
|
||||||
void DetectClick();
|
void DetectMobHovering() const;
|
||||||
void DetectMobHovering() const;
|
void DetectCastleHovering() const;
|
||||||
void DetectCastleHovering() const;
|
void RenderTooltips() const;
|
||||||
void RenderTooltips() const;
|
void RemoveTower();
|
||||||
void RemoveTower();
|
Vec2f GetCursorWorldPos() const;
|
||||||
glm::vec2 GetCursorWorldPos() const;
|
Vec2f GetClickWorldPos() const;
|
||||||
glm::vec2 GetClickWorldPos() const;
|
|
||||||
|
|
||||||
void UpdateCursorPos();
|
void UpdateCursorPos();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace render
|
} // namespace render
|
||||||
|
|||||||
@@ -14,14 +14,14 @@ namespace gui {
|
|||||||
|
|
||||||
class CastleTooltip : public GuiWidget {
|
class CastleTooltip : public GuiWidget {
|
||||||
private:
|
private:
|
||||||
const game::TeamCastle* m_Castle;
|
const game::TeamCastle* m_Castle;
|
||||||
public:
|
public:
|
||||||
CastleTooltip(client::Client* client);
|
CastleTooltip(client::Client* client);
|
||||||
|
|
||||||
virtual void Render();
|
virtual void Render();
|
||||||
|
|
||||||
void SetCastle(const game::TeamCastle* castle) { m_Castle = castle; }
|
void SetCastle(const game::TeamCastle* castle) { m_Castle = castle; }
|
||||||
bool IsShown() { return m_Castle != nullptr; }
|
bool IsShown() { return m_Castle != nullptr; }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace gui
|
} // namespace gui
|
||||||
|
|||||||
@@ -7,13 +7,13 @@ namespace gui {
|
|||||||
|
|
||||||
class FrameMenu : public GuiWidget {
|
class FrameMenu : public GuiWidget {
|
||||||
private:
|
private:
|
||||||
bool m_VSync;
|
bool m_VSync;
|
||||||
bool m_IsometricView;
|
bool m_IsometricView;
|
||||||
bool m_ShowDemoWindow;
|
bool m_ShowDemoWindow;
|
||||||
public:
|
public:
|
||||||
FrameMenu(client::Client* client);
|
FrameMenu(client::Client* client);
|
||||||
|
|
||||||
virtual void Render();
|
virtual void Render();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace gui
|
} // namespace gui
|
||||||
|
|||||||
@@ -7,17 +7,17 @@ namespace gui {
|
|||||||
|
|
||||||
class GameMenu : public GuiWidget {
|
class GameMenu : public GuiWidget {
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<SummonMenu> m_SummonMenu;
|
std::unique_ptr<SummonMenu> m_SummonMenu;
|
||||||
public:
|
public:
|
||||||
GameMenu(client::Client* client);
|
GameMenu(client::Client* client);
|
||||||
|
|
||||||
virtual void Render();
|
virtual void Render();
|
||||||
private:
|
private:
|
||||||
void ShowTPS();
|
void ShowTPS();
|
||||||
void ShowStats();
|
void ShowStats();
|
||||||
void ShowPlayers();
|
void ShowPlayers();
|
||||||
void ShowLobbyProgress();
|
void ShowLobbyProgress();
|
||||||
void ShowTeamSelection();
|
void ShowTeamSelection();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace gui
|
} // namespace gui
|
||||||
|
|||||||
@@ -10,19 +10,19 @@ namespace gui {
|
|||||||
|
|
||||||
class GuiManager {
|
class GuiManager {
|
||||||
private:
|
private:
|
||||||
std::vector<std::unique_ptr<GuiWidget>> m_Widgets;
|
std::vector<std::unique_ptr<GuiWidget>> m_Widgets;
|
||||||
public:
|
public:
|
||||||
GuiManager() {}
|
GuiManager() {}
|
||||||
|
|
||||||
void RenderWidgets() {
|
void RenderWidgets() {
|
||||||
for (auto& widget : m_Widgets) {
|
for (auto& widget : m_Widgets) {
|
||||||
widget->Render();
|
widget->Render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddWidget(std::unique_ptr<GuiWidget>&& widget) {
|
void AddWidget(std::unique_ptr<GuiWidget>&& widget) {
|
||||||
m_Widgets.push_back(std::move(widget));
|
m_Widgets.push_back(std::move(widget));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace gui
|
} // namespace gui
|
||||||
|
|||||||
@@ -10,13 +10,13 @@ namespace gui {
|
|||||||
|
|
||||||
class GuiWidget {
|
class GuiWidget {
|
||||||
protected:
|
protected:
|
||||||
client::Client* m_Client;
|
client::Client* m_Client;
|
||||||
public:
|
public:
|
||||||
GuiWidget(client::Client* client) : m_Client(client) {}
|
GuiWidget(client::Client* client) : m_Client(client) {}
|
||||||
|
|
||||||
client::Client* GetClient() { return m_Client; }
|
client::Client* GetClient() { return m_Client; }
|
||||||
|
|
||||||
virtual void Render() = 0;
|
virtual void Render() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace gui
|
} // namespace gui
|
||||||
|
|||||||
9
include/render/gui/LifeProgress.h
Normal file
9
include/render/gui/LifeProgress.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace td {
|
||||||
|
namespace gui {
|
||||||
|
|
||||||
|
extern void RenderLifeProgress(float progress);
|
||||||
|
|
||||||
|
} // namespace gui
|
||||||
|
} // namespace td
|
||||||
@@ -13,24 +13,24 @@ namespace gui {
|
|||||||
|
|
||||||
class MainMenu : public GuiWidget {
|
class MainMenu : public GuiWidget {
|
||||||
private:
|
private:
|
||||||
bool m_TriedToConnect = false;
|
bool m_TriedToConnect = false;
|
||||||
bool m_TriedToCreate = false;
|
bool m_TriedToCreate = false;
|
||||||
std::string m_ConnectAddress;
|
std::string m_ConnectAddress;
|
||||||
int m_ConnectPort;
|
int m_ConnectPort;
|
||||||
int m_ServerPort = 25565;
|
int m_ServerPort = 25565;
|
||||||
std::string m_WorldFilePath;
|
std::string m_WorldFilePath;
|
||||||
imgui_addons::ImGuiFileBrowser m_FileDialog;
|
imgui_addons::ImGuiFileBrowser m_FileDialog;
|
||||||
|
|
||||||
std::unique_ptr<server::Server> m_Server;
|
std::unique_ptr<server::Server> m_Server;
|
||||||
public:
|
public:
|
||||||
MainMenu(client::Client* client);
|
MainMenu(client::Client* client);
|
||||||
~MainMenu();
|
~MainMenu();
|
||||||
|
|
||||||
virtual void Render();
|
virtual void Render();
|
||||||
|
|
||||||
const server::Server* GetServer() const { return m_Server.get(); }
|
const server::Server* GetServer() const { return m_Server.get(); }
|
||||||
private:
|
private:
|
||||||
bool StartServer();
|
bool StartServer();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace gui
|
} // namespace gui
|
||||||
|
|||||||
@@ -14,14 +14,14 @@ namespace gui {
|
|||||||
|
|
||||||
class MobTooltip : public GuiWidget {
|
class MobTooltip : public GuiWidget {
|
||||||
private:
|
private:
|
||||||
const game::Mob* m_Mob;
|
const game::Mob* m_Mob;
|
||||||
public:
|
public:
|
||||||
MobTooltip(client::Client* client);
|
MobTooltip(client::Client* client);
|
||||||
|
|
||||||
virtual void Render();
|
virtual void Render();
|
||||||
|
|
||||||
void SetMob(const game::Mob* mob) { m_Mob = mob; }
|
void SetMob(const game::Mob* mob) { m_Mob = mob; }
|
||||||
bool IsShown() { return m_Mob != nullptr; }
|
bool IsShown() { return m_Mob != nullptr; }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace gui
|
} // namespace gui
|
||||||
|
|||||||
@@ -10,16 +10,20 @@ namespace gui {
|
|||||||
|
|
||||||
class SummonMenu : public GuiWidget {
|
class SummonMenu : public GuiWidget {
|
||||||
private:
|
private:
|
||||||
bool m_MenuOpened;
|
bool m_MenuOpened;
|
||||||
int m_ImageWidth = 100;
|
int m_ImageWidth = 100;
|
||||||
static constexpr int m_MobTypeCount = static_cast<std::size_t>(td::game::MobType::MOB_COUNT);
|
float m_Cooldown;
|
||||||
std::array<int, static_cast<std::size_t>(m_MobTypeCount)> m_Values;
|
float m_LastCooldown;
|
||||||
|
static constexpr int m_MobTypeCount = static_cast<std::size_t>(td::game::MobType::MOB_COUNT);
|
||||||
|
std::array<int, static_cast<std::size_t>(m_MobTypeCount)> m_Values;
|
||||||
public:
|
public:
|
||||||
SummonMenu(client::Client* client);
|
SummonMenu(client::Client* client);
|
||||||
|
|
||||||
virtual void Render();
|
void SetCooldown(float cooldown);
|
||||||
|
|
||||||
|
virtual void Render();
|
||||||
private:
|
private:
|
||||||
void SetSummonMax(int valueIndex);
|
void SetSummonMax(int valueIndex);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace gui
|
} // namespace gui
|
||||||
|
|||||||
@@ -28,21 +28,21 @@ class Renderer;
|
|||||||
|
|
||||||
class TowerGui {
|
class TowerGui {
|
||||||
private:
|
private:
|
||||||
SDL_Window* m_Window;
|
SDL_Window* m_Window;
|
||||||
SDL_GLContext m_GlContext;
|
SDL_GLContext m_GlContext;
|
||||||
td::render::Renderer* m_Renderer;
|
td::render::Renderer* m_Renderer;
|
||||||
td::gui::GuiManager m_GuiManager;
|
td::gui::GuiManager m_GuiManager;
|
||||||
std::unique_ptr<td::client::Client> m_Client;
|
std::unique_ptr<td::client::Client> m_Client;
|
||||||
public:
|
public:
|
||||||
TowerGui(SDL_Window* wndow, SDL_GLContext glContext, td::render::Renderer* renderer);
|
TowerGui(SDL_Window* wndow, SDL_GLContext glContext, td::render::Renderer* renderer);
|
||||||
~TowerGui();
|
~TowerGui();
|
||||||
|
|
||||||
void Render();
|
void Render();
|
||||||
private:
|
private:
|
||||||
void InitWidgets();
|
void InitWidgets();
|
||||||
void Tick();
|
void Tick();
|
||||||
void BeginFrame();
|
void BeginFrame();
|
||||||
void EndFrame();
|
void EndFrame();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace render
|
} // namespace render
|
||||||
|
|||||||
@@ -2,26 +2,26 @@
|
|||||||
|
|
||||||
#include "GuiWidget.h"
|
#include "GuiWidget.h"
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include "Defines.h"
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
namespace gui {
|
namespace gui {
|
||||||
|
|
||||||
class TowerPlacePopup : public GuiWidget {
|
class TowerPlacePopup : public GuiWidget {
|
||||||
private:
|
private:
|
||||||
glm::vec2 m_ClickWorldPos;
|
Vec2f m_ClickWorldPos;
|
||||||
public:
|
public:
|
||||||
TowerPlacePopup(client::Client* client);
|
TowerPlacePopup(client::Client* client);
|
||||||
|
|
||||||
virtual void Render();
|
virtual void Render();
|
||||||
|
|
||||||
void SetClickPos(const glm::vec2& worldPos);
|
void SetClickPos(const Vec2f& worldPos);
|
||||||
private:
|
private:
|
||||||
static constexpr float m_TowerPopupTileWidth = 200.0f;
|
static constexpr float m_TowerPopupTileWidth = 200.0f;
|
||||||
static constexpr float m_TowerPopupTileHeight = 200.0f;
|
static constexpr float m_TowerPopupTileHeight = 200.0f;
|
||||||
|
|
||||||
static constexpr float m_PlaceTowerButtonWidth = 150.0f;
|
static constexpr float m_PlaceTowerButtonWidth = 150.0f;
|
||||||
static constexpr float m_PlaceTowerButtonHeight = 35.0f;
|
static constexpr float m_PlaceTowerButtonHeight = 35.0f;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace gui
|
} // namespace gui
|
||||||
|
|||||||
32
include/render/gui/TowerUpgradePopup.h
Normal file
32
include/render/gui/TowerUpgradePopup.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "GuiWidget.h"
|
||||||
|
|
||||||
|
#include "Defines.h"
|
||||||
|
|
||||||
|
namespace td {
|
||||||
|
namespace gui {
|
||||||
|
|
||||||
|
class TowerUpgradePopup : public GuiWidget {
|
||||||
|
private:
|
||||||
|
Vec2f m_ClickWorldPos;
|
||||||
|
bool m_ShouldBeClosed;
|
||||||
|
bool m_Opened;
|
||||||
|
public:
|
||||||
|
TowerUpgradePopup(client::Client* client);
|
||||||
|
|
||||||
|
virtual void Render();
|
||||||
|
|
||||||
|
void SetClickPos(const Vec2f& worldPos);
|
||||||
|
|
||||||
|
bool IsPopupOpened();
|
||||||
|
private:
|
||||||
|
static constexpr float m_TowerPopupTileWidth = 200.0f;
|
||||||
|
static constexpr float m_TowerPopupTileHeight = 200.0f;
|
||||||
|
|
||||||
|
static constexpr float m_PlaceTowerButtonWidth = 150.0f;
|
||||||
|
static constexpr float m_PlaceTowerButtonHeight = 35.0f;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace gui
|
||||||
|
} // namespace td
|
||||||
@@ -2,27 +2,34 @@
|
|||||||
|
|
||||||
#include "GuiWidget.h"
|
#include "GuiWidget.h"
|
||||||
|
|
||||||
#include "updater/Updater.h"
|
|
||||||
|
|
||||||
#include <future>
|
#include <future>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
|
|
||||||
|
namespace utils {
|
||||||
|
|
||||||
|
class Updater;
|
||||||
|
|
||||||
|
} // namespace utils
|
||||||
|
|
||||||
namespace gui {
|
namespace gui {
|
||||||
|
|
||||||
class UpdateMenu : public GuiWidget {
|
class UpdateMenu : public GuiWidget {
|
||||||
private:
|
private:
|
||||||
bool m_Opened;
|
bool m_Opened;
|
||||||
std::string m_Error;
|
std::string m_Error;
|
||||||
utils::Updater m_Updater;
|
std::unique_ptr<utils::Updater> m_Updater;
|
||||||
std::shared_future<bool> m_UpdateAvailable;
|
std::shared_future<bool> m_UpdateAvailable;
|
||||||
public:
|
public:
|
||||||
UpdateMenu(client::Client* client);
|
UpdateMenu(client::Client* client);
|
||||||
|
virtual ~UpdateMenu();
|
||||||
|
|
||||||
virtual void Render();
|
virtual void Render();
|
||||||
private:
|
private:
|
||||||
void CheckUpdates();
|
void CheckUpdates();
|
||||||
bool IsUpdateChecked();
|
bool IsUpdateChecked();
|
||||||
void RenderErrorPopup();
|
void RenderErrorPopup();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace gui
|
} // namespace gui
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ namespace render {
|
|||||||
namespace WorldLoader {
|
namespace WorldLoader {
|
||||||
|
|
||||||
struct RenderData {
|
struct RenderData {
|
||||||
std::vector<float> positions;
|
std::vector<float> positions;
|
||||||
std::vector<float> colors;
|
std::vector<float> colors;
|
||||||
};
|
};
|
||||||
|
|
||||||
GL::VertexArray LoadMobModel();
|
GL::VertexArray LoadMobModel();
|
||||||
|
|||||||
@@ -13,17 +13,19 @@ private:
|
|||||||
unsigned int m_LocationAspectRatio = 0;
|
unsigned int m_LocationAspectRatio = 0;
|
||||||
unsigned int m_LocationTranslation = 0;
|
unsigned int m_LocationTranslation = 0;
|
||||||
unsigned int m_LocationViewtype = 0;
|
unsigned int m_LocationViewtype = 0;
|
||||||
|
unsigned int m_LocationColorEffect = 0;
|
||||||
protected:
|
protected:
|
||||||
virtual void GetAllUniformLocation();
|
virtual void GetAllUniformLocation();
|
||||||
public:
|
public:
|
||||||
EntityShader();
|
EntityShader();
|
||||||
|
|
||||||
void LoadShader();
|
void LoadShader();
|
||||||
void SetCamPos(const glm::vec2& camPos);
|
void SetCamPos(const Vec2f& camPos);
|
||||||
void SetZoom(float zoom);
|
void SetZoom(float zoom);
|
||||||
void SetAspectRatio(float aspectRatio);
|
void SetAspectRatio(float aspectRatio);
|
||||||
void SetModelPos(const glm::vec2& modelPos);
|
void SetModelPos(const Vec2f& modelPos);
|
||||||
void SetIsometricView(float isometric);
|
void SetIsometricView(float isometric);
|
||||||
|
void SetColorEffect(const Vec3f& color);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace shader
|
} // namespace shader
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <glm/glm.hpp>
|
#include "Defines.h"
|
||||||
#include "render/GL.h"
|
#include "render/GL.h"
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
@@ -24,11 +24,9 @@ protected:
|
|||||||
|
|
||||||
void LoadFloat(unsigned int location, float value) const;
|
void LoadFloat(unsigned int location, float value) const;
|
||||||
void LoadInt(unsigned int location, int value) const;
|
void LoadInt(unsigned int location, int value) const;
|
||||||
void LoadVector(unsigned int location, const glm::vec2& vector) const;
|
void LoadVector(unsigned int location, const Vec2f& vector) const;
|
||||||
void LoadVector(unsigned int location, const glm::vec3& vector) const;
|
void LoadVector(unsigned int location, const Vec3f& vector) const;
|
||||||
void LoadVector(unsigned int location, const glm::vec4& vector) const;
|
|
||||||
void LoadBoolean(unsigned int location, bool value) const;
|
void LoadBoolean(unsigned int location, bool value) const;
|
||||||
void LoadMatrix(unsigned int location, const glm::mat4& matrix) const;
|
|
||||||
void CleanUp() const;
|
void CleanUp() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ protected:
|
|||||||
public:
|
public:
|
||||||
WorldShader();
|
WorldShader();
|
||||||
void LoadShader();
|
void LoadShader();
|
||||||
void SetCamPos(const glm::vec2& camPos);
|
void SetCamPos(const Vec2f& camPos);
|
||||||
void SetZoom(float zoom);
|
void SetZoom(float zoom);
|
||||||
void SetAspectRatio(float aspectRatio);
|
void SetAspectRatio(float aspectRatio);
|
||||||
void SetIsometricView(float isometric);
|
void SetIsometricView(float isometric);
|
||||||
|
|||||||
@@ -2,42 +2,42 @@
|
|||||||
|
|
||||||
#include "misc/DataBuffer.h"
|
#include "misc/DataBuffer.h"
|
||||||
|
|
||||||
#define TD_VERSION "alpha-0.2.0"
|
#define TD_VERSION "alpha-0.3.0"
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
namespace utils {
|
namespace utils {
|
||||||
|
|
||||||
class Updater {
|
class Updater {
|
||||||
private:
|
private:
|
||||||
float m_Progress;
|
float m_Progress;
|
||||||
bool m_DownloadComplete;
|
bool m_DownloadComplete;
|
||||||
bool m_FileWrited;
|
bool m_FileWrited;
|
||||||
bool m_CancelDownload;
|
bool m_CancelDownload;
|
||||||
DataBuffer m_FileBuffer;
|
DataBuffer m_FileBuffer;
|
||||||
std::string m_LastVersion;
|
std::string m_LastVersion;
|
||||||
public:
|
public:
|
||||||
Updater() : m_Progress(0), m_DownloadComplete(false), m_FileWrited(false), m_CancelDownload(false) {}
|
Updater() : m_Progress(0), m_DownloadComplete(false), m_FileWrited(false), m_CancelDownload(false) {}
|
||||||
|
|
||||||
bool CheckUpdate();
|
bool CheckUpdate();
|
||||||
void DownloadUpdate();
|
void DownloadUpdate();
|
||||||
void CancelDownload() { m_CancelDownload = true; m_Progress = 0.0f; m_DownloadComplete = false; }
|
void CancelDownload() { m_CancelDownload = true; m_Progress = 0.0f; m_DownloadComplete = false; }
|
||||||
bool WriteFile();
|
bool WriteFile();
|
||||||
|
|
||||||
void ClearCache() { m_FileBuffer.Clear(); }
|
void ClearCache() { m_FileBuffer.Clear(); }
|
||||||
|
|
||||||
float GetDownloadProgress() { return m_Progress; }
|
float GetDownloadProgress() { return m_Progress; }
|
||||||
bool IsDownloadComplete() { return m_DownloadComplete; }
|
bool IsDownloadComplete() { return m_DownloadComplete; }
|
||||||
bool IsFileWrited() { return m_FileWrited; }
|
bool IsFileWrited() { return m_FileWrited; }
|
||||||
|
|
||||||
static std::string GetLocalFilePath();
|
static std::string GetLocalFilePath();
|
||||||
static void RemoveOldFile();
|
static void RemoveOldFile();
|
||||||
|
|
||||||
static std::string GetCurrentVersion() { return TD_VERSION; }
|
static std::string GetCurrentVersion() { return TD_VERSION; }
|
||||||
std::string GetLastVersion() { return m_LastVersion; }
|
std::string GetLastVersion() { return m_LastVersion; }
|
||||||
|
|
||||||
bool CanUpdate();
|
bool CanUpdate();
|
||||||
private:
|
private:
|
||||||
std::string GetDownloadFileURL();
|
std::string GetDownloadFileURL();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace utils
|
} // namespace utils
|
||||||
|
|||||||
40
libs/discordrpc/backoff.h
Normal file
40
libs/discordrpc/backoff.h
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <random>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
struct Backoff {
|
||||||
|
int64_t minAmount;
|
||||||
|
int64_t maxAmount;
|
||||||
|
int64_t current;
|
||||||
|
int fails;
|
||||||
|
std::mt19937_64 randGenerator;
|
||||||
|
std::uniform_real_distribution<> randDistribution;
|
||||||
|
|
||||||
|
double rand01() { return randDistribution(randGenerator); }
|
||||||
|
|
||||||
|
Backoff(int64_t min, int64_t max)
|
||||||
|
: minAmount(min)
|
||||||
|
, maxAmount(max)
|
||||||
|
, current(min)
|
||||||
|
, fails(0)
|
||||||
|
, randGenerator((uint64_t)time(0))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset()
|
||||||
|
{
|
||||||
|
fails = 0;
|
||||||
|
current = minAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t nextDelay()
|
||||||
|
{
|
||||||
|
++fails;
|
||||||
|
int64_t delay = (int64_t)((double)current * 2.0 * rand01());
|
||||||
|
current = std::min(current + delay, maxAmount);
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
};
|
||||||
19
libs/discordrpc/connection.h
Normal file
19
libs/discordrpc/connection.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// This is to wrap the platform specific kinds of connect/read/write.
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
// not really connectiony, but need per-platform
|
||||||
|
int GetProcessId();
|
||||||
|
|
||||||
|
struct BaseConnection {
|
||||||
|
static BaseConnection* Create();
|
||||||
|
static void Destroy(BaseConnection*&);
|
||||||
|
bool isOpen{false};
|
||||||
|
bool Open();
|
||||||
|
bool Close();
|
||||||
|
bool Write(const void* data, size_t length);
|
||||||
|
bool Read(void* data, size_t length);
|
||||||
|
};
|
||||||
129
libs/discordrpc/connection_unix.cpp
Normal file
129
libs/discordrpc/connection_unix.cpp
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
#ifdef __unix__
|
||||||
|
|
||||||
|
#include "connection.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int GetProcessId()
|
||||||
|
{
|
||||||
|
return ::getpid();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct BaseConnectionUnix : public BaseConnection {
|
||||||
|
int sock{-1};
|
||||||
|
};
|
||||||
|
|
||||||
|
static BaseConnectionUnix Connection;
|
||||||
|
static sockaddr_un PipeAddr{};
|
||||||
|
#ifdef MSG_NOSIGNAL
|
||||||
|
static int MsgFlags = MSG_NOSIGNAL;
|
||||||
|
#else
|
||||||
|
static int MsgFlags = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const char* GetTempPath()
|
||||||
|
{
|
||||||
|
const char* temp = getenv("XDG_RUNTIME_DIR");
|
||||||
|
temp = temp ? temp : getenv("TMPDIR");
|
||||||
|
temp = temp ? temp : getenv("TMP");
|
||||||
|
temp = temp ? temp : getenv("TEMP");
|
||||||
|
temp = temp ? temp : "/tmp";
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*static*/ BaseConnection* BaseConnection::Create()
|
||||||
|
{
|
||||||
|
PipeAddr.sun_family = AF_UNIX;
|
||||||
|
return &Connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*static*/ void BaseConnection::Destroy(BaseConnection*& c)
|
||||||
|
{
|
||||||
|
auto self = reinterpret_cast<BaseConnectionUnix*>(c);
|
||||||
|
self->Close();
|
||||||
|
c = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BaseConnection::Open()
|
||||||
|
{
|
||||||
|
const char* tempPath = GetTempPath();
|
||||||
|
auto self = reinterpret_cast<BaseConnectionUnix*>(this);
|
||||||
|
self->sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
if (self->sock == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
fcntl(self->sock, F_SETFL, O_NONBLOCK);
|
||||||
|
#ifdef SO_NOSIGPIPE
|
||||||
|
int optval = 1;
|
||||||
|
setsockopt(self->sock, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (int pipeNum = 0; pipeNum < 10; ++pipeNum) {
|
||||||
|
snprintf(
|
||||||
|
PipeAddr.sun_path, sizeof(PipeAddr.sun_path), "%s/discord-ipc-%d", tempPath, pipeNum);
|
||||||
|
int err = connect(self->sock, (const sockaddr*)&PipeAddr, sizeof(PipeAddr));
|
||||||
|
if (err == 0) {
|
||||||
|
self->isOpen = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self->Close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BaseConnection::Close()
|
||||||
|
{
|
||||||
|
auto self = reinterpret_cast<BaseConnectionUnix*>(this);
|
||||||
|
if (self->sock == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
close(self->sock);
|
||||||
|
self->sock = -1;
|
||||||
|
self->isOpen = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BaseConnection::Write(const void* data, size_t length)
|
||||||
|
{
|
||||||
|
auto self = reinterpret_cast<BaseConnectionUnix*>(this);
|
||||||
|
|
||||||
|
if (self->sock == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t sentBytes = send(self->sock, data, length, MsgFlags);
|
||||||
|
if (sentBytes < 0) {
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
return sentBytes == (ssize_t)length;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BaseConnection::Read(void* data, size_t length)
|
||||||
|
{
|
||||||
|
auto self = reinterpret_cast<BaseConnectionUnix*>(this);
|
||||||
|
|
||||||
|
if (self->sock == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int res = (int)recv(self->sock, data, length, MsgFlags);
|
||||||
|
if (res < 0) {
|
||||||
|
if (errno == EAGAIN) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
else if (res == 0) {
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
return res == (int)length;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
132
libs/discordrpc/connection_win.cpp
Normal file
132
libs/discordrpc/connection_win.cpp
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
|
|
||||||
|
#include "connection.h"
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#define NOMCX
|
||||||
|
#define NOSERVICE
|
||||||
|
#define NOIME
|
||||||
|
#include <assert.h>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
int GetProcessId()
|
||||||
|
{
|
||||||
|
return (int)::GetCurrentProcessId();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct BaseConnectionWin : public BaseConnection {
|
||||||
|
HANDLE pipe{INVALID_HANDLE_VALUE};
|
||||||
|
};
|
||||||
|
|
||||||
|
static BaseConnectionWin Connection;
|
||||||
|
|
||||||
|
/*static*/ BaseConnection* BaseConnection::Create()
|
||||||
|
{
|
||||||
|
return &Connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*static*/ void BaseConnection::Destroy(BaseConnection*& c)
|
||||||
|
{
|
||||||
|
auto self = reinterpret_cast<BaseConnectionWin*>(c);
|
||||||
|
self->Close();
|
||||||
|
c = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BaseConnection::Open()
|
||||||
|
{
|
||||||
|
wchar_t pipeName[]{L"\\\\?\\pipe\\discord-ipc-0"};
|
||||||
|
const size_t pipeDigit = sizeof(pipeName) / sizeof(wchar_t) - 2;
|
||||||
|
pipeName[pipeDigit] = L'0';
|
||||||
|
auto self = reinterpret_cast<BaseConnectionWin*>(this);
|
||||||
|
for (;;) {
|
||||||
|
self->pipe = ::CreateFileW(
|
||||||
|
pipeName, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||||
|
if (self->pipe != INVALID_HANDLE_VALUE) {
|
||||||
|
self->isOpen = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lastError = GetLastError();
|
||||||
|
if (lastError == ERROR_FILE_NOT_FOUND) {
|
||||||
|
if (pipeName[pipeDigit] < L'9') {
|
||||||
|
pipeName[pipeDigit]++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (lastError == ERROR_PIPE_BUSY) {
|
||||||
|
if (!WaitNamedPipeW(pipeName, 10000)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BaseConnection::Close()
|
||||||
|
{
|
||||||
|
auto self = reinterpret_cast<BaseConnectionWin*>(this);
|
||||||
|
::CloseHandle(self->pipe);
|
||||||
|
self->pipe = INVALID_HANDLE_VALUE;
|
||||||
|
self->isOpen = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BaseConnection::Write(const void* data, size_t length)
|
||||||
|
{
|
||||||
|
if (length == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
auto self = reinterpret_cast<BaseConnectionWin*>(this);
|
||||||
|
assert(self);
|
||||||
|
if (!self) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (self->pipe == INVALID_HANDLE_VALUE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
assert(data);
|
||||||
|
if (!data) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const DWORD bytesLength = (DWORD)length;
|
||||||
|
DWORD bytesWritten = 0;
|
||||||
|
return ::WriteFile(self->pipe, data, bytesLength, &bytesWritten, nullptr) == TRUE &&
|
||||||
|
bytesWritten == bytesLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BaseConnection::Read(void* data, size_t length)
|
||||||
|
{
|
||||||
|
assert(data);
|
||||||
|
if (!data) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto self = reinterpret_cast<BaseConnectionWin*>(this);
|
||||||
|
assert(self);
|
||||||
|
if (!self) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (self->pipe == INVALID_HANDLE_VALUE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
DWORD bytesAvailable = 0;
|
||||||
|
if (::PeekNamedPipe(self->pipe, nullptr, 0, nullptr, &bytesAvailable, nullptr)) {
|
||||||
|
if (bytesAvailable >= length) {
|
||||||
|
DWORD bytesToRead = (DWORD)length;
|
||||||
|
DWORD bytesRead = 0;
|
||||||
|
if (::ReadFile(self->pipe, data, bytesToRead, &bytesRead, nullptr) == TRUE) {
|
||||||
|
assert(bytesToRead == bytesRead);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
26
libs/discordrpc/discord_register.h
Normal file
26
libs/discordrpc/discord_register.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if defined(DISCORD_DYNAMIC_LIB)
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#if defined(DISCORD_BUILDING_SDK)
|
||||||
|
#define DISCORD_EXPORT __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
#define DISCORD_EXPORT __declspec(dllimport)
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define DISCORD_EXPORT __attribute__((visibility("default")))
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define DISCORD_EXPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DISCORD_EXPORT void Discord_Register(const char* applicationId, const char* command);
|
||||||
|
DISCORD_EXPORT void Discord_RegisterSteamGame(const char* applicationId, const char* steamId);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
106
libs/discordrpc/discord_register_linux.cpp
Normal file
106
libs/discordrpc/discord_register_linux.cpp
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
#ifdef __unix__
|
||||||
|
|
||||||
|
#include "discord_rpc.h"
|
||||||
|
#include "discord_register.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
static bool Mkdir(const char* path)
|
||||||
|
{
|
||||||
|
int result = mkdir(path, 0755);
|
||||||
|
if (result == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (errno == EEXIST) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we want to register games so we can run them from Discord client as discord-<appid>://
|
||||||
|
extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const char* command)
|
||||||
|
{
|
||||||
|
// Add a desktop file and update some mime handlers so that xdg-open does the right thing.
|
||||||
|
|
||||||
|
const char* home = getenv("HOME");
|
||||||
|
if (!home) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char exePath[1024];
|
||||||
|
if (!command || !command[0]) {
|
||||||
|
ssize_t size = readlink("/proc/self/exe", exePath, sizeof(exePath));
|
||||||
|
if (size <= 0 || size >= (ssize_t)sizeof(exePath)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
exePath[size] = '\0';
|
||||||
|
command = exePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* desktopFileFormat = "[Desktop Entry]\n"
|
||||||
|
"Name=Game %s\n"
|
||||||
|
"Exec=%s %%u\n" // note: it really wants that %u in there
|
||||||
|
"Type=Application\n"
|
||||||
|
"NoDisplay=true\n"
|
||||||
|
"Categories=Discord;Games;\n"
|
||||||
|
"MimeType=x-scheme-handler/discord-%s;\n";
|
||||||
|
char desktopFile[2048];
|
||||||
|
int fileLen = snprintf(
|
||||||
|
desktopFile, sizeof(desktopFile), desktopFileFormat, applicationId, command, applicationId);
|
||||||
|
if (fileLen <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char desktopFilename[256];
|
||||||
|
snprintf(desktopFilename, sizeof(desktopFilename), "/discord-%s.desktop", applicationId);
|
||||||
|
|
||||||
|
char desktopFilePath[1024];
|
||||||
|
snprintf(desktopFilePath, sizeof(desktopFilePath), "%s/.local", home);
|
||||||
|
if (!Mkdir(desktopFilePath)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
strcat(desktopFilePath, "/share");
|
||||||
|
if (!Mkdir(desktopFilePath)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
strcat(desktopFilePath, "/applications");
|
||||||
|
if (!Mkdir(desktopFilePath)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
strcat(desktopFilePath, desktopFilename);
|
||||||
|
|
||||||
|
FILE* fp = fopen(desktopFilePath, "w");
|
||||||
|
if (fp) {
|
||||||
|
fwrite(desktopFile, 1, fileLen, fp);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char xdgMimeCommand[1024];
|
||||||
|
snprintf(xdgMimeCommand,
|
||||||
|
sizeof(xdgMimeCommand),
|
||||||
|
"xdg-mime default discord-%s.desktop x-scheme-handler/discord-%s",
|
||||||
|
applicationId,
|
||||||
|
applicationId);
|
||||||
|
if (system(xdgMimeCommand) < 0) {
|
||||||
|
fprintf(stderr, "Failed to register mime handler\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" DISCORD_EXPORT void Discord_RegisterSteamGame(const char* applicationId,
|
||||||
|
const char* steamId)
|
||||||
|
{
|
||||||
|
char command[256];
|
||||||
|
sprintf(command, "xdg-open steam://rungameid/%s", steamId);
|
||||||
|
Discord_Register(applicationId, command);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
190
libs/discordrpc/discord_register_win.cpp
Normal file
190
libs/discordrpc/discord_register_win.cpp
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
|
|
||||||
|
#include "discord_rpc.h"
|
||||||
|
#include "discord_register.h"
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#define NOMCX
|
||||||
|
#define NOSERVICE
|
||||||
|
#define NOIME
|
||||||
|
#include <windows.h>
|
||||||
|
#include <psapi.h>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updated fixes for MinGW and WinXP
|
||||||
|
* This block is written the way it does not involve changing the rest of the code
|
||||||
|
* Checked to be compiling
|
||||||
|
* 1) strsafe.h belongs to Windows SDK and cannot be added to MinGW
|
||||||
|
* #include guarded, functions redirected to <string.h> substitutes
|
||||||
|
* 2) RegSetKeyValueW and LSTATUS are not declared in <winreg.h>
|
||||||
|
* The entire function is rewritten
|
||||||
|
*/
|
||||||
|
#ifdef __MINGW32__
|
||||||
|
#include <wchar.h>
|
||||||
|
/// strsafe.h fixes
|
||||||
|
static HRESULT StringCbPrintfW(LPWSTR pszDest, size_t cbDest, LPCWSTR pszFormat, ...)
|
||||||
|
{
|
||||||
|
HRESULT ret;
|
||||||
|
va_list va;
|
||||||
|
va_start(va, pszFormat);
|
||||||
|
cbDest /= 2; // Size is divided by 2 to convert from bytes to wide characters - causes segfault
|
||||||
|
// othervise
|
||||||
|
ret = vsnwprintf(pszDest, cbDest, pszFormat, va);
|
||||||
|
pszDest[cbDest - 1] = 0; // Terminate the string in case a buffer overflow; -1 will be returned
|
||||||
|
va_end(va);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#include <cwchar>
|
||||||
|
#include <strsafe.h>
|
||||||
|
#endif // __MINGW32__
|
||||||
|
|
||||||
|
/// winreg.h fixes
|
||||||
|
#ifndef LSTATUS
|
||||||
|
#define LSTATUS LONG
|
||||||
|
#endif
|
||||||
|
#ifdef RegSetKeyValueW
|
||||||
|
#undefine RegSetKeyValueW
|
||||||
|
#endif
|
||||||
|
#define RegSetKeyValueW regset
|
||||||
|
static LSTATUS regset(HKEY hkey,
|
||||||
|
LPCWSTR subkey,
|
||||||
|
LPCWSTR name,
|
||||||
|
DWORD type,
|
||||||
|
const void* data,
|
||||||
|
DWORD len)
|
||||||
|
{
|
||||||
|
HKEY htkey = hkey, hsubkey = nullptr;
|
||||||
|
LSTATUS ret;
|
||||||
|
if (subkey && subkey[0]) {
|
||||||
|
if ((ret = RegCreateKeyExW(hkey, subkey, 0, 0, 0, KEY_ALL_ACCESS, 0, &hsubkey, 0)) !=
|
||||||
|
ERROR_SUCCESS)
|
||||||
|
return ret;
|
||||||
|
htkey = hsubkey;
|
||||||
|
}
|
||||||
|
ret = RegSetValueExW(htkey, name, 0, type, (const BYTE*)data, len);
|
||||||
|
if (hsubkey && hsubkey != hkey)
|
||||||
|
RegCloseKey(hsubkey);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Discord_RegisterW(const wchar_t* applicationId, const wchar_t* command)
|
||||||
|
{
|
||||||
|
// https://msdn.microsoft.com/en-us/library/aa767914(v=vs.85).aspx
|
||||||
|
// we want to register games so we can run them as discord-<appid>://
|
||||||
|
// Update the HKEY_CURRENT_USER, because it doesn't seem to require special permissions.
|
||||||
|
|
||||||
|
wchar_t exeFilePath[MAX_PATH];
|
||||||
|
DWORD exeLen = GetModuleFileNameW(nullptr, exeFilePath, MAX_PATH);
|
||||||
|
wchar_t openCommand[1024];
|
||||||
|
|
||||||
|
if (command && command[0]) {
|
||||||
|
StringCbPrintfW(openCommand, sizeof(openCommand), L"%s", command);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// StringCbCopyW(openCommand, sizeof(openCommand), exeFilePath);
|
||||||
|
StringCbPrintfW(openCommand, sizeof(openCommand), L"%s", exeFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t protocolName[64];
|
||||||
|
StringCbPrintfW(protocolName, sizeof(protocolName), L"discord-%s", applicationId);
|
||||||
|
wchar_t protocolDescription[128];
|
||||||
|
StringCbPrintfW(
|
||||||
|
protocolDescription, sizeof(protocolDescription), L"URL:Run game %s protocol", applicationId);
|
||||||
|
wchar_t urlProtocol = 0;
|
||||||
|
|
||||||
|
wchar_t keyName[256];
|
||||||
|
StringCbPrintfW(keyName, sizeof(keyName), L"Software\\Classes\\%s", protocolName);
|
||||||
|
HKEY key;
|
||||||
|
auto status =
|
||||||
|
RegCreateKeyExW(HKEY_CURRENT_USER, keyName, 0, nullptr, 0, KEY_WRITE, nullptr, &key, nullptr);
|
||||||
|
if (status != ERROR_SUCCESS) {
|
||||||
|
fprintf(stderr, "Error creating key\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DWORD len;
|
||||||
|
LSTATUS result;
|
||||||
|
len = (DWORD)lstrlenW(protocolDescription) + 1;
|
||||||
|
result =
|
||||||
|
RegSetKeyValueW(key, nullptr, nullptr, REG_SZ, protocolDescription, len * sizeof(wchar_t));
|
||||||
|
if (FAILED(result)) {
|
||||||
|
fprintf(stderr, "Error writing description\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
len = (DWORD)lstrlenW(protocolDescription) + 1;
|
||||||
|
result = RegSetKeyValueW(key, nullptr, L"URL Protocol", REG_SZ, &urlProtocol, sizeof(wchar_t));
|
||||||
|
if (FAILED(result)) {
|
||||||
|
fprintf(stderr, "Error writing description\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
result = RegSetKeyValueW(
|
||||||
|
key, L"DefaultIcon", nullptr, REG_SZ, exeFilePath, (exeLen + 1) * sizeof(wchar_t));
|
||||||
|
if (FAILED(result)) {
|
||||||
|
fprintf(stderr, "Error writing icon\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
len = (DWORD)lstrlenW(openCommand) + 1;
|
||||||
|
result = RegSetKeyValueW(
|
||||||
|
key, L"shell\\open\\command", nullptr, REG_SZ, openCommand, len * sizeof(wchar_t));
|
||||||
|
if (FAILED(result)) {
|
||||||
|
fprintf(stderr, "Error writing command\n");
|
||||||
|
}
|
||||||
|
RegCloseKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const char* command)
|
||||||
|
{
|
||||||
|
wchar_t appId[32];
|
||||||
|
MultiByteToWideChar(CP_UTF8, 0, applicationId, -1, appId, 32);
|
||||||
|
|
||||||
|
wchar_t openCommand[1024];
|
||||||
|
const wchar_t* wcommand = nullptr;
|
||||||
|
if (command && command[0]) {
|
||||||
|
const auto commandBufferLen = sizeof(openCommand) / sizeof(*openCommand);
|
||||||
|
MultiByteToWideChar(CP_UTF8, 0, command, -1, openCommand, commandBufferLen);
|
||||||
|
wcommand = openCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
Discord_RegisterW(appId, wcommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" DISCORD_EXPORT void Discord_RegisterSteamGame(const char* applicationId,
|
||||||
|
const char* steamId)
|
||||||
|
{
|
||||||
|
wchar_t appId[32];
|
||||||
|
MultiByteToWideChar(CP_UTF8, 0, applicationId, -1, appId, 32);
|
||||||
|
|
||||||
|
wchar_t wSteamId[32];
|
||||||
|
MultiByteToWideChar(CP_UTF8, 0, steamId, -1, wSteamId, 32);
|
||||||
|
|
||||||
|
HKEY key;
|
||||||
|
auto status = RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Valve\\Steam", 0, KEY_READ, &key);
|
||||||
|
if (status != ERROR_SUCCESS) {
|
||||||
|
fprintf(stderr, "Error opening Steam key\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t steamPath[MAX_PATH];
|
||||||
|
DWORD pathBytes = sizeof(steamPath);
|
||||||
|
status = RegQueryValueExW(key, L"SteamExe", nullptr, nullptr, (BYTE*)steamPath, &pathBytes);
|
||||||
|
RegCloseKey(key);
|
||||||
|
if (status != ERROR_SUCCESS || pathBytes < 1) {
|
||||||
|
fprintf(stderr, "Error reading SteamExe key\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD pathChars = pathBytes / sizeof(wchar_t);
|
||||||
|
for (DWORD i = 0; i < pathChars; ++i) {
|
||||||
|
if (steamPath[i] == L'/') {
|
||||||
|
steamPath[i] = L'\\';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t command[1024];
|
||||||
|
StringCbPrintfW(command, sizeof(command), L"\"%s\" steam://rungameid/%s", steamPath, wSteamId);
|
||||||
|
|
||||||
|
Discord_RegisterW(appId, command);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
504
libs/discordrpc/discord_rpc.cpp
Normal file
504
libs/discordrpc/discord_rpc.cpp
Normal file
@@ -0,0 +1,504 @@
|
|||||||
|
#include "discord_rpc.h"
|
||||||
|
|
||||||
|
#include "backoff.h"
|
||||||
|
#include "discord_register.h"
|
||||||
|
#include "msg_queue.h"
|
||||||
|
#include "rpc_connection.h"
|
||||||
|
#include "serialization.h"
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <chrono>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
#ifndef DISCORD_DISABLE_IO_THREAD
|
||||||
|
#include <condition_variable>
|
||||||
|
#include <thread>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
constexpr size_t MaxMessageSize{16 * 1024};
|
||||||
|
constexpr size_t MessageQueueSize{8};
|
||||||
|
constexpr size_t JoinQueueSize{8};
|
||||||
|
|
||||||
|
struct QueuedMessage {
|
||||||
|
size_t length;
|
||||||
|
char buffer[MaxMessageSize];
|
||||||
|
|
||||||
|
void Copy(const QueuedMessage& other)
|
||||||
|
{
|
||||||
|
length = other.length;
|
||||||
|
if (length) {
|
||||||
|
memcpy(buffer, other.buffer, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct User {
|
||||||
|
// snowflake (64bit int), turned into a ascii decimal string, at most 20 chars +1 null
|
||||||
|
// terminator = 21
|
||||||
|
char userId[32];
|
||||||
|
// 32 unicode glyphs is max name size => 4 bytes per glyph in the worst case, +1 for null
|
||||||
|
// terminator = 129
|
||||||
|
char username[344];
|
||||||
|
// 4 decimal digits + 1 null terminator = 5
|
||||||
|
char discriminator[8];
|
||||||
|
// optional 'a_' + md5 hex digest (32 bytes) + null terminator = 35
|
||||||
|
char avatar[128];
|
||||||
|
// Rounded way up because I'm paranoid about games breaking from future changes in these sizes
|
||||||
|
};
|
||||||
|
|
||||||
|
static RpcConnection* Connection{nullptr};
|
||||||
|
static DiscordEventHandlers QueuedHandlers{};
|
||||||
|
static DiscordEventHandlers Handlers{};
|
||||||
|
static std::atomic_bool WasJustConnected{false};
|
||||||
|
static std::atomic_bool WasJustDisconnected{false};
|
||||||
|
static std::atomic_bool GotErrorMessage{false};
|
||||||
|
static std::atomic_bool WasJoinGame{false};
|
||||||
|
static std::atomic_bool WasSpectateGame{false};
|
||||||
|
static std::atomic_bool UpdatePresence{false};
|
||||||
|
static char JoinGameSecret[256];
|
||||||
|
static char SpectateGameSecret[256];
|
||||||
|
static int LastErrorCode{0};
|
||||||
|
static char LastErrorMessage[256];
|
||||||
|
static int LastDisconnectErrorCode{0};
|
||||||
|
static char LastDisconnectErrorMessage[256];
|
||||||
|
static std::mutex PresenceMutex;
|
||||||
|
static std::mutex HandlerMutex;
|
||||||
|
static QueuedMessage QueuedPresence{};
|
||||||
|
static MsgQueue<QueuedMessage, MessageQueueSize> SendQueue;
|
||||||
|
static MsgQueue<User, JoinQueueSize> JoinAskQueue;
|
||||||
|
static User connectedUser;
|
||||||
|
|
||||||
|
// We want to auto connect, and retry on failure, but not as fast as possible. This does expoential
|
||||||
|
// backoff from 0.5 seconds to 1 minute
|
||||||
|
static Backoff ReconnectTimeMs(500, 60 * 1000);
|
||||||
|
static auto NextConnect = std::chrono::system_clock::now();
|
||||||
|
static int Pid{0};
|
||||||
|
static int Nonce{1};
|
||||||
|
|
||||||
|
#ifndef DISCORD_DISABLE_IO_THREAD
|
||||||
|
static void Discord_UpdateConnection(void);
|
||||||
|
class IoThreadHolder {
|
||||||
|
private:
|
||||||
|
std::atomic_bool keepRunning{true};
|
||||||
|
std::mutex waitForIOMutex;
|
||||||
|
std::condition_variable waitForIOActivity;
|
||||||
|
std::thread ioThread;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void Start()
|
||||||
|
{
|
||||||
|
keepRunning.store(true);
|
||||||
|
ioThread = std::thread([&]() {
|
||||||
|
const std::chrono::duration<int64_t, std::milli> maxWait{500LL};
|
||||||
|
Discord_UpdateConnection();
|
||||||
|
while (keepRunning.load()) {
|
||||||
|
std::unique_lock<std::mutex> lock(waitForIOMutex);
|
||||||
|
waitForIOActivity.wait_for(lock, maxWait);
|
||||||
|
Discord_UpdateConnection();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void Notify() { waitForIOActivity.notify_all(); }
|
||||||
|
|
||||||
|
void Stop()
|
||||||
|
{
|
||||||
|
keepRunning.exchange(false);
|
||||||
|
Notify();
|
||||||
|
if (ioThread.joinable()) {
|
||||||
|
ioThread.join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~IoThreadHolder() { Stop(); }
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
class IoThreadHolder {
|
||||||
|
public:
|
||||||
|
void Start() {}
|
||||||
|
void Stop() {}
|
||||||
|
void Notify() {}
|
||||||
|
};
|
||||||
|
#endif // DISCORD_DISABLE_IO_THREAD
|
||||||
|
static IoThreadHolder* IoThread{nullptr};
|
||||||
|
|
||||||
|
static void UpdateReconnectTime()
|
||||||
|
{
|
||||||
|
NextConnect = std::chrono::system_clock::now() +
|
||||||
|
std::chrono::duration<int64_t, std::milli>{ReconnectTimeMs.nextDelay()};
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DISCORD_DISABLE_IO_THREAD
|
||||||
|
extern "C" DISCORD_EXPORT void Discord_UpdateConnection(void)
|
||||||
|
#else
|
||||||
|
static void Discord_UpdateConnection(void)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if (!Connection) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Connection->IsOpen()) {
|
||||||
|
if (std::chrono::system_clock::now() >= NextConnect) {
|
||||||
|
UpdateReconnectTime();
|
||||||
|
Connection->Open();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// reads
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
JsonDocument message;
|
||||||
|
|
||||||
|
if (!Connection->Read(message)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* evtName = GetStrMember(&message, "evt");
|
||||||
|
const char* nonce = GetStrMember(&message, "nonce");
|
||||||
|
|
||||||
|
if (nonce) {
|
||||||
|
// in responses only -- should use to match up response when needed.
|
||||||
|
|
||||||
|
if (evtName && strcmp(evtName, "ERROR") == 0) {
|
||||||
|
auto data = GetObjMember(&message, "data");
|
||||||
|
LastErrorCode = GetIntMember(data, "code");
|
||||||
|
StringCopy(LastErrorMessage, GetStrMember(data, "message", ""));
|
||||||
|
GotErrorMessage.store(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// should have evt == name of event, optional data
|
||||||
|
if (evtName == nullptr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto data = GetObjMember(&message, "data");
|
||||||
|
|
||||||
|
if (strcmp(evtName, "ACTIVITY_JOIN") == 0) {
|
||||||
|
auto secret = GetStrMember(data, "secret");
|
||||||
|
if (secret) {
|
||||||
|
StringCopy(JoinGameSecret, secret);
|
||||||
|
WasJoinGame.store(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strcmp(evtName, "ACTIVITY_SPECTATE") == 0) {
|
||||||
|
auto secret = GetStrMember(data, "secret");
|
||||||
|
if (secret) {
|
||||||
|
StringCopy(SpectateGameSecret, secret);
|
||||||
|
WasSpectateGame.store(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strcmp(evtName, "ACTIVITY_JOIN_REQUEST") == 0) {
|
||||||
|
auto user = GetObjMember(data, "user");
|
||||||
|
auto userId = GetStrMember(user, "id");
|
||||||
|
auto username = GetStrMember(user, "username");
|
||||||
|
auto avatar = GetStrMember(user, "avatar");
|
||||||
|
auto joinReq = JoinAskQueue.GetNextAddMessage();
|
||||||
|
if (userId && username && joinReq) {
|
||||||
|
StringCopy(joinReq->userId, userId);
|
||||||
|
StringCopy(joinReq->username, username);
|
||||||
|
auto discriminator = GetStrMember(user, "discriminator");
|
||||||
|
if (discriminator) {
|
||||||
|
StringCopy(joinReq->discriminator, discriminator);
|
||||||
|
}
|
||||||
|
if (avatar) {
|
||||||
|
StringCopy(joinReq->avatar, avatar);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
joinReq->avatar[0] = 0;
|
||||||
|
}
|
||||||
|
JoinAskQueue.CommitAdd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// writes
|
||||||
|
if (UpdatePresence.exchange(false) && QueuedPresence.length) {
|
||||||
|
QueuedMessage local;
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> guard(PresenceMutex);
|
||||||
|
local.Copy(QueuedPresence);
|
||||||
|
}
|
||||||
|
if (!Connection->Write(local.buffer, local.length)) {
|
||||||
|
// if we fail to send, requeue
|
||||||
|
std::lock_guard<std::mutex> guard(PresenceMutex);
|
||||||
|
QueuedPresence.Copy(local);
|
||||||
|
UpdatePresence.exchange(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (SendQueue.HavePendingSends()) {
|
||||||
|
auto qmessage = SendQueue.GetNextSendMessage();
|
||||||
|
Connection->Write(qmessage->buffer, qmessage->length);
|
||||||
|
SendQueue.CommitSend();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SignalIOActivity()
|
||||||
|
{
|
||||||
|
if (IoThread != nullptr) {
|
||||||
|
IoThread->Notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool RegisterForEvent(const char* evtName)
|
||||||
|
{
|
||||||
|
auto qmessage = SendQueue.GetNextAddMessage();
|
||||||
|
if (qmessage) {
|
||||||
|
qmessage->length =
|
||||||
|
JsonWriteSubscribeCommand(qmessage->buffer, sizeof(qmessage->buffer), Nonce++, evtName);
|
||||||
|
SendQueue.CommitAdd();
|
||||||
|
SignalIOActivity();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool DeregisterForEvent(const char* evtName)
|
||||||
|
{
|
||||||
|
auto qmessage = SendQueue.GetNextAddMessage();
|
||||||
|
if (qmessage) {
|
||||||
|
qmessage->length =
|
||||||
|
JsonWriteUnsubscribeCommand(qmessage->buffer, sizeof(qmessage->buffer), Nonce++, evtName);
|
||||||
|
SendQueue.CommitAdd();
|
||||||
|
SignalIOActivity();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" DISCORD_EXPORT void Discord_Initialize(const char* applicationId,
|
||||||
|
DiscordEventHandlers* handlers,
|
||||||
|
int autoRegister,
|
||||||
|
const char* optionalSteamId)
|
||||||
|
{
|
||||||
|
IoThread = new (std::nothrow) IoThreadHolder();
|
||||||
|
if (IoThread == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (autoRegister) {
|
||||||
|
if (optionalSteamId && optionalSteamId[0]) {
|
||||||
|
Discord_RegisterSteamGame(applicationId, optionalSteamId);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Discord_Register(applicationId, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Pid = GetProcessId();
|
||||||
|
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> guard(HandlerMutex);
|
||||||
|
|
||||||
|
if (handlers) {
|
||||||
|
QueuedHandlers = *handlers;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
QueuedHandlers = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Handlers = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Connection) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Connection = RpcConnection::Create(applicationId);
|
||||||
|
Connection->onConnect = [](JsonDocument& readyMessage) {
|
||||||
|
Discord_UpdateHandlers(&QueuedHandlers);
|
||||||
|
if (QueuedPresence.length > 0) {
|
||||||
|
UpdatePresence.exchange(true);
|
||||||
|
SignalIOActivity();
|
||||||
|
}
|
||||||
|
auto data = GetObjMember(&readyMessage, "data");
|
||||||
|
auto user = GetObjMember(data, "user");
|
||||||
|
auto userId = GetStrMember(user, "id");
|
||||||
|
auto username = GetStrMember(user, "username");
|
||||||
|
auto avatar = GetStrMember(user, "avatar");
|
||||||
|
if (userId && username) {
|
||||||
|
StringCopy(connectedUser.userId, userId);
|
||||||
|
StringCopy(connectedUser.username, username);
|
||||||
|
auto discriminator = GetStrMember(user, "discriminator");
|
||||||
|
if (discriminator) {
|
||||||
|
StringCopy(connectedUser.discriminator, discriminator);
|
||||||
|
}
|
||||||
|
if (avatar) {
|
||||||
|
StringCopy(connectedUser.avatar, avatar);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
connectedUser.avatar[0] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WasJustConnected.exchange(true);
|
||||||
|
ReconnectTimeMs.reset();
|
||||||
|
};
|
||||||
|
Connection->onDisconnect = [](int err, const char* message) {
|
||||||
|
LastDisconnectErrorCode = err;
|
||||||
|
StringCopy(LastDisconnectErrorMessage, message);
|
||||||
|
WasJustDisconnected.exchange(true);
|
||||||
|
UpdateReconnectTime();
|
||||||
|
};
|
||||||
|
|
||||||
|
IoThread->Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" DISCORD_EXPORT void Discord_Shutdown(void)
|
||||||
|
{
|
||||||
|
if (!Connection) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Connection->onConnect = nullptr;
|
||||||
|
Connection->onDisconnect = nullptr;
|
||||||
|
Handlers = {};
|
||||||
|
QueuedPresence.length = 0;
|
||||||
|
UpdatePresence.exchange(false);
|
||||||
|
if (IoThread != nullptr) {
|
||||||
|
IoThread->Stop();
|
||||||
|
delete IoThread;
|
||||||
|
IoThread = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
RpcConnection::Destroy(Connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" DISCORD_EXPORT void Discord_UpdatePresence(const DiscordRichPresence* presence)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> guard(PresenceMutex);
|
||||||
|
QueuedPresence.length = JsonWriteRichPresenceObj(
|
||||||
|
QueuedPresence.buffer, sizeof(QueuedPresence.buffer), Nonce++, Pid, presence);
|
||||||
|
UpdatePresence.exchange(true);
|
||||||
|
}
|
||||||
|
SignalIOActivity();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" DISCORD_EXPORT void Discord_ClearPresence(void)
|
||||||
|
{
|
||||||
|
Discord_UpdatePresence(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" DISCORD_EXPORT void Discord_Respond(const char* userId, /* DISCORD_REPLY_ */ int reply)
|
||||||
|
{
|
||||||
|
// if we are not connected, let's not batch up stale messages for later
|
||||||
|
if (!Connection || !Connection->IsOpen()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto qmessage = SendQueue.GetNextAddMessage();
|
||||||
|
if (qmessage) {
|
||||||
|
qmessage->length =
|
||||||
|
JsonWriteJoinReply(qmessage->buffer, sizeof(qmessage->buffer), userId, reply, Nonce++);
|
||||||
|
SendQueue.CommitAdd();
|
||||||
|
SignalIOActivity();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" DISCORD_EXPORT void Discord_RunCallbacks(void)
|
||||||
|
{
|
||||||
|
// Note on some weirdness: internally we might connect, get other signals, disconnect any number
|
||||||
|
// of times inbetween calls here. Externally, we want the sequence to seem sane, so any other
|
||||||
|
// signals are book-ended by calls to ready and disconnect.
|
||||||
|
|
||||||
|
if (!Connection) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wasDisconnected = WasJustDisconnected.exchange(false);
|
||||||
|
bool isConnected = Connection->IsOpen();
|
||||||
|
|
||||||
|
if (isConnected) {
|
||||||
|
// if we are connected, disconnect cb first
|
||||||
|
std::lock_guard<std::mutex> guard(HandlerMutex);
|
||||||
|
if (wasDisconnected && Handlers.disconnected) {
|
||||||
|
Handlers.disconnected(LastDisconnectErrorCode, LastDisconnectErrorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WasJustConnected.exchange(false)) {
|
||||||
|
std::lock_guard<std::mutex> guard(HandlerMutex);
|
||||||
|
if (Handlers.ready) {
|
||||||
|
DiscordUser du{connectedUser.userId,
|
||||||
|
connectedUser.username,
|
||||||
|
connectedUser.discriminator,
|
||||||
|
connectedUser.avatar};
|
||||||
|
Handlers.ready(&du);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GotErrorMessage.exchange(false)) {
|
||||||
|
std::lock_guard<std::mutex> guard(HandlerMutex);
|
||||||
|
if (Handlers.errored) {
|
||||||
|
Handlers.errored(LastErrorCode, LastErrorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WasJoinGame.exchange(false)) {
|
||||||
|
std::lock_guard<std::mutex> guard(HandlerMutex);
|
||||||
|
if (Handlers.joinGame) {
|
||||||
|
Handlers.joinGame(JoinGameSecret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WasSpectateGame.exchange(false)) {
|
||||||
|
std::lock_guard<std::mutex> guard(HandlerMutex);
|
||||||
|
if (Handlers.spectateGame) {
|
||||||
|
Handlers.spectateGame(SpectateGameSecret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Right now this batches up any requests and sends them all in a burst; I could imagine a world
|
||||||
|
// where the implementer would rather sequentially accept/reject each one before the next invite
|
||||||
|
// is sent. I left it this way because I could also imagine wanting to process these all and
|
||||||
|
// maybe show them in one common dialog and/or start fetching the avatars in parallel, and if
|
||||||
|
// not it should be trivial for the implementer to make a queue themselves.
|
||||||
|
while (JoinAskQueue.HavePendingSends()) {
|
||||||
|
auto req = JoinAskQueue.GetNextSendMessage();
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> guard(HandlerMutex);
|
||||||
|
if (Handlers.joinRequest) {
|
||||||
|
DiscordUser du{req->userId, req->username, req->discriminator, req->avatar};
|
||||||
|
Handlers.joinRequest(&du);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JoinAskQueue.CommitSend();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isConnected) {
|
||||||
|
// if we are not connected, disconnect message last
|
||||||
|
std::lock_guard<std::mutex> guard(HandlerMutex);
|
||||||
|
if (wasDisconnected && Handlers.disconnected) {
|
||||||
|
Handlers.disconnected(LastDisconnectErrorCode, LastDisconnectErrorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" DISCORD_EXPORT void Discord_UpdateHandlers(DiscordEventHandlers* newHandlers)
|
||||||
|
{
|
||||||
|
if (newHandlers) {
|
||||||
|
#define HANDLE_EVENT_REGISTRATION(handler_name, event) \
|
||||||
|
if (!Handlers.handler_name && newHandlers->handler_name) { \
|
||||||
|
RegisterForEvent(event); \
|
||||||
|
} \
|
||||||
|
else if (Handlers.handler_name && !newHandlers->handler_name) { \
|
||||||
|
DeregisterForEvent(event); \
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> guard(HandlerMutex);
|
||||||
|
HANDLE_EVENT_REGISTRATION(joinGame, "ACTIVITY_JOIN")
|
||||||
|
HANDLE_EVENT_REGISTRATION(spectateGame, "ACTIVITY_SPECTATE")
|
||||||
|
HANDLE_EVENT_REGISTRATION(joinRequest, "ACTIVITY_JOIN_REQUEST")
|
||||||
|
|
||||||
|
#undef HANDLE_EVENT_REGISTRATION
|
||||||
|
|
||||||
|
Handlers = *newHandlers;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::lock_guard<std::mutex> guard(HandlerMutex);
|
||||||
|
Handlers = {};
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
90
libs/discordrpc/discord_rpc.h
Normal file
90
libs/discordrpc/discord_rpc.h
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
|
#if defined(DISCORD_DYNAMIC_LIB)
|
||||||
|
# if defined(_WIN32)
|
||||||
|
# if defined(DISCORD_BUILDING_SDK)
|
||||||
|
# define DISCORD_EXPORT __declspec(dllexport)
|
||||||
|
# else
|
||||||
|
# define DISCORD_EXPORT __declspec(dllimport)
|
||||||
|
# endif
|
||||||
|
# else
|
||||||
|
# define DISCORD_EXPORT __attribute__((visibility("default")))
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# define DISCORD_EXPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct DiscordRichPresence {
|
||||||
|
const char* state; /* max 128 bytes */
|
||||||
|
const char* details; /* max 128 bytes */
|
||||||
|
int64_t startTimestamp;
|
||||||
|
int64_t endTimestamp;
|
||||||
|
const char* largeImageKey; /* max 32 bytes */
|
||||||
|
const char* largeImageText; /* max 128 bytes */
|
||||||
|
const char* smallImageKey; /* max 32 bytes */
|
||||||
|
const char* smallImageText; /* max 128 bytes */
|
||||||
|
const char* partyId; /* max 128 bytes */
|
||||||
|
int partySize;
|
||||||
|
int partyMax;
|
||||||
|
int partyPrivacy;
|
||||||
|
const char* matchSecret; /* max 128 bytes */
|
||||||
|
const char* joinSecret; /* max 128 bytes */
|
||||||
|
const char* spectateSecret; /* max 128 bytes */
|
||||||
|
int8_t instance;
|
||||||
|
} DiscordRichPresence;
|
||||||
|
|
||||||
|
typedef struct DiscordUser {
|
||||||
|
const char* userId;
|
||||||
|
const char* username;
|
||||||
|
const char* discriminator;
|
||||||
|
const char* avatar;
|
||||||
|
} DiscordUser;
|
||||||
|
|
||||||
|
typedef struct DiscordEventHandlers {
|
||||||
|
void (*ready)(const DiscordUser* request);
|
||||||
|
void (*disconnected)(int errorCode, const char* message);
|
||||||
|
void (*errored)(int errorCode, const char* message);
|
||||||
|
void (*joinGame)(const char* joinSecret);
|
||||||
|
void (*spectateGame)(const char* spectateSecret);
|
||||||
|
void (*joinRequest)(const DiscordUser* request);
|
||||||
|
} DiscordEventHandlers;
|
||||||
|
|
||||||
|
#define DISCORD_REPLY_NO 0
|
||||||
|
#define DISCORD_REPLY_YES 1
|
||||||
|
#define DISCORD_REPLY_IGNORE 2
|
||||||
|
#define DISCORD_PARTY_PRIVATE 0
|
||||||
|
#define DISCORD_PARTY_PUBLIC 1
|
||||||
|
|
||||||
|
DISCORD_EXPORT void Discord_Initialize(const char* applicationId,
|
||||||
|
DiscordEventHandlers* handlers,
|
||||||
|
int autoRegister,
|
||||||
|
const char* optionalSteamId);
|
||||||
|
DISCORD_EXPORT void Discord_Shutdown(void);
|
||||||
|
|
||||||
|
/* checks for incoming messages, dispatches callbacks */
|
||||||
|
DISCORD_EXPORT void Discord_RunCallbacks(void);
|
||||||
|
|
||||||
|
/* If you disable the lib starting its own io thread, you'll need to call this from your own */
|
||||||
|
#ifdef DISCORD_DISABLE_IO_THREAD
|
||||||
|
DISCORD_EXPORT void Discord_UpdateConnection(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DISCORD_EXPORT void Discord_UpdatePresence(const DiscordRichPresence* presence);
|
||||||
|
DISCORD_EXPORT void Discord_ClearPresence(void);
|
||||||
|
|
||||||
|
DISCORD_EXPORT void Discord_Respond(const char* userid, /* DISCORD_REPLY_ */ int reply);
|
||||||
|
|
||||||
|
DISCORD_EXPORT void Discord_UpdateHandlers(DiscordEventHandlers* handlers);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
12
libs/discordrpc/dllmain.cpp
Normal file
12
libs/discordrpc/dllmain.cpp
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
// outsmart GCC's missing-declarations warning
|
||||||
|
BOOL WINAPI DllMain(HMODULE, DWORD, LPVOID);
|
||||||
|
BOOL WINAPI DllMain(HMODULE, DWORD, LPVOID)
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
36
libs/discordrpc/msg_queue.h
Normal file
36
libs/discordrpc/msg_queue.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
// A simple queue. No locks, but only works with a single thread as producer and a single thread as
|
||||||
|
// a consumer. Mutex up as needed.
|
||||||
|
|
||||||
|
template <typename ElementType, size_t QueueSize>
|
||||||
|
class MsgQueue {
|
||||||
|
ElementType queue_[QueueSize];
|
||||||
|
std::atomic_uint nextAdd_{0};
|
||||||
|
std::atomic_uint nextSend_{0};
|
||||||
|
std::atomic_uint pendingSends_{0};
|
||||||
|
|
||||||
|
public:
|
||||||
|
MsgQueue() {}
|
||||||
|
|
||||||
|
ElementType* GetNextAddMessage()
|
||||||
|
{
|
||||||
|
// if we are falling behind, bail
|
||||||
|
if (pendingSends_.load() >= QueueSize) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
auto index = (nextAdd_++) % QueueSize;
|
||||||
|
return &queue_[index];
|
||||||
|
}
|
||||||
|
void CommitAdd() { ++pendingSends_; }
|
||||||
|
|
||||||
|
bool HavePendingSends() const { return pendingSends_.load() != 0; }
|
||||||
|
ElementType* GetNextSendMessage()
|
||||||
|
{
|
||||||
|
auto index = (nextSend_++) % QueueSize;
|
||||||
|
return &queue_[index];
|
||||||
|
}
|
||||||
|
void CommitSend() { --pendingSends_; }
|
||||||
|
};
|
||||||
271
libs/discordrpc/rapidjson/allocators.h
Normal file
271
libs/discordrpc/rapidjson/allocators.h
Normal file
@@ -0,0 +1,271 @@
|
|||||||
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://opensource.org/licenses/MIT
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
|
#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) {
|
||||||
|
if (size) // behavior of malloc(0) is implementation defined.
|
||||||
|
return std::malloc(size);
|
||||||
|
else
|
||||||
|
return NULL; // standardize to returning NULL.
|
||||||
|
}
|
||||||
|
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
|
||||||
|
(void)originalSize;
|
||||||
|
if (newSize == 0) {
|
||||||
|
std::free(originalPtr);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
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 <typename BaseAllocator = CrtAllocator>
|
||||||
|
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<ChunkHeader*>(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_ && chunkHead_ != userBuffer_) {
|
||||||
|
ChunkHeader* next = chunkHead_->next;
|
||||||
|
baseAllocator_->Free(chunkHead_);
|
||||||
|
chunkHead_ = next;
|
||||||
|
}
|
||||||
|
if (chunkHead_ && chunkHead_ == userBuffer_)
|
||||||
|
chunkHead_->size = 0; // Clear user buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
//! 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) {
|
||||||
|
if (!size)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
size = RAPIDJSON_ALIGN(size);
|
||||||
|
if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
|
||||||
|
if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
void *buffer = reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + 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);
|
||||||
|
|
||||||
|
if (newSize == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
originalSize = RAPIDJSON_ALIGN(originalSize);
|
||||||
|
newSize = RAPIDJSON_ALIGN(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 == reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) {
|
||||||
|
size_t increment = static_cast<size_t>(newSize - originalSize);
|
||||||
|
if (chunkHead_->size + increment <= chunkHead_->capacity) {
|
||||||
|
chunkHead_->size += increment;
|
||||||
|
return originalPtr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Realloc process: allocate and copy memory, do not free original buffer.
|
||||||
|
if (void* newBuffer = Malloc(newSize)) {
|
||||||
|
if (originalSize)
|
||||||
|
std::memcpy(newBuffer, originalPtr, originalSize);
|
||||||
|
return newBuffer;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! 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.
|
||||||
|
\return true if success.
|
||||||
|
*/
|
||||||
|
bool AddChunk(size_t capacity) {
|
||||||
|
if (!baseAllocator_)
|
||||||
|
ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator());
|
||||||
|
if (ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity))) {
|
||||||
|
chunk->capacity = capacity;
|
||||||
|
chunk->size = 0;
|
||||||
|
chunk->next = chunkHead_;
|
||||||
|
chunkHead_ = chunk;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
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_
|
||||||
2575
libs/discordrpc/rapidjson/document.h
Normal file
2575
libs/discordrpc/rapidjson/document.h
Normal file
File diff suppressed because it is too large
Load Diff
299
libs/discordrpc/rapidjson/encodedstream.h
Normal file
299
libs/discordrpc/rapidjson/encodedstream.h
Normal file
@@ -0,0 +1,299 @@
|
|||||||
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://opensource.org/licenses/MIT
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
|
#ifndef RAPIDJSON_ENCODEDSTREAM_H_
|
||||||
|
#define RAPIDJSON_ENCODEDSTREAM_H_
|
||||||
|
|
||||||
|
#include "stream.h"
|
||||||
|
#include "memorystream.h"
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(effc++)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(padded)
|
||||||
|
#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 <typename Encoding, typename InputByteStream>
|
||||||
|
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_;
|
||||||
|
};
|
||||||
|
|
||||||
|
//! Specialized for UTF8 MemoryStream.
|
||||||
|
template <>
|
||||||
|
class EncodedInputStream<UTF8<>, MemoryStream> {
|
||||||
|
public:
|
||||||
|
typedef UTF8<>::Ch Ch;
|
||||||
|
|
||||||
|
EncodedInputStream(MemoryStream& is) : is_(is) {
|
||||||
|
if (static_cast<unsigned char>(is_.Peek()) == 0xEFu) is_.Take();
|
||||||
|
if (static_cast<unsigned char>(is_.Peek()) == 0xBBu) is_.Take();
|
||||||
|
if (static_cast<unsigned char>(is_.Peek()) == 0xBFu) is_.Take();
|
||||||
|
}
|
||||||
|
Ch Peek() const { return is_.Peek(); }
|
||||||
|
Ch Take() { return is_.Take(); }
|
||||||
|
size_t Tell() const { return is_.Tell(); }
|
||||||
|
|
||||||
|
// Not implemented
|
||||||
|
void Put(Ch) {}
|
||||||
|
void Flush() {}
|
||||||
|
Ch* PutBegin() { return 0; }
|
||||||
|
size_t PutEnd(Ch*) { return 0; }
|
||||||
|
|
||||||
|
MemoryStream& is_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
EncodedInputStream(const EncodedInputStream&);
|
||||||
|
EncodedInputStream& operator=(const EncodedInputStream&);
|
||||||
|
};
|
||||||
|
|
||||||
|
//! Output byte stream wrapper with statically bound encoding.
|
||||||
|
/*!
|
||||||
|
\tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
|
||||||
|
\tparam OutputByteStream Type of input byte stream. For example, FileWriteStream.
|
||||||
|
*/
|
||||||
|
template <typename Encoding, typename OutputByteStream>
|
||||||
|
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); return 0;}
|
||||||
|
Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
|
||||||
|
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<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::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 <typename CharType, typename InputByteStream>
|
||||||
|
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) {
|
||||||
|
RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
|
||||||
|
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 = reinterpret_cast<const unsigned char *>(is_->Peek4());
|
||||||
|
if (!c)
|
||||||
|
return;
|
||||||
|
|
||||||
|
unsigned bom = static_cast<unsigned>(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.
|
||||||
|
if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
|
||||||
|
if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 OutputByteStream type of output byte stream to be wrapped.
|
||||||
|
*/
|
||||||
|
template <typename CharType, typename OutputByteStream>
|
||||||
|
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) {
|
||||||
|
RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
|
||||||
|
|
||||||
|
// Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
|
||||||
|
if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
|
||||||
|
if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
|
||||||
|
|
||||||
|
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); return 0;}
|
||||||
|
Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
|
||||||
|
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 __clang__
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // RAPIDJSON_FILESTREAM_H_
|
||||||
716
libs/discordrpc/rapidjson/encodings.h
Normal file
716
libs/discordrpc/rapidjson/encodings.h
Normal file
@@ -0,0 +1,716 @@
|
|||||||
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://opensource.org/licenses/MIT
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
|
#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++)
|
||||||
|
RAPIDJSON_DIAG_OFF(overflow)
|
||||||
|
#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<typename OutputStream>
|
||||||
|
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 <typename InputStream>
|
||||||
|
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 <typename InputStream, typename OutputStream>
|
||||||
|
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 <typename InputByteStream>
|
||||||
|
static CharType TakeBOM(InputByteStream& is);
|
||||||
|
|
||||||
|
//! Take a character from input byte stream.
|
||||||
|
template <typename InputByteStream>
|
||||||
|
static Ch Take(InputByteStream& is);
|
||||||
|
|
||||||
|
//! Put BOM to output byte stream.
|
||||||
|
template <typename OutputByteStream>
|
||||||
|
static void PutBOM(OutputByteStream& os);
|
||||||
|
|
||||||
|
//! Put a character to output byte stream.
|
||||||
|
template <typename OutputByteStream>
|
||||||
|
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<typename CharType = char>
|
||||||
|
struct UTF8 {
|
||||||
|
typedef CharType Ch;
|
||||||
|
|
||||||
|
enum { supportUnicode = 1 };
|
||||||
|
|
||||||
|
template<typename OutputStream>
|
||||||
|
static void Encode(OutputStream& os, unsigned codepoint) {
|
||||||
|
if (codepoint <= 0x7F)
|
||||||
|
os.Put(static_cast<Ch>(codepoint & 0xFF));
|
||||||
|
else if (codepoint <= 0x7FF) {
|
||||||
|
os.Put(static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));
|
||||||
|
os.Put(static_cast<Ch>(0x80 | ((codepoint & 0x3F))));
|
||||||
|
}
|
||||||
|
else if (codepoint <= 0xFFFF) {
|
||||||
|
os.Put(static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF)));
|
||||||
|
os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
|
||||||
|
os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||||
|
os.Put(static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));
|
||||||
|
os.Put(static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));
|
||||||
|
os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
|
||||||
|
os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OutputStream>
|
||||||
|
static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
|
||||||
|
if (codepoint <= 0x7F)
|
||||||
|
PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
|
||||||
|
else if (codepoint <= 0x7FF) {
|
||||||
|
PutUnsafe(os, static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));
|
||||||
|
PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint & 0x3F))));
|
||||||
|
}
|
||||||
|
else if (codepoint <= 0xFFFF) {
|
||||||
|
PutUnsafe(os, static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF)));
|
||||||
|
PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
|
||||||
|
PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F)));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||||
|
PutUnsafe(os, static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));
|
||||||
|
PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));
|
||||||
|
PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
|
||||||
|
PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename InputStream>
|
||||||
|
static bool Decode(InputStream& is, unsigned* codepoint) {
|
||||||
|
#define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast<unsigned char>(c) & 0x3Fu)
|
||||||
|
#define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
|
||||||
|
#define TAIL() COPY(); TRANS(0x70)
|
||||||
|
typename InputStream::Ch c = is.Take();
|
||||||
|
if (!(c & 0x80)) {
|
||||||
|
*codepoint = static_cast<unsigned char>(c);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char type = GetRange(static_cast<unsigned char>(c));
|
||||||
|
if (type >= 32) {
|
||||||
|
*codepoint = 0;
|
||||||
|
} else {
|
||||||
|
*codepoint = (0xFF >> type) & static_cast<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 <typename InputStream, typename OutputStream>
|
||||||
|
static bool Validate(InputStream& is, OutputStream& os) {
|
||||||
|
#define COPY() os.Put(c = is.Take())
|
||||||
|
#define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
|
||||||
|
#define TAIL() COPY(); TRANS(0x70)
|
||||||
|
Ch c;
|
||||||
|
COPY();
|
||||||
|
if (!(c & 0x80))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
bool result = true;
|
||||||
|
switch (GetRange(static_cast<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 <typename InputByteStream>
|
||||||
|
static CharType TakeBOM(InputByteStream& is) {
|
||||||
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
|
typename InputByteStream::Ch c = Take(is);
|
||||||
|
if (static_cast<unsigned char>(c) != 0xEFu) return c;
|
||||||
|
c = is.Take();
|
||||||
|
if (static_cast<unsigned char>(c) != 0xBBu) return c;
|
||||||
|
c = is.Take();
|
||||||
|
if (static_cast<unsigned char>(c) != 0xBFu) return c;
|
||||||
|
c = is.Take();
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename InputByteStream>
|
||||||
|
static Ch Take(InputByteStream& is) {
|
||||||
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
|
return static_cast<Ch>(is.Take());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename OutputByteStream>
|
||||||
|
static void PutBOM(OutputByteStream& os) {
|
||||||
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>(0xEFu));
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>(0xBBu));
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>(0xBFu));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename OutputByteStream>
|
||||||
|
static void Put(OutputByteStream& os, Ch c) {
|
||||||
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>(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<typename CharType = wchar_t>
|
||||||
|
struct UTF16 {
|
||||||
|
typedef CharType Ch;
|
||||||
|
RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2);
|
||||||
|
|
||||||
|
enum { supportUnicode = 1 };
|
||||||
|
|
||||||
|
template<typename OutputStream>
|
||||||
|
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<typename OutputStream::Ch>(codepoint));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||||
|
unsigned v = codepoint - 0x10000;
|
||||||
|
os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
|
||||||
|
os.Put((v & 0x3FF) | 0xDC00);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename OutputStream>
|
||||||
|
static void EncodeUnsafe(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
|
||||||
|
PutUnsafe(os, static_cast<typename OutputStream::Ch>(codepoint));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||||
|
unsigned v = codepoint - 0x10000;
|
||||||
|
PutUnsafe(os, static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
|
||||||
|
PutUnsafe(os, (v & 0x3FF) | 0xDC00);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename InputStream>
|
||||||
|
static bool Decode(InputStream& is, unsigned* codepoint) {
|
||||||
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
|
||||||
|
typename InputStream::Ch c = is.Take();
|
||||||
|
if (c < 0xD800 || c > 0xDFFF) {
|
||||||
|
*codepoint = static_cast<unsigned>(c);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (c <= 0xDBFF) {
|
||||||
|
*codepoint = (static_cast<unsigned>(c) & 0x3FF) << 10;
|
||||||
|
c = is.Take();
|
||||||
|
*codepoint |= (static_cast<unsigned>(c) & 0x3FF);
|
||||||
|
*codepoint += 0x10000;
|
||||||
|
return c >= 0xDC00 && c <= 0xDFFF;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename InputStream, typename OutputStream>
|
||||||
|
static bool Validate(InputStream& is, OutputStream& os) {
|
||||||
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
|
||||||
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
|
||||||
|
typename InputStream::Ch c;
|
||||||
|
os.Put(static_cast<typename OutputStream::Ch>(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<typename CharType = wchar_t>
|
||||||
|
struct UTF16LE : UTF16<CharType> {
|
||||||
|
template <typename InputByteStream>
|
||||||
|
static CharType TakeBOM(InputByteStream& is) {
|
||||||
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
|
CharType c = Take(is);
|
||||||
|
return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename InputByteStream>
|
||||||
|
static CharType Take(InputByteStream& is) {
|
||||||
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
|
unsigned c = static_cast<uint8_t>(is.Take());
|
||||||
|
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
|
||||||
|
return static_cast<CharType>(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename OutputByteStream>
|
||||||
|
static void PutBOM(OutputByteStream& os) {
|
||||||
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename OutputByteStream>
|
||||||
|
static void Put(OutputByteStream& os, CharType c) {
|
||||||
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 0xFFu));
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//! UTF-16 big endian encoding.
|
||||||
|
template<typename CharType = wchar_t>
|
||||||
|
struct UTF16BE : UTF16<CharType> {
|
||||||
|
template <typename InputByteStream>
|
||||||
|
static CharType TakeBOM(InputByteStream& is) {
|
||||||
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
|
CharType c = Take(is);
|
||||||
|
return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename InputByteStream>
|
||||||
|
static CharType Take(InputByteStream& is) {
|
||||||
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
|
unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
|
||||||
|
c |= static_cast<uint8_t>(is.Take());
|
||||||
|
return static_cast<CharType>(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename OutputByteStream>
|
||||||
|
static void PutBOM(OutputByteStream& os) {
|
||||||
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename OutputByteStream>
|
||||||
|
static void Put(OutputByteStream& os, CharType c) {
|
||||||
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu));
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(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<typename CharType = unsigned>
|
||||||
|
struct UTF32 {
|
||||||
|
typedef CharType Ch;
|
||||||
|
RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4);
|
||||||
|
|
||||||
|
enum { supportUnicode = 1 };
|
||||||
|
|
||||||
|
template<typename OutputStream>
|
||||||
|
static void Encode(OutputStream& os, unsigned codepoint) {
|
||||||
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
|
||||||
|
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||||
|
os.Put(codepoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OutputStream>
|
||||||
|
static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
|
||||||
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
|
||||||
|
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||||
|
PutUnsafe(os, codepoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename InputStream>
|
||||||
|
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 <typename InputStream, typename OutputStream>
|
||||||
|
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<typename CharType = unsigned>
|
||||||
|
struct UTF32LE : UTF32<CharType> {
|
||||||
|
template <typename InputByteStream>
|
||||||
|
static CharType TakeBOM(InputByteStream& is) {
|
||||||
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
|
CharType c = Take(is);
|
||||||
|
return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename InputByteStream>
|
||||||
|
static CharType Take(InputByteStream& is) {
|
||||||
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
|
unsigned c = static_cast<uint8_t>(is.Take());
|
||||||
|
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
|
||||||
|
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16;
|
||||||
|
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24;
|
||||||
|
return static_cast<CharType>(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename OutputByteStream>
|
||||||
|
static void PutBOM(OutputByteStream& os) {
|
||||||
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename OutputByteStream>
|
||||||
|
static void Put(OutputByteStream& os, CharType c) {
|
||||||
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>(c & 0xFFu));
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu));
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu));
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>((c >> 24) & 0xFFu));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//! UTF-32 big endian encoding.
|
||||||
|
template<typename CharType = unsigned>
|
||||||
|
struct UTF32BE : UTF32<CharType> {
|
||||||
|
template <typename InputByteStream>
|
||||||
|
static CharType TakeBOM(InputByteStream& is) {
|
||||||
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
|
CharType c = Take(is);
|
||||||
|
return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename InputByteStream>
|
||||||
|
static CharType Take(InputByteStream& is) {
|
||||||
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
|
unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24;
|
||||||
|
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16;
|
||||||
|
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
|
||||||
|
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take()));
|
||||||
|
return static_cast<CharType>(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename OutputByteStream>
|
||||||
|
static void PutBOM(OutputByteStream& os) {
|
||||||
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename OutputByteStream>
|
||||||
|
static void Put(OutputByteStream& os, CharType c) {
|
||||||
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>((c >> 24) & 0xFFu));
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu));
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu));
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>(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<typename CharType = char>
|
||||||
|
struct ASCII {
|
||||||
|
typedef CharType Ch;
|
||||||
|
|
||||||
|
enum { supportUnicode = 0 };
|
||||||
|
|
||||||
|
template<typename OutputStream>
|
||||||
|
static void Encode(OutputStream& os, unsigned codepoint) {
|
||||||
|
RAPIDJSON_ASSERT(codepoint <= 0x7F);
|
||||||
|
os.Put(static_cast<Ch>(codepoint & 0xFF));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename OutputStream>
|
||||||
|
static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
|
||||||
|
RAPIDJSON_ASSERT(codepoint <= 0x7F);
|
||||||
|
PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename InputStream>
|
||||||
|
static bool Decode(InputStream& is, unsigned* codepoint) {
|
||||||
|
uint8_t c = static_cast<uint8_t>(is.Take());
|
||||||
|
*codepoint = c;
|
||||||
|
return c <= 0X7F;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename InputStream, typename OutputStream>
|
||||||
|
static bool Validate(InputStream& is, OutputStream& os) {
|
||||||
|
uint8_t c = static_cast<uint8_t>(is.Take());
|
||||||
|
os.Put(static_cast<typename OutputStream::Ch>(c));
|
||||||
|
return c <= 0x7F;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename InputByteStream>
|
||||||
|
static CharType TakeBOM(InputByteStream& is) {
|
||||||
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
|
uint8_t c = static_cast<uint8_t>(Take(is));
|
||||||
|
return static_cast<Ch>(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename InputByteStream>
|
||||||
|
static Ch Take(InputByteStream& is) {
|
||||||
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
|
return static_cast<Ch>(is.Take());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename OutputByteStream>
|
||||||
|
static void PutBOM(OutputByteStream& os) {
|
||||||
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||||
|
(void)os;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename OutputByteStream>
|
||||||
|
static void Put(OutputByteStream& os, Ch c) {
|
||||||
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||||
|
os.Put(static_cast<typename OutputByteStream::Ch>(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<typename CharType>
|
||||||
|
struct AutoUTF {
|
||||||
|
typedef CharType Ch;
|
||||||
|
|
||||||
|
enum { supportUnicode = 1 };
|
||||||
|
|
||||||
|
#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
|
||||||
|
|
||||||
|
template<typename OutputStream>
|
||||||
|
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<typename OutputStream>
|
||||||
|
RAPIDJSON_FORCEINLINE static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
|
||||||
|
typedef void (*EncodeFunc)(OutputStream&, unsigned);
|
||||||
|
static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) };
|
||||||
|
(*f[os.GetType()])(os, codepoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename InputStream>
|
||||||
|
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 <typename InputStream, typename OutputStream>
|
||||||
|
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<typename SourceEncoding, typename TargetEncoding>
|
||||||
|
struct Transcoder {
|
||||||
|
//! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream.
|
||||||
|
template<typename InputStream, typename OutputStream>
|
||||||
|
RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
|
||||||
|
unsigned codepoint;
|
||||||
|
if (!SourceEncoding::Decode(is, &codepoint))
|
||||||
|
return false;
|
||||||
|
TargetEncoding::Encode(os, codepoint);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename InputStream, typename OutputStream>
|
||||||
|
RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
|
||||||
|
unsigned codepoint;
|
||||||
|
if (!SourceEncoding::Decode(is, &codepoint))
|
||||||
|
return false;
|
||||||
|
TargetEncoding::EncodeUnsafe(os, codepoint);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Validate one Unicode codepoint from an encoded stream.
|
||||||
|
template<typename InputStream, typename OutputStream>
|
||||||
|
RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
|
||||||
|
return Transcode(is, os); // Since source/target encoding is different, must transcode.
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Forward declaration.
|
||||||
|
template<typename Stream>
|
||||||
|
inline void PutUnsafe(Stream& stream, typename Stream::Ch c);
|
||||||
|
|
||||||
|
//! Specialization of Transcoder with same source and target encoding.
|
||||||
|
template<typename Encoding>
|
||||||
|
struct Transcoder<Encoding, Encoding> {
|
||||||
|
template<typename InputStream, typename OutputStream>
|
||||||
|
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<typename InputStream, typename OutputStream>
|
||||||
|
RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
|
||||||
|
PutUnsafe(os, is.Take()); // Just copy one code unit. This semantic is different from primary template class.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename InputStream, typename OutputStream>
|
||||||
|
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(_MSC_VER)
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // RAPIDJSON_ENCODINGS_H_
|
||||||
74
libs/discordrpc/rapidjson/error/en.h
Normal file
74
libs/discordrpc/rapidjson/error/en.h
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://opensource.org/licenses/MIT
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
|
#ifndef RAPIDJSON_ERROR_EN_H_
|
||||||
|
#define RAPIDJSON_ERROR_EN_H_
|
||||||
|
|
||||||
|
#include "error.h"
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(switch-enum)
|
||||||
|
RAPIDJSON_DIAG_OFF(covered-switch-default)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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 be followed 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
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // RAPIDJSON_ERROR_EN_H_
|
||||||
155
libs/discordrpc/rapidjson/error/error.h
Normal file
155
libs/discordrpc/rapidjson/error/error.h
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://opensource.org/licenses/MIT
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
|
#ifndef RAPIDJSON_ERROR_ERROR_H_
|
||||||
|
#define RAPIDJSON_ERROR_ERROR_H_
|
||||||
|
|
||||||
|
#include "../rapidjson.h"
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(padded)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*! \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 {
|
||||||
|
public:
|
||||||
|
//! 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
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // RAPIDJSON_ERROR_ERROR_H_
|
||||||
99
libs/discordrpc/rapidjson/filereadstream.h
Normal file
99
libs/discordrpc/rapidjson/filereadstream.h
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://opensource.org/licenses/MIT
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
|
#ifndef RAPIDJSON_FILEREADSTREAM_H_
|
||||||
|
#define RAPIDJSON_FILEREADSTREAM_H_
|
||||||
|
|
||||||
|
#include "stream.h"
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(padded)
|
||||||
|
RAPIDJSON_DIAG_OFF(unreachable-code)
|
||||||
|
RAPIDJSON_DIAG_OFF(missing-noreturn)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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<size_t>(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
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // RAPIDJSON_FILESTREAM_H_
|
||||||
104
libs/discordrpc/rapidjson/filewritestream.h
Normal file
104
libs/discordrpc/rapidjson/filewritestream.h
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://opensource.org/licenses/MIT
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
|
#ifndef RAPIDJSON_FILEWRITESTREAM_H_
|
||||||
|
#define RAPIDJSON_FILEWRITESTREAM_H_
|
||||||
|
|
||||||
|
#include "stream.h"
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(unreachable-code)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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<size_t>(bufferEnd_ - current_);
|
||||||
|
while (n > avail) {
|
||||||
|
std::memset(current_, c, avail);
|
||||||
|
current_ += avail;
|
||||||
|
Flush();
|
||||||
|
n -= avail;
|
||||||
|
avail = static_cast<size_t>(bufferEnd_ - current_);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n > 0) {
|
||||||
|
std::memset(current_, c, n);
|
||||||
|
current_ += n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Flush() {
|
||||||
|
if (current_ != buffer_) {
|
||||||
|
size_t result = fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_);
|
||||||
|
if (result < static_cast<size_t>(current_ - buffer_)) {
|
||||||
|
// failure deliberately ignored at this time
|
||||||
|
// added to avoid warn_unused_result build errors
|
||||||
|
}
|
||||||
|
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
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // RAPIDJSON_FILESTREAM_H_
|
||||||
151
libs/discordrpc/rapidjson/fwd.h
Normal file
151
libs/discordrpc/rapidjson/fwd.h
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://opensource.org/licenses/MIT
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
|
#ifndef RAPIDJSON_FWD_H_
|
||||||
|
#define RAPIDJSON_FWD_H_
|
||||||
|
|
||||||
|
#include "rapidjson.h"
|
||||||
|
|
||||||
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
// encodings.h
|
||||||
|
|
||||||
|
template<typename CharType> struct UTF8;
|
||||||
|
template<typename CharType> struct UTF16;
|
||||||
|
template<typename CharType> struct UTF16BE;
|
||||||
|
template<typename CharType> struct UTF16LE;
|
||||||
|
template<typename CharType> struct UTF32;
|
||||||
|
template<typename CharType> struct UTF32BE;
|
||||||
|
template<typename CharType> struct UTF32LE;
|
||||||
|
template<typename CharType> struct ASCII;
|
||||||
|
template<typename CharType> struct AutoUTF;
|
||||||
|
|
||||||
|
template<typename SourceEncoding, typename TargetEncoding>
|
||||||
|
struct Transcoder;
|
||||||
|
|
||||||
|
// allocators.h
|
||||||
|
|
||||||
|
class CrtAllocator;
|
||||||
|
|
||||||
|
template <typename BaseAllocator>
|
||||||
|
class MemoryPoolAllocator;
|
||||||
|
|
||||||
|
// stream.h
|
||||||
|
|
||||||
|
template <typename Encoding>
|
||||||
|
struct GenericStringStream;
|
||||||
|
|
||||||
|
typedef GenericStringStream<UTF8<char> > StringStream;
|
||||||
|
|
||||||
|
template <typename Encoding>
|
||||||
|
struct GenericInsituStringStream;
|
||||||
|
|
||||||
|
typedef GenericInsituStringStream<UTF8<char> > InsituStringStream;
|
||||||
|
|
||||||
|
// stringbuffer.h
|
||||||
|
|
||||||
|
template <typename Encoding, typename Allocator>
|
||||||
|
class GenericStringBuffer;
|
||||||
|
|
||||||
|
typedef GenericStringBuffer<UTF8<char>, CrtAllocator> StringBuffer;
|
||||||
|
|
||||||
|
// filereadstream.h
|
||||||
|
|
||||||
|
class FileReadStream;
|
||||||
|
|
||||||
|
// filewritestream.h
|
||||||
|
|
||||||
|
class FileWriteStream;
|
||||||
|
|
||||||
|
// memorybuffer.h
|
||||||
|
|
||||||
|
template <typename Allocator>
|
||||||
|
struct GenericMemoryBuffer;
|
||||||
|
|
||||||
|
typedef GenericMemoryBuffer<CrtAllocator> MemoryBuffer;
|
||||||
|
|
||||||
|
// memorystream.h
|
||||||
|
|
||||||
|
struct MemoryStream;
|
||||||
|
|
||||||
|
// reader.h
|
||||||
|
|
||||||
|
template<typename Encoding, typename Derived>
|
||||||
|
struct BaseReaderHandler;
|
||||||
|
|
||||||
|
template <typename SourceEncoding, typename TargetEncoding, typename StackAllocator>
|
||||||
|
class GenericReader;
|
||||||
|
|
||||||
|
typedef GenericReader<UTF8<char>, UTF8<char>, CrtAllocator> Reader;
|
||||||
|
|
||||||
|
// writer.h
|
||||||
|
|
||||||
|
template<typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags>
|
||||||
|
class Writer;
|
||||||
|
|
||||||
|
// prettywriter.h
|
||||||
|
|
||||||
|
template<typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags>
|
||||||
|
class PrettyWriter;
|
||||||
|
|
||||||
|
// document.h
|
||||||
|
|
||||||
|
template <typename Encoding, typename Allocator>
|
||||||
|
struct GenericMember;
|
||||||
|
|
||||||
|
template <bool Const, typename Encoding, typename Allocator>
|
||||||
|
class GenericMemberIterator;
|
||||||
|
|
||||||
|
template<typename CharType>
|
||||||
|
struct GenericStringRef;
|
||||||
|
|
||||||
|
template <typename Encoding, typename Allocator>
|
||||||
|
class GenericValue;
|
||||||
|
|
||||||
|
typedef GenericValue<UTF8<char>, MemoryPoolAllocator<CrtAllocator> > Value;
|
||||||
|
|
||||||
|
template <typename Encoding, typename Allocator, typename StackAllocator>
|
||||||
|
class GenericDocument;
|
||||||
|
|
||||||
|
typedef GenericDocument<UTF8<char>, MemoryPoolAllocator<CrtAllocator>, CrtAllocator> Document;
|
||||||
|
|
||||||
|
// pointer.h
|
||||||
|
|
||||||
|
template <typename ValueType, typename Allocator>
|
||||||
|
class GenericPointer;
|
||||||
|
|
||||||
|
typedef GenericPointer<Value, CrtAllocator> Pointer;
|
||||||
|
|
||||||
|
// schema.h
|
||||||
|
|
||||||
|
template <typename SchemaDocumentType>
|
||||||
|
class IGenericRemoteSchemaDocumentProvider;
|
||||||
|
|
||||||
|
template <typename ValueT, typename Allocator>
|
||||||
|
class GenericSchemaDocument;
|
||||||
|
|
||||||
|
typedef GenericSchemaDocument<Value, CrtAllocator> SchemaDocument;
|
||||||
|
typedef IGenericRemoteSchemaDocumentProvider<SchemaDocument> IRemoteSchemaDocumentProvider;
|
||||||
|
|
||||||
|
template <
|
||||||
|
typename SchemaDocumentType,
|
||||||
|
typename OutputHandler,
|
||||||
|
typename StateAllocator>
|
||||||
|
class GenericSchemaValidator;
|
||||||
|
|
||||||
|
typedef GenericSchemaValidator<SchemaDocument, BaseReaderHandler<UTF8<char>, void>, CrtAllocator> SchemaValidator;
|
||||||
|
|
||||||
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
|
#endif // RAPIDJSON_RAPIDJSONFWD_H_
|
||||||
290
libs/discordrpc/rapidjson/internal/biginteger.h
Normal file
290
libs/discordrpc/rapidjson/internal/biginteger.h
Normal file
@@ -0,0 +1,290 @@
|
|||||||
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://opensource.org/licenses/MIT
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
|
#ifndef RAPIDJSON_BIGINTEGER_H_
|
||||||
|
#define RAPIDJSON_BIGINTEGER_H_
|
||||||
|
|
||||||
|
#include "../rapidjson.h"
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && defined(_M_AMD64)
|
||||||
|
#include <intrin.h> // for _umul128
|
||||||
|
#pragma intrinsic(_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=(const BigInteger &rhs)
|
||||||
|
{
|
||||||
|
if (this != &rhs) {
|
||||||
|
count_ = rhs.count_;
|
||||||
|
std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
uint64_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<uint32_t>(1220703125u); // 5^13
|
||||||
|
if (exp > 0) *this *= kPow5[exp - 1];
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute absolute difference of this and rhs.
|
||||||
|
// Assume this != rhs
|
||||||
|
bool Difference(const BigInteger& rhs, BigInteger* out) const {
|
||||||
|
int cmp = Compare(rhs);
|
||||||
|
RAPIDJSON_ASSERT(cmp != 0);
|
||||||
|
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<unsigned>(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 * 10u + static_cast<unsigned>(*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__)
|
||||||
|
__extension__ typedef unsigned __int128 uint128;
|
||||||
|
uint128 p = static_cast<uint128>(a) * static_cast<uint128>(b);
|
||||||
|
p += k;
|
||||||
|
*outHigh = static_cast<uint64_t>(p >> 64);
|
||||||
|
return static_cast<uint64_t>(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<uint64_t>(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 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_
|
||||||
258
libs/discordrpc/rapidjson/internal/diyfp.h
Normal file
258
libs/discordrpc/rapidjson/internal/diyfp.h
Normal file
@@ -0,0 +1,258 @@
|
|||||||
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://opensource.org/licenses/MIT
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
|
// 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_
|
||||||
|
|
||||||
|
#include "../rapidjson.h"
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && defined(_M_AMD64)
|
||||||
|
#include <intrin.h>
|
||||||
|
#pragma intrinsic(_BitScanReverse64)
|
||||||
|
#pragma intrinsic(_umul128)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(effc++)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(padded)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct DiyFp {
|
||||||
|
DiyFp() : f(), e() {}
|
||||||
|
|
||||||
|
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 = static_cast<int>((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__)
|
||||||
|
__extension__ typedef unsigned __int128 uint128;
|
||||||
|
uint128 p = static_cast<uint128>(f) * static_cast<uint128>(rhs.f);
|
||||||
|
uint64_t h = static_cast<uint64_t>(p >> 64);
|
||||||
|
uint64_t l = static_cast<uint64_t>(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<uint64_t>(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;
|
||||||
|
const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
|
||||||
|
static_cast<uint64_t>(e + kDpExponentBias);
|
||||||
|
u.u64 = (f & 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<int>(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<int>(dk);
|
||||||
|
if (dk - k > 0.0)
|
||||||
|
k++;
|
||||||
|
|
||||||
|
unsigned index = static_cast<unsigned>((k >> 3) + 1);
|
||||||
|
*K = -(-348 + static_cast<int>(index << 3)); // decimal exponent no need lookup table
|
||||||
|
|
||||||
|
return GetCachedPowerByIndex(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline DiyFp GetCachedPower10(int exp, int *outExp) {
|
||||||
|
unsigned index = (static_cast<unsigned>(exp) + 348u) / 8u;
|
||||||
|
*outExp = -348 + static_cast<int>(index) * 8;
|
||||||
|
return GetCachedPowerByIndex(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
RAPIDJSON_DIAG_OFF(padded)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
|
#endif // RAPIDJSON_DIYFP_H_
|
||||||
245
libs/discordrpc/rapidjson/internal/dtoa.h
Normal file
245
libs/discordrpc/rapidjson/internal/dtoa.h
Normal file
@@ -0,0 +1,245 @@
|
|||||||
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://opensource.org/licenses/MIT
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
|
// 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"
|
||||||
|
#include "ieee754.h"
|
||||||
|
|
||||||
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(effc++)
|
||||||
|
RAPIDJSON_DIAG_OFF(array-bounds) // some gcc versions generate wrong warnings https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124
|
||||||
|
#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;
|
||||||
|
// Will not reach 10 digits in DigitGen()
|
||||||
|
//if (n < 1000000000) return 9;
|
||||||
|
//return 10;
|
||||||
|
return 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
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<uint32_t>(Mp.f >> -one.e);
|
||||||
|
uint64_t p2 = Mp.f & (one.f - 1);
|
||||||
|
unsigned kappa = CountDecimalDigit32(p1); // kappa in [0, 9]
|
||||||
|
*len = 0;
|
||||||
|
|
||||||
|
while (kappa > 0) {
|
||||||
|
uint32_t d = 0;
|
||||||
|
switch (kappa) {
|
||||||
|
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 (d || *len)
|
||||||
|
buffer[(*len)++] = static_cast<char>('0' + static_cast<char>(d));
|
||||||
|
kappa--;
|
||||||
|
uint64_t tmp = (static_cast<uint64_t>(p1) << -one.e) + p2;
|
||||||
|
if (tmp <= delta) {
|
||||||
|
*K += kappa;
|
||||||
|
GrisuRound(buffer, *len, delta, tmp, static_cast<uint64_t>(kPow10[kappa]) << -one.e, wp_w.f);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// kappa = 0
|
||||||
|
for (;;) {
|
||||||
|
p2 *= 10;
|
||||||
|
delta *= 10;
|
||||||
|
char d = static_cast<char>(p2 >> -one.e);
|
||||||
|
if (d || *len)
|
||||||
|
buffer[(*len)++] = static_cast<char>('0' + d);
|
||||||
|
p2 &= one.f - 1;
|
||||||
|
kappa--;
|
||||||
|
if (p2 < delta) {
|
||||||
|
*K += kappa;
|
||||||
|
int index = -static_cast<int>(kappa);
|
||||||
|
GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 9 ? kPow10[-static_cast<int>(kappa)] : 0));
|
||||||
|
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<char>('0' + static_cast<char>(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<char>('0' + static_cast<char>(K));
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces) {
|
||||||
|
const int kk = length + k; // 10^(kk-1) <= v < 10^kk
|
||||||
|
|
||||||
|
if (0 <= k && 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], static_cast<size_t>(length - kk));
|
||||||
|
buffer[kk] = '.';
|
||||||
|
if (0 > k + maxDecimalPlaces) {
|
||||||
|
// When maxDecimalPlaces = 2, 1.2345 -> 1.23, 1.102 -> 1.1
|
||||||
|
// Remove extra trailing zeros (at least one) after truncation.
|
||||||
|
for (int i = kk + maxDecimalPlaces; i > kk + 1; i--)
|
||||||
|
if (buffer[i] != '0')
|
||||||
|
return &buffer[i + 1];
|
||||||
|
return &buffer[kk + 2]; // Reserve one zero
|
||||||
|
}
|
||||||
|
else
|
||||||
|
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], static_cast<size_t>(length));
|
||||||
|
buffer[0] = '0';
|
||||||
|
buffer[1] = '.';
|
||||||
|
for (int i = 2; i < offset; i++)
|
||||||
|
buffer[i] = '0';
|
||||||
|
if (length - kk > maxDecimalPlaces) {
|
||||||
|
// When maxDecimalPlaces = 2, 0.123 -> 0.12, 0.102 -> 0.1
|
||||||
|
// Remove extra trailing zeros (at least one) after truncation.
|
||||||
|
for (int i = maxDecimalPlaces + 1; i > 2; i--)
|
||||||
|
if (buffer[i] != '0')
|
||||||
|
return &buffer[i + 1];
|
||||||
|
return &buffer[3]; // Reserve one zero
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return &buffer[length + offset];
|
||||||
|
}
|
||||||
|
else if (kk < -maxDecimalPlaces) {
|
||||||
|
// Truncate to zero
|
||||||
|
buffer[0] = '0';
|
||||||
|
buffer[1] = '.';
|
||||||
|
buffer[2] = '0';
|
||||||
|
return &buffer[3];
|
||||||
|
}
|
||||||
|
else if (length == 1) {
|
||||||
|
// 1e30
|
||||||
|
buffer[1] = 'e';
|
||||||
|
return WriteExponent(kk - 1, &buffer[2]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// 1234e30 -> 1.234e33
|
||||||
|
std::memmove(&buffer[2], &buffer[1], static_cast<size_t>(length - 1));
|
||||||
|
buffer[1] = '.';
|
||||||
|
buffer[length + 1] = 'e';
|
||||||
|
return WriteExponent(kk - 1, &buffer[0 + length + 2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline char* dtoa(double value, char* buffer, int maxDecimalPlaces = 324) {
|
||||||
|
RAPIDJSON_ASSERT(maxDecimalPlaces >= 1);
|
||||||
|
Double d(value);
|
||||||
|
if (d.IsZero()) {
|
||||||
|
if (d.Sign())
|
||||||
|
*buffer++ = '-'; // -0.0, Issue #289
|
||||||
|
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, maxDecimalPlaces);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
|
#endif // RAPIDJSON_DTOA_
|
||||||
78
libs/discordrpc/rapidjson/internal/ieee754.h
Normal file
78
libs/discordrpc/rapidjson/internal/ieee754.h
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://opensource.org/licenses/MIT
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
|
#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();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Sign() const { return (u_ & kSignMask) != 0; }
|
||||||
|
uint64_t Significand() const { return u_ & kSignificandMask; }
|
||||||
|
int Exponent() const { return static_cast<int>(((u_ & kExponentMask) >> kSignificandSize) - kExponentBias); }
|
||||||
|
|
||||||
|
bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; }
|
||||||
|
bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; }
|
||||||
|
bool IsNanOrInf() const { return (u_ & kExponentMask) == kExponentMask; }
|
||||||
|
bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; }
|
||||||
|
bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 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 static_cast<unsigned>(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_
|
||||||
304
libs/discordrpc/rapidjson/internal/itoa.h
Normal file
304
libs/discordrpc/rapidjson/internal/itoa.h
Normal file
@@ -0,0 +1,304 @@
|
|||||||
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://opensource.org/licenses/MIT
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
|
#ifndef RAPIDJSON_ITOA_
|
||||||
|
#define RAPIDJSON_ITOA_
|
||||||
|
|
||||||
|
#include "../rapidjson.h"
|
||||||
|
|
||||||
|
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<char>('0' + static_cast<char>(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) {
|
||||||
|
uint32_t u = static_cast<uint32_t>(value);
|
||||||
|
if (value < 0) {
|
||||||
|
*buffer++ = '-';
|
||||||
|
u = ~u + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return u32toa(u, 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<uint32_t>(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<uint32_t>(value / kTen8);
|
||||||
|
const uint32_t v1 = static_cast<uint32_t>(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<uint32_t>(value / kTen16); // 1 to 1844
|
||||||
|
value %= kTen16;
|
||||||
|
|
||||||
|
if (a < 10)
|
||||||
|
*buffer++ = static_cast<char>('0' + static_cast<char>(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<char>('0' + static_cast<char>(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<uint32_t>(value / kTen8);
|
||||||
|
const uint32_t v1 = static_cast<uint32_t>(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) {
|
||||||
|
uint64_t u = static_cast<uint64_t>(value);
|
||||||
|
if (value < 0) {
|
||||||
|
*buffer++ = '-';
|
||||||
|
u = ~u + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return u64toa(u, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
|
#endif // RAPIDJSON_ITOA_
|
||||||
181
libs/discordrpc/rapidjson/internal/meta.h
Normal file
181
libs/discordrpc/rapidjson/internal/meta.h
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://opensource.org/licenses/MIT
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
|
#ifndef RAPIDJSON_INTERNAL_META_H_
|
||||||
|
#define RAPIDJSON_INTERNAL_META_H_
|
||||||
|
|
||||||
|
#include "../rapidjson.h"
|
||||||
|
|
||||||
|
#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 <type_traits>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//@cond RAPIDJSON_INTERNAL
|
||||||
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching
|
||||||
|
template <typename T> struct Void { typedef void Type; };
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// BoolType, TrueType, FalseType
|
||||||
|
//
|
||||||
|
template <bool Cond> struct BoolType {
|
||||||
|
static const bool Value = Cond;
|
||||||
|
typedef BoolType Type;
|
||||||
|
};
|
||||||
|
typedef BoolType<true> TrueType;
|
||||||
|
typedef BoolType<false> FalseType;
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr
|
||||||
|
//
|
||||||
|
|
||||||
|
template <bool C> struct SelectIfImpl { template <typename T1, typename T2> struct Apply { typedef T1 Type; }; };
|
||||||
|
template <> struct SelectIfImpl<false> { template <typename T1, typename T2> struct Apply { typedef T2 Type; }; };
|
||||||
|
template <bool C, typename T1, typename T2> struct SelectIfCond : SelectIfImpl<C>::template Apply<T1,T2> {};
|
||||||
|
template <typename C, typename T1, typename T2> struct SelectIf : SelectIfCond<C::Value, T1, T2> {};
|
||||||
|
|
||||||
|
template <bool Cond1, bool Cond2> struct AndExprCond : FalseType {};
|
||||||
|
template <> struct AndExprCond<true, true> : TrueType {};
|
||||||
|
template <bool Cond1, bool Cond2> struct OrExprCond : TrueType {};
|
||||||
|
template <> struct OrExprCond<false, false> : FalseType {};
|
||||||
|
|
||||||
|
template <typename C> struct BoolExpr : SelectIf<C,TrueType,FalseType>::Type {};
|
||||||
|
template <typename C> struct NotExpr : SelectIf<C,FalseType,TrueType>::Type {};
|
||||||
|
template <typename C1, typename C2> struct AndExpr : AndExprCond<C1::Value, C2::Value>::Type {};
|
||||||
|
template <typename C1, typename C2> struct OrExpr : OrExprCond<C1::Value, C2::Value>::Type {};
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// AddConst, MaybeAddConst, RemoveConst
|
||||||
|
template <typename T> struct AddConst { typedef const T Type; };
|
||||||
|
template <bool Constify, typename T> struct MaybeAddConst : SelectIfCond<Constify, const T, T> {};
|
||||||
|
template <typename T> struct RemoveConst { typedef T Type; };
|
||||||
|
template <typename T> struct RemoveConst<const T> { typedef T Type; };
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// IsSame, IsConst, IsMoreConst, IsPointer
|
||||||
|
//
|
||||||
|
template <typename T, typename U> struct IsSame : FalseType {};
|
||||||
|
template <typename T> struct IsSame<T, T> : TrueType {};
|
||||||
|
|
||||||
|
template <typename T> struct IsConst : FalseType {};
|
||||||
|
template <typename T> struct IsConst<const T> : TrueType {};
|
||||||
|
|
||||||
|
template <typename CT, typename T>
|
||||||
|
struct IsMoreConst
|
||||||
|
: AndExpr<IsSame<typename RemoveConst<CT>::Type, typename RemoveConst<T>::Type>,
|
||||||
|
BoolType<IsConst<CT>::Value >= IsConst<T>::Value> >::Type {};
|
||||||
|
|
||||||
|
template <typename T> struct IsPointer : FalseType {};
|
||||||
|
template <typename T> struct IsPointer<T*> : TrueType {};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// IsBaseOf
|
||||||
|
//
|
||||||
|
#if RAPIDJSON_HAS_CXX11_TYPETRAITS
|
||||||
|
|
||||||
|
template <typename B, typename D> struct IsBaseOf
|
||||||
|
: BoolType< ::std::is_base_of<B,D>::value> {};
|
||||||
|
|
||||||
|
#else // simplified version adopted from Boost
|
||||||
|
|
||||||
|
template<typename B, typename D> struct IsBaseOfImpl {
|
||||||
|
RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0);
|
||||||
|
RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0);
|
||||||
|
|
||||||
|
typedef char (&Yes)[1];
|
||||||
|
typedef char (&No) [2];
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
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 <typename B, typename D> struct IsBaseOf
|
||||||
|
: OrExpr<IsSame<B, D>, BoolExpr<IsBaseOfImpl<B, D> > >::Type {};
|
||||||
|
|
||||||
|
#endif // RAPIDJSON_HAS_CXX11_TYPETRAITS
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// EnableIf / DisableIf
|
||||||
|
//
|
||||||
|
template <bool Condition, typename T = void> struct EnableIfCond { typedef T Type; };
|
||||||
|
template <typename T> struct EnableIfCond<false, T> { /* empty */ };
|
||||||
|
|
||||||
|
template <bool Condition, typename T = void> struct DisableIfCond { typedef T Type; };
|
||||||
|
template <typename T> struct DisableIfCond<true, T> { /* empty */ };
|
||||||
|
|
||||||
|
template <typename Condition, typename T = void>
|
||||||
|
struct EnableIf : EnableIfCond<Condition::Value, T> {};
|
||||||
|
|
||||||
|
template <typename Condition, typename T = void>
|
||||||
|
struct DisableIf : DisableIfCond<Condition::Value, T> {};
|
||||||
|
|
||||||
|
// SFINAE helpers
|
||||||
|
struct SfinaeTag {};
|
||||||
|
template <typename T> struct RemoveSfinaeTag;
|
||||||
|
template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { 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 \
|
||||||
|
<RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
|
||||||
|
|
||||||
|
#define RAPIDJSON_DISABLEIF(cond) \
|
||||||
|
typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
|
||||||
|
<RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
|
||||||
|
|
||||||
|
#define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \
|
||||||
|
typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
|
||||||
|
<RAPIDJSON_REMOVEFPTR_(cond), \
|
||||||
|
RAPIDJSON_REMOVEFPTR_(returntype)>::Type
|
||||||
|
|
||||||
|
#define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \
|
||||||
|
typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
|
||||||
|
<RAPIDJSON_REMOVEFPTR_(cond), \
|
||||||
|
RAPIDJSON_REMOVEFPTR_(returntype)>::Type
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
//@endcond
|
||||||
|
|
||||||
|
#if defined(__GNUC__) || defined(_MSC_VER)
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // RAPIDJSON_INTERNAL_META_H_
|
||||||
55
libs/discordrpc/rapidjson/internal/pow10.h
Normal file
55
libs/discordrpc/rapidjson/internal/pow10.h
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://opensource.org/licenses/MIT
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
|
#ifndef RAPIDJSON_POW10_
|
||||||
|
#define RAPIDJSON_POW10_
|
||||||
|
|
||||||
|
#include "../rapidjson.h"
|
||||||
|
|
||||||
|
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_
|
||||||
701
libs/discordrpc/rapidjson/internal/regex.h
Normal file
701
libs/discordrpc/rapidjson/internal/regex.h
Normal file
@@ -0,0 +1,701 @@
|
|||||||
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://opensource.org/licenses/MIT
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
|
#ifndef RAPIDJSON_INTERNAL_REGEX_H_
|
||||||
|
#define RAPIDJSON_INTERNAL_REGEX_H_
|
||||||
|
|
||||||
|
#include "../allocators.h"
|
||||||
|
#include "../stream.h"
|
||||||
|
#include "stack.h"
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(padded)
|
||||||
|
RAPIDJSON_DIAG_OFF(switch-enum)
|
||||||
|
RAPIDJSON_DIAG_OFF(implicit-fallthrough)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(effc++)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef RAPIDJSON_REGEX_VERBOSE
|
||||||
|
#define RAPIDJSON_REGEX_VERBOSE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// GenericRegex
|
||||||
|
|
||||||
|
static const SizeType kRegexInvalidState = ~SizeType(0); //!< Represents an invalid index in GenericRegex::State::out, out1
|
||||||
|
static const SizeType kRegexInvalidRange = ~SizeType(0);
|
||||||
|
|
||||||
|
//! Regular expression engine with subset of ECMAscript grammar.
|
||||||
|
/*!
|
||||||
|
Supported regular expression syntax:
|
||||||
|
- \c ab Concatenation
|
||||||
|
- \c a|b Alternation
|
||||||
|
- \c a? Zero or one
|
||||||
|
- \c a* Zero or more
|
||||||
|
- \c a+ One or more
|
||||||
|
- \c a{3} Exactly 3 times
|
||||||
|
- \c a{3,} At least 3 times
|
||||||
|
- \c a{3,5} 3 to 5 times
|
||||||
|
- \c (ab) Grouping
|
||||||
|
- \c ^a At the beginning
|
||||||
|
- \c a$ At the end
|
||||||
|
- \c . Any character
|
||||||
|
- \c [abc] Character classes
|
||||||
|
- \c [a-c] Character class range
|
||||||
|
- \c [a-z0-9_] Character class combination
|
||||||
|
- \c [^abc] Negated character classes
|
||||||
|
- \c [^a-c] Negated character class range
|
||||||
|
- \c [\b] Backspace (U+0008)
|
||||||
|
- \c \\| \\\\ ... Escape characters
|
||||||
|
- \c \\f Form feed (U+000C)
|
||||||
|
- \c \\n Line feed (U+000A)
|
||||||
|
- \c \\r Carriage return (U+000D)
|
||||||
|
- \c \\t Tab (U+0009)
|
||||||
|
- \c \\v Vertical tab (U+000B)
|
||||||
|
|
||||||
|
\note This is a Thompson NFA engine, implemented with reference to
|
||||||
|
Cox, Russ. "Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby,...).",
|
||||||
|
https://swtch.com/~rsc/regexp/regexp1.html
|
||||||
|
*/
|
||||||
|
template <typename Encoding, typename Allocator = CrtAllocator>
|
||||||
|
class GenericRegex {
|
||||||
|
public:
|
||||||
|
typedef typename Encoding::Ch Ch;
|
||||||
|
|
||||||
|
GenericRegex(const Ch* source, Allocator* allocator = 0) :
|
||||||
|
states_(allocator, 256), ranges_(allocator, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(),
|
||||||
|
stateSet_(), state0_(allocator, 0), state1_(allocator, 0), anchorBegin_(), anchorEnd_()
|
||||||
|
{
|
||||||
|
GenericStringStream<Encoding> ss(source);
|
||||||
|
DecodedStream<GenericStringStream<Encoding> > ds(ss);
|
||||||
|
Parse(ds);
|
||||||
|
}
|
||||||
|
|
||||||
|
~GenericRegex() {
|
||||||
|
Allocator::Free(stateSet_);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsValid() const {
|
||||||
|
return root_ != kRegexInvalidState;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename InputStream>
|
||||||
|
bool Match(InputStream& is) const {
|
||||||
|
return SearchWithAnchoring(is, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Match(const Ch* s) const {
|
||||||
|
GenericStringStream<Encoding> is(s);
|
||||||
|
return Match(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename InputStream>
|
||||||
|
bool Search(InputStream& is) const {
|
||||||
|
return SearchWithAnchoring(is, anchorBegin_, anchorEnd_);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Search(const Ch* s) const {
|
||||||
|
GenericStringStream<Encoding> is(s);
|
||||||
|
return Search(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum Operator {
|
||||||
|
kZeroOrOne,
|
||||||
|
kZeroOrMore,
|
||||||
|
kOneOrMore,
|
||||||
|
kConcatenation,
|
||||||
|
kAlternation,
|
||||||
|
kLeftParenthesis
|
||||||
|
};
|
||||||
|
|
||||||
|
static const unsigned kAnyCharacterClass = 0xFFFFFFFF; //!< For '.'
|
||||||
|
static const unsigned kRangeCharacterClass = 0xFFFFFFFE;
|
||||||
|
static const unsigned kRangeNegationFlag = 0x80000000;
|
||||||
|
|
||||||
|
struct Range {
|
||||||
|
unsigned start; //
|
||||||
|
unsigned end;
|
||||||
|
SizeType next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct State {
|
||||||
|
SizeType out; //!< Equals to kInvalid for matching state
|
||||||
|
SizeType out1; //!< Equals to non-kInvalid for split
|
||||||
|
SizeType rangeStart;
|
||||||
|
unsigned codepoint;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Frag {
|
||||||
|
Frag(SizeType s, SizeType o, SizeType m) : start(s), out(o), minIndex(m) {}
|
||||||
|
SizeType start;
|
||||||
|
SizeType out; //!< link-list of all output states
|
||||||
|
SizeType minIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename SourceStream>
|
||||||
|
class DecodedStream {
|
||||||
|
public:
|
||||||
|
DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); }
|
||||||
|
unsigned Peek() { return codepoint_; }
|
||||||
|
unsigned Take() {
|
||||||
|
unsigned c = codepoint_;
|
||||||
|
if (c) // No further decoding when '\0'
|
||||||
|
Decode();
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Decode() {
|
||||||
|
if (!Encoding::Decode(ss_, &codepoint_))
|
||||||
|
codepoint_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SourceStream& ss_;
|
||||||
|
unsigned codepoint_;
|
||||||
|
};
|
||||||
|
|
||||||
|
State& GetState(SizeType index) {
|
||||||
|
RAPIDJSON_ASSERT(index < stateCount_);
|
||||||
|
return states_.template Bottom<State>()[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
const State& GetState(SizeType index) const {
|
||||||
|
RAPIDJSON_ASSERT(index < stateCount_);
|
||||||
|
return states_.template Bottom<State>()[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
Range& GetRange(SizeType index) {
|
||||||
|
RAPIDJSON_ASSERT(index < rangeCount_);
|
||||||
|
return ranges_.template Bottom<Range>()[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
const Range& GetRange(SizeType index) const {
|
||||||
|
RAPIDJSON_ASSERT(index < rangeCount_);
|
||||||
|
return ranges_.template Bottom<Range>()[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename InputStream>
|
||||||
|
void Parse(DecodedStream<InputStream>& ds) {
|
||||||
|
Allocator allocator;
|
||||||
|
Stack<Allocator> operandStack(&allocator, 256); // Frag
|
||||||
|
Stack<Allocator> operatorStack(&allocator, 256); // Operator
|
||||||
|
Stack<Allocator> atomCountStack(&allocator, 256); // unsigned (Atom per parenthesis)
|
||||||
|
|
||||||
|
*atomCountStack.template Push<unsigned>() = 0;
|
||||||
|
|
||||||
|
unsigned codepoint;
|
||||||
|
while (ds.Peek() != 0) {
|
||||||
|
switch (codepoint = ds.Take()) {
|
||||||
|
case '^':
|
||||||
|
anchorBegin_ = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '$':
|
||||||
|
anchorEnd_ = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '|':
|
||||||
|
while (!operatorStack.Empty() && *operatorStack.template Top<Operator>() < kAlternation)
|
||||||
|
if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
|
||||||
|
return;
|
||||||
|
*operatorStack.template Push<Operator>() = kAlternation;
|
||||||
|
*atomCountStack.template Top<unsigned>() = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '(':
|
||||||
|
*operatorStack.template Push<Operator>() = kLeftParenthesis;
|
||||||
|
*atomCountStack.template Push<unsigned>() = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ')':
|
||||||
|
while (!operatorStack.Empty() && *operatorStack.template Top<Operator>() != kLeftParenthesis)
|
||||||
|
if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
|
||||||
|
return;
|
||||||
|
if (operatorStack.Empty())
|
||||||
|
return;
|
||||||
|
operatorStack.template Pop<Operator>(1);
|
||||||
|
atomCountStack.template Pop<unsigned>(1);
|
||||||
|
ImplicitConcatenation(atomCountStack, operatorStack);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '?':
|
||||||
|
if (!Eval(operandStack, kZeroOrOne))
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '*':
|
||||||
|
if (!Eval(operandStack, kZeroOrMore))
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '+':
|
||||||
|
if (!Eval(operandStack, kOneOrMore))
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '{':
|
||||||
|
{
|
||||||
|
unsigned n, m;
|
||||||
|
if (!ParseUnsigned(ds, &n))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ds.Peek() == ',') {
|
||||||
|
ds.Take();
|
||||||
|
if (ds.Peek() == '}')
|
||||||
|
m = kInfinityQuantifier;
|
||||||
|
else if (!ParseUnsigned(ds, &m) || m < n)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m = n;
|
||||||
|
|
||||||
|
if (!EvalQuantifier(operandStack, n, m) || ds.Peek() != '}')
|
||||||
|
return;
|
||||||
|
ds.Take();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '.':
|
||||||
|
PushOperand(operandStack, kAnyCharacterClass);
|
||||||
|
ImplicitConcatenation(atomCountStack, operatorStack);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '[':
|
||||||
|
{
|
||||||
|
SizeType range;
|
||||||
|
if (!ParseRange(ds, &range))
|
||||||
|
return;
|
||||||
|
SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, kRangeCharacterClass);
|
||||||
|
GetState(s).rangeStart = range;
|
||||||
|
*operandStack.template Push<Frag>() = Frag(s, s, s);
|
||||||
|
}
|
||||||
|
ImplicitConcatenation(atomCountStack, operatorStack);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '\\': // Escape character
|
||||||
|
if (!CharacterEscape(ds, &codepoint))
|
||||||
|
return; // Unsupported escape character
|
||||||
|
// fall through to default
|
||||||
|
|
||||||
|
default: // Pattern character
|
||||||
|
PushOperand(operandStack, codepoint);
|
||||||
|
ImplicitConcatenation(atomCountStack, operatorStack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!operatorStack.Empty())
|
||||||
|
if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Link the operand to matching state.
|
||||||
|
if (operandStack.GetSize() == sizeof(Frag)) {
|
||||||
|
Frag* e = operandStack.template Pop<Frag>(1);
|
||||||
|
Patch(e->out, NewState(kRegexInvalidState, kRegexInvalidState, 0));
|
||||||
|
root_ = e->start;
|
||||||
|
|
||||||
|
#if RAPIDJSON_REGEX_VERBOSE
|
||||||
|
printf("root: %d\n", root_);
|
||||||
|
for (SizeType i = 0; i < stateCount_ ; i++) {
|
||||||
|
State& s = GetState(i);
|
||||||
|
printf("[%2d] out: %2d out1: %2d c: '%c'\n", i, s.out, s.out1, (char)s.codepoint);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Preallocate buffer for SearchWithAnchoring()
|
||||||
|
RAPIDJSON_ASSERT(stateSet_ == 0);
|
||||||
|
if (stateCount_ > 0) {
|
||||||
|
stateSet_ = static_cast<unsigned*>(states_.GetAllocator().Malloc(GetStateSetSize()));
|
||||||
|
state0_.template Reserve<SizeType>(stateCount_);
|
||||||
|
state1_.template Reserve<SizeType>(stateCount_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SizeType NewState(SizeType out, SizeType out1, unsigned codepoint) {
|
||||||
|
State* s = states_.template Push<State>();
|
||||||
|
s->out = out;
|
||||||
|
s->out1 = out1;
|
||||||
|
s->codepoint = codepoint;
|
||||||
|
s->rangeStart = kRegexInvalidRange;
|
||||||
|
return stateCount_++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PushOperand(Stack<Allocator>& operandStack, unsigned codepoint) {
|
||||||
|
SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, codepoint);
|
||||||
|
*operandStack.template Push<Frag>() = Frag(s, s, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImplicitConcatenation(Stack<Allocator>& atomCountStack, Stack<Allocator>& operatorStack) {
|
||||||
|
if (*atomCountStack.template Top<unsigned>())
|
||||||
|
*operatorStack.template Push<Operator>() = kConcatenation;
|
||||||
|
(*atomCountStack.template Top<unsigned>())++;
|
||||||
|
}
|
||||||
|
|
||||||
|
SizeType Append(SizeType l1, SizeType l2) {
|
||||||
|
SizeType old = l1;
|
||||||
|
while (GetState(l1).out != kRegexInvalidState)
|
||||||
|
l1 = GetState(l1).out;
|
||||||
|
GetState(l1).out = l2;
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Patch(SizeType l, SizeType s) {
|
||||||
|
for (SizeType next; l != kRegexInvalidState; l = next) {
|
||||||
|
next = GetState(l).out;
|
||||||
|
GetState(l).out = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Eval(Stack<Allocator>& operandStack, Operator op) {
|
||||||
|
switch (op) {
|
||||||
|
case kConcatenation:
|
||||||
|
RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag) * 2);
|
||||||
|
{
|
||||||
|
Frag e2 = *operandStack.template Pop<Frag>(1);
|
||||||
|
Frag e1 = *operandStack.template Pop<Frag>(1);
|
||||||
|
Patch(e1.out, e2.start);
|
||||||
|
*operandStack.template Push<Frag>() = Frag(e1.start, e2.out, Min(e1.minIndex, e2.minIndex));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case kAlternation:
|
||||||
|
if (operandStack.GetSize() >= sizeof(Frag) * 2) {
|
||||||
|
Frag e2 = *operandStack.template Pop<Frag>(1);
|
||||||
|
Frag e1 = *operandStack.template Pop<Frag>(1);
|
||||||
|
SizeType s = NewState(e1.start, e2.start, 0);
|
||||||
|
*operandStack.template Push<Frag>() = Frag(s, Append(e1.out, e2.out), Min(e1.minIndex, e2.minIndex));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
|
||||||
|
case kZeroOrOne:
|
||||||
|
if (operandStack.GetSize() >= sizeof(Frag)) {
|
||||||
|
Frag e = *operandStack.template Pop<Frag>(1);
|
||||||
|
SizeType s = NewState(kRegexInvalidState, e.start, 0);
|
||||||
|
*operandStack.template Push<Frag>() = Frag(s, Append(e.out, s), e.minIndex);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
|
||||||
|
case kZeroOrMore:
|
||||||
|
if (operandStack.GetSize() >= sizeof(Frag)) {
|
||||||
|
Frag e = *operandStack.template Pop<Frag>(1);
|
||||||
|
SizeType s = NewState(kRegexInvalidState, e.start, 0);
|
||||||
|
Patch(e.out, s);
|
||||||
|
*operandStack.template Push<Frag>() = Frag(s, s, e.minIndex);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
|
||||||
|
default:
|
||||||
|
RAPIDJSON_ASSERT(op == kOneOrMore);
|
||||||
|
if (operandStack.GetSize() >= sizeof(Frag)) {
|
||||||
|
Frag e = *operandStack.template Pop<Frag>(1);
|
||||||
|
SizeType s = NewState(kRegexInvalidState, e.start, 0);
|
||||||
|
Patch(e.out, s);
|
||||||
|
*operandStack.template Push<Frag>() = Frag(e.start, s, e.minIndex);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EvalQuantifier(Stack<Allocator>& operandStack, unsigned n, unsigned m) {
|
||||||
|
RAPIDJSON_ASSERT(n <= m);
|
||||||
|
RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag));
|
||||||
|
|
||||||
|
if (n == 0) {
|
||||||
|
if (m == 0) // a{0} not support
|
||||||
|
return false;
|
||||||
|
else if (m == kInfinityQuantifier)
|
||||||
|
Eval(operandStack, kZeroOrMore); // a{0,} -> a*
|
||||||
|
else {
|
||||||
|
Eval(operandStack, kZeroOrOne); // a{0,5} -> a?
|
||||||
|
for (unsigned i = 0; i < m - 1; i++)
|
||||||
|
CloneTopOperand(operandStack); // a{0,5} -> a? a? a? a? a?
|
||||||
|
for (unsigned i = 0; i < m - 1; i++)
|
||||||
|
Eval(operandStack, kConcatenation); // a{0,5} -> a?a?a?a?a?
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < n - 1; i++) // a{3} -> a a a
|
||||||
|
CloneTopOperand(operandStack);
|
||||||
|
|
||||||
|
if (m == kInfinityQuantifier)
|
||||||
|
Eval(operandStack, kOneOrMore); // a{3,} -> a a a+
|
||||||
|
else if (m > n) {
|
||||||
|
CloneTopOperand(operandStack); // a{3,5} -> a a a a
|
||||||
|
Eval(operandStack, kZeroOrOne); // a{3,5} -> a a a a?
|
||||||
|
for (unsigned i = n; i < m - 1; i++)
|
||||||
|
CloneTopOperand(operandStack); // a{3,5} -> a a a a? a?
|
||||||
|
for (unsigned i = n; i < m; i++)
|
||||||
|
Eval(operandStack, kConcatenation); // a{3,5} -> a a aa?a?
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < n - 1; i++)
|
||||||
|
Eval(operandStack, kConcatenation); // a{3} -> aaa, a{3,} -> aaa+, a{3.5} -> aaaa?a?
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SizeType Min(SizeType a, SizeType b) { return a < b ? a : b; }
|
||||||
|
|
||||||
|
void CloneTopOperand(Stack<Allocator>& operandStack) {
|
||||||
|
const Frag src = *operandStack.template Top<Frag>(); // Copy constructor to prevent invalidation
|
||||||
|
SizeType count = stateCount_ - src.minIndex; // Assumes top operand contains states in [src->minIndex, stateCount_)
|
||||||
|
State* s = states_.template Push<State>(count);
|
||||||
|
memcpy(s, &GetState(src.minIndex), count * sizeof(State));
|
||||||
|
for (SizeType j = 0; j < count; j++) {
|
||||||
|
if (s[j].out != kRegexInvalidState)
|
||||||
|
s[j].out += count;
|
||||||
|
if (s[j].out1 != kRegexInvalidState)
|
||||||
|
s[j].out1 += count;
|
||||||
|
}
|
||||||
|
*operandStack.template Push<Frag>() = Frag(src.start + count, src.out + count, src.minIndex + count);
|
||||||
|
stateCount_ += count;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename InputStream>
|
||||||
|
bool ParseUnsigned(DecodedStream<InputStream>& ds, unsigned* u) {
|
||||||
|
unsigned r = 0;
|
||||||
|
if (ds.Peek() < '0' || ds.Peek() > '9')
|
||||||
|
return false;
|
||||||
|
while (ds.Peek() >= '0' && ds.Peek() <= '9') {
|
||||||
|
if (r >= 429496729 && ds.Peek() > '5') // 2^32 - 1 = 4294967295
|
||||||
|
return false; // overflow
|
||||||
|
r = r * 10 + (ds.Take() - '0');
|
||||||
|
}
|
||||||
|
*u = r;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename InputStream>
|
||||||
|
bool ParseRange(DecodedStream<InputStream>& ds, SizeType* range) {
|
||||||
|
bool isBegin = true;
|
||||||
|
bool negate = false;
|
||||||
|
int step = 0;
|
||||||
|
SizeType start = kRegexInvalidRange;
|
||||||
|
SizeType current = kRegexInvalidRange;
|
||||||
|
unsigned codepoint;
|
||||||
|
while ((codepoint = ds.Take()) != 0) {
|
||||||
|
if (isBegin) {
|
||||||
|
isBegin = false;
|
||||||
|
if (codepoint == '^') {
|
||||||
|
negate = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (codepoint) {
|
||||||
|
case ']':
|
||||||
|
if (start == kRegexInvalidRange)
|
||||||
|
return false; // Error: nothing inside []
|
||||||
|
if (step == 2) { // Add trailing '-'
|
||||||
|
SizeType r = NewRange('-');
|
||||||
|
RAPIDJSON_ASSERT(current != kRegexInvalidRange);
|
||||||
|
GetRange(current).next = r;
|
||||||
|
}
|
||||||
|
if (negate)
|
||||||
|
GetRange(start).start |= kRangeNegationFlag;
|
||||||
|
*range = start;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case '\\':
|
||||||
|
if (ds.Peek() == 'b') {
|
||||||
|
ds.Take();
|
||||||
|
codepoint = 0x0008; // Escape backspace character
|
||||||
|
}
|
||||||
|
else if (!CharacterEscape(ds, &codepoint))
|
||||||
|
return false;
|
||||||
|
// fall through to default
|
||||||
|
|
||||||
|
default:
|
||||||
|
switch (step) {
|
||||||
|
case 1:
|
||||||
|
if (codepoint == '-') {
|
||||||
|
step++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// fall through to step 0 for other characters
|
||||||
|
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
SizeType r = NewRange(codepoint);
|
||||||
|
if (current != kRegexInvalidRange)
|
||||||
|
GetRange(current).next = r;
|
||||||
|
if (start == kRegexInvalidRange)
|
||||||
|
start = r;
|
||||||
|
current = r;
|
||||||
|
}
|
||||||
|
step = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
RAPIDJSON_ASSERT(step == 2);
|
||||||
|
GetRange(current).end = codepoint;
|
||||||
|
step = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SizeType NewRange(unsigned codepoint) {
|
||||||
|
Range* r = ranges_.template Push<Range>();
|
||||||
|
r->start = r->end = codepoint;
|
||||||
|
r->next = kRegexInvalidRange;
|
||||||
|
return rangeCount_++;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename InputStream>
|
||||||
|
bool CharacterEscape(DecodedStream<InputStream>& ds, unsigned* escapedCodepoint) {
|
||||||
|
unsigned codepoint;
|
||||||
|
switch (codepoint = ds.Take()) {
|
||||||
|
case '^':
|
||||||
|
case '$':
|
||||||
|
case '|':
|
||||||
|
case '(':
|
||||||
|
case ')':
|
||||||
|
case '?':
|
||||||
|
case '*':
|
||||||
|
case '+':
|
||||||
|
case '.':
|
||||||
|
case '[':
|
||||||
|
case ']':
|
||||||
|
case '{':
|
||||||
|
case '}':
|
||||||
|
case '\\':
|
||||||
|
*escapedCodepoint = codepoint; return true;
|
||||||
|
case 'f': *escapedCodepoint = 0x000C; return true;
|
||||||
|
case 'n': *escapedCodepoint = 0x000A; return true;
|
||||||
|
case 'r': *escapedCodepoint = 0x000D; return true;
|
||||||
|
case 't': *escapedCodepoint = 0x0009; return true;
|
||||||
|
case 'v': *escapedCodepoint = 0x000B; return true;
|
||||||
|
default:
|
||||||
|
return false; // Unsupported escape character
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename InputStream>
|
||||||
|
bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) const {
|
||||||
|
RAPIDJSON_ASSERT(IsValid());
|
||||||
|
DecodedStream<InputStream> ds(is);
|
||||||
|
|
||||||
|
state0_.Clear();
|
||||||
|
Stack<Allocator> *current = &state0_, *next = &state1_;
|
||||||
|
const size_t stateSetSize = GetStateSetSize();
|
||||||
|
std::memset(stateSet_, 0, stateSetSize);
|
||||||
|
|
||||||
|
bool matched = AddState(*current, root_);
|
||||||
|
unsigned codepoint;
|
||||||
|
while (!current->Empty() && (codepoint = ds.Take()) != 0) {
|
||||||
|
std::memset(stateSet_, 0, stateSetSize);
|
||||||
|
next->Clear();
|
||||||
|
matched = false;
|
||||||
|
for (const SizeType* s = current->template Bottom<SizeType>(); s != current->template End<SizeType>(); ++s) {
|
||||||
|
const State& sr = GetState(*s);
|
||||||
|
if (sr.codepoint == codepoint ||
|
||||||
|
sr.codepoint == kAnyCharacterClass ||
|
||||||
|
(sr.codepoint == kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint)))
|
||||||
|
{
|
||||||
|
matched = AddState(*next, sr.out) || matched;
|
||||||
|
if (!anchorEnd && matched)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!anchorBegin)
|
||||||
|
AddState(*next, root_);
|
||||||
|
}
|
||||||
|
internal::Swap(current, next);
|
||||||
|
}
|
||||||
|
|
||||||
|
return matched;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t GetStateSetSize() const {
|
||||||
|
return (stateCount_ + 31) / 32 * 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return whether the added states is a match state
|
||||||
|
bool AddState(Stack<Allocator>& l, SizeType index) const {
|
||||||
|
RAPIDJSON_ASSERT(index != kRegexInvalidState);
|
||||||
|
|
||||||
|
const State& s = GetState(index);
|
||||||
|
if (s.out1 != kRegexInvalidState) { // Split
|
||||||
|
bool matched = AddState(l, s.out);
|
||||||
|
return AddState(l, s.out1) || matched;
|
||||||
|
}
|
||||||
|
else if (!(stateSet_[index >> 5] & (1 << (index & 31)))) {
|
||||||
|
stateSet_[index >> 5] |= (1 << (index & 31));
|
||||||
|
*l.template PushUnsafe<SizeType>() = index;
|
||||||
|
}
|
||||||
|
return s.out == kRegexInvalidState; // by using PushUnsafe() above, we can ensure s is not validated due to reallocation.
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MatchRange(SizeType rangeIndex, unsigned codepoint) const {
|
||||||
|
bool yes = (GetRange(rangeIndex).start & kRangeNegationFlag) == 0;
|
||||||
|
while (rangeIndex != kRegexInvalidRange) {
|
||||||
|
const Range& r = GetRange(rangeIndex);
|
||||||
|
if (codepoint >= (r.start & ~kRangeNegationFlag) && codepoint <= r.end)
|
||||||
|
return yes;
|
||||||
|
rangeIndex = r.next;
|
||||||
|
}
|
||||||
|
return !yes;
|
||||||
|
}
|
||||||
|
|
||||||
|
Stack<Allocator> states_;
|
||||||
|
Stack<Allocator> ranges_;
|
||||||
|
SizeType root_;
|
||||||
|
SizeType stateCount_;
|
||||||
|
SizeType rangeCount_;
|
||||||
|
|
||||||
|
static const unsigned kInfinityQuantifier = ~0u;
|
||||||
|
|
||||||
|
// For SearchWithAnchoring()
|
||||||
|
uint32_t* stateSet_; // allocated by states_.GetAllocator()
|
||||||
|
mutable Stack<Allocator> state0_;
|
||||||
|
mutable Stack<Allocator> state1_;
|
||||||
|
bool anchorBegin_;
|
||||||
|
bool anchorEnd_;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef GenericRegex<UTF8<> > Regex;
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // RAPIDJSON_INTERNAL_REGEX_H_
|
||||||
230
libs/discordrpc/rapidjson/internal/stack.h
Normal file
230
libs/discordrpc/rapidjson/internal/stack.h
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://opensource.org/licenses/MIT
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
|
#ifndef RAPIDJSON_INTERNAL_STACK_H_
|
||||||
|
#define RAPIDJSON_INTERNAL_STACK_H_
|
||||||
|
|
||||||
|
#include "../allocators.h"
|
||||||
|
#include "swap.h"
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(c++98-compat)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Stack
|
||||||
|
|
||||||
|
//! A type-unsafe stack for storing different types of data.
|
||||||
|
/*! \tparam Allocator Allocator for allocating stack memory.
|
||||||
|
*/
|
||||||
|
template <typename Allocator>
|
||||||
|
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) {
|
||||||
|
}
|
||||||
|
|
||||||
|
#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 Swap(Stack& rhs) RAPIDJSON_NOEXCEPT {
|
||||||
|
internal::Swap(allocator_, rhs.allocator_);
|
||||||
|
internal::Swap(ownAllocator_, rhs.ownAllocator_);
|
||||||
|
internal::Swap(stack_, rhs.stack_);
|
||||||
|
internal::Swap(stackTop_, rhs.stackTop_);
|
||||||
|
internal::Swap(stackEnd_, rhs.stackEnd_);
|
||||||
|
internal::Swap(initialCapacity_, rhs.initialCapacity_);
|
||||||
|
}
|
||||||
|
|
||||||
|
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<typename T>
|
||||||
|
RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) {
|
||||||
|
// Expand the stack if needed
|
||||||
|
if (RAPIDJSON_UNLIKELY(stackTop_ + sizeof(T) * count > stackEnd_))
|
||||||
|
Expand<T>(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) {
|
||||||
|
Reserve<T>(count);
|
||||||
|
return PushUnsafe<T>(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) {
|
||||||
|
RAPIDJSON_ASSERT(stackTop_ + sizeof(T) * count <= stackEnd_);
|
||||||
|
T* ret = reinterpret_cast<T*>(stackTop_);
|
||||||
|
stackTop_ += sizeof(T) * count;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T* Pop(size_t count) {
|
||||||
|
RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
|
||||||
|
stackTop_ -= count * sizeof(T);
|
||||||
|
return reinterpret_cast<T*>(stackTop_);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T* Top() {
|
||||||
|
RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
|
||||||
|
return reinterpret_cast<T*>(stackTop_ - sizeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
const T* Top() const {
|
||||||
|
RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
|
||||||
|
return reinterpret_cast<T*>(stackTop_ - sizeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T* End() { return reinterpret_cast<T*>(stackTop_); }
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
const T* End() const { return reinterpret_cast<T*>(stackTop_); }
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T* Bottom() { return reinterpret_cast<T*>(stack_); }
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
const T* Bottom() const { return reinterpret_cast<T*>(stack_); }
|
||||||
|
|
||||||
|
bool HasAllocator() const {
|
||||||
|
return allocator_ != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Allocator& GetAllocator() {
|
||||||
|
RAPIDJSON_ASSERT(allocator_);
|
||||||
|
return *allocator_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Empty() const { return stackTop_ == stack_; }
|
||||||
|
size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); }
|
||||||
|
size_t GetCapacity() const { return static_cast<size_t>(stackEnd_ - stack_); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
template<typename T>
|
||||||
|
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_ = static_cast<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
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // RAPIDJSON_STACK_H_
|
||||||
55
libs/discordrpc/rapidjson/internal/strfunc.h
Normal file
55
libs/discordrpc/rapidjson/internal/strfunc.h
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://opensource.org/licenses/MIT
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
|
#ifndef RAPIDJSON_INTERNAL_STRFUNC_H_
|
||||||
|
#define RAPIDJSON_INTERNAL_STRFUNC_H_
|
||||||
|
|
||||||
|
#include "../stream.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 <typename Ch>
|
||||||
|
inline SizeType StrLen(const Ch* s) {
|
||||||
|
const Ch* p = s;
|
||||||
|
while (*p) ++p;
|
||||||
|
return SizeType(p - s);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Returns number of code points in a encoded string.
|
||||||
|
template<typename Encoding>
|
||||||
|
bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) {
|
||||||
|
GenericStringStream<Encoding> is(s);
|
||||||
|
const typename Encoding::Ch* end = s + length;
|
||||||
|
SizeType count = 0;
|
||||||
|
while (is.src_ < end) {
|
||||||
|
unsigned codepoint;
|
||||||
|
if (!Encoding::Decode(is, &codepoint))
|
||||||
|
return false;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
*outCount = count;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
|
#endif // RAPIDJSON_INTERNAL_STRFUNC_H_
|
||||||
269
libs/discordrpc/rapidjson/internal/strtod.h
Normal file
269
libs/discordrpc/rapidjson/internal/strtod.h
Normal file
@@ -0,0 +1,269 @@
|
|||||||
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://opensource.org/licenses/MIT
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
|
#ifndef RAPIDJSON_STRTOD_
|
||||||
|
#define RAPIDJSON_STRTOD_
|
||||||
|
|
||||||
|
#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 <typename T>
|
||||||
|
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) {
|
||||||
|
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(static_cast<unsigned>(dS_Exp5)) <<= static_cast<unsigned>(dS_Exp2);
|
||||||
|
|
||||||
|
BigInteger bS(bInt);
|
||||||
|
bS.MultiplyPow5(static_cast<unsigned>(bS_Exp5)) <<= static_cast<unsigned>(bS_Exp2);
|
||||||
|
|
||||||
|
BigInteger hS(1);
|
||||||
|
hS.MultiplyPow5(static_cast<unsigned>(hS_Exp5)) <<= static_cast<unsigned>(hS_Exp2);
|
||||||
|
|
||||||
|
BigInteger delta(0);
|
||||||
|
dS.Difference(bS, &delta);
|
||||||
|
|
||||||
|
return delta.Compare(hS);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 * 10u + static_cast<unsigned>(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;
|
||||||
|
int64_t error = (remaining == 0) ? 0 : kUlp / 2;
|
||||||
|
|
||||||
|
DiyFp v(significand, 0);
|
||||||
|
v = v.Normalize();
|
||||||
|
error <<= -v.e;
|
||||||
|
|
||||||
|
const int dExp = static_cast<int>(decimalPosition) - static_cast<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 + static_cast<unsigned>(adjustment)> 19u) // 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 + static_cast<int>(kUlp);
|
||||||
|
precisionSize -= scaleExp;
|
||||||
|
}
|
||||||
|
|
||||||
|
DiyFp rounded(v.f >> precisionSize, v.e + static_cast<int>(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 + static_cast<unsigned>(error)) {
|
||||||
|
rounded.f++;
|
||||||
|
if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340)
|
||||||
|
rounded.f >>= 1;
|
||||||
|
rounded.e++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*result = rounded.ToDouble();
|
||||||
|
|
||||||
|
return halfWay - static_cast<unsigned>(error) >= precisionBits || precisionBits >= halfWay + static_cast<unsigned>(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 = static_cast<int>(decimalPosition) - static_cast<int>(length) + exp;
|
||||||
|
Double a(approx);
|
||||||
|
int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp);
|
||||||
|
if (cmp < 0)
|
||||||
|
return a.Value(); // within half ULP
|
||||||
|
else if (cmp == 0) {
|
||||||
|
// Round towards even
|
||||||
|
if (a.Significand() & 1)
|
||||||
|
return a.NextPositiveDouble();
|
||||||
|
else
|
||||||
|
return a.Value();
|
||||||
|
}
|
||||||
|
else // adjustment
|
||||||
|
return a.NextPositiveDouble();
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (static_cast<int>(length) > kMaxDecimalDigit) {
|
||||||
|
int delta = (static_cast<int>(length) - kMaxDecimalDigit);
|
||||||
|
exp += delta;
|
||||||
|
decimalPosition -= static_cast<unsigned>(delta);
|
||||||
|
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_
|
||||||
46
libs/discordrpc/rapidjson/internal/swap.h
Normal file
46
libs/discordrpc/rapidjson/internal/swap.h
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://opensource.org/licenses/MIT
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
|
#ifndef RAPIDJSON_INTERNAL_SWAP_H_
|
||||||
|
#define RAPIDJSON_INTERNAL_SWAP_H_
|
||||||
|
|
||||||
|
#include "../rapidjson.h"
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(c++98-compat)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
//! Custom swap() to avoid dependency on C++ <algorithm> header
|
||||||
|
/*! \tparam T Type of the arguments to swap, should be instantiated with primitive C++ types only.
|
||||||
|
\note This has the same semantics as std::swap().
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT {
|
||||||
|
T tmp = a;
|
||||||
|
a = b;
|
||||||
|
b = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // RAPIDJSON_INTERNAL_SWAP_H_
|
||||||
115
libs/discordrpc/rapidjson/istreamwrapper.h
Normal file
115
libs/discordrpc/rapidjson/istreamwrapper.h
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://opensource.org/licenses/MIT
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
|
#ifndef RAPIDJSON_ISTREAMWRAPPER_H_
|
||||||
|
#define RAPIDJSON_ISTREAMWRAPPER_H_
|
||||||
|
|
||||||
|
#include "stream.h"
|
||||||
|
#include <iosfwd>
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(padded)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(4351) // new behavior: elements of array 'array' will be default initialized
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
//! Wrapper of \c std::basic_istream into RapidJSON's Stream concept.
|
||||||
|
/*!
|
||||||
|
The classes can be wrapped including but not limited to:
|
||||||
|
|
||||||
|
- \c std::istringstream
|
||||||
|
- \c std::stringstream
|
||||||
|
- \c std::wistringstream
|
||||||
|
- \c std::wstringstream
|
||||||
|
- \c std::ifstream
|
||||||
|
- \c std::fstream
|
||||||
|
- \c std::wifstream
|
||||||
|
- \c std::wfstream
|
||||||
|
|
||||||
|
\tparam StreamType Class derived from \c std::basic_istream.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template <typename StreamType>
|
||||||
|
class BasicIStreamWrapper {
|
||||||
|
public:
|
||||||
|
typedef typename StreamType::char_type Ch;
|
||||||
|
BasicIStreamWrapper(StreamType& stream) : stream_(stream), count_(), peekBuffer_() {}
|
||||||
|
|
||||||
|
Ch Peek() const {
|
||||||
|
typename StreamType::int_type c = stream_.peek();
|
||||||
|
return RAPIDJSON_LIKELY(c != StreamType::traits_type::eof()) ? static_cast<Ch>(c) : '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
Ch Take() {
|
||||||
|
typename StreamType::int_type c = stream_.get();
|
||||||
|
if (RAPIDJSON_LIKELY(c != StreamType::traits_type::eof())) {
|
||||||
|
count_++;
|
||||||
|
return static_cast<Ch>(c);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// tellg() may return -1 when failed. So we count by ourself.
|
||||||
|
size_t Tell() const { return count_; }
|
||||||
|
|
||||||
|
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 {
|
||||||
|
RAPIDJSON_ASSERT(sizeof(Ch) == 1); // Only usable for byte stream.
|
||||||
|
int i;
|
||||||
|
bool hasError = false;
|
||||||
|
for (i = 0; i < 4; ++i) {
|
||||||
|
typename StreamType::int_type c = stream_.get();
|
||||||
|
if (c == StreamType::traits_type::eof()) {
|
||||||
|
hasError = true;
|
||||||
|
stream_.clear();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
peekBuffer_[i] = static_cast<Ch>(c);
|
||||||
|
}
|
||||||
|
for (--i; i >= 0; --i)
|
||||||
|
stream_.putback(peekBuffer_[i]);
|
||||||
|
return !hasError ? peekBuffer_ : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
BasicIStreamWrapper(const BasicIStreamWrapper&);
|
||||||
|
BasicIStreamWrapper& operator=(const BasicIStreamWrapper&);
|
||||||
|
|
||||||
|
StreamType& stream_;
|
||||||
|
size_t count_; //!< Number of characters read. Note:
|
||||||
|
mutable Ch peekBuffer_[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef BasicIStreamWrapper<std::istream> IStreamWrapper;
|
||||||
|
typedef BasicIStreamWrapper<std::wistream> WIStreamWrapper;
|
||||||
|
|
||||||
|
#if defined(__clang__) || defined(_MSC_VER)
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
|
#endif // RAPIDJSON_ISTREAMWRAPPER_H_
|
||||||
70
libs/discordrpc/rapidjson/memorybuffer.h
Normal file
70
libs/discordrpc/rapidjson/memorybuffer.h
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://opensource.org/licenses/MIT
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
|
#ifndef RAPIDJSON_MEMORYBUFFER_H_
|
||||||
|
#define RAPIDJSON_MEMORYBUFFER_H_
|
||||||
|
|
||||||
|
#include "stream.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 <typename Allocator = CrtAllocator>
|
||||||
|
struct GenericMemoryBuffer {
|
||||||
|
typedef char Ch; // byte
|
||||||
|
|
||||||
|
GenericMemoryBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {}
|
||||||
|
|
||||||
|
void Put(Ch c) { *stack_.template Push<Ch>() = c; }
|
||||||
|
void Flush() {}
|
||||||
|
|
||||||
|
void Clear() { stack_.Clear(); }
|
||||||
|
void ShrinkToFit() { stack_.ShrinkToFit(); }
|
||||||
|
Ch* Push(size_t count) { return stack_.template Push<Ch>(count); }
|
||||||
|
void Pop(size_t count) { stack_.template Pop<Ch>(count); }
|
||||||
|
|
||||||
|
const Ch* GetBuffer() const {
|
||||||
|
return stack_.template Bottom<Ch>();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t GetSize() const { return stack_.GetSize(); }
|
||||||
|
|
||||||
|
static const size_t kDefaultCapacity = 256;
|
||||||
|
mutable internal::Stack<Allocator> 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<char>(n), c, n * sizeof(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
|
#endif // RAPIDJSON_MEMORYBUFFER_H_
|
||||||
71
libs/discordrpc/rapidjson/memorystream.h
Normal file
71
libs/discordrpc/rapidjson/memorystream.h
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://opensource.org/licenses/MIT
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
|
#ifndef RAPIDJSON_MEMORYSTREAM_H_
|
||||||
|
#define RAPIDJSON_MEMORYSTREAM_H_
|
||||||
|
|
||||||
|
#include "stream.h"
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(unreachable-code)
|
||||||
|
RAPIDJSON_DIAG_OFF(missing-noreturn)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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 RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_; }
|
||||||
|
Ch Take() { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_++; }
|
||||||
|
size_t Tell() const { return static_cast<size_t>(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
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // RAPIDJSON_MEMORYBUFFER_H_
|
||||||
316
libs/discordrpc/rapidjson/msinttypes/inttypes.h
Normal file
316
libs/discordrpc/rapidjson/msinttypes/inttypes.h
Normal file
@@ -0,0 +1,316 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// The above software in this distribution may have been modified by
|
||||||
|
// THL A29 Limited ("Tencent Modifications").
|
||||||
|
// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited.
|
||||||
|
|
||||||
|
#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 <inttypes.h>
|
||||||
|
#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_ ]
|
||||||
300
libs/discordrpc/rapidjson/msinttypes/stdint.h
Normal file
300
libs/discordrpc/rapidjson/msinttypes/stdint.h
Normal file
@@ -0,0 +1,300 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// The above software in this distribution may have been modified by
|
||||||
|
// THL A29 Limited ("Tencent Modifications").
|
||||||
|
// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited.
|
||||||
|
|
||||||
|
#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 <stdint.h>
|
||||||
|
|
||||||
|
#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 <boost/cstdint.hpp>.
|
||||||
|
// 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 <limits.h>
|
||||||
|
|
||||||
|
// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
|
||||||
|
// compiling for ARM we have to wrap <wchar.h> include with 'extern "C++" {}'
|
||||||
|
// or compiler would give many errors like this:
|
||||||
|
// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
|
||||||
|
#if defined(__cplusplus) && !defined(_M_ARM)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
# include <wchar.h>
|
||||||
|
#if defined(__cplusplus) && !defined(_M_ARM)
|
||||||
|
}
|
||||||
|
#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 <wchar.h>
|
||||||
|
#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 <boost/cstdint.hpp>.
|
||||||
|
// 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_ ]
|
||||||
81
libs/discordrpc/rapidjson/ostreamwrapper.h
Normal file
81
libs/discordrpc/rapidjson/ostreamwrapper.h
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://opensource.org/licenses/MIT
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
|
#ifndef RAPIDJSON_OSTREAMWRAPPER_H_
|
||||||
|
#define RAPIDJSON_OSTREAMWRAPPER_H_
|
||||||
|
|
||||||
|
#include "stream.h"
|
||||||
|
#include <iosfwd>
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(padded)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
//! Wrapper of \c std::basic_ostream into RapidJSON's Stream concept.
|
||||||
|
/*!
|
||||||
|
The classes can be wrapped including but not limited to:
|
||||||
|
|
||||||
|
- \c std::ostringstream
|
||||||
|
- \c std::stringstream
|
||||||
|
- \c std::wpstringstream
|
||||||
|
- \c std::wstringstream
|
||||||
|
- \c std::ifstream
|
||||||
|
- \c std::fstream
|
||||||
|
- \c std::wofstream
|
||||||
|
- \c std::wfstream
|
||||||
|
|
||||||
|
\tparam StreamType Class derived from \c std::basic_ostream.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template <typename StreamType>
|
||||||
|
class BasicOStreamWrapper {
|
||||||
|
public:
|
||||||
|
typedef typename StreamType::char_type Ch;
|
||||||
|
BasicOStreamWrapper(StreamType& stream) : stream_(stream) {}
|
||||||
|
|
||||||
|
void Put(Ch c) {
|
||||||
|
stream_.put(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Flush() {
|
||||||
|
stream_.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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:
|
||||||
|
BasicOStreamWrapper(const BasicOStreamWrapper&);
|
||||||
|
BasicOStreamWrapper& operator=(const BasicOStreamWrapper&);
|
||||||
|
|
||||||
|
StreamType& stream_;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef BasicOStreamWrapper<std::ostream> OStreamWrapper;
|
||||||
|
typedef BasicOStreamWrapper<std::wostream> WOStreamWrapper;
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
RAPIDJSON_DIAG_POP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
|
#endif // RAPIDJSON_OSTREAMWRAPPER_H_
|
||||||
1358
libs/discordrpc/rapidjson/pointer.h
Normal file
1358
libs/discordrpc/rapidjson/pointer.h
Normal file
File diff suppressed because it is too large
Load Diff
255
libs/discordrpc/rapidjson/prettywriter.h
Normal file
255
libs/discordrpc/rapidjson/prettywriter.h
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://opensource.org/licenses/MIT
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
|
#ifndef RAPIDJSON_PRETTYWRITER_H_
|
||||||
|
#define RAPIDJSON_PRETTYWRITER_H_
|
||||||
|
|
||||||
|
#include "writer.h"
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
RAPIDJSON_DIAG_OFF(effc++)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
//! Combination of PrettyWriter format flags.
|
||||||
|
/*! \see PrettyWriter::SetFormatOptions
|
||||||
|
*/
|
||||||
|
enum PrettyFormatOptions {
|
||||||
|
kFormatDefault = 0, //!< Default pretty formatting.
|
||||||
|
kFormatSingleLineArray = 1 //!< Format arrays on a single line.
|
||||||
|
};
|
||||||
|
|
||||||
|
//! 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 OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
|
||||||
|
class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> {
|
||||||
|
public:
|
||||||
|
typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> 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.
|
||||||
|
*/
|
||||||
|
explicit PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
|
||||||
|
Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {}
|
||||||
|
|
||||||
|
|
||||||
|
explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
|
||||||
|
Base(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Set pretty writer formatting options.
|
||||||
|
/*! \param options Formatting options.
|
||||||
|
*/
|
||||||
|
PrettyWriter& SetFormatOptions(PrettyFormatOptions options) {
|
||||||
|
formatOptions_ = options;
|
||||||
|
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 RawNumber(const Ch* str, SizeType length, bool copy = false) {
|
||||||
|
(void)copy;
|
||||||
|
PrettyPrefix(kNumberType);
|
||||||
|
return Base::WriteString(str, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
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<Ch>& str) {
|
||||||
|
return String(str.data(), SizeType(str.size()));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool StartObject() {
|
||||||
|
PrettyPrefix(kObjectType);
|
||||||
|
new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(false);
|
||||||
|
return Base::WriteStartObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
|
||||||
|
|
||||||
|
#if RAPIDJSON_HAS_STDSTRING
|
||||||
|
bool Key(const std::basic_string<Ch>& str) {
|
||||||
|
return Key(str.data(), SizeType(str.size()));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool EndObject(SizeType memberCount = 0) {
|
||||||
|
(void)memberCount;
|
||||||
|
RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
|
||||||
|
RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray);
|
||||||
|
bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
|
||||||
|
|
||||||
|
if (!empty) {
|
||||||
|
Base::os_->Put('\n');
|
||||||
|
WriteIndent();
|
||||||
|
}
|
||||||
|
bool ret = Base::WriteEndObject();
|
||||||
|
(void)ret;
|
||||||
|
RAPIDJSON_ASSERT(ret == true);
|
||||||
|
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>()) 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<typename Base::Level>()->inArray);
|
||||||
|
bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
|
||||||
|
|
||||||
|
if (!empty && !(formatOptions_ & kFormatSingleLineArray)) {
|
||||||
|
Base::os_->Put('\n');
|
||||||
|
WriteIndent();
|
||||||
|
}
|
||||||
|
bool ret = Base::WriteEndArray();
|
||||||
|
(void)ret;
|
||||||
|
RAPIDJSON_ASSERT(ret == true);
|
||||||
|
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)); }
|
||||||
|
|
||||||
|
//@}
|
||||||
|
|
||||||
|
//! Write a raw JSON value.
|
||||||
|
/*!
|
||||||
|
For user to write a stringified JSON as a value.
|
||||||
|
|
||||||
|
\param json A well-formed JSON value. It should not contain null character within [0, length - 1] range.
|
||||||
|
\param length Length of the json.
|
||||||
|
\param type Type of the root of json.
|
||||||
|
\note When using PrettyWriter::RawValue(), the result json may not be indented correctly.
|
||||||
|
*/
|
||||||
|
bool RawValue(const Ch* json, size_t length, Type type) { PrettyPrefix(type); return Base::WriteRawValue(json, length); }
|
||||||
|
|
||||||
|
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<typename Base::Level>();
|
||||||
|
|
||||||
|
if (level->inArray) {
|
||||||
|
if (level->valueCount > 0) {
|
||||||
|
Base::os_->Put(','); // add comma if it is not the first element in array
|
||||||
|
if (formatOptions_ & kFormatSingleLineArray)
|
||||||
|
Base::os_->Put(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(formatOptions_ & kFormatSingleLineArray)) {
|
||||||
|
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_, static_cast<typename TargetEncoding::Ch>(indentChar_), count);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ch indentChar_;
|
||||||
|
unsigned indentCharCount_;
|
||||||
|
PrettyFormatOptions formatOptions_;
|
||||||
|
|
||||||
|
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_
|
||||||
615
libs/discordrpc/rapidjson/rapidjson.h
Normal file
615
libs/discordrpc/rapidjson/rapidjson.h
Normal file
@@ -0,0 +1,615 @@
|
|||||||
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
|
// in compliance with the License. You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://opensource.org/licenses/MIT
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
|
#ifndef RAPIDJSON_RAPIDJSON_H_
|
||||||
|
#define RAPIDJSON_RAPIDJSON_H_
|
||||||
|
|
||||||
|
/*!\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 <cstdlib> // malloc(), realloc(), free(), size_t
|
||||||
|
#include <cstring> // memset(), memcpy(), memmove(), memcmp()
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// RAPIDJSON_VERSION_STRING
|
||||||
|
//
|
||||||
|
// ALWAYS synchronize the following 3 macros with corresponding variables in /CMakeLists.txt.
|
||||||
|
//
|
||||||
|
|
||||||
|
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
||||||
|
// token stringification
|
||||||
|
#define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x)
|
||||||
|
#define RAPIDJSON_DO_STRINGIFY(x) #x
|
||||||
|
//!@endcond
|
||||||
|
|
||||||
|
/*! \def RAPIDJSON_MAJOR_VERSION
|
||||||
|
\ingroup RAPIDJSON_CONFIG
|
||||||
|
\brief Major version of RapidJSON in integer.
|
||||||
|
*/
|
||||||
|
/*! \def RAPIDJSON_MINOR_VERSION
|
||||||
|
\ingroup RAPIDJSON_CONFIG
|
||||||
|
\brief Minor version of RapidJSON in integer.
|
||||||
|
*/
|
||||||
|
/*! \def RAPIDJSON_PATCH_VERSION
|
||||||
|
\ingroup RAPIDJSON_CONFIG
|
||||||
|
\brief Patch version of RapidJSON in integer.
|
||||||
|
*/
|
||||||
|
/*! \def RAPIDJSON_VERSION_STRING
|
||||||
|
\ingroup RAPIDJSON_CONFIG
|
||||||
|
\brief Version of RapidJSON in "<major>.<minor>.<patch>" string format.
|
||||||
|
*/
|
||||||
|
#define RAPIDJSON_MAJOR_VERSION 1
|
||||||
|
#define RAPIDJSON_MINOR_VERSION 1
|
||||||
|
#define RAPIDJSON_PATCH_VERSION 0
|
||||||
|
#define RAPIDJSON_VERSION_STRING \
|
||||||
|
RAPIDJSON_STRINGIFY(RAPIDJSON_MAJOR_VERSION.RAPIDJSON_MINOR_VERSION.RAPIDJSON_PATCH_VERSION)
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// 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_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
|
||||||
|
*/
|
||||||
|
#endif // !defined(RAPIDJSON_HAS_STDSTRING)
|
||||||
|
|
||||||
|
#if RAPIDJSON_HAS_STDSTRING
|
||||||
|
#include <string>
|
||||||
|
#endif // RAPIDJSON_HAS_STDSTRING
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// 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
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER < 1800) // Visual Studio 2013
|
||||||
|
#include "msinttypes/stdint.h"
|
||||||
|
#include "msinttypes/inttypes.h"
|
||||||
|
#else
|
||||||
|
// Other compilers should have this.
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#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
|
||||||
|
#if defined(_MSC_VER) && defined(NDEBUG)
|
||||||
|
#define RAPIDJSON_FORCEINLINE __forceinline
|
||||||
|
#elif defined(__GNUC__) && __GNUC__ >= 4 && defined(NDEBUG)
|
||||||
|
#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 <endian.h>
|
||||||
|
# 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(_MSC_VER) && defined(_M_ARM)
|
||||||
|
# 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(__x86_64__) && defined(__ILP32__)) || defined(_WIN64) || defined(__EMSCRIPTEN__)
|
||||||
|
#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 on 32-bit platforms and 8 bytes alignment for 64-bit platforms.
|
||||||
|
User can customize by defining the RAPIDJSON_ALIGN function macro.
|
||||||
|
*/
|
||||||
|
#ifndef RAPIDJSON_ALIGN
|
||||||
|
#if RAPIDJSON_64BIT == 1
|
||||||
|
#define RAPIDJSON_ALIGN(x) (((x) + static_cast<uint64_t>(7u)) & ~static_cast<uint64_t>(7u))
|
||||||
|
#else
|
||||||
|
#define RAPIDJSON_ALIGN(x) (((x) + 3u) & ~3u)
|
||||||
|
#endif
|
||||||
|
#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<uint64_t>(high32) << 32) | static_cast<uint64_t>(low32))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// RAPIDJSON_48BITPOINTER_OPTIMIZATION
|
||||||
|
|
||||||
|
//! Use only lower 48-bit address for some pointers.
|
||||||
|
/*!
|
||||||
|
\ingroup RAPIDJSON_CONFIG
|
||||||
|
|
||||||
|
This optimization uses the fact that current X86-64 architecture only implement lower 48-bit virtual address.
|
||||||
|
The higher 16-bit can be used for storing other data.
|
||||||
|
\c GenericValue uses this optimization to reduce its size form 24 bytes to 16 bytes in 64-bit architecture.
|
||||||
|
*/
|
||||||
|
#ifndef RAPIDJSON_48BITPOINTER_OPTIMIZATION
|
||||||
|
#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)
|
||||||
|
#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 1
|
||||||
|
#else
|
||||||
|
#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 0
|
||||||
|
#endif
|
||||||
|
#endif // RAPIDJSON_48BITPOINTER_OPTIMIZATION
|
||||||
|
|
||||||
|
#if RAPIDJSON_48BITPOINTER_OPTIMIZATION == 1
|
||||||
|
#if RAPIDJSON_64BIT != 1
|
||||||
|
#error RAPIDJSON_48BITPOINTER_OPTIMIZATION can only be set to 1 when RAPIDJSON_64BIT=1
|
||||||
|
#endif
|
||||||
|
#define RAPIDJSON_SETPOINTER(type, p, x) (p = reinterpret_cast<type *>((reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0xFFFF0000, 0x00000000))) | reinterpret_cast<uintptr_t>(reinterpret_cast<const void*>(x))))
|
||||||
|
#define RAPIDJSON_GETPOINTER(type, p) (reinterpret_cast<type *>(reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0x0000FFFF, 0xFFFFFFFF))))
|
||||||
|
#else
|
||||||
|
#define RAPIDJSON_SETPOINTER(type, p, x) (p = (x))
|
||||||
|
#define RAPIDJSON_GETPOINTER(type, p) (p)
|
||||||
|
#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 <cassert>
|
||||||
|
#define RAPIDJSON_ASSERT(x) assert(x)
|
||||||
|
#endif // RAPIDJSON_ASSERT
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// RAPIDJSON_STATIC_ASSERT
|
||||||
|
|
||||||
|
// Adopt from boost
|
||||||
|
#ifndef RAPIDJSON_STATIC_ASSERT
|
||||||
|
#ifndef __clang__
|
||||||
|
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
||||||
|
#endif
|
||||||
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
template <bool x> struct STATIC_ASSERTION_FAILURE;
|
||||||
|
template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; };
|
||||||
|
template<int x> 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
|
||||||
|
#ifndef __clang__
|
||||||
|
//!@endcond
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*! \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<bool(x) >)> \
|
||||||
|
RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// RAPIDJSON_LIKELY, RAPIDJSON_UNLIKELY
|
||||||
|
|
||||||
|
//! Compiler branching hint for expression with high probability to be true.
|
||||||
|
/*!
|
||||||
|
\ingroup RAPIDJSON_CONFIG
|
||||||
|
\param x Boolean expression likely to be true.
|
||||||
|
*/
|
||||||
|
#ifndef RAPIDJSON_LIKELY
|
||||||
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
|
#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
|
||||||
|
#else
|
||||||
|
#define RAPIDJSON_LIKELY(x) (x)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//! Compiler branching hint for expression with low probability to be true.
|
||||||
|
/*!
|
||||||
|
\ingroup RAPIDJSON_CONFIG
|
||||||
|
\param x Boolean expression unlikely to be true.
|
||||||
|
*/
|
||||||
|
#ifndef RAPIDJSON_UNLIKELY
|
||||||
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
|
#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
|
||||||
|
#else
|
||||||
|
#define RAPIDJSON_UNLIKELY(x) (x)
|
||||||
|
#endif
|
||||||
|
#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))
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// 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__)
|
||||||
|
#if __has_feature(cxx_rvalue_references) && \
|
||||||
|
(defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306)
|
||||||
|
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
|
||||||
|
#else
|
||||||
|
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0
|
||||||
|
#endif
|
||||||
|
#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
|
||||||
|
|
||||||
|
#ifndef RAPIDJSON_HAS_CXX11_RANGE_FOR
|
||||||
|
#if defined(__clang__)
|
||||||
|
#define RAPIDJSON_HAS_CXX11_RANGE_FOR __has_feature(cxx_range_for)
|
||||||
|
#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
|
||||||
|
(defined(_MSC_VER) && _MSC_VER >= 1700)
|
||||||
|
#define RAPIDJSON_HAS_CXX11_RANGE_FOR 1
|
||||||
|
#else
|
||||||
|
#define RAPIDJSON_HAS_CXX11_RANGE_FOR 0
|
||||||
|
#endif
|
||||||
|
#endif // RAPIDJSON_HAS_CXX11_RANGE_FOR
|
||||||
|
|
||||||
|
//!@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
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Type
|
||||||
|
|
||||||
|
/*! \namespace rapidjson
|
||||||
|
\brief main RapidJSON namespace
|
||||||
|
\see RAPIDJSON_NAMESPACE
|
||||||
|
*/
|
||||||
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
//! 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_
|
||||||
1879
libs/discordrpc/rapidjson/reader.h
Normal file
1879
libs/discordrpc/rapidjson/reader.h
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user