cstring.cpp
来自「Shorthand是一个强大的脚本语言」· C++ 代码 · 共 929 行 · 第 1/2 页
CPP
929 行
/////////////////////////////////////////////////////////////////////////////
// $Header: /shorthand/src/cstring.cpp 8 2/14/03 4:20a Arm $
//---------------------------------------------------------------------------
// This file is part of "libAndrix" library - a collection of classes
// and functions developed by Andrei Remenchuk.
//---------------------------------------------------------------------------
// While you may own complete copyright on the project with which you have
// received this file, the author reserves the right to use code contained
// in this very file for any purposes, including publishing and usage in
// any free or commercial software.
//
// You may re-distribute this file or re-use it in your own free or
// commercial software provided that this text is included in the file.
// If you change this file you must include clear notice stating that
// you changed this file and the date of change.
//
// This statement doesn't apply to other files that are part of the same
// package unless otherwise noted.
//---------------------------------------------------------------------------
// (c) 1998-2002 Andrei Remenchuk <andrei@remenchuk.com>
//---------------------------------------------------------------------------
// cstring.cpp - string class implementation
/////////////////////////////////////////////////////////////////////////////
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <ctype.h>
#ifdef WIN32
#include <io.h>
#else
#include <iostream.h>
#include <unistd.h>
#include <errno.h>
#endif
#include "cstring.h"
#include "except.h"
#include "utils.h"
#pragma hdrstop
void string::ctor()
{
m_capacity = 0;
m_increment = 64;
m_length = 0;
m_buffer = 0;
}
string::string()
{
ctor();
m_capacity = 24;
m_buffer = (char*) malloc(m_capacity);
m_buffer[0] = '\0';
}
string::string(const char* s, int length)
{
ctor();
if (s == NULL) s = "";
if (length == -1) length = strlen(s);
m_length = length;
ensure_capacity(length+1);
memcpy(m_buffer, s, length);
m_buffer[length] = '\0';
}
string::string(const string& s)
{
ctor();
m_length = s.length();
ensure_capacity(m_length+1);
memcpy(m_buffer, s.m_buffer, m_length+1);
}
string* string::clone() const
{
return new string(*this);
}
void string::ensure_capacity(int n)
{
if (n > m_capacity)
{
if (m_increment == 0) m_increment = 64;
m_capacity = (n/m_increment+1)*m_increment;
if (m_buffer == NULL) m_buffer = (char*) malloc(m_capacity);
else m_buffer = (char*) realloc(m_buffer, m_capacity);
}
}
char* string::provide_window(int length)
{
ensure_capacity(length + 1);
return m_buffer;
}
// truncates string length (if within range)
int string::set_length(int n)
{
if (n >= 0 && n < m_length)
{
m_buffer[n] = '\0';
m_length = n;
}
return m_length;
}
void string::printf(const char* format, ...)
{
va_list args; va_start(args, format);
int w = vawidth(format, &args);
ensure_capacity(w+1);
::vsprintf(m_buffer, format, args);
m_length = strlen(m_buffer);
}
void string::vprintf(const char* format, va_list args)
{
int w = vawidth(format, &args);
ensure_capacity(w+1);
::vsprintf(m_buffer, format, args);
m_length = strlen(m_buffer);
}
void string::append(const char* s, int length)
{
if (length == -1) length = strlen(s);
int n = m_length + length;
ensure_capacity(n+1);
memcpy(m_buffer + m_length, s, length);
m_buffer[m_length + length] = '\0';
m_length += length;
}
void string::append(char ch)
{
ensure_capacity(m_length + 2);
m_buffer[m_length] = ch;
m_buffer[m_length+1] = '\0';
m_length++;
}
// formats text and appends it to this string
void string::appendf(const char* format, ...)
{
string text;
va_list args; va_start(args, format);
text.vprintf(format, args);
append(text.m_buffer, text.m_length);
}
void string::clear()
{
m_length = 0;
m_buffer[0] = '\0';
}
const string& string::operator = (const char* s)
{
if (s == NULL) s = "";
m_length = strlen(s);
ensure_capacity(m_length+1);
memcpy(m_buffer, s, m_length+1);
return *this;
}
const string& string::operator = (const string& s)
{
m_length = s.m_length;
ensure_capacity(m_length+1);
memcpy(m_buffer, s.m_buffer, m_length+1);
return *this;
}
void string::set(const char *s, int length)
{
if (s == NULL) s = "";
if (length == -1) length = strlen(s);
ensure_capacity(length+1);
memcpy(m_buffer, s, length);
m_buffer[length] = '\0';
m_length = length;
}
// pastes a piece of another string
void string::paste(const char* s, int start, int end)
{
set(s+start, end-start);
}
const char* string::nv() const
{
if (m_length == 0) return NULL;
else return m_buffer;
}
static char* hexs = "0123456789ABCDEF";
static int hex2c(char ch)
{
const char* p = strchr(hexs, toupper(ch));
if (p == NULL) return -1;
else return p - hexs;
}
void string::urldecode(string& target) const
{
target.clear();
for(int i=0,n=m_length; i<n; i++)
{
char ch = m_buffer[i];
if (ch == '%') {
if (i + 2 < m_length)
{
unsigned int hi = hex2c(m_buffer[i+1])&0xf;
unsigned int lo = hex2c(m_buffer[i+2])&0xf;
if (hi >= 0 && lo >= 0)
{
target.append((unsigned char)((hi<<4) | lo));
}
}
i += 2;
} else if (ch == '+') {
target.append(' ' );
} else {
target.append(ch);
}
}
}
void string::urlencode(const char* source, string& target)
{
target.clear();
const char* p = source;
while(*p)
{
char ch = *p++;
if (ch == ' ')
{
target.append('+');
}
else if (isalnum(ch) || strchr("._,", ch) != NULL)
{
target.append(ch);
}
else
{
target.appendf("%%%02x", ch&0xff);
}
}
}
void string::urlencode(string& target) const
{
urlencode(m_buffer, target);
}
void string::rtrim()
{
for(int i=m_length-1; i>=0; i--)
{
if (isspace(m_buffer[i]))
{
m_buffer[i] = '\0';
m_length--;
}
else
break;
}
}
// removes all leading whitespace characters
void string::ltrim()
{
int i=0;
while(i<m_length && isspace(m_buffer[i])) i++;
if (i == m_length) clear();
else if (i > 0)
{
memmove(m_buffer, m_buffer+i, m_length-i+1);
m_length -= i;
}
}
void string::trim()
{
rtrim();
ltrim();
}
// converts string to lowercase
void string::lowercase()
{
for(int i=0,n=m_length; i<n; i++)
m_buffer[i] = tolower(m_buffer[i]);
}
// converts string to lowercase
void string::uppercase()
{
for(int i=0,n=m_length; i<n; i++)
m_buffer[i] = toupper(m_buffer[i]);
}
bool string::ieq(const char* s) const
{
return stricmp(m_buffer, s) == 0;
}
bool string::operator == (const char* s) const
{
return strcmp(m_buffer, s) == 0;
}
bool string::operator != (const char* s) const
{
return strcmp(m_buffer, s) != 0;
}
string::~string()
{
if (m_buffer != NULL) free(m_buffer);
}
const char* string::set_from_quoted(const char* s, char stopchar, bool stop_on_space)
{
clear();
const char* src = s;
bool quoted = (*src == '"');
if (quoted)
{
src++;
while(*src && *src != '"' && *src != stopchar)
{
char c = *src;
if (c == '\\')
{
src++;
c = *src;
switch(c)
{
case 'n': c = '\n'; break;
case 'r': c = '\r'; break;
case 't': c = '\t'; break;
}
}
append(c);
src++;
}
if (*src == '"') src++;
return src;
}
else if (stop_on_space)
{
const char* field_start = src;
while(*src && !isspace(*src) && *src != stopchar) src++;
set(field_start, src-field_start);
return src;
}
else
{
const char* field_start = src;
while(*src && *src != stopchar) src++;
set(field_start, src-field_start);
return src;
}
}
// removes last character
const char* string::chop()
{
if (m_length > 0) m_buffer[--m_length] = '\0';
return m_buffer;
}
// removes last character if it is one of specified characters
const char* string::chop(const char* pat)
{
while (m_length > 1 && strchr(pat, m_buffer[m_length-1]))
{
m_buffer[--m_length] = '\0';
}
return m_buffer;
}
int string::split(string_array& list)
{
return split(m_buffer, list);
}
int string::split(const char* s, array<string, true>& list)
{
return split(s, list, NULL);
}
int string::split(const char* s, array<string, true>& list, const char* separators)
{
int count = 0;
list.clear();
const char* src = s;
while(*src)
{
while(*src && (separators == NULL && isspace(*src) || separators != NULL && strchr(separators, *src) != NULL))
src++;
if (*src == '\0') break;
string* s = new string();
src = s->set_from_quoted(src, '\0', true);
list.add(s);
count++;
}
return count;
}
int string::split(const char* pattern, ...)
{
va_list ap; va_start(ap, pattern);
return split(m_buffer, pattern, ap);
}
int string::split(const char* s, const char* pattern, ...)
{
va_list ap; va_start(ap, pattern);
return split(s, pattern, ap);
}
/**
* Divides text string into numeric and/or string fields according to the specified
* pattern.
*
* pattern consists of one or more following characters:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?