📄 rvstring.c
字号:
/******************************************************************************
Filename: rvstring.c
Description: copy-on-write string class definitions
*******************************************************************************
Copyright (c) 2000 RADVision Inc.
*******************************************************************************
NOTICE:
This document contains information that is proprietary to RADVision LTD.
No part of this publication may be reproduced in any form whatsoever
without written prior approval by RADVision LTD..
RADVision LTD. reserves the right to revise this publication and make
changes without obligation to notify any person of such revisions or
changes.
******************************************************************************/
#include "rvstring.h"
#include "rvstr.h"
#include <string.h>
#include <ctype.h>
/* Make macro
static RvStringHeader *rvStringGetHeader(const RvString *x)
{
return (RvStringHeader *)(*x - sizeof(RvStringHeader));
}
*/
static char *rvStringConstructBuffer(RvString *x, size_t stringlen, size_t maxlen, RvAlloc *allocator)
{
RvStringHeader *header;
if(maxlen < 15)
maxlen = 15;
header = (RvStringHeader *)rvAllocAllocate(allocator, maxlen + 1 + sizeof(RvStringHeader));
if(header == NULL)
return *x = NULL;
header->length = stringlen;
header->maxlen = maxlen;
header->refs = 1;
header->alloc = allocator;
return *x = (char *)header + sizeof(RvStringHeader);
}
static void rvStringReleaseBuffer(RvString *x)
{
RvStringHeader *header = rvStringGetHeader(x);
rvAllocDeallocate(header->alloc, header->maxlen + 1 + sizeof(RvStringHeader), header);
}
static RvString *rvStringIsolate(RvString *x, size_t len, RvBool preserveContents)
{
RvStringHeader *header = rvStringGetHeader(x);
if(header->refs > 1)
{
char *oldBuffer = *x;
--header->refs;
if(rvStringConstructBuffer(x, len, len + header->length, header->alloc) == NULL) /* alloc extra */
return NULL;
if(preserveContents)
strcpy(*x, oldBuffer);
}
else if(len > header->maxlen)
{
char *oldBuffer = *x;
if(rvStringConstructBuffer(x, len, len + header->length, header->alloc) == NULL) /* alloc extra */
return NULL;
if(preserveContents)
strcpy(*x, oldBuffer);
rvStringReleaseBuffer(&oldBuffer);
}
else
header->length = len;
return x;
}
RvString *rvStringReserve(RvString *x, size_t n)
{
RvStringHeader *header = rvStringGetHeader(x);
if(n > header->maxlen)
{
size_t sz = header->length;
if(rvStringIsolate(x, n, rvTrue) == NULL)
return NULL;
(*x)[rvStringGetHeader(x)->length = sz] = 0; /* 'header' no longer vaild */
}
return x;
}
RvString *rvStringResize(RvString *x, size_t n)
{
size_t origsize = rvStringGetHeader(x)->length;
if(rvStringIsolate(x, n, rvTrue) == NULL)
return NULL;
if(n > origsize)
memset(*x + origsize, ' ', n - origsize);
(*x)[n] = 0;
return x;
}
/* Make macro
RvString* rvStringConstruct(RvString *x, const char *str, RvAlloc *allocator)
{
return rvStringConstructN(x, str, strlen(str), allocator);
}
*/
RvString* rvStringConstructN(RvString *x, const char *str, size_t n, RvAlloc *allocator)
{
if(rvStringConstructBuffer(x, n, n, allocator) == NULL)
return NULL;
strncpy(*x, str, n);
(*x)[n] = 0;
return x;
}
RvString* rvStringConstructAndReserve(RvString *x, size_t n, RvAlloc *allocator)
{
if(rvStringConstructBuffer(x, 0, n, allocator) == NULL)
return NULL;
**x = 0;
return x;
}
RvString* rvStringConstructCopy(RvString *d, const RvString *s, RvAlloc *allocator)
{
RvStringHeader *header = rvStringGetHeader(s);
if(header->alloc != allocator)
return rvStringConstructN(d, rvStringGetData(s), rvStringGetSize(s), allocator);
*d = *s;
++header->refs;
return d;
}
void rvStringDestruct(RvString *x)
{
if(--rvStringGetHeader(x)->refs == 0)
rvStringReleaseBuffer(x);
}
RvString* rvStringCopy(RvString *d, const RvString *s)
{
if(d != s)
{
RvStringHeader *dstHeader = rvStringGetHeader(d);
RvStringHeader *srcHeader = rvStringGetHeader(s);
if(dstHeader->alloc != srcHeader->alloc)
return rvStringAssignN(d, rvStringGetData(s), rvStringGetSize(s));
rvStringDestruct(d);
*d = *s;
++srcHeader->refs;
}
return d;
}
/* Make macro
size_t rvStringGetSize(const RvString *x)
{
return rvStringGetHeader(x)->length;
}
*/
/* Make macro
size_t rvStringGetCapacity(const RvString *x)
{
return rvStringGetHeader(x)->maxlen;
}
*/
RvString* rvStringAssign(RvString *x, const char *str)
{
if(rvStringIsolate(x, strlen(str), rvFalse) == NULL)
return NULL;
strcpy(*x, str);
return x;
}
RvString* rvStringAssignN(RvString *x, const char* str, size_t n)
{
if(rvStringIsolate(x, n, rvFalse) == NULL)
return NULL;
strncpy(*x, str, n);
(*x)[n] = 0;
return x;
}
RvString* rvStringMakeUppercase(RvString *x)
{
char *p;
if(rvStringIsolate(x, rvStringGetSize(x), rvTrue) == NULL)
return NULL;
for(p = *x; *p; p++)
*p = toupper(*p);
return x;
}
RvString* rvStringMakeLowercase(RvString *x)
{
char *p;
if(rvStringIsolate(x, rvStringGetSize(x), rvTrue) == NULL)
return NULL;
for(p = *x; *p; p++)
*p = tolower(*p);
return x;
}
/* Make macro
RvString* rvStringConcatenate(RvString *x, const char *str)
{
return rvStringConcatenateN(x, str, strlen(str));
}
*/
RvString* rvStringConcatenateN(RvString *x, const char* str, size_t n)
{
size_t len = rvStringGetSize(x);
if(rvStringIsolate(x, len + n, rvTrue) == NULL)
return NULL;
strncpy(*x + len, str, n);
(*x)[len + n] = 0;
return x;
}
/* Make macro
RvString* rvStringConcatenateString(RvString *x, const RvString *s)
{
return rvStringConcatenateN(x, rvStringGetData(s), rvStringGetSize(s));
}
*/
RvString* rvStringPushBack(RvString *x, char c)
{
size_t len = rvStringGetSize(x);
if(rvStringIsolate(x, len + 1, rvTrue) == NULL)
return NULL;
(*x)[len] = c;
(*x)[len + 1] = 0;
return x;
}
/* Make macro
const char* rvStringGetData(const RvString *x)
{
return *x;
}
*/
RvBool rvStringEqual(const RvString *a, const RvString *b)
{
return rvStringGetSize(a) == rvStringGetSize(b) &&
!strcmp(rvStringGetData(a), rvStringGetData(b));
}
RvBool rvStringEqualIgnoreCase(const RvString *a, const RvString *b)
{
return rvStringGetSize(a) == rvStringGetSize(b) &&
!rvStrIcmp(rvStringGetData(a), rvStringGetData(b));
}
RvBool rvStringLess(const RvString *a, const RvString *b)
{
return strcmp(rvStringGetData(a), rvStringGetData(b)) < 0;
}
RvBool rvStringLessIgnoreCase(const RvString *a, const RvString *b)
{
return rvStrIcmp(rvStringGetData(a), rvStringGetData(b)) < 0;
}
RvAlloc *rvStringGetAllocator(const RvString *x)
{
return rvStringGetHeader(x)->alloc;
}
rvDefineVector(RvString)
void rvStringListAdd(RvStringList *x, const char *str)
{
RvString s;
rvStringConstructA(&s, str, rvVectorGetAllocator(x));
rvVectorPushBack(RvString)(x, &s);
rvStringDestruct(&s);
}
void rvStringListAddN(RvStringList *x, const char *str, size_t n)
{
RvString s;
rvStringConstructN(&s, str, n, rvVectorGetAllocator(x));
rvVectorPushBack(RvString)(x, &s);
rvStringDestruct(&s);
}
const char* rvStringListGetElem(const RvStringList *x, size_t idx)
{
return rvStringGetData(rvVectorAt(x, idx));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -