string.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 627 行 · 第 1/2 页
C
627 行
/* String.c -- implementation of character strings
THIS SOFTWARE FITS THE DESCRIPTION IN THE U.S. COPYRIGHT ACT OF A
"UNITED STATES GOVERNMENT WORK". IT WAS WRITTEN AS A PART OF THE
AUTHOR'S OFFICIAL DUTIES AS A GOVERNMENT EMPLOYEE. THIS MEANS IT
CANNOT BE COPYRIGHTED. THIS SOFTWARE IS FREELY AVAILABLE TO THE
PUBLIC FOR USE WITHOUT A COPYRIGHT NOTICE, AND THERE ARE NO
RESTRICTIONS ON ITS USE, NOW OR SUBSEQUENTLY.
Authors:
C. J. Eppich and K. E. Gorlen
Bg. 12A, Rm. 2033
Computer Systems Laboratory
Division of Computer Research and Technology
National Institutes of Health
Bethesda, Maryland 20892
Phone: (301) 496-1111
uucp: uunet!nih-csl!kgorlen
Internet: kgorlen@alw.nih.gov
December, 1987
Function:
Class String implements character string objects. Operations provided
include & (concatenation) and () (substring extraction). Type
conversions between String and char* are provided, permitting the two
to be used interchangeably in many contexts. Note also that
SubStrings are not derived classes from Object.
log: STRING.C $
Revision 1.1 93/02/16 16:33:28 Anthony_Scian
.
* Revision 3.0 90/05/20 00:21:32 kgorlen
* Release for 1st edition.
*
*/
#include "String.ho"
#include "Range.h"
//#include "nihclconfig.h"
#include "nihclIO.h"
#include <ctype.h>
#define THIS String
#define BASE Object
#define BASE_CLASSES BASE::desc()
#define MEMBER_CLASSES
#define VIRTUAL_BASE_CLASSES Object::desc()
DEFINE_CLASS(String,1,"header: D:\PLUSTEST\regress\nih\x:\groupdir\cproj\plustest\regress\nih\rcs\STRING.C 1.1 93/02/16 16:33:28 Anthony_Scian Exp Locker: NT_Test_Machine $",NULL,NULL);
extern const int NIHCL_BADCLASS, NIHCL_BADRANGE, NIHCL_INDEXRANGE, NIHCL_SUBSTRERR;
/* System-independent versions of toupper and tolower */
inline char to_upper(unsigned char c) { return (islower(c) ? (c-'a'+'A') : c); }
inline char to_lower(unsigned char c) { return (isupper(c) ? (c-'A'+'a') : c); }
//==== SubString functions:
/*
The following compare functions were implemented because strncmp is
not adequate for comparing character strings of unequal length. For
example, strncmp("abc","abcd",3) will return 0.
*/
int SubString::compare(const char* cs) const
/*
Return integer greater than, equal to, or less than 0, according as
this SubString is lexicographically greater than, equal to, or less
than cs.
*/
{
int cl = strlen(cs);
int result = strncmp(sp,cs,sl);
if (result != 0 || sl == cl) return result;
return (sl>cl ? 1 : -1);
}
int SubString::compare(const String& s) const
/*
Return integer greater than, equal to, or less than 0, according as
this SubString is lexicographically greater than, equal to, or less
than s.
*/
{
int result = strncmp(sp,s.p,sl);
if (result != 0 || sl == s.len) return result;
return (sl>s.len ? 1 : -1);
}
int SubString::compare(const SubString& ss) const
/*
Return integer greater than, equal to, or less than 0, according as
this SubString is lexicographically greater than, equal to, or less
than SubString ss.
*/
{
int result = strncmp(sp,ss.sp,MIN(sl,ss.sl));
if (result != 0 || sl == ss.sl) return result;
return (sl>ss.sl ? 1 : -1);
}
void SubString::dumpOn(ostream& strm) const
// Dump this SubString on output stream strm.
{
strm << String(*this);
strm << '[' << st->p << '(' << position() << ',' << sl << ")]";
}
void SubString::printOn(ostream& strm) const
// Print this SubString on output stream strm.
{
strm << String(*this);
}
void SubString::operator=(const String& s)
{
if (sl == s.length()) strncpy(sp,s.p,sl);
else replace(s.p,s.len);
}
void SubString::operator=(const SubString& ss)
{
if (sl == ss.sl) strncpy(sp,ss.sp,sl);
else replace(ss.sp,ss.sl);
}
void SubString::operator=(const char* cs)
{
int cslen = strlen(cs);
if (sl == cslen) strncpy(sp,cs,sl);
else replace(cs,cslen);
}
void SubString::replace(const char* src, unsigned srclen)
// Replace this SubString with the argument string
// Terminology:
// head: portion of destination string before this SubString
// tail: portion of destination string after this SubString
{
#ifdef DEBUG
cerr << "replacing " << *this << " by ";
cerr.write(src, srclen);
cerr << " ...\n";
#endif
bool overlap = NO; // src overlaps destination String
int tailDelta = 0; // amount to adjust for tail movement
char* srcbuf = 0; // buffer to hold src if it overlaps SubString
// src overlap destination String?
if (src >= st->p && src <= st->p+st->len) {
overlap = YES; // src overlaps destination String
// src overlap only tail of destination String?
if (src >= sp+sl) tailDelta = srclen-sl;
else {
// src overlap this SubString?
if (src+srclen > sp) { // move src to buffer
srcbuf = new char[srclen];
strncpy(srcbuf,src,srclen);
src = srcbuf;
overlap = NO; // no overlap now
}
}
}
#ifdef DEBUG
cerr << "overlap=" << overlap << " tailDelta=" << tailDelta << " srcbuf=" << (int)srcbuf << '\n';
#endif
if (srclen+st->len >= sl+st->alloc) { // need to make String bigger
char* p = st->p;
st->alloc = st->len+srclen-sl+DEFAULT_STRING_EXTRA+1;
st->p = (char*)realloc(st->p, st->alloc);
sp += st->p-p;
if (overlap) src += st->p-p;
#ifdef DEBUG
cerr << "realloc(" << st->alloc << ") " << *this << '\n';
#endif
}
if (sl > srclen) { // shift tail down
register const char* p = sp+sl;
register char* q = sp+srclen;
while (*q++ = *p++);
}
else { // shift tail up
register const char* p = st->p+st->len;
register char* q = (char*)p+srclen-sl;
register unsigned n = p-(sp+sl)+1;
while (n--) *q-- = *p--;
}
src += tailDelta;
st->len += srclen-sl;
#ifdef DEBUG
cerr << "target " << *this << " source ";
cerr.write(src, srclen);
cerr << endl;
#endif
strncpy(sp,src,srclen); // insert src into destination
if (srcbuf) free(srcbuf);
#ifdef DEBUG
cerr << "... result: " << *this << '\n';
#endif
}
String SubString::operator&(const SubString& ss) const
{
String t(sl + ss.sl);
strncpy (t.p, sp, sl);
strncpy (&(t.p[sl]), ss.sp, ss.sl);
t.len = sl + ss.sl;
t.p[t.len] = '\0';
return t;
}
String SubString::operator&(const String& s) const
{
String t(sl + s.alloc -1);
strncpy(t.p, sp, sl);
strcpy(&(t.p[sl]), s.p);
t.len = sl + s.len;
return t;
}
String SubString::operator&(const char* cs) const
{
int cslen = strlen(cs);
String t(sl + cslen);
strncpy(t.p,sp,sl);
strcpy(&(t.p[sl]),cs);
t.len = sl + cslen;
return t;
}
String operator&(const char* cs, const SubString& ss)
{
unsigned cslen = strlen(cs);
String t(cslen + ss.sl);
strcpy(t.p,cs);
strncpy(&(t.p[cslen]),ss.sp,ss.sl);
t.len = cslen + ss.sl;
t.p[t.len] = '\0';
return t;
}
void SubString::checkSubStr() const
// check for legal SubString
{
unsigned pos = position();
unsigned len = st->len;
if (pos+sl <= len) return;
if (sl == 0 && pos == len) return;
setError(NIHCL_SUBSTRERR,DEFAULT,st,st->className(),pos,sl);
}
//==== String Private functions:
void String::indexRangeErr() const
{
setError(NIHCL_INDEXRANGE,DEFAULT,this,className());
}
//==== String Constructors:
String::String(const char& c, unsigned l, unsigned extra)
{
len = l;
alloc = len + extra + 1;
p = (char*)malloc(alloc);
register unsigned i=len;
p[i] = '\0';
while (i > 0) p[--i] = c;
}
String::String()
{
len = 0;
alloc = DEFAULT_STRING_EXTRA + 1;
p = (char*)malloc(alloc);
*p = '\0';
}
String::String(unsigned extra)
{
len = 0;
alloc = extra + 1;
p = (char*)malloc(alloc);
*p = '\0';
}
String::String(const char* cs)
{
len = strlen(cs);
alloc = len + DEFAULT_STRING_EXTRA + 1;
p = (char*)malloc(alloc);
strcpy(p,cs);
}
String::String(const char* cs, unsigned extra)
{
len = strlen(cs);
alloc = len + extra + 1;
p = (char*)malloc(alloc);
strcpy(p,cs);
}
String::String(const String& s)
{
len = s.len;
alloc = len + DEFAULT_STRING_EXTRA + 1;
p = (char*)malloc(alloc);
strcpy (p,s.p);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?