string.cpp
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C++ 代码 · 共 1,198 行 · 第 1/2 页
CPP
1,198 行
/*
*
* Copyright (C) 1994, M. A. Sridhar
*
*
* This software is Copyright M. A. Sridhar, 1994. You are free
* to copy, modify or distribute this software as you see fit,
* and to use it for any purpose, provided this copyright
* notice and the following disclaimer are included with all
* copies.
*
* DISCLAIMER
*
* The author makes no warranties, either expressed or implied,
* with respect to this software, its quality, performance,
* merchantability, or fitness for any particular purpose. This
* software is distributed AS IS. The user of this software
* assumes all risks as to its quality and performance. In no
* event shall the author be liable for any direct, indirect or
* consequential damages, even if the author has been advised
* as to the possibility of such damages.
*
*/
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <math.h>
#include <iostream.h>
#include "base/string.h"
#include "base/strsplit.h"
#include "base/bytstrng.h"
#include "base/error.h"
#include "base/strgseq.h"
#include "base/binding.h"
#include "base/stream.h"
#ifdef DEBUG
#include "base/memory.h"
#endif
#if defined(__BORLANDC__) && !defined(__OS2__)
#define STRNCMP _fstrncmp
#else
#define STRNCMP strncmp
#endif
#ifdef __DEC_ULTRIX__
extern "C" int gcvt (double, int, char*);
#endif
#ifdef __GNUC__
#pragma implementation
#endif
#define NEW_OP new
const short DEFAULT_START_SIZE = 12; // Must be at least 10 to
// accommodate long integers
// Some utility functions
void int_to_as (long val, char out[], short minwidth, char padChar = ' ')
{
char tmp[50]; // Won't have more than this many digits
short i, n, sign = 0;
if (val == 0) {
n = (short) maxl (minwidth, 1);
for (i = 0; i < n-1; i++)
out[i] = padChar;
out[n-1] = '0';
out[n] = '\0';
return;
}
if (val < 0) {
sign = -1;
val = -val;
}
for (n = 0; val > 0; n++) {
tmp[n] = (char) (val % 10 + '0');
val /= 10;
}
if (sign < 0) minwidth--;
if (padChar != ' ') {
for (; n < minwidth; n++) {
tmp[n] = padChar;
}
if (sign == -1)
tmp[n++] = '-';
}
else {
if (sign == -1)
tmp[n++] = '-';
for (; n < minwidth; n++) {
tmp[n] = padChar;
}
}
for (i = n-1; i >= 0; i--) {
out[n-1-i] = tmp[i];
}
out [n] = '\0';
}
#ifdef __GNUC__
// G++ does not have the strstr function for finding substring
// occurrences. So here we implement the naive algorithm for string
// search.
static char* strstr (char* s1, const char* s2)
{
if (!s1 || !s2)
return NULL;
long m = strlen (s1);
long n = strlen (s2);
long i, j;
for (i = 0; i < m-n+1; i++) {
for (j = 0; j < n; j++)
if (s2[j] != s1[i+j])
break;
if (j == n)
return s1+i;
}
return NULL;
}
#endif
CL_DEFINE_CLASS(CL_String, _CL_String_CLASSID);
CL_String::CL_String ()
{
_Init (DEFAULT_START_SIZE);
}
CL_String::CL_String (const char* strg)
{
if (strg != NULL) {
long n = strlen (strg);
if (!_Init (n + DEFAULT_START_SIZE + 1))
return;
strcpy (_string, strg);
_size = n;
}
else
_Init (DEFAULT_START_SIZE+1);
}
CL_String::CL_String (const CL_String& strg)
{
long n = strg.Size();
if (!_Init (n + DEFAULT_START_SIZE + 1))
return;
*this = strg;
_size = n;
}
CL_String::CL_String (long value, short minwidth, char padChar)
{
if (!_Init ((minwidth > DEFAULT_START_SIZE ? minwidth :
DEFAULT_START_SIZE) + 1))
return;
int_to_as (value, _string, minwidth, padChar);
_size = strlen (_string);
}
CL_String::CL_String (short value, short minwidth, char padChar)
{
if (!_Init ((minwidth > DEFAULT_START_SIZE ? minwidth :
DEFAULT_START_SIZE) + 1))
return;
int_to_as ((long) value, _string, minwidth, padChar);
_size = strlen (_string);
}
CL_String::CL_String (CL_ByteArray& b)
{
char* b_ptr = (char*) b.AsPtr();
char* p = b_ptr;
long i;
long n = b.Size();
for (i = 0; i < n; i++, p++)
if (*p == 0)
break;
if (!_Init (i))
return;
strncpy (_string, b_ptr, i);
_string[i] = '\0';
_size = i;
}
CL_String::CL_String (char c, short count)
{
if (!_Init (count+1))
return;
for (short i=0; i < count; i++)
_string[i] = c;
_string[count] = '\0';
_size = strlen (_string); // Might not equal count, if
// c is the null character!
}
CL_String::~CL_String()
{
if (_string)
delete [] _string;
}
long CL_String::AsLong() const
{
short i = 0, sign = 1;
long value = 0;
while (i < Size() && _string[i] == ' ') i++;
if (i >= Size())
return 0;
if (_string[i] == '-') {
i++;
sign = -1;
}
while (_string[i] >= '0' && _string[i] <= '9') {
value = value * 10 + _string[i] - '0';
i++;
}
return value * sign;
}
double CL_String::AsDouble () const
{
return atof (_string);
}
bool CL_String::Insert (const char* p, long pos)
{
if (!PrepareToChange())
return FALSE;
if (!_DoInsert (p, pos))
return FALSE;
Notify();
return TRUE;
}
bool CL_String::_DoInsert (const char* p, long pos)
{
if (pos < -1 || pos >= _size)
return FALSE;
long n = strlen (p);
if (n <= 0)
return TRUE;
if (n + _size >= _capacity) {
// Not enough room: expand the string
long new_cap = _capacity + n + DEFAULT_START_SIZE;
char* new_data = new char[new_cap];
if (!new_data)
return FALSE;
_capacity = new_cap;
strncpy (new_data, _string, pos+1);
strncpy (new_data + pos + 1, p, n);
if (pos < _size - 1)
strcpy (new_data + pos + n + 1, _string + pos + 1);
else
new_data [_size + n] = '\0';
delete [] _string;
_string = new_data;
}
else {
if (pos < _size - 1) {
memmove (_string+pos+n+1, _string+pos+1, _size-pos-1);
memcpy (_string+pos+1, p, n);
}
else
strcpy (_string + _size, p);
}
_size += n;
return TRUE;
}
bool CL_String::Insert (char c, long pos)
{
char buf[2];
buf[0] = c;
buf[1] = '\0';
return Insert (buf, pos);
}
bool CL_String::PadTo (long num_chars, char pad_char,
bool left_justified)
{
if (!PrepareToChange())
return FALSE;
if (num_chars <= _size)
return FALSE;
char* pad_strg = new char [_capacity = num_chars+DEFAULT_START_SIZE+1];
if (!pad_strg)
return FALSE;
memset (pad_strg, pad_char, num_chars);
pad_strg[num_chars] = '\0';
if (left_justified)
strncpy (pad_strg, _string, _size);
else
strncpy (pad_strg + num_chars - _size,
_string, _size);
delete _string;
_string = pad_strg;
_size = num_chars;
Notify ();
return TRUE;
}
CL_String CL_String::InUpperCase () const
{
CL_String t (*this);
t.ToUpper ();
return t;
}
CL_String CL_String::InLowerCase () const
{
CL_String t (*this);
t.ToLower ();
return t;
}
long CL_String::ToUpper ()
{
if (!PrepareToChange())
return 0;
long count = 0;
for (long i = 0; i < _size; i++)
if (islower (_string[i])) {
_string[i] = toupper (_string[i]);
count++;
};
Notify ();
return count;
}
long CL_String::ToLower ()
{
if (!PrepareToChange())
return 0;
long count = 0;
for (long i = 0; i < _size; i++)
if (isupper (_string[i])) {
_string[i] = tolower (_string[i]);
count++;
};
Notify ();
return count;
}
bool CL_String::WordCapitalize ()
{
if (!PrepareToChange())
return FALSE;
if (_size <= 0 || !isalpha (_string[0]))
return FALSE;
if (islower (_string[0]))
_string[0] = toupper (_string[0]);
for (long i = 1; i < _size; i++) {
if (!isalpha (_string[i]))
break;
if (isupper (_string[i]))
_string[i] = tolower (_string[i]);
}
Notify ();
return TRUE;
}
//
// Substructure extraction
//
long CL_String::CharIndex (char c, long pos) const
{
for (long i=pos; i < _size; i++) {
if (_string[i] == c) return i;
}
return -1;
}
long CL_String::NCharIndex (char c, long pos) const
{
for (long i=pos; i < _size; i++) {
if (_string[i] != c) return i;
}
return -1;
}
CL_Substring CL_String::operator () (long position, long size)
{
if (position >= _size)
return CL_Substring (*this, _size, 0);
long len = minl (size, _size-position);
return CL_Substring (*this, position, len);
// return sub;
}
long CL_String::CharIndex (const char* s, long pos) const
{
if (!s)
return 0;
long n = strlen(s);
for (long i=pos; i < _size; i++) {
for (long j = 0; j < n; j++)
if (_string[i] == s[j]) return i;
}
return -1;
}
long CL_String::NCharIndex (const char* s, long pos) const
{
if (!s)
return 0;
long n = strlen(s);
for (long i = pos; i < _size; i++) {
long j;
for (j = 0; j < n; j++) {
if (_string[i] == s[j]) break;
}
if (j >= n) return i;
}
return -1;
}
bool CL_String::IsPrefixOf (const char* p) const
{
if (!p)
return FALSE;
long l = strlen (p);
if (_size > l)
return FALSE;
short b = STRNCMP (_string, p, _size);
return (b == 0) ? TRUE : FALSE;
}
long CL_String::Index (const char* p, long pos, long n) const
{
if (!p || !_string)
return -1;
long len = strlen(p);
if (pos > _size - len)
return -1;
char* q = _string + pos;
for (; n > 0; n--) {
q = strstr (q, p);
if (q == NULL)
return -1;
if (n > 1) q++;
}
return (q == NULL) ? -1 : (q - _string);
}
long CL_String::Replace (const char* s1, const char* s2, long n, long pos)
{
if (!PrepareToChange())
return 0;
long len1, len2;
if (!s1 || (len1 = strlen (s1)) == 0)
return 0;
const char* repl = (s2) ? s2 : "";
len2 = strlen (repl);
long new_cap = maxl (_capacity + n* (len2 - len1), _capacity);
char* new_array = new char [new_cap];
if (!new_array)
return 0;
char* in = _string+pos;
char* out = new_array;
strncpy (out, _string, pos);
out += pos;
char* q;
long repl_count = 0;
while (repl_count < n && in - _string < _size) {
q = strstr (in, s1);
if (!q) break;
long copy_len = q-in;
strncpy (out, in, copy_len);
strncpy (out + copy_len, repl, len2);
out += copy_len + len2;
in = q+len1;
repl_count ++;
}
strcpy (out, in);
_size = strlen (new_array);
_capacity = new_cap;
delete [] _string;
_string = new_array;
Notify();
return repl_count;
}
// Beginning at position pos, replace all occurrences of s1 with
// s2, as in Replace. Return the number of replacements that took
// place.
long CL_String::ReplaceAll (const char* s1, const char* s2, long pos)
{
return Replace (s1, s2, _size, pos);
}
CL_String CL_String::Field (long n, const char field_seps[]) const
{
if (_size <= 0)
return "";
if (n == 0)
return *this;
CL_StringSplitter splitter (*this, field_seps);
CL_String s;
for (splitter.Reset(); n > 0; n--) {
s = splitter.Next();
if (s.Length() == 0) break;
}
return s;
}
CL_StringSequence CL_String::Split (const char field_seps[]) const
{
CL_StringSplitter splitter (*this, field_seps);
CL_StringSequence seq;
CL_String s;
do {
s = splitter.Next();
if (s.Length() == 0) break;
seq.Add (s);
} while (1);
return seq;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?