crlib: remove local headers
This commit is contained in:
parent
f870e7db4a
commit
f41b63dc97
24 changed files with 0 additions and 5502 deletions
|
|
@ -1,408 +0,0 @@
|
|||
//
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2021 YaPB Project <yapb@jeefo.net>.
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <crlib/cr-basic.h>
|
||||
#include <crlib/cr-memory.h>
|
||||
#include <crlib/cr-movable.h>
|
||||
#include <crlib/cr-random.h>
|
||||
|
||||
#include <initializer_list>
|
||||
|
||||
// policy to reserve memory
|
||||
CR_DECLARE_SCOPED_ENUM (ReservePolicy,
|
||||
Multiple,
|
||||
Single,
|
||||
)
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
// simple array class like std::vector
|
||||
template <typename T, ReservePolicy R = ReservePolicy::Multiple, size_t S = 0> class Array : public DenyCopying {
|
||||
private:
|
||||
T *contents_ {};
|
||||
size_t capacity_ {};
|
||||
size_t length_ {};
|
||||
|
||||
public:
|
||||
explicit Array () {
|
||||
if (fix (S > 0)) {
|
||||
reserve (S);
|
||||
}
|
||||
}
|
||||
|
||||
Array (const size_t amount) {
|
||||
reserve (amount);
|
||||
}
|
||||
|
||||
Array (Array &&rhs) noexcept {
|
||||
contents_ = rhs.contents_;
|
||||
length_ = rhs.length_;
|
||||
capacity_ = rhs.capacity_;
|
||||
|
||||
rhs.reset ();
|
||||
}
|
||||
|
||||
Array (const std::initializer_list <T> &list) {
|
||||
for (const auto &elem : list) {
|
||||
push (elem);
|
||||
}
|
||||
}
|
||||
|
||||
~Array () {
|
||||
destroy ();
|
||||
}
|
||||
|
||||
private:
|
||||
void destructElements () noexcept {
|
||||
for (size_t i = 0; i < length_; ++i) {
|
||||
Memory::destruct (&contents_[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void transferElements (T *dest, T *src, size_t length) noexcept {
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
Memory::construct (&dest[i], cr::move (src[i]));
|
||||
Memory::destruct (&src[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void destroy () {
|
||||
destructElements ();
|
||||
Memory::release (contents_);
|
||||
}
|
||||
|
||||
void reset () {
|
||||
contents_ = nullptr;
|
||||
capacity_ = 0;
|
||||
length_ = 0;
|
||||
}
|
||||
|
||||
public:
|
||||
bool reserve (const size_t amount) {
|
||||
if (length_ + amount < capacity_) {
|
||||
return true;
|
||||
}
|
||||
auto capacity = capacity_ ? capacity_ : 12;
|
||||
|
||||
if (cr::fix (R == ReservePolicy::Multiple)) {
|
||||
while (length_ + amount > capacity) {
|
||||
capacity *= 2;
|
||||
}
|
||||
}
|
||||
else {
|
||||
capacity = amount + capacity_ + 1;
|
||||
}
|
||||
auto data = Memory::get <T> (capacity);
|
||||
|
||||
if (contents_) {
|
||||
transferElements (data, contents_, length_);
|
||||
Memory::release (contents_);
|
||||
}
|
||||
|
||||
contents_ = data;
|
||||
capacity_ = capacity;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool resize (const size_t amount) {
|
||||
if (amount < length_) {
|
||||
while (amount < length_) {
|
||||
discard ();
|
||||
}
|
||||
}
|
||||
else if (amount > length_) {
|
||||
if (!ensure (amount)) {
|
||||
return false;
|
||||
}
|
||||
size_t resizeLength = amount - length_;
|
||||
|
||||
while (resizeLength--) {
|
||||
emplace ();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ensure (const size_t amount) {
|
||||
if (amount <= length_) {
|
||||
return true;
|
||||
}
|
||||
return reserve (amount - length_);
|
||||
}
|
||||
|
||||
template <typename U = size_t> U length () const {
|
||||
return static_cast <U> (length_);
|
||||
}
|
||||
|
||||
size_t capacity () const {
|
||||
return capacity_;
|
||||
}
|
||||
|
||||
template <typename U> bool set (size_t index, U &&object) {
|
||||
if (index >= capacity_) {
|
||||
if (!reserve (index + 1)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Memory::construct (&contents_[index], cr::forward <U> (object));
|
||||
|
||||
if (index >= length_) {
|
||||
length_ = index + 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename U> bool insert (size_t index, U &&object) {
|
||||
return insert (index, &object, 1);
|
||||
}
|
||||
|
||||
template <typename U> bool insert (size_t index, U *objects, size_t count = 1) {
|
||||
if (!objects || !count) {
|
||||
return false;
|
||||
}
|
||||
const size_t capacity = (length_ > index ? length_ : index) + count;
|
||||
|
||||
if (capacity >= capacity_ && !reserve (capacity)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (index >= length_) {
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
Memory::construct (&contents_[i + index], cr::forward <U> (objects[i]));
|
||||
}
|
||||
length_ = capacity;
|
||||
}
|
||||
else {
|
||||
size_t i = 0;
|
||||
|
||||
for (i = length_; i > index; --i) {
|
||||
contents_[i + count - 1] = cr::move (contents_[i - 1]);
|
||||
}
|
||||
for (i = 0; i < count; ++i) {
|
||||
Memory::construct (&contents_[i + index], cr::forward <U> (objects[i]));
|
||||
}
|
||||
length_ += count;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool insert (size_t at, const Array &rhs) {
|
||||
if (&rhs == this) {
|
||||
return false;
|
||||
}
|
||||
return insert (at, &rhs.contents_[0], rhs.length_);
|
||||
}
|
||||
|
||||
bool erase (const size_t index, const size_t count) {
|
||||
if (index + count > capacity_) {
|
||||
return false;
|
||||
}
|
||||
for (size_t i = index; i < index + count; ++i) {
|
||||
Memory::destruct (&contents_[i]);
|
||||
}
|
||||
length_ -= count;
|
||||
|
||||
for (size_t i = index; i < length_; ++i) {
|
||||
contents_[i] = cr::move (contents_[i + count]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool shift () {
|
||||
return erase (0, 1);
|
||||
}
|
||||
|
||||
template <typename U> bool unshift (U &&object) {
|
||||
return insert (0, &object);
|
||||
}
|
||||
|
||||
bool remove (const T &object) {
|
||||
return erase (index (object), 1);
|
||||
}
|
||||
|
||||
template <typename U> bool push (U &&object) {
|
||||
if (!reserve (1)) {
|
||||
return false;
|
||||
}
|
||||
Memory::construct (&contents_[length_], cr::forward <U> (object));
|
||||
++length_;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename ...Args> bool emplace (Args &&...args) {
|
||||
if (!reserve (1)) {
|
||||
return false;
|
||||
}
|
||||
Memory::construct (&contents_[length_], cr::forward <Args> (args)...);
|
||||
++length_;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
T pop () {
|
||||
auto object = cr::move (contents_[length_ - 1]);
|
||||
discard ();
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
void discard () {
|
||||
erase (length_ - 1, 1);
|
||||
}
|
||||
|
||||
size_t index (const T &object) const {
|
||||
return &object - &contents_[0];
|
||||
}
|
||||
|
||||
void shuffle () {
|
||||
int32 shuffleLength = length <int32> ();
|
||||
|
||||
for (int32 i = shuffleLength; i >= 1; --i) {
|
||||
cr::swap (contents_[i - 1], contents_[rg.get (i, shuffleLength - 2)]);
|
||||
}
|
||||
}
|
||||
|
||||
void reverse () {
|
||||
for (size_t i = 0; i < length_ / 2; ++i) {
|
||||
cr::swap (contents_[i], contents_[length_ - 1 - i]);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename U> bool extend (U &&rhs) {
|
||||
if (length_ == 0) {
|
||||
*this = cr::move (rhs);
|
||||
}
|
||||
else {
|
||||
for (size_t i = 0; i < rhs.length (); ++i) {
|
||||
if (!push (cr::move (rhs[i]))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename U> bool assign (U &&rhs) {
|
||||
clear ();
|
||||
return extend (cr::move (rhs));
|
||||
}
|
||||
|
||||
void clear () {
|
||||
destructElements ();
|
||||
length_ = 0;
|
||||
}
|
||||
|
||||
bool empty () const {
|
||||
return length_ == 0;
|
||||
}
|
||||
|
||||
bool shrink () {
|
||||
if (length_ == capacity_ || !length_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto data = Memory::get <T> (length_);
|
||||
transferElements (data, contents_, length_);
|
||||
|
||||
Memory::release (contents_);
|
||||
|
||||
contents_ = data;
|
||||
capacity_ = length_;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const T &at (size_t index) const {
|
||||
return contents_[index];
|
||||
}
|
||||
|
||||
T &at (size_t index) {
|
||||
return contents_[index];
|
||||
}
|
||||
|
||||
const T &first () const {
|
||||
return contents_[0];
|
||||
}
|
||||
|
||||
T &first () {
|
||||
return contents_[0];
|
||||
}
|
||||
|
||||
T &last () {
|
||||
return contents_[length_ - 1];
|
||||
}
|
||||
|
||||
const T &last () const {
|
||||
return contents_[length_ - 1];
|
||||
}
|
||||
|
||||
const T &random () const {
|
||||
return contents_[rg.get (0, length <int32> () - 1)];
|
||||
}
|
||||
|
||||
T &random () {
|
||||
return contents_[rg.get (0, length <int32> () - 1)];
|
||||
}
|
||||
|
||||
T *data () {
|
||||
return contents_;
|
||||
}
|
||||
|
||||
T *data () const {
|
||||
return contents_;
|
||||
}
|
||||
|
||||
public:
|
||||
Array &operator = (Array &&rhs) noexcept {
|
||||
if (this != &rhs) {
|
||||
destroy ();
|
||||
|
||||
contents_ = rhs.contents_;
|
||||
length_ = rhs.length_;
|
||||
capacity_ = rhs.capacity_;
|
||||
|
||||
rhs.reset ();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
public:
|
||||
const T &operator [] (size_t index) const {
|
||||
return at (index);
|
||||
}
|
||||
|
||||
T &operator [] (size_t index) {
|
||||
return at (index);
|
||||
}
|
||||
|
||||
// for range-based loops
|
||||
public:
|
||||
T *begin () {
|
||||
return contents_;
|
||||
}
|
||||
|
||||
T *begin () const {
|
||||
return contents_;
|
||||
}
|
||||
|
||||
T *end () {
|
||||
return contents_ + length_;
|
||||
}
|
||||
|
||||
T *end () const {
|
||||
return contents_ + length_;
|
||||
}
|
||||
};
|
||||
|
||||
// small array (with minimal reserve policy, something like fixed array, but still able to grow, by default allocates 64 elements)
|
||||
template <typename T> using SmallArray = Array <T, ReservePolicy::Single, 64>;
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -1,130 +0,0 @@
|
|||
//
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2021 YaPB Project <yapb@jeefo.net>.
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
// our global namaespace
|
||||
#define CR_NAMESPACE_BEGIN namespace cr {
|
||||
#define CR_NAMESPACE_END }
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <limits.h>
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
//
|
||||
// some useful type definitions
|
||||
//
|
||||
namespace types {
|
||||
using int8 = signed char;
|
||||
using int16 = signed short;
|
||||
using int32 = signed int;
|
||||
using uint8 = unsigned char;
|
||||
using uint16 = unsigned short;
|
||||
using uint32 = unsigned int;
|
||||
using uint64 = unsigned long long;
|
||||
}
|
||||
|
||||
// make types available for our own use
|
||||
using namespace cr::types;
|
||||
|
||||
//
|
||||
// global helper stuff
|
||||
//
|
||||
template <typename T, size_t N> constexpr size_t bufsize (const T (&)[N]) {
|
||||
return N - 1;
|
||||
}
|
||||
|
||||
template <typename T> constexpr T abs (const T &a) {
|
||||
return a > 0 ? a : -a;
|
||||
}
|
||||
|
||||
template <typename T> constexpr T bit (const T &a) {
|
||||
return static_cast <T> (1ULL << a);
|
||||
}
|
||||
|
||||
template <typename T> constexpr T min (const T &a, const T &b) {
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
template <typename T> constexpr T max (const T &a, const T &b) {
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
template <typename T> constexpr T square (const T &value) {
|
||||
return value * value;
|
||||
}
|
||||
|
||||
template <typename T> constexpr T clamp (const T &x, const T &a, const T &b) {
|
||||
return min (max (x, a), b);
|
||||
}
|
||||
|
||||
template <typename T> const T &fix (const T &type) {
|
||||
return type;
|
||||
}
|
||||
|
||||
//
|
||||
// base classes
|
||||
//
|
||||
|
||||
// simple non-copying base class
|
||||
class DenyCopying {
|
||||
protected:
|
||||
explicit DenyCopying () = default;
|
||||
~DenyCopying () = default;
|
||||
|
||||
public:
|
||||
DenyCopying (const DenyCopying &) = delete;
|
||||
DenyCopying &operator = (const DenyCopying &) = delete;
|
||||
};
|
||||
|
||||
// singleton for objects
|
||||
template<typename T> class Singleton : public DenyCopying {
|
||||
protected:
|
||||
Singleton ()
|
||||
{ }
|
||||
|
||||
public:
|
||||
static T &instance () {
|
||||
static T __instance {};
|
||||
return __instance;
|
||||
}
|
||||
|
||||
public:
|
||||
T *operator -> () {
|
||||
return &instance ();
|
||||
}
|
||||
};
|
||||
|
||||
// simple scoped enum, instaed of enum class
|
||||
#define CR_DECLARE_SCOPED_ENUM_TYPE(enumName, enumType, ...) \
|
||||
CR_NAMESPACE_BEGIN \
|
||||
namespace enums { \
|
||||
struct _##enumName : protected DenyCopying { \
|
||||
enum Type : enumType { \
|
||||
__VA_ARGS__ \
|
||||
}; \
|
||||
}; \
|
||||
} \
|
||||
CR_NAMESPACE_END \
|
||||
using enumName = ::cr::enums::_##enumName::Type; \
|
||||
|
||||
// same as above, but with int32 type
|
||||
#define CR_DECLARE_SCOPED_ENUM(enumName, ...) \
|
||||
CR_DECLARE_SCOPED_ENUM_TYPE(enumName, int32, __VA_ARGS__) \
|
||||
|
||||
// exposes global variable from class singleton
|
||||
#define CR_EXPOSE_GLOBAL_SINGLETON(className, variable) \
|
||||
static auto &variable { className::instance () } \
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
||||
// platform-dependant-stuff
|
||||
#include <crlib/cr-platform.h>
|
||||
|
|
@ -1,151 +0,0 @@
|
|||
//
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2021 YaPB Project <yapb@jeefo.net>.
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <crlib/cr-array.h>
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
// simple priority queue
|
||||
template <typename T> class BinaryHeap final : public DenyCopying {
|
||||
private:
|
||||
Array <T> contents_;
|
||||
|
||||
public:
|
||||
explicit BinaryHeap () = default;
|
||||
|
||||
BinaryHeap (BinaryHeap &&rhs) noexcept : contents_ (cr::move (rhs.contents_))
|
||||
{ }
|
||||
|
||||
~BinaryHeap () = default;
|
||||
|
||||
public:
|
||||
template <typename U> bool push (U &&item) {
|
||||
if (!contents_.push (cr::move (item))) {
|
||||
return false;
|
||||
}
|
||||
const size_t length = contents_.length ();
|
||||
|
||||
if (length > 1) {
|
||||
percolateUp (length - 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename ...Args> bool emplace (Args &&...args) {
|
||||
if (!contents_.emplace (cr::forward <Args> (args)...)) {
|
||||
return false;
|
||||
}
|
||||
const size_t length = contents_.length ();
|
||||
|
||||
if (length > 1) {
|
||||
percolateUp (length - 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const T &top () const {
|
||||
return contents_[0];
|
||||
}
|
||||
|
||||
T pop () {
|
||||
if (contents_.length () == 1) {
|
||||
return contents_.pop ();
|
||||
}
|
||||
auto key (cr::move (contents_[0]));
|
||||
|
||||
contents_[0] = cr::move (contents_.last ());
|
||||
contents_.discard ();
|
||||
|
||||
percolateDown (0);
|
||||
return key;
|
||||
}
|
||||
|
||||
public:
|
||||
size_t length () const {
|
||||
return contents_.length ();
|
||||
}
|
||||
|
||||
bool empty () const {
|
||||
return !contents_.length ();
|
||||
}
|
||||
|
||||
void clear () {
|
||||
contents_.clear ();
|
||||
}
|
||||
|
||||
private:
|
||||
void percolateUp (size_t index) {
|
||||
while (index != 0) {
|
||||
const size_t parentIndex = parent (index);
|
||||
|
||||
if (contents_[parentIndex] > contents_[index]) {
|
||||
cr::swap (contents_[index], contents_[parentIndex]);
|
||||
index = parentIndex;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void percolateDown (size_t index) {
|
||||
while (hasLeft (index)) {
|
||||
size_t bestIndex = left (index);
|
||||
|
||||
if (hasRight (index)) {
|
||||
const size_t rightIndex = right (index);
|
||||
|
||||
if (contents_[rightIndex] < contents_[bestIndex]) {
|
||||
bestIndex = rightIndex;
|
||||
}
|
||||
}
|
||||
|
||||
if (contents_[index] > contents_[bestIndex]) {
|
||||
cr::swap (contents_[index], contents_[bestIndex]);
|
||||
|
||||
index = bestIndex;
|
||||
bestIndex = left (index);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
BinaryHeap &operator = (BinaryHeap &&rhs) noexcept {
|
||||
if (this != &rhs) {
|
||||
contents_ = cr::move (rhs.contents_);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr size_t parent (size_t index) {
|
||||
return (index - 1) / 2;
|
||||
}
|
||||
|
||||
static constexpr size_t left (size_t index) {
|
||||
return (index * 2) + 1;
|
||||
}
|
||||
|
||||
static constexpr size_t right (size_t index) {
|
||||
return (index * 2) + 2;
|
||||
}
|
||||
|
||||
bool hasLeft (size_t index) const {
|
||||
return left (index) < contents_.length ();
|
||||
}
|
||||
|
||||
bool hasRight (size_t index) const {
|
||||
return right (index) < contents_.length ();
|
||||
}
|
||||
};
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
//
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2021 YaPB Project <yapb@jeefo.net>.
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <crlib/cr-basic.h>
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
// simple color holder
|
||||
class Color final {
|
||||
public:
|
||||
int32 red = 0, green = 0, blue = 0;
|
||||
|
||||
public:
|
||||
Color (int32 r, int32 g, int32 b) : red (r), green (g), blue (b) { }
|
||||
|
||||
explicit Color () = default;
|
||||
~Color () = default;
|
||||
|
||||
public:
|
||||
void reset () {
|
||||
red = green = blue = 0;
|
||||
}
|
||||
|
||||
int32 avg () const {
|
||||
return sum () / (sizeof (Color) / sizeof (int32));
|
||||
}
|
||||
|
||||
int32 sum () const {
|
||||
return red + green + blue;
|
||||
}
|
||||
};
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
//
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2021 YaPB Project <yapb@jeefo.net>.
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <crlib/cr-basic.h>
|
||||
#include <crlib/cr-memory.h>
|
||||
#include <crlib/cr-array.h>
|
||||
#include <crlib/cr-deque.h>
|
||||
#include <crlib/cr-binheap.h>
|
||||
#include <crlib/cr-files.h>
|
||||
#include <crlib/cr-lambda.h>
|
||||
#include <crlib/cr-http.h>
|
||||
#include <crlib/cr-library.h>
|
||||
#include <crlib/cr-hashmap.h>
|
||||
#include <crlib/cr-logger.h>
|
||||
#include <crlib/cr-math.h>
|
||||
#include <crlib/cr-vector.h>
|
||||
#include <crlib/cr-random.h>
|
||||
#include <crlib/cr-ulz.h>
|
||||
#include <crlib/cr-color.h>
|
||||
#include <crlib/cr-detour.h>
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
namespace types {
|
||||
using StringArray = Array <String>;
|
||||
using IntArray = Array <int>;
|
||||
}
|
||||
|
||||
using namespace cr::types;
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -1,230 +0,0 @@
|
|||
//
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2021 YaPB Project <yapb@jeefo.net>.
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <crlib/cr-memory.h>
|
||||
#include <crlib/cr-twin.h>
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
template <typename T> class Deque : private DenyCopying {
|
||||
private:
|
||||
size_t capacity_ {};
|
||||
T *contents_ {};
|
||||
|
||||
Twin <size_t, size_t> index_ {};
|
||||
|
||||
private:
|
||||
size_t pickFrontIndex () {
|
||||
if (index_.first == 0) {
|
||||
if (capacity_ && index_.second != capacity_ - 1) {
|
||||
return capacity_ - 1;
|
||||
}
|
||||
}
|
||||
else if (index_.first - 1 != index_.second) {
|
||||
return index_.first - 1;
|
||||
}
|
||||
extendCapacity ();
|
||||
|
||||
return capacity_ - 1;
|
||||
}
|
||||
|
||||
size_t pickRearIndex () {
|
||||
if (index_.second < index_.first) {
|
||||
if (index_.second + 1 != index_.first) {
|
||||
return index_.second + 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (index_.second + 1 < capacity_) {
|
||||
return index_.second + 1;
|
||||
}
|
||||
if (index_.first != 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
extendCapacity ();
|
||||
|
||||
return index_.second + 1;
|
||||
}
|
||||
|
||||
void extendCapacity () {
|
||||
auto capacity = capacity_ ? capacity_ * 2 : 8;
|
||||
auto contents = Memory::get <T> (sizeof (T) * capacity);
|
||||
|
||||
auto transfer = [] (T &dst, T &src) {
|
||||
Memory::construct (&dst, cr::move (src));
|
||||
Memory::destruct (&src);
|
||||
};
|
||||
|
||||
if (index_.first < index_.second) {
|
||||
for (size_t i = 0; i < index_.second - index_.first; ++i) {
|
||||
transfer (contents[i], contents_[index_.first + i]);
|
||||
}
|
||||
index_.second = index_.second - index_.first;
|
||||
index_.first = 0;
|
||||
}
|
||||
else {
|
||||
for (size_t i = 0; i < capacity_ - index_.first; ++i) {
|
||||
transfer (contents[i], contents_[index_.first + i]);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < index_.second; ++i) {
|
||||
transfer (contents[capacity_ - index_.first + i], contents_[i]);
|
||||
}
|
||||
index_.second = index_.second + (capacity_ - index_.first);
|
||||
index_.first = 0;
|
||||
}
|
||||
Memory::release (contents_);
|
||||
|
||||
contents_ = contents;
|
||||
capacity_ = capacity;
|
||||
}
|
||||
|
||||
void destroy () {
|
||||
auto destruct = [&] (size_t start, size_t end) {
|
||||
for (size_t i = start; i < end; ++i) {
|
||||
Memory::destruct (&contents_[i]);
|
||||
}
|
||||
};
|
||||
|
||||
if (index_.first <= index_.second) {
|
||||
destruct (index_.first, index_.second);
|
||||
}
|
||||
else {
|
||||
destruct (index_.first, capacity_);
|
||||
destruct (0, index_.second);
|
||||
}
|
||||
Memory::release (contents_);
|
||||
}
|
||||
|
||||
void reset () {
|
||||
contents_ = nullptr;
|
||||
capacity_ = 0;
|
||||
|
||||
clear ();
|
||||
}
|
||||
|
||||
public:
|
||||
explicit Deque () : capacity_ (0), contents_ (nullptr)
|
||||
{ }
|
||||
|
||||
Deque (Deque &&rhs) : contents_ (rhs.contents_), capacity_ (rhs.capacity_) {
|
||||
index_.first (rhs.index_.first);
|
||||
index_.second (rhs.index_.second);
|
||||
|
||||
rhs.reset ();
|
||||
}
|
||||
|
||||
~Deque () {
|
||||
destroy ();
|
||||
}
|
||||
|
||||
public:
|
||||
bool empty () const {
|
||||
return index_.first == index_.second;
|
||||
}
|
||||
|
||||
template <typename ...Args> void emplaceLast (Args &&...args) {
|
||||
auto rear = pickRearIndex ();
|
||||
|
||||
Memory::construct (&contents_[index_.second], cr::forward <Args> (args)...);
|
||||
index_.second = rear;
|
||||
}
|
||||
|
||||
template <typename ...Args> void emplaceFront (Args &&...args) {
|
||||
index_.first = pickFrontIndex ();
|
||||
Memory::construct (&contents_[index_.first], cr::forward <Args> (args)...);
|
||||
}
|
||||
|
||||
void discardFront () {
|
||||
Memory::destruct (&contents_[index_.first]);
|
||||
|
||||
if (index_.first == capacity_ - 1) {
|
||||
index_.first = 0;
|
||||
}
|
||||
else {
|
||||
index_.first++;
|
||||
}
|
||||
}
|
||||
|
||||
void discardLast () {
|
||||
if (index_.second == 0) {
|
||||
index_.second = capacity_ - 1;
|
||||
}
|
||||
else {
|
||||
index_.second--;
|
||||
}
|
||||
Memory::destruct (&contents_[index_.second]);
|
||||
}
|
||||
|
||||
T popFront () {
|
||||
auto object (front ());
|
||||
discardFront ();
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
T popLast () {
|
||||
auto object (last ());
|
||||
discardLast ();
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
public:
|
||||
const T &front () const {
|
||||
return contents_[index_.first];
|
||||
}
|
||||
|
||||
const T &last () const {
|
||||
if (index_.second == 0) {
|
||||
return contents_[capacity_ - 1];
|
||||
}
|
||||
return contents_[index_.second - 1];
|
||||
}
|
||||
|
||||
T &front () {
|
||||
return contents_[index_.first];
|
||||
}
|
||||
|
||||
T &last () {
|
||||
if (index_.second == 0) {
|
||||
return contents_[capacity_ - 1];
|
||||
}
|
||||
return contents_[index_.second - 1];
|
||||
}
|
||||
|
||||
size_t length () const {
|
||||
if (index_.first == index_.second) {
|
||||
return 0;
|
||||
}
|
||||
return index_.first < index_.second ? index_.second - index_.first : index_.second + (capacity_ - index_.first);
|
||||
}
|
||||
|
||||
void clear () {
|
||||
index_.first = 0;
|
||||
index_.second = 0;
|
||||
}
|
||||
|
||||
public:
|
||||
Deque &operator = (Deque &&rhs) {
|
||||
destroy ();
|
||||
|
||||
contents_ = rhs.contents_;
|
||||
capacity_ = rhs.capacity_;
|
||||
|
||||
index_.first = rhs.index_.first;
|
||||
index_.second = rhs.index_.second;
|
||||
|
||||
rhs.reset ();
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -1,249 +0,0 @@
|
|||
//
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2021 YaPB Project <yapb@jeefo.net>.
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <crlib/cr-basic.h>
|
||||
|
||||
#if !defined (CR_WINDOWS)
|
||||
# include <sys/mman.h>
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
// simple wrapper for critical sections
|
||||
class CriticalSection final : public DenyCopying {
|
||||
private:
|
||||
#if defined (CR_WINDOWS)
|
||||
CRITICAL_SECTION cs_;
|
||||
#else
|
||||
pthread_mutex_t mutex_;
|
||||
#endif
|
||||
|
||||
public:
|
||||
CriticalSection () {
|
||||
#if defined (CR_WINDOWS)
|
||||
InitializeCriticalSection (&cs_);
|
||||
#else
|
||||
pthread_mutex_init (&mutex_, nullptr);
|
||||
#endif
|
||||
}
|
||||
~CriticalSection () {
|
||||
#if defined (CR_WINDOWS)
|
||||
DeleteCriticalSection (&cs_);
|
||||
#else
|
||||
pthread_mutex_destroy (&mutex_);
|
||||
#endif
|
||||
}
|
||||
|
||||
void lock () {
|
||||
#if defined (CR_WINDOWS)
|
||||
EnterCriticalSection (&cs_);
|
||||
#else
|
||||
pthread_mutex_lock (&mutex_);
|
||||
#endif
|
||||
}
|
||||
|
||||
void unlock () {
|
||||
#if defined (CR_WINDOWS)
|
||||
LeaveCriticalSection (&cs_);
|
||||
#else
|
||||
pthread_mutex_unlock (&mutex_);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
// simple autolock wrapper
|
||||
class AutoLock final : public DenyCopying {
|
||||
private:
|
||||
CriticalSection *cs_;
|
||||
|
||||
public:
|
||||
AutoLock (CriticalSection *cs) : cs_ (cs) {
|
||||
cs_->lock ();
|
||||
}
|
||||
|
||||
~AutoLock () {
|
||||
cs_->unlock ();
|
||||
}
|
||||
};
|
||||
|
||||
// simple detour class for x86/x64
|
||||
template <typename T> class Detour final : public DenyCopying {
|
||||
private:
|
||||
enum : uint32 {
|
||||
PtrSize = sizeof (void *),
|
||||
|
||||
#if defined (CR_ARCH_X64)
|
||||
Offset = 2
|
||||
#else
|
||||
Offset = 1
|
||||
#endif
|
||||
};
|
||||
|
||||
#if defined (CR_ARCH_X64)
|
||||
using uintptr = uint64;
|
||||
#else
|
||||
using uintptr = uint32;
|
||||
#endif
|
||||
|
||||
private:
|
||||
CriticalSection cs_;
|
||||
|
||||
void *original_ = nullptr;
|
||||
void *detour_ = nullptr;
|
||||
|
||||
Array <uint8> savedBytes_ { };
|
||||
Array <uint8> jmpBuffer_
|
||||
|
||||
#ifdef CR_ARCH_X64
|
||||
{ 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0 };
|
||||
#else
|
||||
{ 0xb8, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0 };
|
||||
#endif
|
||||
|
||||
#if !defined (CR_WINDOWS)
|
||||
unsigned long pageSize_ { 0 };
|
||||
uintptr pageStart_ { 0 };
|
||||
#endif
|
||||
|
||||
bool overwritten_ { false };
|
||||
|
||||
private:
|
||||
bool overwriteMemory (const Array <uint8> &to, const bool overwritten) noexcept {
|
||||
overwritten_ = overwritten;
|
||||
|
||||
AutoLock lock (&cs_);
|
||||
#if defined (CR_WINDOWS)
|
||||
unsigned long oldProtect {};
|
||||
|
||||
if (VirtualProtect (original_, to.length (), PAGE_EXECUTE_READWRITE, &oldProtect)) {
|
||||
memcpy (original_, to.data (), to.length ());
|
||||
|
||||
// restore protection
|
||||
return VirtualProtect (original_, to.length (), oldProtect, &oldProtect);
|
||||
}
|
||||
#else
|
||||
if (mprotect (reinterpret_cast <void *> (pageStart_), pageSize_, PROT_READ | PROT_WRITE | PROT_EXEC) != -1) {
|
||||
memcpy (original_, to.data (), to.length ());
|
||||
|
||||
// restore protection
|
||||
return mprotect (reinterpret_cast <void *> (pageStart_), pageSize_, PROT_READ | PROT_EXEC) != -1;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
Detour () = default;
|
||||
|
||||
Detour (StringRef module, StringRef name, T *address) {
|
||||
initialize (module, name, address);
|
||||
}
|
||||
|
||||
~Detour () {
|
||||
restore ();
|
||||
|
||||
original_ = nullptr;
|
||||
detour_ = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
class DetourSwitch final {
|
||||
private:
|
||||
Detour <T> *detour_;
|
||||
|
||||
public:
|
||||
DetourSwitch (Detour *detour) : detour_ (detour) {
|
||||
detour_->restore ();
|
||||
}
|
||||
|
||||
~DetourSwitch () {
|
||||
detour_->detour ();
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
void initialize (StringRef module, StringRef name, T *address) {
|
||||
savedBytes_.resize (jmpBuffer_.length ());
|
||||
|
||||
#if !defined (CR_WINDOWS)
|
||||
(void) module;
|
||||
(void) name;
|
||||
|
||||
auto ptr = reinterpret_cast <uint8 *> (address);
|
||||
|
||||
while (*reinterpret_cast <uint16 *> (ptr) == 0x25ff) {
|
||||
ptr = **reinterpret_cast <uint8 ***> (ptr + 2);
|
||||
}
|
||||
|
||||
original_ = ptr;
|
||||
pageSize_ = static_cast <unsigned long> (sysconf (_SC_PAGE_SIZE));
|
||||
#else
|
||||
auto handle = GetModuleHandleA (module.chars ());
|
||||
|
||||
if (!handle) {
|
||||
original_ = reinterpret_cast <void *> (address);
|
||||
return;
|
||||
}
|
||||
original_ = reinterpret_cast <void *> (GetProcAddress (handle, name.chars ()));
|
||||
|
||||
if (!original_) {
|
||||
original_ = reinterpret_cast <void *> (address);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void install (void *detour, const bool enable = false) {
|
||||
if (!original_) {
|
||||
return;
|
||||
}
|
||||
detour_ = detour;
|
||||
|
||||
#if !defined (CR_WINDOWS)
|
||||
pageStart_ = reinterpret_cast <uintptr> (original_) & -pageSize_;
|
||||
#endif
|
||||
|
||||
memcpy (savedBytes_.data (), original_, savedBytes_.length ());
|
||||
memcpy (reinterpret_cast <void *> (reinterpret_cast <uintptr> (jmpBuffer_.data ()) + Offset), &detour_, PtrSize);
|
||||
|
||||
if (enable) {
|
||||
this->detour ();
|
||||
}
|
||||
}
|
||||
|
||||
bool valid () const {
|
||||
return original_ && detour_;
|
||||
}
|
||||
|
||||
bool detoured () const {
|
||||
return overwritten_;
|
||||
}
|
||||
|
||||
bool detour () {
|
||||
if (!valid ()) {
|
||||
return false;
|
||||
}
|
||||
return overwriteMemory (jmpBuffer_, true);
|
||||
}
|
||||
|
||||
bool restore () {
|
||||
if (!valid ()) {
|
||||
return false;
|
||||
}
|
||||
return overwriteMemory (savedBytes_, false);
|
||||
}
|
||||
|
||||
template <typename... Args > decltype (auto) operator () (Args &&...args) {
|
||||
DetourSwitch sw (this);
|
||||
return reinterpret_cast <T *> (original_) (args...);
|
||||
}
|
||||
};
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -1,389 +0,0 @@
|
|||
//
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2021 YaPB Project <yapb@jeefo.net>.
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <crlib/cr-string.h>
|
||||
#include <crlib/cr-lambda.h>
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
// simple stdio file wrapper
|
||||
class File final : private DenyCopying {
|
||||
private:
|
||||
FILE *handle_ = nullptr;
|
||||
size_t length_ {};
|
||||
|
||||
public:
|
||||
explicit File () = default;
|
||||
|
||||
File (StringRef file, StringRef mode = "rt") {
|
||||
open (file, mode);
|
||||
}
|
||||
|
||||
~File () {
|
||||
close ();
|
||||
}
|
||||
|
||||
public:
|
||||
bool open (StringRef file, StringRef mode) {
|
||||
if (!openFile (file, mode)) {
|
||||
return false;
|
||||
}
|
||||
fseek (handle_, 0L, SEEK_END);
|
||||
length_ = ftell (handle_);
|
||||
fseek (handle_, 0L, SEEK_SET);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void close () {
|
||||
if (handle_ != nullptr) {
|
||||
fclose (handle_);
|
||||
handle_ = nullptr;
|
||||
}
|
||||
length_ = 0;
|
||||
}
|
||||
|
||||
bool eof () const {
|
||||
return !!feof (handle_);
|
||||
}
|
||||
|
||||
bool flush () const {
|
||||
return !!fflush (handle_);
|
||||
}
|
||||
|
||||
int get () const {
|
||||
return fgetc (handle_);
|
||||
}
|
||||
|
||||
char *getString (char *buffer, int count) const {
|
||||
return fgets (buffer, count, handle_);
|
||||
}
|
||||
|
||||
bool getLine (String &line) {
|
||||
int ch = 0;
|
||||
SmallArray <char> data (255);
|
||||
|
||||
line.clear ();
|
||||
|
||||
while ((ch = get ()) != EOF && !eof ()) {
|
||||
data.push (static_cast <char> (ch));
|
||||
|
||||
if (ch == '\n') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!data.empty ()) {
|
||||
line.assign (data.data (), data.length ());
|
||||
}
|
||||
return !line.empty ();
|
||||
}
|
||||
|
||||
template <typename ...Args> size_t puts (const char *fmt, Args &&...args) {
|
||||
if (!*this) {
|
||||
return 0;
|
||||
}
|
||||
return fputs (strings.format (fmt, cr::forward <Args> (args)...), handle_);
|
||||
}
|
||||
|
||||
bool puts (const char *buffer) {
|
||||
if (!*this) {
|
||||
return 0;
|
||||
}
|
||||
if (fputs (buffer, handle_) < 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int putChar (int ch) {
|
||||
return fputc (ch, handle_);
|
||||
}
|
||||
|
||||
size_t read (void *buffer, size_t size, size_t count = 1) {
|
||||
return fread (buffer, size, count, handle_);
|
||||
}
|
||||
|
||||
size_t write (void *buffer, size_t size, size_t count = 1) {
|
||||
return fwrite (buffer, size, count, handle_);
|
||||
}
|
||||
|
||||
bool seek (long offset, int origin) {
|
||||
if (fseek (handle_, offset, origin) != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void rewind () {
|
||||
::rewind (handle_);
|
||||
}
|
||||
|
||||
size_t length () const {
|
||||
return length_;
|
||||
}
|
||||
|
||||
public:
|
||||
explicit operator bool () const {
|
||||
return handle_ != nullptr;
|
||||
}
|
||||
|
||||
public:
|
||||
static inline bool exists (StringRef file) {
|
||||
File fp;
|
||||
|
||||
if (fp.open (file, "rb")) {
|
||||
fp.close ();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void createPath (const char *path) {
|
||||
for (auto str = const_cast <char *> (path) + 1; *str; ++str) {
|
||||
if (*str == '/') {
|
||||
*str = 0;
|
||||
plat.createDirectory (path);
|
||||
*str = '/';
|
||||
}
|
||||
}
|
||||
plat.createDirectory (path);
|
||||
}
|
||||
|
||||
private:
|
||||
bool openFile (StringRef filename, StringRef mode) {
|
||||
if (*this) {
|
||||
close ();
|
||||
}
|
||||
|
||||
#if defined (CR_WINDOWS)
|
||||
fopen_s (&handle_, filename.chars (), mode.chars ());
|
||||
#else
|
||||
handle_ = fopen (filename.chars (), mode.chars ());
|
||||
#endif
|
||||
return handle_ != nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
// wrapper for memory file for loading data into the memory
|
||||
class MemFileStorage : public Singleton <MemFileStorage> {
|
||||
private:
|
||||
using LoadFunction = Lambda <uint8 * (const char *, int *)>;
|
||||
using FreeFunction = Lambda <void (void *)>;
|
||||
|
||||
private:
|
||||
LoadFunction loadFun_ = nullptr;
|
||||
FreeFunction freeFun_ = nullptr;
|
||||
|
||||
public:
|
||||
explicit MemFileStorage () = default;
|
||||
~MemFileStorage () = default;
|
||||
|
||||
public:
|
||||
void initizalize (LoadFunction loader, FreeFunction unloader) {
|
||||
loadFun_ = cr::move (loader);
|
||||
freeFun_ = cr::move (unloader);
|
||||
}
|
||||
|
||||
public:
|
||||
uint8 *load (StringRef file, int *size) {
|
||||
if (loadFun_) {
|
||||
return loadFun_ (file.chars (), size);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void unload (void *buffer) {
|
||||
if (freeFun_) {
|
||||
freeFun_ (buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
static uint8 *defaultLoad (const char *path, int *size) {
|
||||
File file (path, "rb");
|
||||
|
||||
if (!file) {
|
||||
*size = 0;
|
||||
return nullptr;
|
||||
}
|
||||
*size = static_cast <int> (file.length ());
|
||||
auto data = Memory::get <uint8> (*size);
|
||||
|
||||
file.read (data, *size);
|
||||
return data;
|
||||
}
|
||||
|
||||
static void defaultUnload (void *buffer) {
|
||||
Memory::release (buffer);
|
||||
}
|
||||
|
||||
static String loadToString (StringRef filename) {
|
||||
int32 result = 0;
|
||||
auto buffer = defaultLoad (filename.chars (), &result);
|
||||
|
||||
if (result > 0 && buffer) {
|
||||
String data (reinterpret_cast <char *> (buffer), result);
|
||||
defaultUnload (buffer);
|
||||
|
||||
return data;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
class MemFile final : public DenyCopying {
|
||||
private:
|
||||
enum : char {
|
||||
Eof = static_cast <char> (-1)
|
||||
};
|
||||
|
||||
private:
|
||||
uint8 *contents_ = nullptr;
|
||||
size_t length_ {};
|
||||
size_t seek_ {};
|
||||
|
||||
public:
|
||||
explicit MemFile () = default;
|
||||
|
||||
MemFile (StringRef file) {
|
||||
open (file);
|
||||
}
|
||||
|
||||
~MemFile () {
|
||||
close ();
|
||||
}
|
||||
|
||||
public:
|
||||
bool open (StringRef file) {
|
||||
length_ = 0;
|
||||
seek_ = 0;
|
||||
contents_ = MemFileStorage::instance ().load (file.chars (), reinterpret_cast <int *> (&length_));
|
||||
|
||||
if (!contents_) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void close () {
|
||||
MemFileStorage::instance ().unload (contents_);
|
||||
|
||||
length_ = 0;
|
||||
seek_ = 0;
|
||||
contents_ = nullptr;
|
||||
}
|
||||
|
||||
char get () {
|
||||
if (!contents_ || seek_ >= length_) {
|
||||
return Eof;
|
||||
}
|
||||
return static_cast <char> (contents_[seek_++]);
|
||||
}
|
||||
|
||||
char *getString (char *buffer, size_t count) {
|
||||
if (!contents_ || seek_ >= length_) {
|
||||
return nullptr;
|
||||
}
|
||||
size_t index = 0;
|
||||
buffer[0] = 0;
|
||||
|
||||
for (; index < count - 1;) {
|
||||
if (seek_ < length_) {
|
||||
buffer[index] = contents_[seek_++];
|
||||
|
||||
if (buffer[index++] == '\n') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
buffer[index] = 0;
|
||||
return index ? buffer : nullptr;
|
||||
}
|
||||
|
||||
bool getLine (String &line) {
|
||||
char ch;
|
||||
SmallArray <char> data (255);
|
||||
|
||||
line.clear ();
|
||||
|
||||
while ((ch = get ()) != Eof && !eof ()) {
|
||||
data.push (ch);
|
||||
|
||||
if (ch == '\n') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!data.empty ()) {
|
||||
line.assign (data.data (), data.length ());
|
||||
}
|
||||
return !line.empty ();
|
||||
}
|
||||
|
||||
size_t read (void *buffer, size_t size, size_t count = 1) {
|
||||
if (!contents_ || length_ <= seek_ || !buffer || !size || !count) {
|
||||
return 0;
|
||||
}
|
||||
size_t blocksRead = size * count <= length_ - seek_ ? size * count : length_ - seek_;
|
||||
|
||||
memcpy (buffer, &contents_[seek_], blocksRead);
|
||||
seek_ += blocksRead;
|
||||
|
||||
return blocksRead / size;
|
||||
}
|
||||
|
||||
bool seek (size_t offset, int origin) {
|
||||
if (!contents_ || seek_ >= length_) {
|
||||
return false;
|
||||
}
|
||||
if (origin == SEEK_SET) {
|
||||
if (offset >= length_) {
|
||||
return false;
|
||||
}
|
||||
seek_ = offset;
|
||||
}
|
||||
else if (origin == SEEK_END) {
|
||||
if (offset >= length_) {
|
||||
return false;
|
||||
}
|
||||
seek_ = length_ - offset;
|
||||
}
|
||||
else {
|
||||
if (seek_ + offset >= length_) {
|
||||
return false;
|
||||
}
|
||||
seek_ += offset;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t length () const {
|
||||
return length_;
|
||||
}
|
||||
|
||||
bool eof () const {
|
||||
return seek_ >= length_;
|
||||
}
|
||||
|
||||
void rewind () {
|
||||
seek_ = 0;
|
||||
}
|
||||
|
||||
public:
|
||||
explicit operator bool () const {
|
||||
return !!contents_ && length_ > 0;
|
||||
}
|
||||
};
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -1,236 +0,0 @@
|
|||
//
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2021 YaPB Project <yapb@jeefo.net>.
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <crlib/cr-basic.h>
|
||||
#include <crlib/cr-array.h>
|
||||
#include <crlib/cr-string.h>
|
||||
#include <crlib/cr-twin.h>
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
template <typename T> struct Hash;
|
||||
|
||||
template <> struct Hash <String> {
|
||||
uint32 operator () (const String &key) const noexcept {
|
||||
return key.hash ();
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct Hash <StringRef> {
|
||||
uint32 operator () (const StringRef &key) const noexcept {
|
||||
return key.hash ();
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct Hash <const char *> {
|
||||
uint32 operator () (const char *key) const noexcept {
|
||||
return StringRef::fnv1a32 (key);
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct Hash <int32> {
|
||||
uint32 operator () (int32 key) const noexcept {
|
||||
auto result = static_cast <uint32> (key);
|
||||
|
||||
result = ((result >> 16) ^ result) * 0x119de1f3;
|
||||
result = ((result >> 16) ^ result) * 0x119de1f3;
|
||||
result = (result >> 16) ^ result;
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> struct EmptyHash {
|
||||
uint32 operator () (T key) const noexcept {
|
||||
return static_cast <uint32> (key);
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
template <typename K, typename V> struct HashEntry final : DenyCopying {
|
||||
public:
|
||||
K key {};
|
||||
V value {};
|
||||
bool used { false };
|
||||
|
||||
public:
|
||||
HashEntry () = default;
|
||||
~HashEntry () = default;
|
||||
|
||||
public:
|
||||
HashEntry (HashEntry &&rhs) noexcept : used (rhs.used), key (cr::move (rhs.key)), value (cr::move (rhs.value))
|
||||
{ }
|
||||
|
||||
public:
|
||||
HashEntry &operator = (HashEntry &&rhs) noexcept {
|
||||
if (this != &rhs) {
|
||||
key = cr::move (rhs.key);
|
||||
value = cr::move (rhs.value);
|
||||
used = rhs.used;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template <typename K, typename V, typename H = Hash <K>> class HashMap final : public DenyCopying {
|
||||
public:
|
||||
using Entries = detail::HashEntry <K, V> [];
|
||||
|
||||
private:
|
||||
size_t capacity_ {};
|
||||
size_t length_ {};
|
||||
H hash_;
|
||||
|
||||
UniquePtr <Entries> contents_;
|
||||
|
||||
public:
|
||||
explicit HashMap (const size_t capacity = 3) : capacity_ (capacity), length_ (0) {
|
||||
contents_ = cr::makeUnique <Entries> (capacity);
|
||||
}
|
||||
|
||||
HashMap (HashMap &&rhs) noexcept : contents_ (cr::move (rhs.contents_)), hash_ (cr::move (rhs.hash_)), capacity_ (rhs.capacity_), length_ (rhs.length_)
|
||||
{ }
|
||||
|
||||
~HashMap () = default;
|
||||
|
||||
private:
|
||||
size_t getIndex (const K &key, size_t length) const {
|
||||
return hash_ (key) % length;
|
||||
}
|
||||
|
||||
void rehash (size_t targetCapacity) {
|
||||
if (length_ + targetCapacity < capacity_) {
|
||||
return;
|
||||
}
|
||||
auto capacity = capacity_ ? capacity_ : 3;
|
||||
|
||||
while (length_ + targetCapacity > capacity) {
|
||||
capacity *= 2;
|
||||
}
|
||||
auto contents = cr::makeUnique <Entries> (capacity);
|
||||
|
||||
for (size_t i = 0; i < capacity_; ++i) {
|
||||
if (contents_[i].used) {
|
||||
auto result = put (contents_[i].key, contents, capacity);
|
||||
contents[result.second].value = cr::move (contents_[i].value);
|
||||
}
|
||||
}
|
||||
contents_ = cr::move (contents);
|
||||
capacity_ = capacity;
|
||||
}
|
||||
|
||||
Twin <bool, size_t> put (const K &key, UniquePtr <Entries> &contents, const size_t capacity) {
|
||||
size_t index = getIndex (key, capacity);
|
||||
|
||||
for (size_t i = 0; i < capacity; ++i) {
|
||||
if (!contents[index].used) {
|
||||
contents[index].key = key;
|
||||
contents[index].used = true;
|
||||
|
||||
return { true, index };
|
||||
}
|
||||
|
||||
if (contents[index].key == key) {
|
||||
return { false, index };
|
||||
}
|
||||
index++;
|
||||
|
||||
if (index == capacity) {
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
return { false, 0 };
|
||||
}
|
||||
|
||||
public:
|
||||
bool empty () const {
|
||||
return !length_;
|
||||
}
|
||||
|
||||
size_t length () const {
|
||||
return length_;
|
||||
}
|
||||
|
||||
bool has (const K &key) const {
|
||||
if (empty ()) {
|
||||
return false;
|
||||
}
|
||||
size_t index = getIndex (key, capacity_);
|
||||
|
||||
for (size_t i = 0; i < capacity_; ++i) {
|
||||
if (contents_[index].used && contents_[index].key == key) {
|
||||
return true;
|
||||
}
|
||||
if (++index == capacity_) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void erase (const K &key) {
|
||||
size_t index = getIndex (key, capacity_);
|
||||
|
||||
for (size_t i = 0; i < capacity_; ++i) {
|
||||
if (contents_[index].used && contents_[index].key == key) {
|
||||
contents_[index].used = false;
|
||||
--length_;
|
||||
|
||||
break;
|
||||
}
|
||||
if (++index == capacity_) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void clear () {
|
||||
length_ = 0;
|
||||
|
||||
for (size_t i = 0; i < capacity_; ++i) {
|
||||
contents_[i].used = false;
|
||||
}
|
||||
rehash (0);
|
||||
}
|
||||
|
||||
void foreach (Lambda <void (const K &, const V &)> callback) {
|
||||
for (size_t i = 0; i < capacity_; ++i) {
|
||||
if (contents_[i].used) {
|
||||
callback (contents_[i].key, contents_[i].value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
V &operator [] (const K &key) {
|
||||
if (length_ >= capacity_) {
|
||||
rehash (length_ << 1);
|
||||
}
|
||||
auto result = put (key, contents_, capacity_);
|
||||
|
||||
if (result.first) {
|
||||
++length_;
|
||||
}
|
||||
return contents_[result.second].value;
|
||||
}
|
||||
|
||||
HashMap &operator = (HashMap &&rhs) noexcept {
|
||||
if (this != &rhs) {
|
||||
contents_ = cr::move (rhs.contents_);
|
||||
hash_ = cr::move (rhs.hash_);
|
||||
|
||||
length_ = rhs.length_;
|
||||
capacity_ = rhs.capacity_;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -1,515 +0,0 @@
|
|||
//
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2021 YaPB Project <yapb@jeefo.net>.
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <crlib/cr-string.h>
|
||||
#include <crlib/cr-files.h>
|
||||
#include <crlib/cr-logger.h>
|
||||
#include <crlib/cr-twin.h>
|
||||
#include <crlib/cr-platform.h>
|
||||
#include <crlib/cr-uniqueptr.h>
|
||||
#include <crlib/cr-random.h>
|
||||
|
||||
#if defined (CR_LINUX) || defined (CR_OSX)
|
||||
# include <netinet/in.h>
|
||||
# include <sys/socket.h>
|
||||
# include <sys/types.h>
|
||||
# include <sys/uio.h>
|
||||
# include <arpa/inet.h>
|
||||
# include <unistd.h>
|
||||
# include <errno.h>
|
||||
# include <netdb.h>
|
||||
# include <fcntl.h>
|
||||
#elif defined (CR_WINDOWS)
|
||||
# include <winsock2.h>
|
||||
# include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
// status codes for http client
|
||||
CR_DECLARE_SCOPED_ENUM (HttpClientResult,
|
||||
Continue = 100,
|
||||
SwitchingProtocol = 101,
|
||||
Processing = 102,
|
||||
EarlyHints = 103,
|
||||
|
||||
Ok = 200,
|
||||
Created = 201,
|
||||
Accepted = 202,
|
||||
NonAuthoritativeInformation = 203,
|
||||
NoContent = 204,
|
||||
ResetContent = 205,
|
||||
PartialContent = 206,
|
||||
MultiStatus = 207,
|
||||
AlreadyReported = 208,
|
||||
ImUsed = 226,
|
||||
|
||||
MultipleChoice = 300,
|
||||
MovedPermanently = 301,
|
||||
Found = 302,
|
||||
SeeOther = 303,
|
||||
NotModified = 304,
|
||||
UseProxy = 305,
|
||||
TemporaryRedirect = 307,
|
||||
PermanentRedirect = 308,
|
||||
|
||||
BadRequest = 400,
|
||||
Unauthorized = 401,
|
||||
PaymentRequired = 402,
|
||||
Forbidden = 403,
|
||||
NotFound = 404,
|
||||
MethodNotAllowed = 405,
|
||||
NotAcceptable = 406,
|
||||
ProxyAuthenticationRequired = 407,
|
||||
RequestTimeout = 408,
|
||||
Conflict = 409,
|
||||
Gone = 410,
|
||||
LengthRequired = 411,
|
||||
PreconditionFailed = 412,
|
||||
PayloadTooLarge = 413,
|
||||
UriTooLong = 414,
|
||||
UnsupportedMediaType = 415,
|
||||
RangeNotSatisfiable = 416,
|
||||
ExpectationFailed = 417,
|
||||
ImaTeapot = 418,
|
||||
MisdirectedRequest = 421,
|
||||
UnprocessableEntity = 422,
|
||||
Locked = 423,
|
||||
FailedDependency = 424,
|
||||
TooEarly = 425,
|
||||
UpgradeRequired = 426,
|
||||
PreconditionRequired = 428,
|
||||
TooManyRequests = 429,
|
||||
RequestHeaderFieldsTooLarge = 431,
|
||||
UnavailableForLegalReasons = 451,
|
||||
|
||||
InternalServerError = 500,
|
||||
NotImplemented = 501,
|
||||
BadGateway = 502,
|
||||
ServiceUnavailable = 503,
|
||||
GatewayTimeout = 504,
|
||||
HttpVersionNotSupported = 505,
|
||||
VariantAlsoNegotiates = 506,
|
||||
InsufficientStorage = 507,
|
||||
LoopDetected = 508,
|
||||
NotExtended = 510,
|
||||
NetworkAuthenticationRequired = 511,
|
||||
|
||||
SocketError = -1,
|
||||
ConnectError = -2,
|
||||
HttpOnly = -3,
|
||||
Undefined = -4,
|
||||
NoLocalFile = -5,
|
||||
LocalFileExists = -6
|
||||
)
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
namespace detail {
|
||||
|
||||
// simple http uri omitting query-string and port
|
||||
struct HttpUri {
|
||||
String path, protocol, host;
|
||||
|
||||
public:
|
||||
static HttpUri parse (StringRef uri) {
|
||||
HttpUri result;
|
||||
|
||||
if (uri.empty ()) {
|
||||
return result;
|
||||
}
|
||||
size_t protocol = uri.find ("://");
|
||||
|
||||
if (protocol != String::InvalidIndex) {
|
||||
result.protocol = uri.substr (0, protocol);
|
||||
|
||||
size_t hostIndex = uri.find ("/", protocol + 3);
|
||||
|
||||
if (hostIndex != String::InvalidIndex) {
|
||||
result.path = uri.substr (hostIndex + 1);
|
||||
result.host = uri.substr (protocol + 3, hostIndex - protocol - 3);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
struct SocketInit {
|
||||
public:
|
||||
static void start () {
|
||||
#if defined(CR_WINDOWS)
|
||||
WSADATA wsa;
|
||||
|
||||
if (WSAStartup (MAKEWORD (2, 2), &wsa) != 0) {
|
||||
logger.error ("Unable to inialize sockets.");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
class Socket final : public DenyCopying {
|
||||
private:
|
||||
int32 socket_;
|
||||
uint32 timeout_;
|
||||
|
||||
public:
|
||||
Socket () : socket_ (-1), timeout_ (2)
|
||||
{ }
|
||||
|
||||
~Socket () {
|
||||
disconnect ();
|
||||
}
|
||||
|
||||
public:
|
||||
bool connect (StringRef hostname) {
|
||||
addrinfo hints {}, *result = nullptr;
|
||||
plat.bzero (&hints, sizeof (hints));
|
||||
|
||||
constexpr auto NumericServ = 0x00000008;
|
||||
|
||||
hints.ai_flags = NumericServ;
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
if (getaddrinfo (hostname.chars (), "80", &hints, &result) != 0) {
|
||||
return false;
|
||||
}
|
||||
socket_ = static_cast <int> (socket (result->ai_family, result->ai_socktype, 0));
|
||||
|
||||
if (socket_ < 0) {
|
||||
freeaddrinfo (result);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto getTimeouts = [&]() -> Twin <char *, int32> {
|
||||
#if defined (CR_WINDOWS)
|
||||
DWORD tv = timeout_ * 1000;
|
||||
#else
|
||||
timeval tv { static_cast <time_t> (timeout_), 0 };
|
||||
#endif
|
||||
return { reinterpret_cast <char *> (&tv), static_cast <int32> (sizeof (tv)) };
|
||||
};
|
||||
auto timeouts = getTimeouts ();
|
||||
|
||||
if (setsockopt (socket_, SOL_SOCKET, SO_RCVTIMEO, timeouts.first, timeouts.second) == -1) {
|
||||
logger.message ("Unable to set SO_RCVTIMEO.");
|
||||
}
|
||||
|
||||
if (setsockopt (socket_, SOL_SOCKET, SO_SNDTIMEO, timeouts.first, timeouts.second) == -1) {
|
||||
logger.message ("Unable to set SO_SNDTIMEO.");
|
||||
}
|
||||
|
||||
if (::connect (socket_, result->ai_addr, static_cast <int32> (result->ai_addrlen)) == -1) {
|
||||
disconnect ();
|
||||
freeaddrinfo (result);
|
||||
|
||||
return false;
|
||||
}
|
||||
freeaddrinfo (result);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void setTimeout (uint32 timeout) {
|
||||
timeout_ = timeout;
|
||||
}
|
||||
|
||||
void disconnect () {
|
||||
#if defined(CR_WINDOWS)
|
||||
if (socket_ != -1) {
|
||||
closesocket (socket_);
|
||||
}
|
||||
#else
|
||||
if (socket_ != -1)
|
||||
close (socket_);
|
||||
#endif
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename U> int32 send (const U *buffer, int32 length) const {
|
||||
return ::send (socket_, reinterpret_cast <const char *> (buffer), length, 0);
|
||||
}
|
||||
|
||||
template <typename U> int32 recv (U *buffer, int32 length) {
|
||||
return ::recv (socket_, reinterpret_cast <char *> (buffer), length, 0);
|
||||
}
|
||||
|
||||
public:
|
||||
static int32 CR_STDCALL sendto (int socket, const void *message, size_t length, int flags, const struct sockaddr *dest, int32 destLength) {
|
||||
#if defined (CR_WINDOWS)
|
||||
WSABUF buffer = { static_cast <ULONG> (length), const_cast <char *> (reinterpret_cast <const char *> (message)) };
|
||||
DWORD sendLength = 0;
|
||||
|
||||
if (WSASendTo (socket, &buffer, 1, &sendLength, flags, dest, destLength, NULL, NULL) == SOCKET_ERROR) {
|
||||
errno = WSAGetLastError ();
|
||||
return -1;
|
||||
}
|
||||
return static_cast <int32> (sendLength);
|
||||
#else
|
||||
iovec iov = { const_cast <void *> (message), length };
|
||||
msghdr msg {};
|
||||
|
||||
msg.msg_name = reinterpret_cast <void *> (const_cast <struct sockaddr *> (dest));
|
||||
msg.msg_namelen = destLength;
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
return sendmsg (socket, &msg, flags);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
// simple http client for downloading/uploading files only
|
||||
class HttpClient final : public Singleton <HttpClient> {
|
||||
private:
|
||||
enum : int32 {
|
||||
MaxReceiveErrors = 12,
|
||||
DefaultSocketTimeout = 32
|
||||
};
|
||||
|
||||
private:
|
||||
String userAgent_ = "crlib";
|
||||
HttpClientResult statusCode_ = HttpClientResult::Undefined;
|
||||
int32 chunkSize_ = 4096;
|
||||
bool initialized_ = false;
|
||||
|
||||
public:
|
||||
HttpClient () = default;
|
||||
~HttpClient () = default;
|
||||
|
||||
private:
|
||||
HttpClientResult parseResponseHeader (Socket *socket, uint8 *buffer) {
|
||||
bool isFinished = false;
|
||||
int32 pos = 0, symbols = 0, errors = 0;
|
||||
|
||||
// prase response header
|
||||
while (!isFinished && pos < chunkSize_) {
|
||||
if (socket->recv (&buffer[pos], 1) < 1) {
|
||||
if (++errors > MaxReceiveErrors) {
|
||||
isFinished = true;
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
switch (buffer[pos]) {
|
||||
case '\r':
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
isFinished = (symbols == 0);
|
||||
symbols = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
++symbols;
|
||||
break;
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
String response { reinterpret_cast <const char *> (buffer) };
|
||||
size_t responseCodeStart = response.find ("HTTP/1.1");
|
||||
|
||||
if (responseCodeStart != String::InvalidIndex) {
|
||||
String respCode = response.substr (responseCodeStart + 9, 3);
|
||||
respCode.trim ();
|
||||
|
||||
return static_cast <HttpClientResult> (respCode.int_ ());
|
||||
}
|
||||
return HttpClientResult::NotFound;
|
||||
}
|
||||
|
||||
public:
|
||||
void startup () {
|
||||
detail::SocketInit::start ();
|
||||
initialized_ = true;
|
||||
}
|
||||
|
||||
// simple blocked download
|
||||
bool downloadFile (StringRef url, StringRef localPath, int32 timeout = DefaultSocketTimeout) {
|
||||
if (plat.win && !initialized_) {
|
||||
plat.abort ("Sockets not initialized.");
|
||||
}
|
||||
|
||||
if (File::exists (localPath)) {
|
||||
statusCode_ = HttpClientResult::LocalFileExists;
|
||||
return false;
|
||||
}
|
||||
auto uri = detail::HttpUri::parse (url);
|
||||
auto socket = cr::makeUnique <Socket> ();
|
||||
|
||||
// no https...
|
||||
if (uri.protocol == "https") {
|
||||
statusCode_ = HttpClientResult::HttpOnly;
|
||||
return false;
|
||||
}
|
||||
socket->setTimeout (timeout);
|
||||
|
||||
// unable to connect...
|
||||
if (!socket->connect (uri.host)) {
|
||||
statusCode_ = HttpClientResult::ConnectError;
|
||||
return false;
|
||||
}
|
||||
|
||||
String request;
|
||||
request.appendf ("GET /%s HTTP/1.1\r\n", uri.path);
|
||||
request.append ("Accept: */*\r\n");
|
||||
request.append ("Connection: close\r\n");
|
||||
request.append ("Keep-Alive: 115\r\n");
|
||||
request.appendf ("User-Agent: %s\r\n", userAgent_);
|
||||
request.appendf ("Host: %s\r\n\r\n", uri.host);
|
||||
|
||||
if (socket->send (request.chars (), static_cast <int32> (request.length ())) < 1) {
|
||||
statusCode_ = HttpClientResult::SocketError;
|
||||
|
||||
return false;
|
||||
}
|
||||
SmallArray <uint8> buffer (chunkSize_);
|
||||
statusCode_ = parseResponseHeader (socket.get (), buffer.data ());
|
||||
|
||||
if (statusCode_ != HttpClientResult::Ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// receive the file
|
||||
File file (localPath, "wb");
|
||||
|
||||
if (!file) {
|
||||
statusCode_ = HttpClientResult::Undefined;
|
||||
return false;
|
||||
}
|
||||
int32 length = 0;
|
||||
int32 errors = 0;
|
||||
|
||||
for (;;) {
|
||||
length = socket->recv (buffer.data (), chunkSize_);
|
||||
|
||||
if (length > 0) {
|
||||
file.write (buffer.data (), length);
|
||||
}
|
||||
else if (++errors > 12) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
statusCode_ = HttpClientResult::Ok;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool uploadFile (StringRef url, StringRef localPath, const int32 timeout = DefaultSocketTimeout) {
|
||||
if (plat.win && !initialized_) {
|
||||
plat.abort ("Sockets not initialized.");
|
||||
}
|
||||
|
||||
if (!File::exists (localPath)) {
|
||||
statusCode_ = HttpClientResult::NoLocalFile;
|
||||
return false;
|
||||
}
|
||||
auto uri = detail::HttpUri::parse (url);
|
||||
auto socket = cr::makeUnique <Socket> ();
|
||||
|
||||
// no https...
|
||||
if (uri.protocol == "https") {
|
||||
statusCode_ = HttpClientResult::HttpOnly;
|
||||
return false;
|
||||
}
|
||||
socket->setTimeout (timeout);
|
||||
|
||||
// unable to connect...
|
||||
if (!socket->connect (uri.host)) {
|
||||
statusCode_ = HttpClientResult::ConnectError;
|
||||
return false;
|
||||
}
|
||||
|
||||
// receive the file
|
||||
File file (localPath, "rb");
|
||||
|
||||
if (!file) {
|
||||
statusCode_ = HttpClientResult::Undefined;
|
||||
return false;
|
||||
}
|
||||
String boundaryName = localPath;
|
||||
size_t boundarySlash = localPath.findLastOf ("\\/");
|
||||
|
||||
if (boundarySlash != String::InvalidIndex) {
|
||||
boundaryName = localPath.substr (boundarySlash + 1);
|
||||
}
|
||||
StringRef boundaryLine = strings.format ("---crlib_upload_boundary_%d%d%d%d", rg.get (0, 9), rg.get (0, 9), rg.get (0, 9), rg.get (0, 9));
|
||||
|
||||
String request, start, end;
|
||||
start.appendf ("--%s\r\n", boundaryLine);
|
||||
start.appendf ("Content-Disposition: form-data; name='file'; filename='%s'\r\n", boundaryName);
|
||||
start.append ("Content-Type: application/octet-stream\r\n\r\n");
|
||||
|
||||
end.appendf ("\r\n--%s--\r\n\r\n", boundaryLine);
|
||||
|
||||
request.appendf ("POST /%s HTTP/1.1\r\n", uri.path);
|
||||
request.appendf ("Host: %s\r\n", uri.host);
|
||||
request.appendf ("User-Agent: %s\r\n", userAgent_);
|
||||
request.appendf ("Content-Type: multipart/form-data; boundary=%s\r\n", boundaryLine);
|
||||
request.appendf ("Content-Length: %d\r\n\r\n", file.length () + start.length () + end.length ());
|
||||
|
||||
// send the main request
|
||||
if (socket->send (request.chars (), static_cast <int32> (request.length ())) < 1) {
|
||||
statusCode_ = HttpClientResult::SocketError;
|
||||
return false;
|
||||
}
|
||||
|
||||
// send boundary start
|
||||
if (socket->send (start.chars (), static_cast <int32> (start.length ())) < 1) {
|
||||
statusCode_ = HttpClientResult::SocketError;
|
||||
|
||||
return false;
|
||||
}
|
||||
SmallArray <uint8> buffer (chunkSize_);
|
||||
int32 length = 0;
|
||||
|
||||
for (;;) {
|
||||
length = static_cast <int32> (file.read (buffer.data (), 1, chunkSize_));
|
||||
|
||||
if (length > 0) {
|
||||
socket->send (buffer.data (), length);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// send boundary end
|
||||
if (socket->send (end.chars (), static_cast <int32> (end.length ())) < 1) {
|
||||
statusCode_ = HttpClientResult::SocketError;
|
||||
return false;
|
||||
}
|
||||
statusCode_ = parseResponseHeader (socket.get (), buffer.data ());
|
||||
|
||||
return statusCode_ == HttpClientResult::Ok;
|
||||
}
|
||||
|
||||
public:
|
||||
void setUserAgent (StringRef ua) {
|
||||
userAgent_ = ua;
|
||||
}
|
||||
|
||||
HttpClientResult getLastStatusCode () {
|
||||
return statusCode_;
|
||||
}
|
||||
|
||||
void setChunkSize (int32 chunkSize) {
|
||||
chunkSize_ = chunkSize;
|
||||
}
|
||||
};
|
||||
|
||||
// expose global http client
|
||||
CR_EXPOSE_GLOBAL_SINGLETON (HttpClient, http);
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -1,169 +0,0 @@
|
|||
//
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2021 YaPB Project <yapb@jeefo.net>.
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <crlib/cr-memory.h>
|
||||
#include <crlib/cr-uniqueptr.h>
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
template <typename> class Lambda;
|
||||
template <typename R, typename ...Args> class Lambda <R (Args...)> {
|
||||
private:
|
||||
enum : uint32 {
|
||||
LamdaSmallBufferLength = sizeof (void *) * 16
|
||||
};
|
||||
|
||||
private:
|
||||
class LambdaFunctorWrapper {
|
||||
public:
|
||||
LambdaFunctorWrapper () = default;
|
||||
virtual ~LambdaFunctorWrapper () = default;
|
||||
|
||||
public:
|
||||
virtual void move (uint8 *to) = 0;
|
||||
virtual void small (uint8 *to) const = 0;
|
||||
|
||||
virtual R invoke (Args &&...) = 0;
|
||||
virtual UniquePtr <LambdaFunctorWrapper> clone () const = 0;
|
||||
};
|
||||
|
||||
template <typename T> class LambdaFunctor : public LambdaFunctorWrapper {
|
||||
private:
|
||||
T callable_;
|
||||
|
||||
public:
|
||||
LambdaFunctor (const T &callable) : LambdaFunctorWrapper (), callable_ (callable)
|
||||
{ }
|
||||
|
||||
LambdaFunctor (T &&callable) : LambdaFunctorWrapper (), callable_ (cr::move (callable))
|
||||
{ }
|
||||
|
||||
~LambdaFunctor () override = default;
|
||||
|
||||
public:
|
||||
void move (uint8 *to) override {
|
||||
new (to) LambdaFunctor <T> (cr::move (callable_));
|
||||
}
|
||||
|
||||
void small (uint8 *to) const override {
|
||||
new (to) LambdaFunctor <T> (callable_);
|
||||
}
|
||||
|
||||
R invoke (Args &&... args) override {
|
||||
return callable_ (cr::forward <Args> (args)...);
|
||||
}
|
||||
|
||||
UniquePtr <LambdaFunctorWrapper> clone () const override {
|
||||
return makeUnique <LambdaFunctor <T>> (callable_);
|
||||
}
|
||||
};
|
||||
|
||||
union {
|
||||
UniquePtr <LambdaFunctorWrapper> functor_;
|
||||
uint8 small_[LamdaSmallBufferLength] { };
|
||||
};
|
||||
|
||||
bool ssoObject_ = false;
|
||||
|
||||
private:
|
||||
void destroy () {
|
||||
if (ssoObject_) {
|
||||
reinterpret_cast <LambdaFunctorWrapper *> (small_)->~LambdaFunctorWrapper ();
|
||||
}
|
||||
else {
|
||||
functor_.reset ();
|
||||
}
|
||||
}
|
||||
|
||||
void swap (Lambda &rhs) noexcept {
|
||||
cr::swap (rhs, *this);
|
||||
}
|
||||
|
||||
public:
|
||||
explicit Lambda () noexcept : Lambda (nullptr)
|
||||
{ }
|
||||
|
||||
Lambda (decltype (nullptr)) noexcept : functor_ (nullptr), ssoObject_ (false)
|
||||
{ }
|
||||
|
||||
Lambda (const Lambda &rhs) {
|
||||
if (rhs.ssoObject_) {
|
||||
reinterpret_cast <const LambdaFunctorWrapper *> (rhs.small_)->small (small_);
|
||||
}
|
||||
else {
|
||||
new (small_) UniquePtr <LambdaFunctorWrapper> (rhs.functor_->clone ());
|
||||
}
|
||||
ssoObject_ = rhs.ssoObject_;
|
||||
}
|
||||
|
||||
Lambda (Lambda &&rhs) noexcept {
|
||||
if (rhs.ssoObject_) {
|
||||
reinterpret_cast <LambdaFunctorWrapper *> (rhs.small_)->move (small_);
|
||||
new (rhs.small_) UniquePtr <LambdaFunctorWrapper> (nullptr);
|
||||
}
|
||||
else {
|
||||
new (small_) UniquePtr <LambdaFunctorWrapper> (cr::move (rhs.functor_));
|
||||
}
|
||||
ssoObject_ = rhs.ssoObject_;
|
||||
rhs.ssoObject_ = false;
|
||||
}
|
||||
|
||||
template <typename F> Lambda (F function) {
|
||||
if (cr::fix (sizeof (function) > LamdaSmallBufferLength)) {
|
||||
ssoObject_ = false;
|
||||
new (small_) UniquePtr <LambdaFunctorWrapper> (makeUnique <LambdaFunctor <F>> (cr::move (function)));
|
||||
}
|
||||
else {
|
||||
ssoObject_ = true;
|
||||
new (small_) LambdaFunctor <F> (cr::move (function));
|
||||
}
|
||||
}
|
||||
|
||||
~Lambda () {
|
||||
destroy ();
|
||||
}
|
||||
|
||||
public:
|
||||
Lambda &operator = (const Lambda &rhs) {
|
||||
destroy ();
|
||||
|
||||
Lambda tmp (rhs);
|
||||
swap (tmp);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Lambda &operator = (Lambda &&rhs) noexcept {
|
||||
destroy ();
|
||||
|
||||
if (rhs.ssoObject_) {
|
||||
reinterpret_cast <LambdaFunctorWrapper *> (rhs.small_)->move (small_);
|
||||
new (rhs.small_) UniquePtr <LambdaFunctorWrapper> (nullptr);
|
||||
}
|
||||
else {
|
||||
new (small_) UniquePtr <LambdaFunctorWrapper> (cr::move (rhs.functor_));
|
||||
}
|
||||
|
||||
ssoObject_ = rhs.ssoObject_;
|
||||
rhs.ssoObject_ = false;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit operator bool () const noexcept {
|
||||
return ssoObject_ || !!functor_;
|
||||
}
|
||||
|
||||
public:
|
||||
R operator () (Args ...args) {
|
||||
return ssoObject_ ? reinterpret_cast <LambdaFunctorWrapper *> (small_)->invoke (cr::forward <Args> (args)...) : functor_->invoke (cr::forward <Args> (args)...);
|
||||
}
|
||||
};
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -1,132 +0,0 @@
|
|||
//
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2021 YaPB Project <yapb@jeefo.net>.
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <crlib/cr-basic.h>
|
||||
#include <crlib/cr-string.h>
|
||||
|
||||
#if defined (CR_LINUX) || defined (CR_OSX)
|
||||
# include <dlfcn.h>
|
||||
# include <errno.h>
|
||||
# include <fcntl.h>
|
||||
# include <sys/stat.h>
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
// handling dynamic library loading
|
||||
class SharedLibrary final : public DenyCopying {
|
||||
public:
|
||||
using Handle = void *;
|
||||
|
||||
private:
|
||||
Handle handle_ = nullptr;
|
||||
bool unloadable_ = true;
|
||||
|
||||
public:
|
||||
explicit SharedLibrary () = default;
|
||||
|
||||
SharedLibrary (StringRef file) {
|
||||
if (file.empty ()) {
|
||||
return;
|
||||
}
|
||||
load (file);
|
||||
}
|
||||
|
||||
~SharedLibrary () {
|
||||
unload ();
|
||||
}
|
||||
|
||||
public:
|
||||
bool load (StringRef file, bool unloadable = true) noexcept {
|
||||
if (*this) {
|
||||
unload ();
|
||||
}
|
||||
unloadable_ = unloadable;
|
||||
|
||||
#if defined (CR_WINDOWS)
|
||||
handle_ = LoadLibraryA (file.chars ());
|
||||
#else
|
||||
auto loadFlags = RTLD_NOW | RTLD_LOCAL;
|
||||
|
||||
#if defined (CR_LINUX) && !defined (__SANITIZE_ADDRESS__)
|
||||
loadFlags |= RTLD_DEEPBIND;
|
||||
#endif
|
||||
handle_ = dlopen (file.chars (), loadFlags);
|
||||
#endif
|
||||
return handle_ != nullptr;
|
||||
}
|
||||
|
||||
bool locate (Handle address) {
|
||||
unloadable_ = false;
|
||||
|
||||
#if defined (CR_WINDOWS)
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
|
||||
if (!VirtualQuery (address, &mbi, sizeof (mbi))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mbi.State != MEM_COMMIT) {
|
||||
return false;
|
||||
}
|
||||
handle_ = reinterpret_cast <Handle> (mbi.AllocationBase);
|
||||
#else
|
||||
Dl_info dli;
|
||||
plat.bzero (&dli, sizeof (dli));
|
||||
|
||||
if (dladdr (address, &dli)) {
|
||||
return load (dli.dli_fname, false);
|
||||
}
|
||||
#endif
|
||||
return handle_ != nullptr;
|
||||
}
|
||||
|
||||
void unload () noexcept {
|
||||
if (!handle_ || !unloadable_) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined (CR_WINDOWS)
|
||||
FreeLibrary (static_cast <HMODULE> (handle_));
|
||||
#else
|
||||
dlclose (handle_);
|
||||
#endif
|
||||
handle_ = nullptr;
|
||||
}
|
||||
|
||||
template <typename R> R resolve (const char *function) const {
|
||||
if (!*this) {
|
||||
return nullptr;
|
||||
}
|
||||
return SharedLibrary::getSymbol <R> (handle (), function);
|
||||
}
|
||||
|
||||
Handle handle () const {
|
||||
return handle_;
|
||||
}
|
||||
|
||||
public:
|
||||
explicit operator bool () const {
|
||||
return handle_ != nullptr;
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename R> static inline R CR_STDCALL getSymbol (Handle module, const char *function) {
|
||||
return reinterpret_cast <R> (
|
||||
#if defined (CR_WINDOWS)
|
||||
GetProcAddress (static_cast <HMODULE> (module), function)
|
||||
#else
|
||||
dlsym (module, function)
|
||||
#endif
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -1,112 +0,0 @@
|
|||
//
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2021 YaPB Project <yapb@jeefo.net>.
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include <crlib/cr-files.h>
|
||||
#include <crlib/cr-lambda.h>
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
class SimpleLogger final : public Singleton <SimpleLogger> {
|
||||
public:
|
||||
using PrintFunction = Lambda <void (const char *)>;
|
||||
|
||||
private:
|
||||
String filename_;
|
||||
PrintFunction printFun_;
|
||||
|
||||
public:
|
||||
explicit SimpleLogger () = default;
|
||||
~SimpleLogger () = default;
|
||||
|
||||
public:
|
||||
class LogFile final {
|
||||
private:
|
||||
File handle_;
|
||||
|
||||
public:
|
||||
LogFile (StringRef filename) {
|
||||
handle_.open (filename, "at");
|
||||
}
|
||||
|
||||
~LogFile () {
|
||||
handle_.close ();
|
||||
}
|
||||
|
||||
public:
|
||||
void print (StringRef msg) {
|
||||
if (!handle_) {
|
||||
return;
|
||||
}
|
||||
handle_.puts (msg.chars ());
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
void logToFile (const char *level, const char *msg) {
|
||||
time_t ticks = time (&ticks);
|
||||
tm timeinfo {};
|
||||
|
||||
#if defined (CR_WINDOWS)
|
||||
localtime_s (&timeinfo, &ticks);
|
||||
#else
|
||||
localtime_r (&ticks, &timeinfo);
|
||||
#endif
|
||||
|
||||
auto timebuf = strings.chars ();
|
||||
strftime (timebuf, StringBuffer::StaticBufferSize, "%Y-%m-%d %H:%M:%S", &timeinfo);
|
||||
|
||||
LogFile lf (filename_);
|
||||
lf.print (strings.format ("%s (%s): %s\n", timebuf, level, msg));
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename ...Args> void fatal (const char *fmt, Args &&...args) {
|
||||
auto msg = strings.format (fmt, cr::forward <Args> (args)...);
|
||||
|
||||
logToFile ("FATAL", msg);
|
||||
|
||||
if (printFun_) {
|
||||
printFun_ (msg);
|
||||
}
|
||||
plat.abort (msg);
|
||||
}
|
||||
|
||||
template <typename ...Args> void error (const char *fmt, Args &&...args) {
|
||||
auto msg = strings.format (fmt, cr::forward <Args> (args)...);
|
||||
|
||||
logToFile ("ERROR", msg);
|
||||
|
||||
if (printFun_) {
|
||||
printFun_ (msg);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename ...Args> void message (const char *fmt, Args &&...args) {
|
||||
auto msg = strings.format (fmt, cr::forward <Args> (args)...);
|
||||
|
||||
logToFile ("INFO", msg);
|
||||
|
||||
if (printFun_) {
|
||||
printFun_ (msg);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
void initialize (StringRef filename, PrintFunction printFunction) {
|
||||
printFun_ = cr::move (printFunction);
|
||||
filename_ = filename;
|
||||
}
|
||||
};
|
||||
|
||||
// expose global instance
|
||||
CR_EXPOSE_GLOBAL_SINGLETON (SimpleLogger, logger);
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -1,135 +0,0 @@
|
|||
//
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2021 YaPB Project <yapb@jeefo.net>.
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <crlib/cr-basic.h>
|
||||
|
||||
#if defined (CR_HAS_SSE)
|
||||
# include <pmmintrin.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
constexpr float kFloatEpsilon = 0.01f;
|
||||
constexpr float kFloatEqualEpsilon = 0.001f;
|
||||
constexpr float kFloatCmpEpsilon = 1.192092896e-07f;
|
||||
|
||||
constexpr float kMathPi = 3.141592653589793115997963468544185161590576171875f;
|
||||
constexpr float kMathPiHalf = kMathPi * 0.5f;
|
||||
|
||||
constexpr float kDegreeToRadians = kMathPi / 180.0f;
|
||||
constexpr float kRadiansToDegree = 180.0f / kMathPi;
|
||||
|
||||
constexpr bool fzero (const float e) {
|
||||
return cr::abs (e) < kFloatEpsilon;
|
||||
}
|
||||
|
||||
constexpr bool fequal (const float a, const float b) {
|
||||
return cr:: abs (a - b) < kFloatEqualEpsilon;
|
||||
}
|
||||
|
||||
constexpr float rad2deg (const float r) {
|
||||
return r * kRadiansToDegree;
|
||||
}
|
||||
|
||||
constexpr float deg2rad (const float d) {
|
||||
return d * kDegreeToRadians;
|
||||
}
|
||||
|
||||
constexpr float modAngles (const float a) {
|
||||
return 360.0f / 65536.0f * (static_cast <int> (a * (65536.0f / 360.0f)) & 65535);
|
||||
}
|
||||
|
||||
constexpr float normalizeAngles (const float a) {
|
||||
return 360.0f / 65536.0f * (static_cast <int> ((a + 180.0f) * (65536.0f / 360.0f)) & 65535) - 180.0f;
|
||||
}
|
||||
|
||||
constexpr float anglesDifference (const float a, const float b) {
|
||||
return normalizeAngles (a - b);
|
||||
}
|
||||
|
||||
inline float sinf (const float value) {
|
||||
return ::sinf (value);
|
||||
}
|
||||
|
||||
inline float cosf (const float value) {
|
||||
return ::cosf (value);
|
||||
}
|
||||
|
||||
inline float atanf (const float value) {
|
||||
return ::atanf (value);
|
||||
}
|
||||
|
||||
inline float atan2f (const float y, const float x) {
|
||||
return ::atan2f (y, x);
|
||||
}
|
||||
|
||||
inline float powf (const float x, const float y) {
|
||||
return ::powf (x, y);
|
||||
}
|
||||
|
||||
inline float sqrtf (const float value) {
|
||||
return ::sqrtf (value);
|
||||
}
|
||||
|
||||
inline float tanf (const float value) {
|
||||
return ::tanf (value);
|
||||
}
|
||||
|
||||
inline float ceilf (const float value) {
|
||||
return ::ceilf (value);
|
||||
}
|
||||
|
||||
inline void sincosf (const float x, const float y, const float z, float *sines, float *cosines) {
|
||||
#if defined (CR_HAS_SSE)
|
||||
auto set = _mm_set_ps (x, y, z, 0.0f);
|
||||
|
||||
auto _mm_sin = [] (__m128 rad) -> __m128 {
|
||||
static auto pi2 = _mm_set_ps1 (kMathPi * 2);
|
||||
static auto rp1 = _mm_set_ps1 (4.0f / kMathPi);
|
||||
static auto rp2 = _mm_set_ps1 (-4.0f / (kMathPi * kMathPi));
|
||||
static auto val = _mm_cmpnlt_ps (rad, _mm_set_ps1 (kMathPi));
|
||||
static auto csi = _mm_castsi128_ps (_mm_set1_epi32 (0x80000000));
|
||||
|
||||
val = _mm_and_ps (val, pi2);
|
||||
rad = _mm_sub_ps (rad, val);
|
||||
val = _mm_cmpngt_ps (rad, _mm_set_ps1 (-kMathPi));
|
||||
val = _mm_and_ps (val, pi2);
|
||||
rad = _mm_add_ps (rad, val);
|
||||
val = _mm_mul_ps (_mm_andnot_ps (csi, rad), rp2);
|
||||
val = _mm_add_ps (val, rp1);
|
||||
|
||||
auto si = _mm_mul_ps (val, rad);
|
||||
|
||||
val = _mm_mul_ps (_mm_andnot_ps (csi, si), si);
|
||||
val = _mm_sub_ps (val, si);
|
||||
val = _mm_mul_ps (val, _mm_set_ps1 (0.225f));
|
||||
|
||||
return _mm_add_ps (val, si);
|
||||
};
|
||||
static auto hpi = _mm_set_ps1 (kMathPiHalf);
|
||||
|
||||
auto s = _mm_sin (set);
|
||||
auto c = _mm_sin (_mm_add_ps (set, hpi));
|
||||
|
||||
_mm_store_ps (sines, _mm_shuffle_ps (s, s, _MM_SHUFFLE (0, 1, 2, 3)));
|
||||
_mm_store_ps (cosines, _mm_shuffle_ps (c, c, _MM_SHUFFLE (0, 1, 2, 3)));
|
||||
#else
|
||||
sines[0] = cr::sinf (x);
|
||||
sines[1] = cr::sinf (y);
|
||||
sines[2] = cr::sinf (z);
|
||||
|
||||
cosines[0] = cr::cosf (x);
|
||||
cosines[1] = cr::cosf (y);
|
||||
cosines[2] = cr::cosf (z);
|
||||
#endif
|
||||
}
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
//
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2021 YaPB Project <yapb@jeefo.net>.
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <crlib/cr-basic.h>
|
||||
#include <crlib/cr-movable.h>
|
||||
#include <crlib/cr-platform.h>
|
||||
|
||||
// provide placment new to avoid stdc++ <new> header
|
||||
inline void *operator new (const size_t, void *ptr) noexcept {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
// internal memory manager
|
||||
class Memory final {
|
||||
public:
|
||||
Memory () = default;
|
||||
~Memory () = default;
|
||||
|
||||
public:
|
||||
template <typename T> static T *get (const size_t length = 1) {
|
||||
auto memory = reinterpret_cast <T *> (malloc (cr::max <size_t> (1u, length * sizeof (T))));
|
||||
|
||||
if (!memory) {
|
||||
plat.abort ();
|
||||
}
|
||||
return memory;
|
||||
}
|
||||
|
||||
template <typename T> static void release (T *memory) {
|
||||
free (memory);
|
||||
memory = nullptr;
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename T, typename ...Args> static void construct (T *memory, Args &&...args) {
|
||||
new (memory) T (cr::forward <Args> (args)...);
|
||||
}
|
||||
|
||||
template <typename T> static void destruct (T *memory) {
|
||||
memory->~T ();
|
||||
}
|
||||
};
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
//
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2021 YaPB Project <yapb@jeefo.net>.
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <crlib/cr-basic.h>
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
namespace detail {
|
||||
template <typename T> struct ClearRef {
|
||||
using Type = T;
|
||||
};
|
||||
template <typename T> struct ClearRef <T &> {
|
||||
using Type = T;
|
||||
};
|
||||
template <typename T> struct ClearRef <T &&> {
|
||||
using Type = T;
|
||||
};
|
||||
}
|
||||
|
||||
template <typename T> typename detail::ClearRef <T>::Type constexpr &&move (T &&type) noexcept {
|
||||
return static_cast <typename detail::ClearRef <T>::Type &&> (type);
|
||||
}
|
||||
|
||||
template <typename T> constexpr T &&forward (typename detail::ClearRef <T>::Type &type) noexcept {
|
||||
return static_cast <T &&> (type);
|
||||
}
|
||||
|
||||
template <typename T> constexpr T &&forward (typename detail::ClearRef <T>::Type &&type) noexcept {
|
||||
return static_cast <T &&> (type);
|
||||
}
|
||||
|
||||
template <typename T> inline void swap (T &left, T &right) noexcept {
|
||||
auto temp = cr::move (left);
|
||||
left = cr::move (right);
|
||||
right = cr::move (temp);
|
||||
}
|
||||
|
||||
template <typename T, size_t S> inline void swap (T (&left)[S], T (&right)[S]) noexcept {
|
||||
if (&left == &right) {
|
||||
return;
|
||||
}
|
||||
auto begin = left;
|
||||
auto end = begin + S;
|
||||
|
||||
for (auto temp = right; begin != end; ++begin, ++temp) {
|
||||
cr::swap (*begin, *temp);
|
||||
}
|
||||
}
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
//
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2021 YaPB Project <yapb@jeefo.net>.
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <crlib/cr-memory.h>
|
||||
#include <crlib/cr-platform.h>
|
||||
|
||||
void *operator new (size_t size) {
|
||||
return cr::Memory::get <void *> (size);
|
||||
}
|
||||
|
||||
void *operator new [] (size_t size) {
|
||||
return cr::Memory::get <void *> (size);
|
||||
}
|
||||
|
||||
void operator delete (void *ptr) noexcept {
|
||||
cr::Memory::release (ptr);
|
||||
}
|
||||
|
||||
void operator delete [] (void *ptr) noexcept {
|
||||
cr::Memory::release (ptr);
|
||||
}
|
||||
|
||||
void operator delete (void *ptr, size_t) noexcept {
|
||||
cr::Memory::release (ptr);
|
||||
}
|
||||
|
||||
void operator delete [] (void *ptr, size_t) noexcept {
|
||||
cr::Memory::release (ptr);
|
||||
}
|
||||
|
||||
CR_LINKAGE_C void __cxa_pure_virtual () {
|
||||
cr::plat.abort ("pure virtual function call");
|
||||
}
|
||||
|
|
@ -1,301 +0,0 @@
|
|||
//
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2021 YaPB Project <yapb@jeefo.net>.
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
// detects the build platform
|
||||
#if defined(__linux__)
|
||||
# define CR_LINUX
|
||||
#elif defined(__APPLE__)
|
||||
# define CR_OSX
|
||||
#elif defined(_WIN32)
|
||||
# define CR_WINDOWS
|
||||
#endif
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
# define CR_ANDROID
|
||||
# if defined(LOAD_HARDFP)
|
||||
# define CR_ANDROID_HARD_FP
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// detects the compiler
|
||||
#if defined(_MSC_VER)
|
||||
# define CR_CXX_MSVC _MSC_VER
|
||||
#endif
|
||||
|
||||
#if defined(__clang__)
|
||||
# define CR_CXX_CLANG __clang__
|
||||
#endif
|
||||
|
||||
#if defined(__INTEL_COMPILER)
|
||||
# define CR_CXX_INTEL __INTEL_COMPILER
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# define CR_CXX_GCC __GNUC__
|
||||
#endif
|
||||
|
||||
// configure macroses
|
||||
#define CR_LINKAGE_C extern "C"
|
||||
|
||||
#if defined(CR_WINDOWS)
|
||||
# define CR_EXPORT CR_LINKAGE_C __declspec (dllexport)
|
||||
# define CR_STDCALL __stdcall
|
||||
#elif defined(CR_LINUX) || defined(CR_OSX)
|
||||
# define CR_EXPORT CR_LINKAGE_C __attribute__((visibility("default")))
|
||||
# define CR_STDCALL
|
||||
#else
|
||||
# error "Can't configure export macros. Compiler unrecognized."
|
||||
#endif
|
||||
|
||||
#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(__amd64) || (defined(_MSC_VER) && defined(_M_X64))
|
||||
# define CR_ARCH_X64
|
||||
#elif defined(__i686) || defined(__i686__) || defined(__i386) || defined(__i386__) || defined(i386) || (defined(_MSC_VER) && defined(_M_IX86))
|
||||
# define CR_ARCH_X86
|
||||
#endif
|
||||
|
||||
#if defined(__arm__)
|
||||
# define CR_ARCH_ARM
|
||||
# if defined(__aarch64__)
|
||||
# define CR_ARCH_ARM64
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if (defined(CR_ARCH_X86) || defined(CR_ARCH_X64)) && !defined(CR_DEBUG)
|
||||
# define CR_HAS_SSE
|
||||
#endif
|
||||
|
||||
#if defined(CR_HAS_SSE)
|
||||
# if defined (CR_CXX_MSVC)
|
||||
# define CR_ALIGN16 __declspec (align (16))
|
||||
# else
|
||||
# define CR_ALIGN16 __attribute__((aligned(16)))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// disable warnings regarding intel compiler
|
||||
#if defined(CR_CXX_INTEL)
|
||||
# pragma warning (disable : 3280) // declaration hides member "XXX" (declared at line XX)
|
||||
# pragma warning (disable : 2415) // variable "XXX" of static storage duration was declared but never referenced
|
||||
# pragma warning (disable : 873) // function "operator new(size_t={unsigned int}, void *)" has no corresponding operator delete (to be called if an exception is thrown during initialization of an allocated object)
|
||||
# pragma warning (disable : 383) // value copied to temporary, reference to temporary used
|
||||
# pragma warning (disable : 11074 11075) // remarks about inlining bla-bla-bla
|
||||
#endif
|
||||
|
||||
// msvc provides us placement new by default
|
||||
#if defined (CR_CXX_MSVC)
|
||||
# define __PLACEMENT_NEW_INLINE 1
|
||||
#endif
|
||||
|
||||
// disabled gcc warnings
|
||||
#if defined (CR_CXX_GCC)
|
||||
# pragma GCC diagnostic ignored "-Wignored-attributes"
|
||||
#endif
|
||||
|
||||
// avoid linking to GLIBC_2.27
|
||||
#if defined (CR_LINUX) && !defined (CR_CXX_INTEL)
|
||||
__asm__ (".symver powf, powf@GLIBC_2.0");
|
||||
#endif
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
||||
#if defined(CR_WINDOWS)
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <windows.h>
|
||||
# include <direct.h>
|
||||
|
||||
# if defined (max)
|
||||
# undef max
|
||||
# endif
|
||||
|
||||
# if defined (min)
|
||||
# undef min
|
||||
# endif
|
||||
|
||||
#else
|
||||
# include <unistd.h>
|
||||
# include <strings.h>
|
||||
# include <sys/stat.h>
|
||||
# include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <locale.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#if defined (CR_ANDROID)
|
||||
# include <android/log.h>
|
||||
#endif
|
||||
|
||||
#include <time.h>
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
// helper struct for platform detection
|
||||
struct Platform : public Singleton <Platform> {
|
||||
bool win = false;
|
||||
bool nix = false;
|
||||
bool osx = false;
|
||||
bool android = false;
|
||||
bool hfp = false;
|
||||
bool x64 = false;
|
||||
bool arm = false;
|
||||
|
||||
char appName[64] = {};
|
||||
|
||||
Platform () {
|
||||
#if defined(CR_WINDOWS)
|
||||
win = true;
|
||||
#endif
|
||||
|
||||
#if defined(CR_ANDROID)
|
||||
android = true;
|
||||
|
||||
# if defined (CR_ANDROID_HARD_FP)
|
||||
hfp = true;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(CR_LINUX)
|
||||
nix = true;
|
||||
#endif
|
||||
|
||||
#if defined(CR_OSX)
|
||||
osx = true;
|
||||
#endif
|
||||
|
||||
#if defined(CR_ARCH_X64) || defined(CR_ARCH_ARM64)
|
||||
x64 = true;
|
||||
#endif
|
||||
|
||||
#if defined(CR_ARCH_ARM)
|
||||
arm = true;
|
||||
android = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
// set the app name
|
||||
void setAppName (const char *name) {
|
||||
snprintf (appName, cr::bufsize (appName), "%s", name);
|
||||
}
|
||||
|
||||
// helper platform-dependant functions
|
||||
template <typename U> bool checkPointer (U *ptr) {
|
||||
#if defined(CR_WINDOWS)
|
||||
if (IsBadCodePtr (reinterpret_cast <FARPROC> (ptr))) {
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
(void) (ptr);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool createDirectory (const char *dir) {
|
||||
int result = 0;
|
||||
#if defined(CR_WINDOWS)
|
||||
result = _mkdir (dir);
|
||||
#else
|
||||
result = mkdir (dir, 0777);
|
||||
#endif
|
||||
return !!result;
|
||||
}
|
||||
|
||||
bool removeFile (const char *dir) {
|
||||
#if defined(CR_WINDOWS)
|
||||
_unlink (dir);
|
||||
#else
|
||||
unlink (dir);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool hasModule (const char *mod) {
|
||||
#if defined(CR_WINDOWS)
|
||||
return GetModuleHandleA (mod) != nullptr;
|
||||
#else
|
||||
(void) (mod);
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
float seconds () {
|
||||
#if defined(CR_WINDOWS)
|
||||
LARGE_INTEGER count, freq;
|
||||
|
||||
count.QuadPart = 0;
|
||||
freq.QuadPart = 0;
|
||||
|
||||
QueryPerformanceFrequency (&freq);
|
||||
QueryPerformanceCounter (&count);
|
||||
|
||||
return static_cast <float> (count.QuadPart / freq.QuadPart);
|
||||
#else
|
||||
timeval tv;
|
||||
gettimeofday (&tv, nullptr);
|
||||
|
||||
static auto startTime = tv.tv_sec;
|
||||
|
||||
return static_cast <float> (tv.tv_sec - startTime);
|
||||
#endif
|
||||
}
|
||||
|
||||
void abort (const char *msg = "OUT OF MEMORY!") noexcept {
|
||||
fprintf (stderr, "%s\n", msg);
|
||||
|
||||
#if defined (CR_ANDROID)
|
||||
__android_log_write (ANDROID_LOG_ERROR, appName, msg);
|
||||
#endif
|
||||
|
||||
#if defined(CR_WINDOWS)
|
||||
DestroyWindow (GetForegroundWindow ());
|
||||
MessageBoxA (GetActiveWindow (), msg, appName, MB_ICONSTOP);
|
||||
#endif
|
||||
::abort ();
|
||||
}
|
||||
|
||||
// anologue of memset
|
||||
template <typename U> void bzero (U *ptr, size_t len) noexcept {
|
||||
#if defined (CR_WINDOWS)
|
||||
memset (ptr, 0, len);
|
||||
#else
|
||||
auto zeroing = reinterpret_cast <uint8 *> (ptr);
|
||||
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
zeroing[i] = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *env (const char *var) {
|
||||
static char result[256];
|
||||
bzero (result, sizeof (result));
|
||||
|
||||
#if defined(CR_WINDOWS) && !defined(CR_CXX_GCC)
|
||||
char *buffer = nullptr;
|
||||
size_t size = 0;
|
||||
|
||||
if (_dupenv_s (&buffer, &size, var) == 0 && buffer != nullptr) {
|
||||
strncpy_s (result, buffer, sizeof (result));
|
||||
free (buffer);
|
||||
}
|
||||
#else
|
||||
strncpy (result, getenv (var), cr::bufsize (result));
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
// expose platform singleton
|
||||
CR_EXPOSE_GLOBAL_SINGLETON (Platform, plat);
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
//
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2021 YaPB Project <yapb@jeefo.net>.
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <crlib/cr-basic.h>
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
// based on: https://github.com/jeudesprits/PSWyhash/blob/master/Sources/CWyhash/include/wyhash.h
|
||||
class Random : public Singleton <Random> {
|
||||
private:
|
||||
uint64 div_ { static_cast <uint64> (1) << 32ull };
|
||||
uint64 state_ { static_cast <uint64> (time (nullptr)) };
|
||||
|
||||
public:
|
||||
explicit Random () = default;
|
||||
~Random () = default;
|
||||
|
||||
private:
|
||||
uint64 wyrand64 () {
|
||||
constexpr uint64 wyp0 = 0xa0761d6478bd642full, wyp1 = 0xe7037ed1a0b428dbull;
|
||||
state_ += wyp0;
|
||||
|
||||
return mul (state_ ^ wyp1, state_);
|
||||
}
|
||||
|
||||
uint32 wyrand32 () {
|
||||
return static_cast <uint32> (wyrand64 ());
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t rotr (uint64 v, uint32 k) {
|
||||
return (v >> k) | (v << (64 - k));
|
||||
}
|
||||
|
||||
uint64 mul (uint64 a, uint64 b) {
|
||||
uint64 hh = (a >> 32) * (b >> 32);
|
||||
uint64 hl = (b >> 32) * static_cast <uint32> (b);
|
||||
|
||||
uint64 lh = static_cast <uint32> (a) * (b >> 32);
|
||||
uint64 ll = static_cast <uint64> (static_cast <double> (a) * static_cast <double> (b));
|
||||
|
||||
return rotr (hl, 32) ^ rotr (lh, 32) ^ hh ^ ll;
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename U, typename Void = void> U get (U, U) = delete;
|
||||
|
||||
template <typename Void = void> int32 get (int32 low, int32 high) {
|
||||
return static_cast <int32> (wyrand32 () * (static_cast <double> (high) - static_cast <double> (low) + 1.0) / div_ + static_cast <double> (low));
|
||||
}
|
||||
|
||||
template <typename Void = void> float get (float low, float high) {
|
||||
return static_cast <float> (wyrand32 () * (static_cast <double> (high) - static_cast <double> (low)) / (div_ - 1) + static_cast <double> (low));
|
||||
}
|
||||
|
||||
public:
|
||||
bool chance (int32 limit) {
|
||||
return get <int32> (0, 100) < limit;
|
||||
}
|
||||
};
|
||||
|
||||
// expose global random generator
|
||||
CR_EXPOSE_GLOBAL_SINGLETON (Random, rg);
|
||||
|
||||
CR_NAMESPACE_END
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,56 +0,0 @@
|
|||
//
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2021 YaPB Project <yapb@jeefo.net>.
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <crlib/cr-basic.h>
|
||||
#include <crlib/cr-movable.h>
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
// simple pair (twin)
|
||||
template <typename A, typename B> class Twin final {
|
||||
public:
|
||||
A first;
|
||||
B second;
|
||||
|
||||
public:
|
||||
template <typename T, typename U> Twin (T &&a, U &&b) : first (cr::forward <T> (a)), second (cr::forward <U> (b)) { }
|
||||
template <typename T, typename U> Twin (const Twin <T, U> &rhs) : first (rhs.first), second (rhs.second) { }
|
||||
template <typename T, typename U> Twin (Twin <T, U> &&rhs) noexcept : first (cr::move (rhs.first)), second (cr::move (rhs.second)) { }
|
||||
|
||||
public:
|
||||
explicit Twin () = default;
|
||||
~Twin () = default;
|
||||
|
||||
public:
|
||||
template <typename T, typename U> Twin &operator = (const Twin <T, U> &rhs) {
|
||||
first = rhs.first;
|
||||
second = rhs.second;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T, typename U> Twin &operator = (Twin <T, U> &&rhs) {
|
||||
first = cr::move (rhs.first);
|
||||
second = cr::move (rhs.second);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// specialized operators for binary heap, do not use as it's test only second element
|
||||
public:
|
||||
friend bool operator < (const Twin &a, const Twin &b) {
|
||||
return a.second < b.second;
|
||||
}
|
||||
|
||||
friend bool operator > (const Twin &a, const Twin &b) {
|
||||
return b.second < a.second;
|
||||
}
|
||||
};
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -1,312 +0,0 @@
|
|||
//
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2021 YaPB Project <yapb@jeefo.net>.
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <crlib/cr-array.h>
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
// see https://github.com/encode84/ulz/
|
||||
class ULZ final : public Singleton <ULZ> {
|
||||
public:
|
||||
enum : int32 {
|
||||
Excess = 16,
|
||||
UncompressFailure = -1
|
||||
};
|
||||
|
||||
private:
|
||||
enum : int32 {
|
||||
WindowBits = 17,
|
||||
WindowSize = cr::bit (WindowBits),
|
||||
WindowMask = WindowSize - 1,
|
||||
|
||||
MinMatch = 4,
|
||||
MaxChain = cr::bit (5),
|
||||
|
||||
HashBits = 19,
|
||||
HashLength = cr::bit (HashBits),
|
||||
EmptyHash = -1,
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
SmallArray <int32> hashTable_;
|
||||
SmallArray <int32> prevTable_;
|
||||
|
||||
public:
|
||||
explicit ULZ () {
|
||||
hashTable_.resize (HashLength);
|
||||
prevTable_.resize (WindowSize);
|
||||
}
|
||||
|
||||
~ULZ () = default;
|
||||
|
||||
public:
|
||||
int32 compress (uint8 *in, int32 inputLength, uint8 *out) {
|
||||
for (auto &htb : hashTable_) {
|
||||
htb = EmptyHash;
|
||||
}
|
||||
auto op = out;
|
||||
|
||||
int32 anchor = 0;
|
||||
int32 cur = 0;
|
||||
|
||||
while (cur < inputLength) {
|
||||
const int32 maxMatch = inputLength - cur;
|
||||
|
||||
int32 bestLength = 0;
|
||||
int32 dist = 0;
|
||||
|
||||
if (maxMatch >= MinMatch) {
|
||||
const auto limit = cr::max <int32> (cur - WindowSize, EmptyHash);
|
||||
|
||||
int32 chainLength = MaxChain;
|
||||
int32 lookup = hashTable_[hash32 (&in[cur])];
|
||||
|
||||
while (lookup > limit) {
|
||||
if (in[lookup + bestLength] == in[cur + bestLength] && load <uint32> (&in[lookup]) == load <uint32> (&in[cur])) {
|
||||
int32 length = MinMatch;
|
||||
|
||||
while (length < maxMatch && in[lookup + length] == in[cur + length]) {
|
||||
++length;
|
||||
}
|
||||
|
||||
if (length > bestLength) {
|
||||
bestLength = length;
|
||||
dist = cur - lookup;
|
||||
|
||||
if (length == maxMatch) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (--chainLength == 0) {
|
||||
break;
|
||||
}
|
||||
lookup = prevTable_[lookup & WindowMask];
|
||||
}
|
||||
}
|
||||
|
||||
if (bestLength == MinMatch && (cur - anchor) >= (7 + 128)) {
|
||||
bestLength = 0;
|
||||
}
|
||||
|
||||
if (bestLength >= MinMatch && bestLength < maxMatch && (cur - anchor) != 6) {
|
||||
const auto next = cur + 1;
|
||||
const auto target = bestLength + 1;
|
||||
const auto limit = cr::max <int32> (next - WindowSize, EmptyHash);
|
||||
|
||||
int32 chainLength = MaxChain;
|
||||
int32 lookup = hashTable_[hash32 (&in[next])];
|
||||
|
||||
while (lookup > limit) {
|
||||
if (in[lookup + bestLength] == in[next + bestLength] && load <uint32> (&in[lookup]) == load <uint32> (&in[next])) {
|
||||
int32 length = MinMatch;
|
||||
|
||||
while (length < target && in[lookup + length] == in[next + length]) {
|
||||
++length;
|
||||
}
|
||||
|
||||
if (length == target) {
|
||||
bestLength = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (--chainLength == 0) {
|
||||
break;
|
||||
}
|
||||
lookup = prevTable_[lookup & WindowMask];
|
||||
}
|
||||
}
|
||||
|
||||
if (bestLength >= MinMatch) {
|
||||
const auto length = bestLength - MinMatch;
|
||||
const auto token = ((dist >> 12) & 16) + cr::min <int32> (length, 15);
|
||||
|
||||
if (anchor != cur) {
|
||||
const auto run = cur - anchor;
|
||||
|
||||
if (run >= 7) {
|
||||
add (op, (7 << 5) + token);
|
||||
encode (op, run - 7);
|
||||
}
|
||||
else {
|
||||
add (op, (run << 5) + token);
|
||||
}
|
||||
copy (op, &in[anchor], run);
|
||||
op += run;
|
||||
}
|
||||
else {
|
||||
add (op, token);
|
||||
}
|
||||
|
||||
if (length >= 15) {
|
||||
encode (op, length - 15);
|
||||
}
|
||||
store16 (op, static_cast <uint16> (dist));
|
||||
op += 2;
|
||||
|
||||
while (bestLength-- != 0) {
|
||||
const auto hash = hash32 (&in[cur]);
|
||||
|
||||
prevTable_[cur & WindowMask] = hashTable_[hash];
|
||||
hashTable_[hash] = cur++;
|
||||
}
|
||||
anchor = cur;
|
||||
}
|
||||
else {
|
||||
const auto hash = hash32 (&in[cur]);
|
||||
|
||||
prevTable_[cur & WindowMask] = hashTable_[hash];
|
||||
hashTable_[hash] = cur++;
|
||||
}
|
||||
}
|
||||
|
||||
if (anchor != cur) {
|
||||
const auto run = cur - anchor;
|
||||
|
||||
if (run >= 7) {
|
||||
add (op, 7 << 5);
|
||||
encode (op, run - 7);
|
||||
}
|
||||
else {
|
||||
add (op, run << 5);
|
||||
}
|
||||
copy (op, &in[anchor], run);
|
||||
op += run;
|
||||
}
|
||||
return static_cast <int32> (op - out);
|
||||
}
|
||||
|
||||
int32 uncompress (uint8 *in, int32 inputLength, uint8 *out, int32 outLength) {
|
||||
auto op = out;
|
||||
auto ip = in;
|
||||
|
||||
const auto opEnd = op + outLength;
|
||||
const auto ipEnd = ip + inputLength;
|
||||
|
||||
while (ip < ipEnd) {
|
||||
const auto token = *ip++;
|
||||
|
||||
if (token >= 32) {
|
||||
auto run = token >> 5;
|
||||
|
||||
if (run == 7) {
|
||||
run += decode (ip);
|
||||
}
|
||||
|
||||
if ((opEnd - op) < run || (ipEnd - ip) < run) {
|
||||
return UncompressFailure;
|
||||
}
|
||||
copy (op, ip, run);
|
||||
|
||||
op += run;
|
||||
ip += run;
|
||||
|
||||
if (ip >= ipEnd) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
auto length = (token & 15) + MinMatch;
|
||||
|
||||
if (length == (15 + MinMatch)) {
|
||||
length += decode (ip);
|
||||
}
|
||||
|
||||
if ((opEnd - op) < length) {
|
||||
return UncompressFailure;
|
||||
}
|
||||
const auto dist = ((token & 16) << 12) + load <uint16> (ip);
|
||||
ip += 2;
|
||||
|
||||
auto cp = op - dist;
|
||||
|
||||
if ((op - out) < dist) {
|
||||
return UncompressFailure;
|
||||
}
|
||||
|
||||
if (dist >= 8) {
|
||||
copy (op, cp, length);
|
||||
op += length;
|
||||
}
|
||||
else {
|
||||
for (int32 i = 0; i < 4; ++i) {
|
||||
*op++ = *cp++;
|
||||
}
|
||||
|
||||
while (length-- != 4) {
|
||||
*op++ = *cp++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return static_cast <int32> (ip == ipEnd) ? static_cast <int32> (op - out) : UncompressFailure;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename U> U load (void *ptr) {
|
||||
U ret;
|
||||
memcpy (&ret, ptr, sizeof (U));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void store16 (void *ptr, uint16 val) {
|
||||
memcpy (ptr, &val, sizeof (uint16));
|
||||
}
|
||||
|
||||
void copy64 (void *dst, void *src) {
|
||||
memcpy (dst, src, sizeof (uint64));
|
||||
}
|
||||
|
||||
uint32 hash32 (void *ptr) {
|
||||
return (load <uint32> (ptr) * 0x9e3779b9) >> (32 - HashBits);
|
||||
}
|
||||
|
||||
void copy (uint8 *dst, uint8 *src, int32 count) {
|
||||
copy64 (dst, src);
|
||||
|
||||
for (int32 i = 8; i < count; i += 8) {
|
||||
copy64 (dst + i, src + i);
|
||||
}
|
||||
}
|
||||
|
||||
void add (uint8 *&dst, int32 val) {
|
||||
*dst++ = static_cast <uint8> (val);
|
||||
}
|
||||
|
||||
void encode (uint8 *&ptr, uint32 val) {
|
||||
while (val >= 128) {
|
||||
val -= 128;
|
||||
|
||||
*ptr++ = 128 + (val & 127);
|
||||
val >>= 7;
|
||||
}
|
||||
*ptr++ = static_cast <uint8> (val);
|
||||
}
|
||||
|
||||
uint32 decode (uint8 *&ptr) {
|
||||
uint32 val = 0;
|
||||
|
||||
for (int32 i = 0; i <= 21; i += 7) {
|
||||
const uint32 cur = *ptr++;
|
||||
val += cur << i;
|
||||
|
||||
if (cur < 128) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
};
|
||||
|
||||
// expose global ulz object
|
||||
CR_EXPOSE_GLOBAL_SINGLETON (ULZ, ulz);
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -1,206 +0,0 @@
|
|||
//
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2021 YaPB Project <yapb@jeefo.net>.
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <crlib/cr-basic.h>
|
||||
#include <crlib/cr-memory.h>
|
||||
#include <crlib/cr-movable.h>
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
// simple unique ptr
|
||||
template <typename T> class UniquePtr final : public DenyCopying {
|
||||
private:
|
||||
T *ptr_ {};
|
||||
|
||||
public:
|
||||
UniquePtr () = default;
|
||||
|
||||
explicit UniquePtr (T *ptr) : ptr_ (ptr)
|
||||
{ }
|
||||
|
||||
UniquePtr (UniquePtr &&rhs) noexcept : ptr_ (rhs.release ())
|
||||
{ }
|
||||
|
||||
template <typename U> UniquePtr (UniquePtr <U> &&rhs) noexcept : ptr_ (rhs.release ())
|
||||
{ }
|
||||
|
||||
~UniquePtr () {
|
||||
destroy ();
|
||||
}
|
||||
|
||||
public:
|
||||
T *get () const {
|
||||
return ptr_;
|
||||
}
|
||||
|
||||
T *release () {
|
||||
auto ret = ptr_;
|
||||
ptr_ = nullptr;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void reset (T *ptr = nullptr) {
|
||||
destroy ();
|
||||
ptr_ = ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
void destroy () {
|
||||
delete ptr_;
|
||||
ptr_ = nullptr;
|
||||
}
|
||||
|
||||
public:
|
||||
UniquePtr &operator = (UniquePtr &&rhs) noexcept {
|
||||
if (this != &rhs) {
|
||||
reset (rhs.release ());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename U> UniquePtr &operator = (UniquePtr <U> &&rhs) noexcept {
|
||||
if (this != &rhs) {
|
||||
reset (rhs.release ());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
UniquePtr &operator = (decltype (nullptr)) {
|
||||
destroy ();
|
||||
return *this;
|
||||
}
|
||||
|
||||
T &operator * () const {
|
||||
return *ptr_;
|
||||
}
|
||||
|
||||
T *operator -> () const {
|
||||
return ptr_;
|
||||
}
|
||||
|
||||
explicit operator bool () const {
|
||||
return ptr_ != nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> class UniquePtr <T[]> final : public DenyCopying {
|
||||
private:
|
||||
T *ptr_ { };
|
||||
|
||||
public:
|
||||
UniquePtr () = default;
|
||||
|
||||
explicit UniquePtr (T *ptr) : ptr_ (ptr)
|
||||
{ }
|
||||
|
||||
UniquePtr (UniquePtr &&rhs) noexcept : ptr_ (rhs.release ())
|
||||
{ }
|
||||
|
||||
template <typename U> UniquePtr (UniquePtr <U> &&rhs) noexcept : ptr_ (rhs.release ())
|
||||
{ }
|
||||
|
||||
~UniquePtr () {
|
||||
destroy ();
|
||||
}
|
||||
|
||||
public:
|
||||
T *get () const {
|
||||
return ptr_;
|
||||
}
|
||||
|
||||
T *release () {
|
||||
auto ret = ptr_;
|
||||
ptr_ = nullptr;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void reset (T *ptr = nullptr) {
|
||||
destroy ();
|
||||
ptr_ = ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
void destroy () {
|
||||
delete[] ptr_;
|
||||
ptr_ = nullptr;
|
||||
}
|
||||
|
||||
public:
|
||||
UniquePtr &operator = (UniquePtr &&rhs) noexcept {
|
||||
if (this != &rhs) {
|
||||
reset (rhs.release ());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename U> UniquePtr &operator = (UniquePtr <U> &&rhs) noexcept {
|
||||
if (this != &rhs) {
|
||||
reset (rhs.release ());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
UniquePtr &operator = (decltype (nullptr)) {
|
||||
destroy ();
|
||||
return *this;
|
||||
}
|
||||
|
||||
T &operator [] (size_t index) {
|
||||
return ptr_[index];
|
||||
}
|
||||
|
||||
const T &operator [] (size_t index) const {
|
||||
return ptr_[index];
|
||||
}
|
||||
|
||||
explicit operator bool () const {
|
||||
return ptr_ != nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
template <typename T> struct ClearExtent {
|
||||
using Type = T;
|
||||
};
|
||||
|
||||
template <typename T> struct ClearExtent <T[]> {
|
||||
using Type = T;
|
||||
};
|
||||
|
||||
template <typename T, size_t N> struct ClearExtent <T[N]> {
|
||||
using Type = T;
|
||||
};
|
||||
|
||||
template <typename T> struct UniqueIf {
|
||||
using SingleObject = UniquePtr <T>;
|
||||
};
|
||||
|
||||
template <typename T> struct UniqueIf<T[]> {
|
||||
using UnknownBound = UniquePtr <T[]>;
|
||||
};
|
||||
|
||||
template <typename T, size_t N> struct UniqueIf <T[N]> {
|
||||
using KnownBound = void;
|
||||
};
|
||||
}
|
||||
|
||||
template <typename T, typename... Args> typename detail::UniqueIf <T>::SingleObject makeUnique (Args &&... args) {
|
||||
return UniquePtr <T> (new T (cr::forward <Args> (args)...));
|
||||
}
|
||||
|
||||
template <typename T> typename detail::UniqueIf <T>::UnknownBound makeUnique (size_t size) {
|
||||
using Type = typename detail::ClearExtent <T>::Type;
|
||||
return UniquePtr<T> (new Type[size] ());
|
||||
}
|
||||
|
||||
template <typename T, typename... Args> typename detail::UniqueIf <T>::KnownBound makeUnique (Args &&...) = delete;
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -1,325 +0,0 @@
|
|||
//
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2021 YaPB Project <yapb@jeefo.net>.
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <crlib/cr-math.h>
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
// small simd operations for 3d vector
|
||||
#if defined (CR_HAS_SSE)
|
||||
|
||||
template <typename T> class CR_ALIGN16 SimdWrap {
|
||||
private:
|
||||
__m128 wrap_dp_sse2 (__m128 v1, __m128 v2) {
|
||||
auto mul = _mm_mul_ps (v1, v2);
|
||||
auto res = _mm_add_ps (_mm_shuffle_ps (v2, mul, _MM_SHUFFLE (1, 0, 0, 0)), mul);
|
||||
|
||||
mul = _mm_add_ps (_mm_shuffle_ps (mul, res, _MM_SHUFFLE (0, 3, 0, 0)), res);
|
||||
|
||||
return _mm_shuffle_ps (mul, mul, _MM_SHUFFLE (2, 2, 2, 2));
|
||||
}
|
||||
|
||||
public:
|
||||
union {
|
||||
__m128 m;
|
||||
|
||||
struct {
|
||||
T x, y, z;
|
||||
} vec;
|
||||
};
|
||||
|
||||
SimdWrap (const T &x, const T &y, const T &z) {
|
||||
m = _mm_set_ps (0.0f, z, y, x);
|
||||
}
|
||||
|
||||
SimdWrap (const T &x, const T &y) {
|
||||
m = _mm_set_ps (0.0f, 0.0f, y, x);
|
||||
}
|
||||
|
||||
SimdWrap (__m128 m) : m (m)
|
||||
{ }
|
||||
|
||||
public:
|
||||
SimdWrap normalize () {
|
||||
return { _mm_div_ps (m, _mm_sqrt_ps (wrap_dp_sse2 (m, m))) };
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// 3dmath vector
|
||||
template <typename T> class Vec3D {
|
||||
public:
|
||||
T x {};
|
||||
T y {};
|
||||
T z {};
|
||||
|
||||
public:
|
||||
Vec3D (const T &scaler = 0.0f) : x (scaler), y (scaler), z (scaler)
|
||||
{ }
|
||||
|
||||
Vec3D (const T &x, const T &y, const T &z) : x (x), y (y), z (z)
|
||||
{ }
|
||||
|
||||
Vec3D (T *rhs) : x (rhs[0]), y (rhs[1]), z (rhs[2])
|
||||
{ }
|
||||
|
||||
#if defined (CR_HAS_SSE)
|
||||
Vec3D (const SimdWrap <T> &rhs) : x (rhs.vec.x), y (rhs.vec.y), z (rhs.vec.z)
|
||||
{ }
|
||||
#endif
|
||||
|
||||
Vec3D (const Vec3D &) = default;
|
||||
|
||||
Vec3D (decltype (nullptr)) {
|
||||
clear ();
|
||||
}
|
||||
|
||||
public:
|
||||
operator T * () {
|
||||
return &x;
|
||||
}
|
||||
|
||||
operator const T * () const {
|
||||
return &x;
|
||||
}
|
||||
|
||||
Vec3D operator + (const Vec3D &rhs) const {
|
||||
return { x + rhs.x, y + rhs.y, z + rhs.z };
|
||||
}
|
||||
|
||||
Vec3D operator - (const Vec3D &rhs) const {
|
||||
return { x - rhs.x, y - rhs.y, z - rhs.z };
|
||||
}
|
||||
|
||||
Vec3D operator - () const {
|
||||
return { -x, -y, -z };
|
||||
}
|
||||
|
||||
friend Vec3D operator * (const T &scale, const Vec3D &rhs) {
|
||||
return { rhs.x * scale, rhs.y * scale, rhs.z * scale };
|
||||
}
|
||||
|
||||
Vec3D operator * (const T &scale) const {
|
||||
return { scale * x, scale * y, scale * z };
|
||||
}
|
||||
|
||||
Vec3D operator / (const T &rhs) const {
|
||||
const auto inv = 1 / (rhs + kFloatEqualEpsilon);
|
||||
return { inv * x, inv * y, inv * z };
|
||||
}
|
||||
|
||||
// cross product
|
||||
Vec3D operator ^ (const Vec3D &rhs) const {
|
||||
return { y * rhs.z - z * rhs.y, z * rhs.x - x * rhs.z, x * rhs.y - y * rhs.x };
|
||||
}
|
||||
|
||||
// dot product
|
||||
T operator | (const Vec3D &rhs) const {
|
||||
return x * rhs.x + y * rhs.y + z * rhs.z;
|
||||
}
|
||||
|
||||
const Vec3D &operator += (const Vec3D &rhs) {
|
||||
x += rhs.x;
|
||||
y += rhs.y;
|
||||
z += rhs.z;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Vec3D &operator -= (const Vec3D &rhs) {
|
||||
x -= rhs.x;
|
||||
y -= rhs.y;
|
||||
z -= rhs.z;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Vec3D &operator *= (const T &rhs) {
|
||||
x *= rhs;
|
||||
y *= rhs;
|
||||
z *= rhs;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Vec3D &operator /= (const T &rhs) {
|
||||
const auto inv = 1 / (rhs + kFloatEqualEpsilon);
|
||||
|
||||
x *= inv;
|
||||
y *= inv;
|
||||
z *= inv;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator == (const Vec3D &rhs) const {
|
||||
return cr::fequal (x, rhs.x) && cr::fequal (y, rhs.y) && cr::fequal (z, rhs.z);
|
||||
}
|
||||
|
||||
bool operator != (const Vec3D &rhs) const {
|
||||
return !operator == (rhs);
|
||||
}
|
||||
|
||||
void operator = (decltype (nullptr)) {
|
||||
clear ();
|
||||
}
|
||||
|
||||
const float &operator [] (const int i) const {
|
||||
return &(x)[i];
|
||||
}
|
||||
|
||||
float &operator [] (const int i) {
|
||||
return &(x)[i];
|
||||
}
|
||||
|
||||
Vec3D &operator = (const Vec3D &) = default;
|
||||
|
||||
public:
|
||||
T length () const {
|
||||
return cr::sqrtf (lengthSq ());
|
||||
}
|
||||
|
||||
T length2d () const {
|
||||
return cr::sqrtf (cr::square (x) + cr::square (y));
|
||||
}
|
||||
|
||||
T lengthSq () const {
|
||||
return cr::square (x) + cr::square (y) + cr::square (z);
|
||||
}
|
||||
|
||||
Vec3D get2d () const {
|
||||
return { x, y, 0.0f };
|
||||
}
|
||||
|
||||
Vec3D normalize () const {
|
||||
#if defined (CR_HAS_SSE)
|
||||
return SimdWrap <T> { x, y, z }.normalize ();
|
||||
#else
|
||||
auto len = length () + cr::kFloatCmpEpsilon;
|
||||
|
||||
if (cr::fzero (len)) {
|
||||
return { 0.0f, 0.0f, 1.0f };
|
||||
}
|
||||
len = 1.0f / len;
|
||||
return { x * len, y * len, z * len };
|
||||
#endif
|
||||
}
|
||||
|
||||
Vec3D normalize2d () const {
|
||||
#if defined (CR_HAS_SSE)
|
||||
return SimdWrap <T> { x, y }.normalize ();
|
||||
#else
|
||||
auto len = length2d () + cr::kFloatCmpEpsilon;
|
||||
|
||||
if (cr::fzero (len)) {
|
||||
return { 0.0f, 1.0f, 0.0f };
|
||||
}
|
||||
len = 1.0f / len;
|
||||
return { x * len, y * len, 0.0f };
|
||||
#endif
|
||||
}
|
||||
|
||||
bool empty () const {
|
||||
return cr::fzero (x) && cr::fzero (y) && cr::fzero (z);
|
||||
}
|
||||
|
||||
void clear () {
|
||||
x = y = z = 0.0f;
|
||||
}
|
||||
|
||||
Vec3D clampAngles () {
|
||||
x = cr::normalizeAngles (x);
|
||||
y = cr::normalizeAngles (y);
|
||||
z = 0.0f;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
T pitch () const {
|
||||
if (cr::fzero (z)) {
|
||||
return 0.0f;
|
||||
}
|
||||
return cr::deg2rad (cr::atan2f (z, length2d ()));
|
||||
}
|
||||
|
||||
T yaw () const {
|
||||
if (cr::fzero (x) && cr::fzero (y)) {
|
||||
return 0.0f;
|
||||
}
|
||||
return cr::rad2deg (cr:: atan2f (y, x));
|
||||
}
|
||||
|
||||
Vec3D angles () const {
|
||||
if (cr::fzero (x) && cr::fzero (y)) {
|
||||
return { z > 0.0f ? 90.0f : 270.0f, 0.0, 0.0f };
|
||||
}
|
||||
return { cr::rad2deg (cr::atan2f (z, length2d ())), cr::rad2deg (cr::atan2f (y, x)), 0.0f };
|
||||
}
|
||||
|
||||
void angleVectors (Vec3D *forward, Vec3D *right, Vec3D *upward) const {
|
||||
enum { pitch, yaw, roll, unused, max };
|
||||
|
||||
T sines[max] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
T cosines[max] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
|
||||
// compute the sine and cosine compontents
|
||||
cr::sincosf (cr::deg2rad (x), cr::deg2rad (y), cr::deg2rad (z), sines, cosines);
|
||||
|
||||
if (forward) {
|
||||
*forward = {
|
||||
cosines[pitch] * cosines[yaw],
|
||||
cosines[pitch] * sines[yaw],
|
||||
-sines[pitch]
|
||||
};
|
||||
}
|
||||
|
||||
if (right) {
|
||||
*right = {
|
||||
-sines[roll] * sines[pitch] * cosines[yaw] + cosines[roll] * sines[yaw],
|
||||
-sines[roll] * sines[pitch] * sines[yaw] - cosines[roll] * cosines[yaw],
|
||||
-sines[roll] * cosines[pitch]
|
||||
};
|
||||
}
|
||||
|
||||
if (upward) {
|
||||
*upward = {
|
||||
cosines[roll] * sines[pitch] * cosines[yaw] + sines[roll] * sines[yaw],
|
||||
upward->y = cosines[roll] * sines[pitch] * sines[yaw] - sines[roll] * cosines[yaw],
|
||||
upward->z = cosines[roll] * cosines[pitch]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const Vec3D &forward () {
|
||||
static Vec3D s_fwd {};
|
||||
angleVectors (&s_fwd, nullptr, nullptr);
|
||||
|
||||
return s_fwd;
|
||||
}
|
||||
|
||||
const Vec3D &upward () {
|
||||
static Vec3D s_up {};
|
||||
angleVectors (nullptr, nullptr, &s_up);
|
||||
|
||||
return s_up;
|
||||
}
|
||||
|
||||
const Vec3D &right () {
|
||||
static Vec3D s_right {};
|
||||
angleVectors (nullptr, &s_right, nullptr);
|
||||
|
||||
return s_right;
|
||||
}
|
||||
};
|
||||
|
||||
// default is float
|
||||
using Vector = Vec3D <float>;
|
||||
|
||||
CR_NAMESPACE_END
|
||||
Loading…
Add table
Add a link
Reference in a new issue