Get latest changes from LPP bot
This commit is contained in:
+2
-2
@@ -36,11 +36,11 @@ DN_API DN_USize DN_CPU_HasFeatureArray(DN_CPUReport const *report, DN_CPUFeature
|
||||
{
|
||||
DN_USize result = 0;
|
||||
DN_USize const BITS = sizeof(report->features[0]) * 8;
|
||||
DN_ForIndexU(feature_index, features_size) {
|
||||
for (DN_ForIndexU(feature_index, features_size)) {
|
||||
DN_CPUFeatureQuery *query = features + feature_index;
|
||||
DN_USize chunk_index = query->feature / BITS;
|
||||
DN_USize chunk_bit = query->feature % BITS;
|
||||
DN_U64 chunk = report->features[chunk_index];
|
||||
DN_U64 chunk = report->features[chunk_index];
|
||||
query->available = chunk & (1ULL << chunk_bit);
|
||||
result += DN_CAST(int) query->available;
|
||||
}
|
||||
|
||||
+26
-25
@@ -16,11 +16,11 @@
|
||||
#include <stdlib.h> // exit()
|
||||
#endif
|
||||
|
||||
#define DN_ForIndexU(index, size) for (DN_USize index = 0; index < size; index++)
|
||||
#define DN_ForIndexI(index, size) for (DN_ISize index = 0; index < size; index++)
|
||||
#define DN_ForItSize(it, T, array, size) for (struct { DN_USize index; T *data; } it = {0, &(array)[0]}; it.index < (size); it.index++, it.data++)
|
||||
#define DN_ForIt(it, T, array) for (struct { DN_USize index; T *data; } it = {0, &(array)->data[0]}; it.index < (array)->size; it.index++, it.data++)
|
||||
#define DN_ForItCArray(it, T, array) for (struct { DN_USize index; T *data; } it = {0, &(array)[0]}; it.index < DN_ArrayCountU(array); it.index++, it.data++)
|
||||
#define DN_ForIndexU(index, size) DN_USize index = 0; index < size; index++
|
||||
#define DN_ForIndexI(index, size) DN_ISize index = 0; index < size; index++
|
||||
#define DN_ForItSize(it, T, array, size) struct { DN_USize index; T *data; } it = {0, &(array)[0]}; it.index < (size); it.index++, it.data++
|
||||
#define DN_ForIt(it, T, array) struct { DN_USize index; T *data; } it = {0, &(array)->data[0]}; it.index < (array)->size; it.index++, it.data++
|
||||
#define DN_ForItCArray(it, T, array) struct { DN_USize index; T *data; } it = {0, &(array)[0]}; it.index < DN_ArrayCountU(array); it.index++, it.data++
|
||||
|
||||
#define DN_AlignUpPowerOfTwo(value, pot) (((uintptr_t)(value) + ((uintptr_t)(pot) - 1)) & ~((uintptr_t)(pot) - 1))
|
||||
#define DN_AlignDownPowerOfTwo(value, pot) ((uintptr_t)(value) & ~((uintptr_t)(pot) - 1))
|
||||
@@ -152,10 +152,10 @@ struct DN_DeferHelper
|
||||
#define DN_DEFER const auto DN_UniqueName(defer_lambda_) = DN_DeferHelper() + [&]()
|
||||
#endif // defined(__cplusplus)
|
||||
|
||||
#define DN_DEFER_LOOP(begin, end) \
|
||||
for (bool DN_UniqueName(once) = (begin, true); \
|
||||
DN_UniqueName(once); \
|
||||
end, DN_UniqueName(once) = false)
|
||||
#define DN_DeferLoop(begin, end) \
|
||||
bool DN_UniqueName(once) = (begin, true); \
|
||||
DN_UniqueName(once); \
|
||||
end, DN_UniqueName(once) = false
|
||||
|
||||
// NOTE: Types /////////////////////////////////////////////////////////////////////////////////////
|
||||
typedef intptr_t DN_ISize;
|
||||
@@ -246,20 +246,18 @@ struct DN_CallSite
|
||||
#include <intrin.h>
|
||||
#define DN_Atomic_CompareExchange64(dest, desired_val, prev_val) _InterlockedCompareExchange64((__int64 volatile *)dest, desired_val, prev_val)
|
||||
#define DN_Atomic_CompareExchange32(dest, desired_val, prev_val) _InterlockedCompareExchange((long volatile *)dest, desired_val, prev_val)
|
||||
|
||||
#define DN_Atomic_LoadU64(target) *(target)
|
||||
#define DN_Atomic_LoadU32(target) *(target)
|
||||
#define DN_Atomic_AddU32(target, value) _InterlockedExchangeAdd((long volatile *)target, value)
|
||||
#define DN_Atomic_AddU64(target, value) _InterlockedExchangeAdd64((__int64 volatile *)target, value)
|
||||
#define DN_Atomic_SubU32(target, value) DN_Atomic_AddU32(DN_CAST(long volatile *) target, (long)-value)
|
||||
#define DN_Atomic_SubU64(target, value) DN_Atomic_AddU64(target, (DN_U64) - value)
|
||||
|
||||
#define DN_CountLeadingZerosU64(value) __lzcnt64(value)
|
||||
|
||||
#define DN_CPU_TSC() __rdtsc()
|
||||
#define DN_CompilerReadBarrierAndCPUReadFence \
|
||||
_ReadBarrier(); \
|
||||
_mm_lfence()
|
||||
#define DN_CompilerWriteBarrierAndCPUWriteFence \
|
||||
_WriteBarrier(); \
|
||||
_mm_sfence()
|
||||
#define DN_CountLeadingZerosU64(value) __lzcnt64(value)
|
||||
#define DN_CPU_TSC() __rdtsc()
|
||||
#define DN_CompilerReadBarrierAndCPUReadFence _ReadBarrier(); _mm_lfence()
|
||||
#define DN_CompilerWriteBarrierAndCPUWriteFence _WriteBarrier(); _mm_sfence()
|
||||
#elif defined(DN_COMPILER_GCC) || defined(DN_COMPILER_CLANG)
|
||||
#if defined(__ANDROID__)
|
||||
#elif defined(DN_PLATFORM_EMSCRIPTEN)
|
||||
@@ -268,17 +266,20 @@ struct DN_CallSite
|
||||
#include <x86intrin.h>
|
||||
#endif
|
||||
|
||||
#define DN_Atomic_AddU32(target, value) __atomic_fetch_add(target, value, __ATOMIC_ACQ_REL)
|
||||
#define DN_Atomic_AddU64(target, value) __atomic_fetch_add(target, value, __ATOMIC_ACQ_REL)
|
||||
#define DN_Atomic_SubU32(target, value) __atomic_fetch_sub(target, value, __ATOMIC_ACQ_REL)
|
||||
#define DN_Atomic_SubU64(target, value) __atomic_fetch_sub(target, value, __ATOMIC_ACQ_REL)
|
||||
#define DN_Atomic_LoadU64(target) __atomic_load_n(x, __ATOMIC_SEQ_CST)
|
||||
#define DN_Atomic_LoadU32(target) __atomic_load_n(x, __ATOMIC_SEQ_CST)
|
||||
#define DN_Atomic_AddU32(target, value) __atomic_fetch_add(target, value, __ATOMIC_ACQ_REL)
|
||||
#define DN_Atomic_AddU64(target, value) __atomic_fetch_add(target, value, __ATOMIC_ACQ_REL)
|
||||
#define DN_Atomic_SubU32(target, value) __atomic_fetch_sub(target, value, __ATOMIC_ACQ_REL)
|
||||
#define DN_Atomic_SubU64(target, value) __atomic_fetch_sub(target, value, __ATOMIC_ACQ_REL)
|
||||
|
||||
#define DN_CountLeadingZerosU64(value) __builtin_clzll(value)
|
||||
#define DN_CountLeadingZerosU64(value) __builtin_clzll(value)
|
||||
#if defined(DN_COMPILER_GCC)
|
||||
#define DN_CPU_TSC() __rdtsc()
|
||||
#else
|
||||
#define DN_CPU_TSC() __builtin_readcyclecounter()
|
||||
#endif
|
||||
|
||||
#if defined(DN_PLATFORM_EMSCRIPTEN)
|
||||
#define DN_CompilerReadBarrierAndCPUReadFence
|
||||
#define DN_CompilerWriteBarrierAndCPUWriteFence
|
||||
@@ -406,7 +407,7 @@ struct DN_TicketMutex
|
||||
|
||||
// NOTE: Intrinsics ////////////////////////////////////////////////////////////////////////////////
|
||||
DN_FORCE_INLINE DN_U64 DN_Atomic_SetValue64 (DN_U64 volatile *target, DN_U64 value);
|
||||
DN_FORCE_INLINE long DN_Atomic_SetValue32 (long volatile *target, long value);
|
||||
DN_FORCE_INLINE DN_U32 DN_Atomic_SetValue32 (DN_U32 volatile *target, DN_U32 value);
|
||||
|
||||
#if !defined (DN_PLATFORM_ARM64)
|
||||
DN_API DN_CPUIDResult DN_CPU_ID (DN_CPUIDArgs args);
|
||||
@@ -515,7 +516,7 @@ DN_FORCE_INLINE DN_U64 DN_Atomic_SetValue64(DN_U64 volatile *target, DN_U64 valu
|
||||
#endif
|
||||
}
|
||||
|
||||
DN_FORCE_INLINE long DN_Atomic_SetValue32(long volatile *target, long value)
|
||||
DN_FORCE_INLINE DN_U32 DN_Atomic_SetValue32(DN_U32 volatile *target, DN_U32 value)
|
||||
{
|
||||
#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL)
|
||||
long result;
|
||||
|
||||
@@ -1,5 +1,49 @@
|
||||
#define DN_CONTAINERS_CPP
|
||||
|
||||
#include "../dn_base_inc.h"
|
||||
|
||||
DN_API bool DN_Ring_HasSpace(DN_Ring const *ring, DN_U64 size)
|
||||
{
|
||||
DN_U64 avail = ring->write_pos - ring->read_pos;
|
||||
DN_U64 space = ring->size - avail;
|
||||
bool result = space >= size;
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_Ring_HasData(DN_Ring const *ring, DN_U64 size)
|
||||
{
|
||||
DN_U64 data = ring->write_pos - ring->read_pos;
|
||||
bool result = data >= size;
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API void DN_Ring_Write(DN_Ring *ring, void const *src, DN_U64 src_size)
|
||||
{
|
||||
DN_Assert(src_size <= ring->size);
|
||||
DN_U64 offset = ring->write_pos % ring->size;
|
||||
DN_U64 bytes_before_split = ring->size - offset;
|
||||
DN_U64 pre_split_bytes = DN_Min(bytes_before_split, src_size);
|
||||
DN_U64 post_split_bytes = src_size - pre_split_bytes;
|
||||
void const *pre_split_data = src;
|
||||
void const *post_split_data = ((char *)src + pre_split_bytes);
|
||||
DN_Memcpy(ring->base + offset, pre_split_data, pre_split_bytes);
|
||||
DN_Memcpy(ring->base, post_split_data, post_split_bytes);
|
||||
ring->write_pos += src_size;
|
||||
}
|
||||
|
||||
DN_API void DN_Ring_Read(DN_Ring *ring, void *dest, DN_U64 dest_size)
|
||||
{
|
||||
DN_Assert(dest_size <= ring->size);
|
||||
DN_U64 offset = ring->read_pos % ring->size;
|
||||
DN_U64 bytes_before_split = ring->size - offset;
|
||||
DN_U64 pre_split_bytes = DN_Min(bytes_before_split, dest_size);
|
||||
DN_U64 post_split_bytes = dest_size - pre_split_bytes;
|
||||
DN_Memcpy(dest, ring->base + offset, pre_split_bytes);
|
||||
DN_Memcpy((char *)dest + pre_split_bytes, ring->base, post_split_bytes);
|
||||
ring->read_pos += dest_size;
|
||||
}
|
||||
#define DN_Ring_WriteStruct(ring, item) DN_Ring_Write((ring), (item), sizeof(*(item)))
|
||||
|
||||
// NOTE: DN_CArray /////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
DN_ArrayEraseResult DN_CArray_EraseRange(T *data, DN_USize *size, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase)
|
||||
@@ -936,7 +980,7 @@ template <typename T, size_t N>
|
||||
DN_List<T> DN_List_InitCArray(DN_Arena *arena, DN_USize chunk_size, T const (&array)[N])
|
||||
{
|
||||
DN_List<T> result = DN_List_Init<T>(arena, chunk_size);
|
||||
DN_ForIndexU(index, N)
|
||||
for (DN_ForIndexU(index, N))
|
||||
DN_List_Add(&result, array[index]);
|
||||
return result;
|
||||
}
|
||||
@@ -945,7 +989,7 @@ template <typename T>
|
||||
DN_List<T> DN_List_InitSliceCopy(DN_Arena *arena, DN_USize chunk_size, DN_Slice<T> slice)
|
||||
{
|
||||
DN_List<T> result = DN_List_Init<T>(arena, chunk_size);
|
||||
DN_ForIndexU(index, slice.size)
|
||||
for (DN_ForIndexU(index, slice.size))
|
||||
DN_List_Add(&result, slice.data[index]);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
#if !defined(DN_CONTAINERS_H)
|
||||
#define DN_CONTAINERS_H
|
||||
|
||||
#include "../dn_base_inc.h"
|
||||
|
||||
struct DN_Ring
|
||||
{
|
||||
DN_U64 size;
|
||||
char *base;
|
||||
DN_U64 write_pos;
|
||||
DN_U64 read_pos;
|
||||
};
|
||||
|
||||
// NOTE: DN_CArray /////////////////////////////////////////////////////////////////////////////////
|
||||
enum DN_ArrayErase
|
||||
{
|
||||
@@ -149,6 +159,11 @@ template <typename T> struct DN_List
|
||||
};
|
||||
#endif // !defined(DN_NO_LIST)
|
||||
|
||||
DN_API bool DN_Ring_HasSpace (DN_Ring const *ring, DN_U64 size);
|
||||
DN_API bool DN_Ring_HasData (DN_Ring const *ring, DN_U64 size);
|
||||
DN_API void DN_Ring_Write (DN_Ring *ring, void const *src, DN_U64 src_size);
|
||||
DN_API void DN_Ring_Read (DN_Ring *ring, void *dest, DN_U64 dest_size);
|
||||
|
||||
template <typename T> DN_ArrayEraseResult DN_CArray_EraseRange (T *data, DN_USize *size, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase);
|
||||
template <typename T> T * DN_CArray_MakeArray (T *data, DN_USize *size, DN_USize max, DN_USize count, DN_ZeroMem zero_mem);
|
||||
template <typename T> T * DN_CArray_InsertArray (T *data, DN_USize *size, DN_USize max, DN_USize index, T const *items, DN_USize count);
|
||||
|
||||
@@ -151,7 +151,7 @@ DN_API DN_Str8 DN_CVT_F64ToAge(DN_Arena *arena, DN_F64 age_s, DN_CVTU64AgeUnit u
|
||||
if (!arena)
|
||||
return result;
|
||||
|
||||
char buffer[128];
|
||||
char buffer[256];
|
||||
DN_Arena stack_arena = DN_Arena_InitFromBuffer(buffer, sizeof(buffer), DN_ArenaFlags_NoPoison);
|
||||
DN_Str8Builder builder = DN_Str8Builder_Init(&stack_arena);
|
||||
DN_F64 remainder = age_s;
|
||||
|
||||
@@ -60,12 +60,14 @@ DN_API DN_LOGPrefixSize DN_LOG_MakePrefix(DN_LOGStyle style, DN_LOGTypeParam typ
|
||||
DN_GCC_WARNING_PUSH
|
||||
DN_GCC_WARNING_DISABLE(-Wformat)
|
||||
DN_GCC_WARNING_DISABLE(-Wformat-extra-args)
|
||||
DN_MSVC_WARNING_PUSH
|
||||
DN_MSVC_WARNING_DISABLE(4477)
|
||||
int size = DN_SNPrintF(dest,
|
||||
DN_CAST(int)dest_size,
|
||||
"%04u-%02u-%02uT%02u:%02u:%02u" // date
|
||||
"%S" // colour
|
||||
"%S" // bold
|
||||
"%S" // type
|
||||
" %S" // type
|
||||
"%.*s" // type padding
|
||||
"%S" // reset
|
||||
" %S" // file name
|
||||
@@ -85,6 +87,7 @@ DN_API DN_LOGPrefixSize DN_LOG_MakePrefix(DN_LOGStyle style, DN_LOGTypeParam typ
|
||||
reset_esc, // reset
|
||||
file_name, // file name
|
||||
call_site.line); // line number
|
||||
DN_MSVC_WARNING_POP // '%S' requires an argument of type 'wchar_t *', but variadic argument 7 has type 'DN_Str8'
|
||||
DN_GCC_WARNING_POP
|
||||
|
||||
static DN_USize max_header_length = 0;
|
||||
|
||||
@@ -336,13 +336,12 @@ DN_API bool DN_Arena_OwnsPtr(DN_Arena const *arena, void *ptr)
|
||||
DN_API DN_ArenaStats DN_Arena_SumStatsArray(DN_ArenaStats const *array, DN_USize size)
|
||||
{
|
||||
DN_ArenaStats result = {};
|
||||
DN_ForItSize(it, DN_ArenaStats const, array, size)
|
||||
{
|
||||
DN_ArenaStats stats = *it.data;
|
||||
result.info.used += stats.info.used;
|
||||
result.info.commit += stats.info.commit;
|
||||
for (DN_ForItSize(it, DN_ArenaStats const, array, size)) {
|
||||
DN_ArenaStats stats = *it.data;
|
||||
result.info.used += stats.info.used;
|
||||
result.info.commit += stats.info.commit;
|
||||
result.info.reserve += stats.info.reserve;
|
||||
result.info.blocks += stats.info.blocks;
|
||||
result.info.blocks += stats.info.blocks;
|
||||
|
||||
result.hwm.used = DN_Max(result.hwm.used, result.info.used);
|
||||
result.hwm.commit = DN_Max(result.hwm.commit, result.info.commit);
|
||||
|
||||
@@ -272,7 +272,7 @@ DN_API DN_Str8 DN_Str8_Segment(DN_Arena *arena, DN_Str8 src, DN_USize segment_si
|
||||
DN_USize segment_counter = 0;
|
||||
DN_Str8 result = DN_Str8_Alloc(arena, src.size + segments, DN_ZeroMem_Yes);
|
||||
DN_USize write_index = 0;
|
||||
DN_ForIndexU(src_index, src.size) {
|
||||
for (DN_ForIndexU(src_index, src.size)) {
|
||||
result.data[write_index++] = src.data[src_index];
|
||||
if ((src_index + 1) % segment_size == 0 && segment_counter < segments) {
|
||||
result.data[write_index++] = segment_char;
|
||||
@@ -664,7 +664,7 @@ DN_API DN_Str8DotTruncateResult DN_Str8_DotTruncateMiddle(DN_Arena *arena, DN_St
|
||||
DN_API DN_Str8 DN_Str8_Lower(DN_Arena *arena, DN_Str8 string)
|
||||
{
|
||||
DN_Str8 result = DN_Str8_Copy(arena, string);
|
||||
DN_ForIndexU(index, result.size)
|
||||
for (DN_ForIndexU(index, result.size))
|
||||
result.data[index] = DN_Char_ToLower(result.data[index]);
|
||||
return result;
|
||||
}
|
||||
@@ -672,7 +672,7 @@ DN_API DN_Str8 DN_Str8_Lower(DN_Arena *arena, DN_Str8 string)
|
||||
DN_API DN_Str8 DN_Str8_Upper(DN_Arena *arena, DN_Str8 string)
|
||||
{
|
||||
DN_Str8 result = DN_Str8_Copy(arena, string);
|
||||
DN_ForIndexU(index, result.size)
|
||||
for (DN_ForIndexU(index, result.size))
|
||||
result.data[index] = DN_Char_ToUpper(result.data[index]);
|
||||
return result;
|
||||
}
|
||||
@@ -774,7 +774,7 @@ DN_API bool DN_Str8Builder_AddArrayRef(DN_Str8Builder *builder, DN_Str8 const *s
|
||||
return false;
|
||||
|
||||
if (add == DN_Str8BuilderAdd_Append) {
|
||||
DN_ForIndexU(index, size) {
|
||||
for (DN_ForIndexU(index, size)) {
|
||||
DN_Str8 string = strings[index];
|
||||
DN_Str8Link *link = links + index;
|
||||
|
||||
@@ -821,8 +821,7 @@ DN_API bool DN_Str8Builder_AddArrayCopy(DN_Str8Builder *builder, DN_Str8 const *
|
||||
DN_ArenaTempMem tmp_mem = DN_Arena_TempMemBegin(builder->arena);
|
||||
bool result = true;
|
||||
DN_Str8 *strings_copy = DN_Arena_NewArray(builder->arena, DN_Str8, size, DN_ZeroMem_No);
|
||||
DN_ForIndexU(index, size)
|
||||
{
|
||||
for (DN_ForIndexU(index, size)) {
|
||||
strings_copy[index] = DN_Str8_Copy(builder->arena, strings[index]);
|
||||
if (strings_copy[index].size != strings[index].size) {
|
||||
result = false;
|
||||
|
||||
+15
-23
@@ -1,30 +1,22 @@
|
||||
#if !defined(DN_BASE_STRING_H)
|
||||
#define DN_BASE_STRING_H
|
||||
|
||||
#if defined(DN_USE_STD_PRINTF)
|
||||
#include <stdio.h>
|
||||
#define DN_SPrintF(...) sprintf(__VA_ARGS__)
|
||||
#define DN_SNPrintF(...) snprintf(__VA_ARGS__)
|
||||
#define DN_VSPrintF(...) vsprintf(__VA_ARGS__)
|
||||
#define DN_VSNPrintF(...) vsnprintf(__VA_ARGS__)
|
||||
#else
|
||||
#if !defined(DN_STB_SPRINTF_HEADER_ONLY)
|
||||
#define STB_SPRINTF_IMPLEMENTATION
|
||||
#define STB_SPRINTF_STATIC
|
||||
#endif
|
||||
DN_MSVC_WARNING_PUSH
|
||||
DN_MSVC_WARNING_DISABLE(4505) // Unused function warning
|
||||
DN_GCC_WARNING_PUSH
|
||||
DN_GCC_WARNING_DISABLE(-Wunused-function)
|
||||
#include "../External/stb_sprintf.h"
|
||||
DN_GCC_WARNING_POP
|
||||
DN_MSVC_WARNING_POP
|
||||
|
||||
#define DN_SPrintF(...) STB_SPRINTF_DECORATE(sprintf)(__VA_ARGS__)
|
||||
#define DN_SNPrintF(...) STB_SPRINTF_DECORATE(snprintf)(__VA_ARGS__)
|
||||
#define DN_VSPrintF(...) STB_SPRINTF_DECORATE(vsprintf)(__VA_ARGS__)
|
||||
#define DN_VSNPrintF(...) STB_SPRINTF_DECORATE(vsnprintf)(__VA_ARGS__)
|
||||
#if !defined(DN_STB_SPRINTF_HEADER_ONLY)
|
||||
#define STB_SPRINTF_IMPLEMENTATION
|
||||
#define STB_SPRINTF_STATIC
|
||||
#endif
|
||||
DN_MSVC_WARNING_PUSH
|
||||
DN_MSVC_WARNING_DISABLE(4505) // Unused function warning
|
||||
DN_GCC_WARNING_PUSH
|
||||
DN_GCC_WARNING_DISABLE(-Wunused-function)
|
||||
#include "../External/stb_sprintf.h"
|
||||
DN_GCC_WARNING_POP
|
||||
DN_MSVC_WARNING_POP
|
||||
|
||||
#define DN_SPrintF(...) STB_SPRINTF_DECORATE(sprintf)(__VA_ARGS__)
|
||||
#define DN_SNPrintF(...) STB_SPRINTF_DECORATE(snprintf)(__VA_ARGS__)
|
||||
#define DN_VSPrintF(...) STB_SPRINTF_DECORATE(vsprintf)(__VA_ARGS__)
|
||||
#define DN_VSNPrintF(...) STB_SPRINTF_DECORATE(vsnprintf)(__VA_ARGS__)
|
||||
|
||||
/*
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Reference in New Issue
Block a user