<commit_before>
// ByteBuffer.cpp

// Implements the cByteBuffer class representing a ringbuffer of bytes

#include "Globals.h"

#include "ByteBuffer.h"
#include "Endianness.h"
#include "OSSupport/IsThread.h"





/** When defined, each access to a cByteBuffer object is checked whether it's done in the same thread.
cByteBuffer assumes that it is not used by multiple threads at once, this macro adds a runtime check for that.
Unfortunately it is very slow, so it is disabled even for regular DEBUG builds. */
// #define DEBUG_SINGLE_THREAD_ACCESS





// Try to determine endianness:
#if ( \
	defined(__i386__) || defined(__alpha__) || \
	defined(__ia64) || defined(__ia64__) || \
	defined(_M_IX86) || defined(_M_IA64) || \
	defined(_M_ALPHA) || defined(__amd64) || \
	defined(__amd64__) || defined(_M_AMD64) || \
	defined(__x86_64) || defined(__x86_64__) || \
	defined(_M_X64) || defined(__bfin__) || \
	defined(__ARMEL__) || \
	(defined(_WIN32) && defined(__ARM__) && defined(_MSC_VER)) \
)
	#define IS_LITTLE_ENDIAN
#elif ( \
	defined (__ARMEB__) || defined(__sparc) || defined(__powerpc__) || defined(__POWERPC__) \
)
	#define IS_BIG_ENDIAN
#else
	#error Cannot determine endianness of this platform
#endif

// If a string sent over the protocol is larger than this, a warning is emitted to the console
#define MAX_STRING_SIZE (512 KiB)

#define NEEDBYTES(Num) if (!CanReadBytes(Num))  return false;  // Check if at least Num bytes can be read from  the buffer, return false if not
#define PUTBYTES(Num)  if (!CanWriteBytes(Num)) return false;  // Check if at least Num bytes can be written to the buffer, return false if not





#ifdef SELF_TEST

/// Self-test of the VarInt-reading and writing code
static class cByteBufferSelfTest
{
public:
	cByteBufferSelfTest(void)
	{
		TestRead();
		TestWrite();
		TestWrap();
	}
	
	void TestRead(void)
	{
		cByteBuffer buf(50);
		buf.Write("\x05\xac\x02\x00", 4);
		UInt32 v1;
		assert_test(buf.ReadVarInt(v1) && (v1 == 5));
		UInt32 v2;
		assert_test(buf.ReadVarInt(v2) && (v2 == 300));
		UInt32 v3;
		assert_test(buf.ReadVarInt(v3) && (v3 == 0));
	}
	
	void TestWrite(void)
	{
		cByteBuffer buf(50);
		buf.WriteVarInt(5);
		buf.WriteVarInt(300);
		buf.WriteVarInt(0);
		AString All;
		buf.ReadAll(All);
		assert_test(All.size() == 4);
		assert_test(memcmp(All.data(), "\x05\xac\x02\x00", All.size()) == 0);
	}
	
	void TestWrap(void)
	{
		cByteBuffer buf(3);
		for (int i = 0; i < 1000; i++)
		{
			size_t FreeSpace = buf.GetFreeSpace();
			assert_test(buf.GetReadableSpace() == 0);
			assert_test(FreeSpace > 0);
			assert_test(buf.Write("a", 1));
			assert_test(buf.CanReadBytes(1));
			assert_test(buf.GetReadableSpace() == 1);
			unsigned char v = 0;
			assert_test(buf.ReadByte(v));
			assert_test(v == 'a');
			assert_test(buf.GetReadableSpace() == 0);
			buf.CommitRead();
			assert_test(buf.GetFreeSpace() == FreeSpace);  // We're back to normal
		}
	}
	
} g_ByteBufferTest;

#endif





#ifdef DEBUG_SINGLE_THREAD_ACCESS

	/** Simple RAII class that is used for checking that no two threads are using an object simultanously.
	It requires the monitored object to provide the storage for a thread ID.
	It uses that storage to check if the thread ID of consecutive calls is the same all the time. */
	class cSingleThreadAccessChecker
	{
	public:
		cSingleThreadAccessChecker(std::thread::id * a_ThreadID) :
			m_ThreadID(a_ThreadID)
		{
			ASSERT(
				(*a_ThreadID == std::this_thread::get_id()) ||  // Either the object is used by current thread...
				(*a_ThreadID == std::thread::id())              // ... or by no thread at all
			);

			// Mark as being used by this thread:
			*m_ThreadID = std::this_thread::get_id();
		}

		~cSingleThreadAccessChecker()
		{
			// Mark as not being used by any thread:
			*m_ThreadID = std::thread::id();
		}

	protected:
		/** Points to the storage used for ID of the thread using the object. */
		std::thread::id * m_ThreadID;
	};

	#define CHECK_THREAD cSingleThreadAccessChecker Checker(&m_ThreadID);

#else<commit_msg>cByteBuffer: Improved SingleThreadAccessChecker performance.<commit_after>
// ByteBuffer.cpp

// Implements the cByteBuffer class representing a ringbuffer of bytes

#include "Globals.h"

#include "ByteBuffer.h"
#include "Endianness.h"
#include "OSSupport/IsThread.h"





/** When defined, each access to a cByteBuffer object is checked whether it's done in the same thread.
cByteBuffer assumes that it is not used by multiple threads at once, this macro adds a runtime check for that.
Unfortunately it is very slow, so it is disabled even for regular DEBUG builds. */
// #define DEBUG_SINGLE_THREAD_ACCESS





// Try to determine endianness:
#if ( \
	defined(__i386__) || defined(__alpha__) || \
	defined(__ia64) || defined(__ia64__) || \
	defined(_M_IX86) || defined(_M_IA64) || \
	defined(_M_ALPHA) || defined(__amd64) || \
	defined(__amd64__) || defined(_M_AMD64) || \
	defined(__x86_64) || defined(__x86_64__) || \
	defined(_M_X64) || defined(__bfin__) || \
	defined(__ARMEL__) || \
	(defined(_WIN32) && defined(__ARM__) && defined(_MSC_VER)) \
)
	#define IS_LITTLE_ENDIAN
#elif ( \
	defined (__ARMEB__) || defined(__sparc) || defined(__powerpc__) || defined(__POWERPC__) \
)
	#define IS_BIG_ENDIAN
#else
	#error Cannot determine endianness of this platform
#endif

// If a string sent over the protocol is larger than this, a warning is emitted to the console
#define MAX_STRING_SIZE (512 KiB)

#define NEEDBYTES(Num) if (!CanReadBytes(Num))  return false;  // Check if at least Num bytes can be read from  the buffer, return false if not
#define PUTBYTES(Num)  if (!CanWriteBytes(Num)) return false;  // Check if at least Num bytes can be written to the buffer, return false if not





#ifdef SELF_TEST

/// Self-test of the VarInt-reading and writing code
static class cByteBufferSelfTest
{
public:
	cByteBufferSelfTest(void)
	{
		TestRead();
		TestWrite();
		TestWrap();
	}
	
	void TestRead(void)
	{
		cByteBuffer buf(50);
		buf.Write("\x05\xac\x02\x00", 4);
		UInt32 v1;
		assert_test(buf.ReadVarInt(v1) && (v1 == 5));
		UInt32 v2;
		assert_test(buf.ReadVarInt(v2) && (v2 == 300));
		UInt32 v3;
		assert_test(buf.ReadVarInt(v3) && (v3 == 0));
	}
	
	void TestWrite(void)
	{
		cByteBuffer buf(50);
		buf.WriteVarInt(5);
		buf.WriteVarInt(300);
		buf.WriteVarInt(0);
		AString All;
		buf.ReadAll(All);
		assert_test(All.size() == 4);
		assert_test(memcmp(All.data(), "\x05\xac\x02\x00", All.size()) == 0);
	}
	
	void TestWrap(void)
	{
		cByteBuffer buf(3);
		for (int i = 0; i < 1000; i++)
		{
			size_t FreeSpace = buf.GetFreeSpace();
			assert_test(buf.GetReadableSpace() == 0);
			assert_test(FreeSpace > 0);
			assert_test(buf.Write("a", 1));
			assert_test(buf.CanReadBytes(1));
			assert_test(buf.GetReadableSpace() == 1);
			unsigned char v = 0;
			assert_test(buf.ReadByte(v));
			assert_test(v == 'a');
			assert_test(buf.GetReadableSpace() == 0);
			buf.CommitRead();
			assert_test(buf.GetFreeSpace() == FreeSpace);  // We're back to normal
		}
	}
	
} g_ByteBufferTest;

#endif





#ifdef DEBUG_SINGLE_THREAD_ACCESS

	/** Simple RAII class that is used for checking that no two threads are using an object simultanously.
	It requires the monitored object to provide the storage for a thread ID.
	It uses that storage to check if the thread ID of consecutive calls is the same all the time. */
	class cSingleThreadAccessChecker
	{
	public:
		cSingleThreadAccessChecker(std::thread::id * a_ThreadID) :
			m_ThreadID(a_ThreadID)
		{
			ASSERT(
				(*a_ThreadID == std::this_thread::get_id()) ||  // Either the object is used by current thread...
				(*a_ThreadID == m_EmptyThreadID)                // ... or by no thread at all
			);

			// Mark as being used by this thread:
			*m_ThreadID = std::this_thread::get_id();
		}

		~cSingleThreadAccessChecker()
		{
			// Mark as not being used by any thread:
			*m_ThreadID = std::thread::id();
		}

	protected:
		/** Points to the storage used for ID of the thread using the object. */
		std::thread::id * m_ThreadID;

		/** The value of an unassigned thread ID, used to speed up checking. */
		static std::thread::id m_EmptyThreadID;
	};

	std::thread::id cSingleThreadAccessChecker::m_EmptyThreadID;

	#define CHECK_THREAD cSingleThreadAccessChecker Checker(&m_ThreadID);

#else
{'fraction_non_alphanumeric': 0.12785774767146485, 'fraction_numerical': 0.02153138986331196, 'mean_word_length': 4.004842615012106, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6229970', 'n_tokens_mistral': 3131, 'n_tokens_neox': 2803, 'n_words': 805}