mirror of
https://github.com/acidanthera/OpenCorePkg.git
synced 2025-12-08 19:25:01 +00:00
208 lines
4.7 KiB
C
208 lines
4.7 KiB
C
/** @file
|
|
String buffer.
|
|
|
|
Copyright (c) 2021, Mike Beaton. All rights reserved.<BR>
|
|
SPDX-License-Identifier: BSD-3-Clause
|
|
**/
|
|
|
|
#include <Base.h>
|
|
#include <Library/BaseLib.h>
|
|
#include <Library/BaseOverflowLib.h>
|
|
#include <Library/MemoryAllocationLib.h>
|
|
#include <Library/OcDebugLogLib.h>
|
|
#include <Library/OcFlexArrayLib.h>
|
|
#include <Library/PrintLib.h>
|
|
|
|
OC_ASCII_STRING_BUFFER *
|
|
OcAsciiStringBufferInit (
|
|
VOID
|
|
)
|
|
{
|
|
OC_ASCII_STRING_BUFFER *Buffer;
|
|
|
|
Buffer = AllocateZeroPool (sizeof (OC_ASCII_STRING_BUFFER));
|
|
|
|
return Buffer;
|
|
}
|
|
|
|
EFI_STATUS
|
|
OcAsciiStringBufferAppend (
|
|
IN OUT OC_ASCII_STRING_BUFFER *Buffer,
|
|
IN CONST CHAR8 *AppendString OPTIONAL
|
|
)
|
|
{
|
|
return OcAsciiStringBufferAppendN (Buffer, AppendString, MAX_UINTN);
|
|
}
|
|
|
|
/**
|
|
Extend string buffer by a specified length.
|
|
|
|
@param[in,out] Buffer String buffer to be extended.
|
|
@param[in] AppendLength Length to be appended.
|
|
@param[out] TargetLength Target length of the extended buffer.
|
|
|
|
@retval EFI_SUCCESS The buffer was extended successfully.
|
|
@retval EFI_OUT_OF_RESOURCES The extension failed due to the lack of resources.
|
|
@retval EFI_UNSUPPORTED The buffer has no size.
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
InternalAsciiStringBufferExtendBy (
|
|
IN OUT OC_ASCII_STRING_BUFFER *Buffer,
|
|
IN CONST UINTN AppendLength,
|
|
OUT UINTN *TargetLength
|
|
)
|
|
{
|
|
UINTN NewSize;
|
|
|
|
ASSERT (AppendLength != 0);
|
|
|
|
if (Buffer->String == NULL) {
|
|
ASSERT (Buffer->BufferSize == 0);
|
|
|
|
Buffer->String = AllocatePool (AppendLength + 1);
|
|
if (Buffer->String == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
Buffer->BufferSize = AppendLength + 1;
|
|
*TargetLength = AppendLength;
|
|
} else {
|
|
if (Buffer->BufferSize == 0) {
|
|
ASSERT (FALSE);
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
NewSize = Buffer->BufferSize;
|
|
if (BaseOverflowAddUN (Buffer->StringLength, AppendLength, TargetLength)) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
while (NewSize <= *TargetLength) {
|
|
if (BaseOverflowMulUN (NewSize, 2, &NewSize)) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
}
|
|
|
|
if (NewSize > Buffer->BufferSize) {
|
|
Buffer->String = ReallocatePool (Buffer->BufferSize, NewSize, Buffer->String);
|
|
if (Buffer->String == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
Buffer->BufferSize = NewSize;
|
|
}
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
OcAsciiStringBufferAppendN (
|
|
IN OUT OC_ASCII_STRING_BUFFER *Buffer,
|
|
IN CONST CHAR8 *AppendString, OPTIONAL
|
|
IN CONST UINTN Length
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN AppendLength;
|
|
UINTN TargetLength;
|
|
|
|
if (AppendString == NULL) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
AppendLength = AsciiStrnLenS (AppendString, Length);
|
|
|
|
//
|
|
// Buffer stays NULL if zero appended.
|
|
//
|
|
if (AppendLength == 0) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
Status = InternalAsciiStringBufferExtendBy (Buffer, AppendLength, &TargetLength);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Status = AsciiStrnCpyS (&Buffer->String[Buffer->StringLength], AppendLength + 1, AppendString, AppendLength);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Buffer->StringLength = TargetLength;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
OcAsciiStringBufferSPrint (
|
|
IN OUT OC_ASCII_STRING_BUFFER *Buffer,
|
|
IN CONST CHAR8 *FormatString,
|
|
...
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
VA_LIST Marker;
|
|
VA_LIST Marker2;
|
|
UINTN NumberOfPrinted;
|
|
UINTN TargetLength;
|
|
|
|
ASSERT (FormatString != NULL);
|
|
|
|
VA_START (Marker, FormatString);
|
|
|
|
VA_COPY (Marker2, Marker);
|
|
NumberOfPrinted = SPrintLengthAsciiFormat (FormatString, Marker2);
|
|
VA_END (Marker2);
|
|
|
|
//
|
|
// Buffer stays NULL if zero appended.
|
|
//
|
|
if (NumberOfPrinted == 0) {
|
|
Status = EFI_SUCCESS;
|
|
} else {
|
|
Status = InternalAsciiStringBufferExtendBy (Buffer, NumberOfPrinted, &TargetLength);
|
|
if (!EFI_ERROR (Status)) {
|
|
AsciiVSPrint (&Buffer->String[Buffer->StringLength], NumberOfPrinted + 1, FormatString, Marker);
|
|
Buffer->StringLength = TargetLength;
|
|
}
|
|
}
|
|
|
|
VA_END (Marker);
|
|
return Status;
|
|
}
|
|
|
|
CHAR8 *
|
|
OcAsciiStringBufferFreeContainer (
|
|
IN OUT OC_ASCII_STRING_BUFFER **StringBuffer
|
|
)
|
|
{
|
|
CHAR8 *String;
|
|
|
|
if ((StringBuffer == NULL) || (*StringBuffer == NULL)) {
|
|
ASSERT (FALSE);
|
|
return NULL;
|
|
}
|
|
|
|
String = (*StringBuffer)->String;
|
|
FreePool (*StringBuffer);
|
|
*StringBuffer = NULL;
|
|
|
|
return String;
|
|
}
|
|
|
|
VOID
|
|
OcAsciiStringBufferFree (
|
|
IN OUT OC_ASCII_STRING_BUFFER **StringBuffer
|
|
)
|
|
{
|
|
CHAR8 *Result;
|
|
|
|
Result = OcAsciiStringBufferFreeContainer (StringBuffer);
|
|
if (Result != NULL) {
|
|
FreePool (Result);
|
|
}
|
|
}
|