📄 dstring.cpp
字号:
#include <stdio.h>#include <string.h>#include <stdlib.h>#include <ctype.h>#include "dstring.h"#include "genarray.h"#include <stdarg.h>#pragma intrinsic strcpy#pragma intrinsic memset#pragma intrinsic memcpyconst char *String::NULLCHARSTRING = "";String String::NULLSTRING;inline void String::String_data::operator++(){refcnt++;}void String::String_data::operator--(){if(--refcnt == 0)delete this;}String::String_data *String::newsdp(size_t nbytes){ String::String_data *sp = (String::String_data*)new char[sizeof(int)+nbytes]; sp->refcnt = 1; assert(sp); return sp;}String::String_data *String::newsdp(String::String_data *sdp){ unsigned nbytes = strlen(sdp->data)+1; String::String_data *sp = newsdp(nbytes); memcpy(sp->data, sdp->data, nbytes); return sp;}unsigned String::hashval(const char *cp){ unsigned res = 0; char c; while((c = *cp++) != 0) res += c; return res;}#ifdef STRING_POOL_ALLOC// A special allocation pool for Strings (the String handle is small// and is allocated a lot).String * String::freelist = 0;const int allocblocksize = 100;void * String::operator new(size_t size){ // First of all, check that we are allocating the right size of // object. This may not be true if we are allocating a derived // kind of object which is bigger, and the appropriate redefinition // of of operator new() has not been done for that class. // If the size is "wrong", then we let the standard operator handle it. // See also the comment in operator delete() for a similar concern if(size != sizeof(String)) return ::operator new(size); // Is there no remaining space allocated? if(freelist == 0){ // Grab a new chunk of allocblocksize elements freelist = (String *)new char[allocblocksize * sizeof(String)]; if(freelist == 0) return 0; // Now make sure that they all form an appropriately-linked list for(int i = 0; i < allocblocksize-1; i++) freelist[i].freeptr = &freelist[i+1]; freelist[i].freeptr = 0; } // Retrieve first item from the list and return it String *shp = freelist; freelist = freelist->freeptr; return shp;}void String::operator delete(void *vp, size_t size){ // We do not have a cast-iron guarantee that the size is right, // since we may be deleting a derived class object through its // base class pointer and it's apparent size will be wrong. // On the other hand, if it has a virtual destructor, or the // delete is applied to a non-base pointer, the size WILL be right. // If we can tell that this was not really allocated from the pool, // hand it back to the global delete operator. if(size != sizeof(String)){ ::delete(vp); return; } // Well, it looks as if it is one of ours. Stitch it into the free // list. If it wasn't allocated the normal way and is bigger, this // means that we will lose some memory ((String *)vp)->freeptr = freelist; freelist = (String *)vp;}#endif// if our current data is shared with others, take a copy of it (it is// about to be changed)void String::single_copy(){ if(sdp->refcnt == 1) return; String_data *nsdp = newsdp(sdp); --*sdp; sdp = nsdp;}// WARNING - init() must only be called by constructors (assumes cp unset)void String::init(const char *ccp){ if(ccp){ size_t l = strlen(ccp)+1; sdp = newsdp(l); memcpy(sdp->data, ccp, l); }else{ sdp = newsdp(1); sdp->data[0] = 0; }}String::String(){ init("");}String::String(const char * s){ init(s);}String::String(char c){ static char car[2]; car[0] = c; car[1] = 0; init(car);}// Create a substringString::String(const char *ccp, size_t nbytes){ size_t l = strlen(ccp); if(nbytes < l) l = nbytes; sdp = newsdp(l+1); memcpy(sdp->data, ccp, l); sdp->data[l] = 0;}/* * This is very awk-like! * Construct a String from an int - build the character representation * of the int first, then build a String! */String::String(int i){ char car[20]; ::sprintf(car,"%d", i); init(car);}String::String(unsigned u){ char car[20]; ::sprintf(car,"%u", u); init(car);}String::String(long l){ char car[20]; ::sprintf(car,"%ld", l); init(car);}String::String(unsigned long l){ char car[20]; ::sprintf(car,"%lu", l); init(car);}String::String(const String& s){ sdp = s.sdp; ++*sdp;}String & String::operator =(const String & s){ ++*s.sdp; --*sdp; sdp = s.sdp; return *this;}String & String::operator = (const char *ccp){ if(ccp == 0){ printf("Panic: assigning null String\n"); exit(-1); } size_t l = strlen(ccp)+1; String_data *nsdp = newsdp(l); memcpy(nsdp->data, ccp, l); --*sdp; sdp = nsdp; return *this;}String::~String(){ --*sdp;}String operator +(const String &s1, const String &s2){ size_t newlen, oldlen; oldlen = s1.nchars(); size_t s2len = s2.nchars(); newlen = oldlen + s2len; assert(newlen >= oldlen && newlen >= s2len); String::String_data *nsdp = String::newsdp(newlen+1); // strcpy(nsdp->data, s1.sdp->data); memcpy(nsdp->data, s1.sdp->data, oldlen); // strcpy(nsdp->data+oldlen, s2.sdp->data); memcpy(nsdp->data+oldlen, s2.sdp->data, s2len+1); // String reslt(nsdp); // --*reslt.sdp; // reslt.sdp = nsdp; // return reslt; return nsdp; // Use special constructor}String operator +(const String &cs, const char *csp){ return cs + String(csp);}String operator +(const String &cs, char c){ return cs + String(c);}String operator +(char c, const String &cs){ return String(c) + cs;}String operator +(const char *csp, const String &cs){ return String(csp)+cs;}String & String::operator +=(char c){ static char car[2]; car[0] = c; car[1] = 0; return operator +=(car);}String & String::operator +=(const String& s){ return operator = (*this+s);}String & String::operator +=(const char *csp){ return operator = (*this+csp);}void String::operator ++(){ String i(operator int() + 1); operator =(i);}String::operator int()const{ return (int)strtol(sdp->data, 0, 0);}int operator ==(const String& s1, const String& s2){ return(strcmp(s1.sdp->data, s2.sdp->data) == 0);}int operator ==(const String& s1, const char *s2){ return(strcmp(s1.sdp->data, s2) == 0);}int operator >(const String& cs1, const String& cs2){ return strcmp(cs1.sdp->data, cs2.sdp->data) > 0;}int operator >(const String& cs1, const char * cs2){ return strcmp(cs1.sdp->data, cs2) > 0;}int operator <(const String& cs1, const String& cs2){ return strcmp(cs1.sdp->data, cs2.sdp->data) < 0;}int operator <(const String& cs1, const char * cs2){ return strcmp(cs1.sdp->data, cs2) < 0;}char String::operator [](size_t index1)const{ if(index1 <= 0 || index1 > nchars()){ return(0); } return(sdp->data[index1-1]);}String String::substr(size_t start, size_t len)const{ const size_t nc = nchars(); //printf("substring: start %lu, len %lu nc %lu\n", start, len, nc); if(start < 1 || start > nc){ return(""); } if(len < 1){ return(""); } /* * len is allowed to be `too' long. Shorten if necessary * Explanation of arithmetic: assume n bytes length (1..n) * then start+allowable_length == n+1 (consider start==1, len == n). * Clearly, allowable_length = n+1 - start */ // This first test should eliminate nasty problems caused by overflow. // The problem was caused by substr(6,-6); if(len > nc){ len = nc; } if(start+len > nc+1) len = nc + 1 - start; //printf("substring: start %lu, len %lu nc %lu\n", start, len, nc); /* can't use strncpy - doesn't guarantee a null at the end */ String_data *nsdp = newsdp(len+1); // char *ncp = new char [nc+1]; memcpy(nsdp->data, sdp->data+start-1, len); nsdp->data[len] = 0; // String temp = ncp; // delete [] ncp; return(nsdp);}String String::left(size_t n)const{ return substr(1, n);}String String::right(size_t n)const{ const nc = nchars(); int start = nc-n+1; if(start < 1) start = 1; return substr(start, n);}// Could be more efficient, but this hack works for the presentString String::tailstr(size_t startpos1)const{ return substr(startpos1, nchars());}// copy cp2 into cp - don't ovewrite the end or copy the nullvoid copystr(char *cp, const char *cp2){ while(*cp) if(*cp2) *cp++ = *cp2++; else return;}// Set the designated character to the designated valuevoid String::set_char(size_t index1, char cval){ if(index1 <= 0 || index1 > nchars()) return; single_copy(); sdp->data[index1-1] = cval;}// Set the subString at startpos with the contents of set_from.// Make room at the end if necessary.// The funny stuff with tmpstr is because we may be setting a subString// of ourselves with ourself (this is like String assign, but nastier)void String::set_substr(size_t startpos, const char * set_from, char filler){ const size_t oldlen = nchars(); if(startpos < 1){ return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -