/* strcomp.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* Macro Assembler AS */
/* */
/* Definition of a source line's component present after parsing */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <string.h>
#include <ctype.h>
#include "datatypes.h"
#include "strutil.h"
#include "strcomp.h"
static void check_capacity(const tStrComp *pComp)
{
if (!pComp->str.capacity)
{
fprintf(stderr
, "copy to zero-capacity StrComp\n");
}
}
static void check_no_capacity(const tStrComp *pComp)
{
if (pComp->str.capacity)
{
fprintf(stderr
, "ptr move on non-zero-capacity StrComp\n");
}
}
static size_t check_realloc(as_dynstr_t *p_str, size_t req_count)
{
if ((req_count >= p_str->capacity) && p_str->dynamic)
as_dynstr_realloc(p_str, as_dynstr_roundup_len(req_count));
if (req_count >= p_str->capacity)
req_count = p_str->capacity - 1;
return req_count;
}
/*!------------------------------------------------------------------------
* \fn StrCompAlloc(tStrComp *pComp, size_t capacity)
* \brief initialize string component with dynamic buffer
* \param pComp component to fill
* \param capacity requested capacity of buffer
* ------------------------------------------------------------------------ */
void StrCompAlloc(tStrComp *pComp, size_t capacity)
{
as_dynstr_ini(&pComp->str, capacity);
StrCompReset(pComp);
}
/*!------------------------------------------------------------------------
* \fn StrCompReset(tStrComp *pComp)
* \brief reset string component to "empty" state
* \param pComp component to set
* ------------------------------------------------------------------------ */
void StrCompReset(tStrComp *pComp)
{
LineCompReset(&pComp->Pos);
*pComp->str.p_str = '\0';
}
/*!------------------------------------------------------------------------
* \fn LineCompReset(tLineComp *pComp)
* \brief reset line position to "empty" state
* \param pComp component to set
* ------------------------------------------------------------------------ */
void LineCompReset(tLineComp *pComp)
{
pComp->StartCol = -1;
pComp->Len = 0;
}
/*!------------------------------------------------------------------------
* \fn StrCompFree(tStrComp *pComp)
* \brief free/clean string component
* \param pComp string component to be cleared
* ------------------------------------------------------------------------ */
void StrCompFree(tStrComp *pComp)
{
LineCompReset(&pComp->Pos);
as_dynstr_free(&pComp->str);
}
/*!------------------------------------------------------------------------
* \fn StrCompMkTemp(tStrComp *pComp, char *pStr, size_t capacity)
* \brief create a dummy StrComp from plain string
* \param pComp comp to create
* \param pStr string to use
* \param capacity string's capacity
* ------------------------------------------------------------------------ */
void StrCompMkTemp(tStrComp *pComp, char *pStr, size_t capacity)
{
LineCompReset(&pComp->Pos);
pComp->str.p_str = pStr;
pComp->str.capacity = capacity;
pComp->str.dynamic = 0;
}
/*!------------------------------------------------------------------------
* \fn StrCompRefRight(tStrComp *pDest, const tStrComp *pSrc, size_t StartOffs)
* \brief create a right-aligned substring component of string component (no copy)
* \param pDest destination component
* \param pSrc source component
* \param StartOffs how many characters to omit at the left
* ------------------------------------------------------------------------ */
void StrCompRefRight(tStrComp *pDest, const tStrComp *pSrc, size_t StartOffs)
{
pDest->str.p_str = pSrc->str.p_str + StartOffs;
pDest->str.capacity = 0;
pDest->str.dynamic = 0;
pDest->Pos.StartCol = pSrc->Pos.StartCol + StartOffs;
pDest->Pos.Len = pSrc->Pos.Len - StartOffs;
}
/*!------------------------------------------------------------------------
* \fn StrCompCopy(tStrComp *pDest, tStrComp *pSrc)
* \brief copy string component
* \param pDest destination component
* \param pSrc source component
* ------------------------------------------------------------------------ */
void StrCompCopy(tStrComp *pDest, const tStrComp *pSrc)
{
pDest->Pos = pSrc->Pos;
pDest->Pos.Len = as_dynstr_copy(&pDest->str, &pSrc->str);
}
/*!------------------------------------------------------------------------
* \fn StrCompCopySub(tStrComp *pDest, const tStrComp *pSrc, size_t Start, size_t Count)
* \brief copy substring
* \param pDest destination
* \param pSrc source
* \param Start start index to copy from
* \param Count # of characters to copy
* ------------------------------------------------------------------------ */
void StrCompCopySub(tStrComp *pDest, const tStrComp *pSrc, size_t Start, size_t Count)
{
unsigned l
= strlen(pSrc
->str.
p_str);
if (Start >= l)
Count = 0;
else if (Start + Count > l)
Count = l - Start;
check_capacity(pDest);
Count = check_realloc(&pDest->str, Count);
memcpy(pDest
->str.
p_str, pSrc
->str.
p_str + Start
, Count
);
pDest->str.p_str[Count] = '\0';
pDest->Pos.StartCol = pSrc->Pos.StartCol + Start;
pDest->Pos.Len = Count;
}
/*!------------------------------------------------------------------------
* \fn StrCompSplitRight(tStrComp *pSrc, tStrComp *pDest, char *pSrcSplitPos)
* \brief split off another component at the right of the source
* \param pSrc source to split off
* \param pDest where to put part splitted off
* \param pSrcSplitPos split position (not included in source or dest any more)
* ------------------------------------------------------------------------ */
void StrCompSplitRight(tStrComp *pSrc, tStrComp *pDest, char *pSrcSplitPos)
{
size_t SrcLen
= strlen(pSrcSplitPos
+ 1);
check_capacity(pDest);
SrcLen = check_realloc(&pDest->str, SrcLen);
memcpy(pDest
->str.
p_str, pSrcSplitPos
+ 1, SrcLen
);
pDest->str.p_str[SrcLen] = '\0';
pDest->Pos.StartCol = pSrc->Pos.StartCol + pSrcSplitPos + 1 - pSrc->str.p_str;
pDest->Pos.Len = SrcLen;
*pSrcSplitPos = '\0';
pSrc->Pos.Len = pSrcSplitPos - pSrc->str.p_str;
}
/*!------------------------------------------------------------------------
* \fn StrCompSplitLeft(tStrComp *pSrc, tStrComp *pDest, char *pSrcSplitPos)
* \brief split off another component at the left of the source
* \param pSrc source to split off
* \param pDest where to put part splitted off
* \param pSrcSplitPos split position (not included in source or dest any more)
* ------------------------------------------------------------------------ */
void StrCompSplitLeft(tStrComp *pSrc, tStrComp *pDest, char *pSrcSplitPos)
{
size_t SrcLen;
*pSrcSplitPos = '\0';
SrcLen
= strlen(pSrc
->str.
p_str);
check_capacity(pDest);
SrcLen = check_realloc(&pDest->str, SrcLen);
memcpy(pDest
->str.
p_str, pSrc
->str.
p_str, SrcLen
);
pDest->str.p_str[SrcLen] = '\0';
pDest->Pos.StartCol = pSrc->Pos.StartCol;
pDest->Pos.Len = pSrcSplitPos - pSrc->str.p_str;
strmov(pSrc->str.p_str, pSrcSplitPos + 1);
pSrc->Pos.StartCol += pSrcSplitPos - pSrc->str.p_str + 1;
pSrc->Pos.Len -= pSrcSplitPos - pSrc->str.p_str + 1;
}
/*!------------------------------------------------------------------------
* \fn StrCompSplitCopy(tStrComp *pLeft, tStrComp *pRight, const tStrComp *pSrc, char *pSplitPos)
* \brief copy left & right part of string to new components
* \param pLeft dest for left part
* \param pRight dest for right part
* \param pSrc character source
* \param pSplitPos split position in source
* ------------------------------------------------------------------------ */
void StrCompSplitCopy(tStrComp *pLeft, tStrComp *pRight, const tStrComp *pSrc, char *pSplitPos)
{
/* pLeft may be equal to pSrc, use memmove() and save SrcLen */
size_t SrcLen = pSrc->Pos.Len;
check_capacity(pLeft);
pLeft->Pos.StartCol = pSrc->Pos.StartCol;
pLeft->Pos.Len = check_realloc(&pLeft->str, pSplitPos - pSrc->str.p_str);
memmove(pLeft
->str.
p_str, pSrc
->str.
p_str, pLeft
->Pos.
Len);
pLeft->str.p_str[pLeft->Pos.Len] = '\0';
check_capacity(pRight);
pRight->Pos.StartCol = pSrc->Pos.StartCol + (pLeft->Pos.Len + 1);
pRight->Pos.Len = check_realloc(&pRight->str, SrcLen - (pLeft->Pos.Len + 1));
memcpy(pRight
->str.
p_str, pSplitPos
+ 1, pRight
->Pos.
Len);
pRight->str.p_str[pRight->Pos.Len] = '\0';
}
/*!------------------------------------------------------------------------
* \fn StrCompSplitRef(tStrComp *pLeft, tStrComp *pRight, const tStrComp *pSrc, char *pSplitPos)
* \brief split string into left & right and form references
* \param pLeft dest for left part
* \param pRight dest for right part
* \param pSrc character source
* \param pSplitPos split position in source
* ------------------------------------------------------------------------ */
char StrCompSplitRef(tStrComp *pLeft, tStrComp *pRight, const tStrComp *pSrc, char *pSplitPos)
{
char Old = *pSplitPos;
/* save because pLeft and pSrc might be equal */
tLineComp SrcPos = pSrc->Pos;
*pSplitPos = '\0';
pLeft->str.p_str = pSrc->str.p_str;
if (pLeft != pSrc)
{
pLeft->str.capacity = 0;
pLeft->str.dynamic = 0;
}
pLeft->Pos.StartCol = SrcPos.StartCol;
pLeft->Pos.Len = pSplitPos - pLeft->str.p_str;
pRight->str.p_str = pSrc->str.p_str + (pLeft->Pos.Len + 1);
pRight->str.capacity = 0;
pRight->str.dynamic = 0;
pRight->Pos.StartCol = SrcPos.StartCol + (pLeft->Pos.Len + 1);
pRight->Pos.Len = SrcPos.Len - (pLeft->Pos.Len + 1);
return Old;
}
/*!------------------------------------------------------------------------
* \fn KillPrefBlanksStrComp(struct sStrComp *pComp)
* \brief remove leading spaces on string component
* \param pComp component to handle
* ------------------------------------------------------------------------ */
void KillPrefBlanksStrComp(struct sStrComp *pComp)
{
int Delta = KillPrefBlanks(pComp->str.p_str);
pComp->Pos.StartCol += Delta;
pComp->Pos.Len -= Delta;
}
/*!------------------------------------------------------------------------
* \fn KillPrefBlanksStrCompRef(struct sStrComp *pComp)
* \brief remove leading spaces on string component by inc'ing pointer
* \param pComp component to handle
* ------------------------------------------------------------------------ */
void KillPrefBlanksStrCompRef(struct sStrComp *pComp)
{
check_no_capacity(pComp);
{
pComp->str.p_str++;
if (pComp->str.capacity > 0)
pComp->str.capacity--;
pComp->Pos.StartCol++;
pComp->Pos.Len--;
}
}
/*!------------------------------------------------------------------------
* \fn KillPostBlanksStrComp(struct sStrComp *pComp)
* \brief remove trailing spaces on string component
* \param pComp component to handle
* ------------------------------------------------------------------------ */
void KillPostBlanksStrComp(struct sStrComp *pComp)
{
pComp->Pos.Len -= KillPostBlanks(pComp->str.p_str);
}
/*!------------------------------------------------------------------------
* \fn StrCompShorten(struct sStrComp *pComp, size_t Delta)
* \brief shorten string component by n characters
* \param pComp component to shorten
* \param Delta # of characters to chop off (no checks!)
* ------------------------------------------------------------------------ */
void StrCompShorten(struct sStrComp *pComp, size_t Delta)
{
pComp
->str.
p_str[strlen(pComp
->str.
p_str) - Delta
] = '\0';
pComp->Pos.Len -= Delta;
}
/*!------------------------------------------------------------------------
* \fn StrCompCutLeft(struct sStrComp *pComp, size_t Delta)
* \brief remove n characters at start of component
* \param pComp component to shorten
* \param Delta # of characters to cut off
* \return actual # of characters cut off
* ------------------------------------------------------------------------ */
size_t StrCompCutLeft(struct sStrComp *pComp, size_t Delta)
{
size_t len
= strlen(pComp
->str.
p_str);
if (Delta > len)
Delta = len;
if (Delta > pComp->Pos.Len)
Delta = pComp->Pos.Len;
strmov(pComp->str.p_str, pComp->str.p_str + Delta);
pComp->Pos.StartCol += Delta;
pComp->Pos.Len -= Delta;
return Delta;
}
/*!------------------------------------------------------------------------
* \fn StrCompIncRefLeft(struct sStrComp *pComp, size_t Delta)
* \brief move start of component by n characters
* \param pComp component to shorten
* \param Delta # of characters to move by (no checks!)
* ------------------------------------------------------------------------ */
void StrCompIncRefLeft(struct sStrComp *pComp, size_t Delta)
{
check_no_capacity(pComp);
pComp->str.p_str += Delta;
pComp->str.capacity = (pComp->str.capacity > Delta) ? pComp->str.capacity - Delta : 0;
pComp->Pos.StartCol += Delta;
pComp->Pos.Len -= Delta;
}
/*!------------------------------------------------------------------------
* \fn DumpStrComp(const char *pTitle, const struct sStrComp *pComp)
* \brief debug dump of component
* \param pTitle description of component
* \param pComp component to dump
* ------------------------------------------------------------------------ */
void DumpStrComp(const char *pTitle, const struct sStrComp *pComp)
{
fprintf(stderr
, "%s: @ col %u len %u '%s'\n", pTitle
, pComp
->Pos.
StartCol, pComp
->Pos.
Len, pComp
->str.
p_str);
}