Skip to content

Commit

Permalink
[STRSAFE] Implement StrSafe_CchCopy(A/W)
Browse files Browse the repository at this point in the history
  • Loading branch information
RatinCN committed Sep 22, 2024
1 parent 402648d commit c500ed2
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 12 deletions.
100 changes: 88 additions & 12 deletions Source/Include/KNSoft/NDK/Extension/StrSafe.h
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
#pragma once
/*
* KNSoft.NDK StrSafe.h licensed under the MIT license.
*
* Make C string routines a bit more safe and easy.
* Not equals to the strsafe.h in Windows SDK.
*
* When output to a buffer, usually:
* Return == 0: Error or no data
* Return < BufferCount: Success, returns the number of characters or bytes written, not including null-terminator
* Return >= BufferCount: Truncated, returns required size in character or byte, not including null-terminator
*
* Define `_NO_CRT_STDIO_INLINE` to use `legacy_stdio_definitions.lib`.
*/

#pragma once

#include <stdio.h>
#include <stdarg.h>

#pragma region String PrintF

/*
* StrSafe_Cch[V]Printf(A/W)
*
* Return == 0: Error or no data
* Return < BufferCount: Success
* Return >= BufferCount: Truncated, returns required size in character, not including null-terminator
*/

_Success_(
return > 0 && return < BufferCount
)
Expand Down Expand Up @@ -110,7 +116,8 @@ __cdecl
StrSafe_CchPrintfA(
_Out_writes_opt_(BufferCount) _Always_(_Post_z_) char* const Buffer,
_In_ size_t const BufferCount,
_In_z_ _Printf_format_string_ const char* Format, ...)
_In_z_ _Printf_format_string_ const char* Format,
...)
{
va_list ArgList;

Expand All @@ -127,12 +134,81 @@ __cdecl
StrSafe_CchPrintfW(
_Out_writes_opt_(BufferCount) _Always_(_Post_z_) wchar_t* const Buffer,
_In_ size_t const BufferCount,
_In_z_ _Printf_format_string_ const wchar_t* Format, ...)
_In_z_ _Printf_format_string_ const wchar_t* Format,
...)
{
va_list ArgList;

va_start(ArgList, Format);
return StrSafe_CchVPrintfW(Buffer, BufferCount, Format, ArgList);
}

#pragma endregion
#pragma endregion StrSafe_Cch[V]Printf(A/W)

#pragma region String Copy

_Success_(
return > 0 && return < BufferCount
)
__inline
size_t
__cdecl
StrSafe_CchCopyA(
_Out_writes_opt_(BufferCount) _When_(BufferCount > 0, _Notnull_) _Always_(_Post_z_) char* const Buffer,
_In_ size_t const BufferCount,
_In_z_ const char* Source)
{
size_t i;

for (i = 0; i < BufferCount; i++)
{
if ((Buffer[i] = Source[i]) == '\0')
{
return i;
}
}

if (BufferCount > 0)
{
Buffer[BufferCount - 1] = '\0';
}
while (Source[i] != '\0')
{
i++;
}
return i;
}

_Success_(
return > 0 && return < BufferCount
)
__inline
size_t
__cdecl
StrSafe_CchCopyW(
_Out_writes_opt_(BufferCount) _When_(BufferCount > 0, _Notnull_) _Always_(_Post_z_) wchar_t* const Buffer,
_In_ size_t const BufferCount,
_In_z_ const wchar_t* Source)
{
size_t i;

for (i = 0; i < BufferCount; i++)
{
if ((Buffer[i] = Source[i]) == L'\0')
{
return i;
}
}

if (BufferCount > 0)
{
Buffer[BufferCount - 1] = L'\0';
}
while (Source[i] != L'\0')
{
i++;
}
return i;
}

#pragma endregion StrSafe_CchCopy(A/W)
7 changes: 7 additions & 0 deletions Source/Test/StrSafe.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,11 @@ TEST_FUNC(StrSafeFunc)
TEST_OK(wcscmp(szTempW, TEST_STRING1_PART1_W) == 0);
TEST_OK(StrSafe_CchPrintfW(szTempW, ARRAYSIZE(szTempW), L"%ls$", TEST_STRING1_W) == _STR_CCH_LEN(TEST_STRING1_W) + 1);
TEST_OK(wcscmp(szTempW, TEST_STRING1_W) == 0);

TEST_OK(StrSafe_CchCopyA(NULL, 0, TEST_STRING1_A) == _STR_CCH_LEN(TEST_STRING1_A));
TEST_OK(StrSafe_CchCopyA(szTempA, ARRAYSIZE(szTempA), TEST_STRING1_A) == _STR_CCH_LEN(TEST_STRING1_A));
TEST_OK(strcmp(szTempA, TEST_STRING1_A) == 0);
TEST_OK(StrSafe_CchCopyW(NULL, 0, TEST_STRING1_W) == _STR_CCH_LEN(TEST_STRING1_W));
TEST_OK(StrSafe_CchCopyW(szTempW, ARRAYSIZE(szTempW), TEST_STRING1_W) == _STR_CCH_LEN(TEST_STRING1_W));
TEST_OK(wcscmp(szTempW, TEST_STRING1_W) == 0);
}

0 comments on commit c500ed2

Please sign in to comment.