AnsiString的内部结构是什么?

BCB 2001-08-01 09:40:41
加精
Delphi与BCB中有一个长串AnsiString,用很最多,
我初步分析它的结构:
它只有4个字节长,实为一串指针,
指向一个含尾0的字符串,这个字符串的前4个字节为一
长整数,存放的是串长,所以串长可达 2^32-1 (4TB),
好象就这样简单,现在有没有AnsiString源码定义?!!!!!!!!!!!!!我想看看!

AnsiString s1="test123";
void __fastcall TForm1::Button1Click(TObject *Sender)
{
ShowMessage(sizeof(s1)); // 为4,实为串指针
char *p=(char * &)s1; // s1的内容当作指针
ShowMessage(p); // 显示的就是串本身,说明s1就是指向串缓冲
long sl=*((long *)(p-4)); // 串前四个字节为长整数,实为串长
ShowMessage(sl); // 显示串长为7
}
谁能找一找AnsiString的源码定义内容?一定给分!!!!!!!!!!!!!!


...全文
395 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
BCB 2001-08-01
  • 打赏
  • 举报
回复
!
weenyboy 2001-08-01
  • 打赏
  • 举报
回复
呵呵, 你应该少用指针方式来思考问题, 向老火多学习点C++吧, 你看到的是对象在内存中的存放,第一个属性是长度啊,后面是字符串, 所以看起来就象你说的那样
holyfire 2001-08-01
  • 打赏
  • 举报
回复
__DSTRING_INLINE const AnsiString::StrRec &AnsiString::GetRec() const
{
return reinterpret_cast<const StrRec *>(Data)[-1];
}

__DSTRING_INLINE AnsiString::StrRec &AnsiString::GetRec()
{
return reinterpret_cast<StrRec *>(Data)[-1];
}

__DSTRING_INLINE int __fastcall AnsiString::Length() const
{
return (Data)? GetRec().length : 0;
}
串长放在Data前面
BCB 2001-08-01
  • 打赏
  • 举报
回复
肯定还要有串长的定义,比如:
unsigned int Len;
char Data[sz];
gqxs 2001-08-01
  • 打赏
  • 举报
回复
up
holyfire 2001-08-01
  • 打赏
  • 举报
回复
wchar_t* __fastcall AnsiString::WideChar(wchar_t* dest, int destSize) const
{
MultiByteToWideChar(CP_ACP,0,(Data)?Data: (const PChar)"",-1,dest,destSize);
return dest;
}

只是调用函数来转化一下而已
BCB 2001-08-01
  • 打赏
  • 举报
回复
只见到短串的结构,长串的结构仍未见到
template <unsigned char sz> class SmallStringBase
{
protected:
unsigned char Len;
char Data[sz];
};


holyfire 2001-08-01
  • 打赏
  • 举报
回复
private:
// assert(offsetof(AnsiString, Data) == 0);
char *Data;

很简单的,一个变长的数组而已
BCB 2001-08-01
  • 打赏
  • 举报
回复
太长了,要仔细研究;据此
大家再邦助分析: AnsiString的数据结构!

chzhli186858 2001-08-01
  • 打赏
  • 举报
回复
dingzhenhhy(人言落日是天涯,望及天涯不见家(快疯了) 
慢拉
我也慢拉
路人丁 2001-08-01
  • 打赏
  • 举报
回复
奥!已经有人贴出来了,这么快……
路人丁 2001-08-01
  • 打赏
  • 举报
回复
几乎每个vcl组件都会有Sring类型的属性,所以当使用vcl组件时,会使用到String类型,而c++采用字符串指针的方式来处理字符串,他没有像Sting一样的数据类型,为了能顺利存取vcl组件属性,c++Builder就提供了一个类型AnsiString来模拟delphi中的String类型,可以看看这个文件,找到AnsiSting这个类的定义:
...Borland\CBuilder5\Include\Vcl\dstring.h


// dstring.cpp - support for delphi strings in cpp
// $Revision: 1.24.1.7 $
// Copyright (c) 1997, 1999 Borland International

#pragma inline
#define __DSTRING_INLINE

#include <windows.hpp>
#include <sysutils.hpp>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <limits.h>

#include <dstring.h>

#ifdef near
#undef near
#endif

static void dummy()
{
// extern all asm symbols used here
asm
{
extrn @System@@LStrAsg$qqrv:near
extrn @System@@LStrCat$qqrv:near
extrn @System@@LStrCat3$qqrv:near
extrn @System@@LStrClr$qqrr17System@AnsiString:near
extrn @System@@LStrCmp$qqrv:near
extrn @System@@LStrCopy$qqrv:near
extrn @System@@LStrDelete$qqrv:near
extrn @System@@LStrFromArray$qqrr17System@AnsiStringpci:near
extrn @System@@LStrFromWStr$qqrr17System@AnsiStringx17System@WideString:near
extrn @System@@LStrInsert$qqrv:near
extrn @System@@LStrFromPChar$qqrr17System@AnsiStringpc:near
extrn @System@@LStrLen$qqrv:near
extrn @System@@LStrPos$qqrv:near
extrn @System@@LStrSetLength$qqrv:near
}
}


namespace System
{
void AnsiString::ThrowIfOutOfRange(int idx) const
{
if (idx < 1 || idx > Length()) // NOTE: AnsiString are 1-based !!
throw ERangeError(Sysconst_SRangeError);
}

__fastcall AnsiString::AnsiString(const char*)
{
asm
{
xor ecx,ecx
mov eax, this
mov [eax], ecx
call @System@@LStrFromPChar$qqrr17System@AnsiStringpc
}
}

__fastcall AnsiString::AnsiString(const AnsiString&)
{
asm
{
mov edx,[edx]
xor ecx,ecx
mov eax, this
mov [eax],ecx
call @System@@LStrAsg$qqrv
}
}

__fastcall AnsiString::AnsiString(const WideString &)
{
asm
{
xor ecx, ecx
mov eax, this
mov [eax], ecx /* this->data = NULL */
mov edx, [edx] /* edx = src->data */
call @System@@LStrFromWStr$qqrr17System@AnsiStringx17System@WideString
}
}



__fastcall AnsiString::AnsiString(const char* src, unsigned int len) : Data(0)
{
// We only handle up to INT_MAX (the sign bit is ignored)
SetLength(int(len & INT_MAX));
memcpy(Data, src, int(len & INT_MAX));
}


__fastcall AnsiString::AnsiString(const wchar_t* src) : Data(0)
{
int len = WideCharToMultiByte(CP_ACP, 0, const_cast<wchar_t*>(src), -1, 0, 0, 0, 0);

if (len > 1)
{
SetLength(len - 1);
WideCharToMultiByte(CP_ACP, 0, const_cast<wchar_t*>(src), -1, Data, len, 0, 0);
}
}

__fastcall AnsiString::AnsiString(char src) : Data(0)
{
sprintf("%c", src);
}

__fastcall AnsiString::AnsiString(short src) : Data(0)
{
sprintf("%hd", src);
}

__fastcall AnsiString::AnsiString(unsigned short src) : Data(0)
{
sprintf("%hu", src);
}

__fastcall AnsiString::AnsiString(int src) : Data(0)
{
sprintf("%i", src);
}

__fastcall AnsiString::AnsiString(unsigned int src) : Data(0)
{
sprintf("%u", src);
}

__fastcall AnsiString::AnsiString(long src) : Data(0)
{
sprintf("%ld", src);
}

__fastcall AnsiString::AnsiString(unsigned long src) : Data(0)
{
sprintf("%lu", src);
}

__fastcall AnsiString::AnsiString(__int64 src) : Data(0)
{
sprintf("%Li", src);
}

__fastcall AnsiString::AnsiString(unsigned __int64 src) : Data(0)
{
sprintf("%Lu", src);
}

__fastcall AnsiString::AnsiString(double src) : Data(0)
{
*this = Sysutils::FloatToStr(src);
}

__fastcall AnsiString::~AnsiString()
{
asm
{
mov eax,this
call @System@@LStrClr$qqrr17System@AnsiString
}
}

AnsiString& __fastcall AnsiString::operator=(const AnsiString&)
{
asm
{
mov edx,[edx]
call @System@@LStrAsg$qqrv
}
return *this;
}

AnsiString& __fastcall AnsiString::operator+=(const AnsiString&)
{
asm
{
mov edx,[edx]
call @System@@LStrCat$qqrv
}
return *this;
}

AnsiString __fastcall AnsiString::operator+(const AnsiString& rhs) const
{
#if 0
//!JK Per Peter S., change to push 0 onto the stack
//!JK and use as the first parm
//!JK need to take out double contruction (return tmp)
#endif
AnsiString tmp;
AnsiString* ptmp = &tmp;
asm
{
mov edx, this
mov edx, [edx]
mov eax, ptmp
mov ecx, rhs
mov ecx, [ecx]
call @System@@LStrCat3$qqrv
}
return tmp;
}

#pragma option push -w-rvl

bool __fastcall AnsiString::operator==(const AnsiString&) const
{
asm
{
mov eax, [eax]
mov edx, [edx]
call @System@@LStrCmp$qqrv
sete al
and eax, 1
}
}

bool __fastcall AnsiString::operator!=(const AnsiString&) const
{
asm
{
mov eax, [eax]
mov edx, [edx]
call @System@@LStrCmp$qqrv
setne al
and eax, 1
}
}

bool __fastcall AnsiString::operator<(const AnsiString&) const
{
asm
{
mov eax, [eax]
mov edx, [edx]
call @System@@LStrCmp$qqrv
setb al
and eax, 1
}
}

bool __fastcall AnsiString::operator>(const AnsiString&) const
{
asm
{
mov eax, [eax]
mov edx, [edx]
call @System@@LStrCmp$qqrv
seta al
and eax, 1
}
}
#pragma option pop

bool __fastcall AnsiString::operator<=(const AnsiString& rhs) const
{
return !operator>(rhs);
}

bool __fastcall AnsiString::operator >=(const AnsiString& rhs) const
{
return !operator<(rhs);
}

int __fastcall AnsiString::AnsiCompare(const AnsiString& rhs) const
{
return Sysutils::AnsiCompareStr(*this, rhs);
}

int __fastcall AnsiString::AnsiCompareIC(const AnsiString& rhs) const
{
return Sysutils::AnsiCompareText(*this, rhs);
}


// Return AnsiString of count chars of value ch
AnsiString __fastcall AnsiString::StringOfChar(char ch, int count)
{
AnsiString tmp;
tmp.SetLength(count);
memset(tmp.Data, ch, count);
return tmp;
}

AnsiString __fastcall AnsiString::LoadStr(int ident)
{
return Sysutils::LoadStr(ident);
}

AnsiString __fastcall AnsiString::LoadStr(HINSTANCE hInstance, int ident)
{
AnsiString str;
str.LoadString(hInstance, ident);
return str;
}

AnsiString& __fastcall AnsiString::LoadString(HINSTANCE hInstance, int id)
{
HRSRC resHdl = ::FindResource(hInstance, MAKEINTRESOURCE(id/16+1), RT_STRING);
if (resHdl)
{
HGLOBAL gblHdl = ::LoadResource(hInstance, resHdl);
if (gblHdl)
{
WCHAR* resData = (WCHAR*)::LockResource(gblHdl);
if (resData)
{
unsigned int len;
for (int cnt = id % 16; len = *resData++, cnt--; resData += len)
;
if (len != 0)
{
SetLength(len);
len = ::WideCharToMultiByte(CP_ACP, 0, resData, len, Data, len, 0, 0);
if (len > 0)
Data[len] = 0;
}
/* Unnecessary in Win32
::UnlockResource(gblHdl);
*/
}
::FreeResource(resHdl);
}
}

return *this;
}

AnsiString __fastcall AnsiString::FmtLoadStr(int ident, const TVarRec* args, int size)
{
return Sysutils::FmtLoadStr(ident, args, size);
}

AnsiString __fastcall AnsiString::Format(const AnsiString& format, const TVarRec *args, int size)
{
return Sysutils::Format(format, args, size);
}

AnsiString __fastcall AnsiString::FormatFloat(const AnsiString& format, const long double& value)
{
return Sysutils::FormatFloat(format, value);
}


#undef vprintf
#undef printf
#undef sprintf

int __cdecl AnsiString::vprintf(const char* format, va_list paramList)
{
int size = vsnprintf(NULL, 0, format, paramList);
SetLength(size);
return vsnprintf(Data, size, format, paramList);
}

int __cdecl AnsiString::cat_vprintf(const char* format, va_list paramList)
{
int size = vsnprintf(NULL, 0, format, paramList);
int len = Length();
SetLength(len + size);
return vsnprintf(Data + len, len + size, format, paramList);
}


int __cdecl AnsiString::printf(const char* format, ...)
{
int rc;
va_list paramList;
va_start(paramList, format);
rc = vprintf(format, paramList);
va_end(paramList);
return rc;
}

AnsiString& __cdecl AnsiString::sprintf(const char* format, ...)
{
va_list paramList;
va_start(paramList, format);
vprintf(format, paramList);
va_end(paramList);
return *this;
}


int __cdecl AnsiString::cat_printf(const char* format, ...)
{
int rc;
va_list paramList;
va_start(paramList, format);
rc = cat_vprintf(format, paramList);
va_end(paramList);
return rc;
}

AnsiString& __cdecl AnsiString::cat_sprintf(const char* format, ...)
{
va_list paramList;
va_start(paramList, format);
cat_vprintf(format, paramList);
va_end(paramList);
return *this;
}


AnsiString __fastcall AnsiString::FloatToStrF(long double value, TStringFloatFormat format, int precision, int digits)
{
#if 0
//!JK this code requires TStringFloatFormat and TFloatFormat to be identical
#endif
return Sysutils::FloatToStrF(value, TFloatFormat(format), precision, digits);
}

AnsiString __fastcall AnsiString::IntToHex(int value, int digits)
{
return Sysutils::IntToHex(value, digits);
}

AnsiString __fastcall AnsiString::CurrToStr(Currency value)
{
return ::CurrToStr(value);
}

AnsiString __fastcall AnsiString::CurrToStrF(Currency value, TStringFloatFormat format, int digits)
{
#if 0
//!JK this code requires TStringFloatFormat and TFloatFormat to be identical
#endif
return Sysutils::CurrToStrF(value, TFloatFormat(format), digits);
}

int __fastcall AnsiString::WideCharBufSize() const
{
// return size of buffer required to call WideChar()
return MultiByteToWideChar(CP_ACP,0,(Data)? Data: (const PChar)"", -1, 0,0);
}

//Convert to Unicode
wchar_t* __fastcall AnsiString::WideChar(wchar_t* dest, int destSize) const
{
MultiByteToWideChar(CP_ACP,0,(Data)?Data: (const PChar)"",-1,dest,destSize);
return dest;
}

AnsiString& __fastcall AnsiString::Unique()
{
System::UniqueString(*this);
return *this;
}

AnsiString& __fastcall AnsiString::Insert(const String& source, int index)
{
asm
{
// edx must be a pointer to the characters
mov edx, this
// eax must be the characters themselves
mov eax, source
mov eax, [eax]
mov ecx, index
call @System@@LStrInsert$qqrv
}
return *this;
}

AnsiString& __fastcall AnsiString::Delete(int index, int count)
{
asm
{
// eax must be a pointer to the characters
mov eax, this
mov edx, index
mov ecx, count
call @System@@LStrDelete$qqrv
}
return *this;
}

AnsiString& __fastcall AnsiString::SetLength(int newLength)
{
asm
{
// eax must be a pointer to the characters
mov eax, this
mov edx, newLength
call @System@@LStrSetLength$qqrv
}
return *this;
}

int __fastcall AnsiString::Pos(const AnsiString& subStr) const
{
asm
{
// edx must be the characters themselves
mov edx, this
mov edx, [edx]
// eax must be the characters themselves!
mov eax, subStr
mov eax, [eax]
call @System@@LStrPos$qqrv
//Result left in eax
}
return _EAX;
}

AnsiString __fastcall AnsiString::LowerCase() const
{
return Sysutils::AnsiLowerCase(*this);
}

AnsiString __fastcall AnsiString::UpperCase() const
{
return Sysutils::AnsiUpperCase(*this);
}

AnsiString __fastcall AnsiString::Trim() const
{
return Sysutils::Trim(*this);
}

AnsiString __fastcall AnsiString::TrimLeft() const
{
return Sysutils::TrimLeft(*this);
}

AnsiString __fastcall AnsiString::TrimRight() const
{
return Sysutils::TrimRight(*this);
}

AnsiString __fastcall AnsiString::SubString(int index, int count) const
{
// Emulate Pascal's _LStrCopy: if 'index' is bogus, or the 'count' is negative,
// return an empty string.
if (index < 1 || index > Length() || count < 0)
return AnsiString();

// If 'count' is too large, copy the rest of the string.
int n = Length() - index + 1;
if (n > count)
n = count;
return AnsiString(Data + index - 1, n);
}

int __fastcall AnsiString::ToInt() const
{
return Sysutils::StrToInt(*this);
}

int __fastcall AnsiString::ToIntDef(int defaultValue) const
{
return Sysutils::StrToIntDef(*this, defaultValue);
}

double __fastcall AnsiString::ToDouble() const
{
#if 0
//!JK change this to return a long double when the compiler properly
//!JK promotes/demotes long doubles/doubles
#endif
return Sysutils::StrToFloat(*this);
}

bool __fastcall AnsiString::IsDelimiter(const AnsiString& delimiters, int index) const
{
return Sysutils::IsDelimiter(delimiters, *this, index);
}

int __fastcall AnsiString::AnsiPos(const AnsiString& subStr) const
{
return Sysutils::AnsiPos(subStr, *this);
}

bool __fastcall AnsiString::IsPathDelimiter(int index) const
{
return Sysutils::IsPathDelimiter(*this, index);
}

int __fastcall AnsiString::LastDelimiter(const AnsiString& delimiters) const
{
return Sysutils::LastDelimiter(delimiters, *this);
}

AnsiString::TStringMbcsByteType __fastcall AnsiString::ByteType(int index) const
{
//!GCD this code requires TStringMbcsByteType and TMbcsByteType to be identical
return TStringMbcsByteType(Sysutils::ByteType(*this, index));
}

bool __fastcall AnsiString::IsLeadByte(int index) const
{
return ByteType(index) == mbLeadByte;
}

bool __fastcall AnsiString::IsTrailByte(int index) const
{
return ByteType(index) == mbTrailByte;
}

char* __fastcall AnsiString::AnsiLastChar() const
{
return Sysutils::AnsiLastChar(*this);
}

AnsiString __fastcall operator+(const char* lhs, const AnsiString& rhs)
{
AnsiString tmp(lhs);
AnsiString* ptmp = &tmp;
asm
{
mov eax,ptmp
mov edx,rhs
mov edx,[edx]
call @System@@LStrCat$qqrv
}
return tmp;
}


} // System Namespace


******************************************************************************


// DSTRING.H - Support for delphi strings in C++
// (AnsiString and template<sz> SmallString)
// $Revision: 1.33.1.3 $
// $Date: 14 Dec 1999 17:58:10 $
//
// Copyright (c) 1997, 1999 Borland International

#ifndef DSTRING_H
#define DSTRING_H

#pragma delphiheader begin

#include <sysmac.h>
#include <stdarg.h>


namespace System
{
class TVarRec;
class RTL_DELPHIRETURN Currency;
class RTL_DELPHIRETURN WideString;

/////////////////////////////////////////////////////////////////////////////
// AnsiString: String class compatible with Delphi's Native 'string' type
/////////////////////////////////////////////////////////////////////////////
class RTL_DELPHIRETURN AnsiString
{
friend AnsiString __fastcall operator +(const char*, const AnsiString& rhs);
public:
// the TStringFloatFormat enum is used by FloatToStrF
enum TStringFloatFormat
{sffGeneral, sffExponent, sffFixed, sffNumber, sffCurrency};
static AnsiString __fastcall StringOfChar(char ch, int count);
static AnsiString __fastcall LoadStr(int ident);
static AnsiString __fastcall LoadStr(HINSTANCE hInstance, int ident);
static AnsiString __fastcall FmtLoadStr(int ident, const TVarRec *args,
int size);

AnsiString& __fastcall LoadString(HINSTANCE hInstance, int ident);

// Delphi style 'Format'
//
static AnsiString __fastcall Format(const AnsiString& format,
const TVarRec *args, int size);

// C style 'sprintf' (NOTE: Target buffer is the string)
//
AnsiString& __cdecl sprintf(const char* format, ...); // Returns *this
int __cdecl printf(const char* format, ...); // Returns formatted length
int __cdecl vprintf(const char* format, va_list); // Returns formatted length


// Like above, but appends to the string rather than overwrite
AnsiString& __cdecl cat_sprintf(const char* format, ...); // Returns *this
int __cdecl cat_printf(const char* format, ...); // Returns formatted length
int __cdecl cat_vprintf(const char* format, va_list); // Returns formatted length

static AnsiString __fastcall FormatFloat(const AnsiString& format,
const long double& value);
static AnsiString __fastcall FloatToStrF(long double value,
TStringFloatFormat format, int precision, int digits);
static AnsiString __fastcall IntToHex(int value, int digits);
static AnsiString __fastcall CurrToStr(Currency value);
static AnsiString __fastcall CurrToStrF(Currency value,
TStringFloatFormat format, int digits);

// Constructors
__fastcall AnsiString(): Data(0) {}
__fastcall AnsiString(const char* src);
__fastcall AnsiString(const AnsiString& src);
// __fastcall AnsiString(const char* src, unsigned char len);
__fastcall AnsiString(const char* src, unsigned int len);
__fastcall AnsiString(const wchar_t* src);
__fastcall AnsiString(char src);
__fastcall AnsiString(short);
__fastcall AnsiString(unsigned short);
__fastcall AnsiString(int src);
__fastcall AnsiString(unsigned int);
__fastcall AnsiString(long);
__fastcall AnsiString(unsigned long);
__fastcall AnsiString(__int64);
__fastcall AnsiString(unsigned __int64);
__fastcall AnsiString(double src);
__fastcall AnsiString(const WideString &src);

// Destructor
__fastcall ~AnsiString();

// Assignments
AnsiString& __fastcall operator =(const AnsiString& rhs);
AnsiString& __fastcall operator +=(const AnsiString& rhs);

// Comparisons
bool __fastcall operator ==(const AnsiString& rhs) const;
bool __fastcall operator !=(const AnsiString& rhs) const;
bool __fastcall operator <(const AnsiString& rhs) const;
bool __fastcall operator >(const AnsiString& rhs) const;
bool __fastcall operator <=(const AnsiString& rhs) const;
bool __fastcall operator >=(const AnsiString& rhs) const;
int __fastcall AnsiCompare(const AnsiString& rhs) const;
int __fastcall AnsiCompareIC(const AnsiString& rhs) const; //ignorecase

// Accessing character at specified index

char __fastcall operator [](const int idx) const
{
ThrowIfOutOfRange(idx); // Should Range-checking be optional to avoid overhead ??
return Data[idx-1];
}

#if defined(ANSISTRING_USE_PROXY_FOR_SUBSCRIPT)

// The use of a proxy class optimizes the case where Unique() must be called
// when accessing the string via the subscript operator. However, the use of
// of the proxy class has some drawbacks. First, it breaks code that apply
// operators to the return value. For example, &MyString[i]. Second, it
// fails in cases where a implicit conversion was relied upon. For example,
// callFuncThatTakesAnObjectWithACharCtr(MyString[i]);
// In that case, two implicit conversions would be required...
// The first issue can be remedied by enhancing the proxy class to support
// all valid operators. The second issue can be lessened but not completely
// eliminated. Hence, the use of the PROXY class is not the default!
//
private:
class TCharProxy;
friend TCharProxy;
class TCharProxy
{
public:
TCharProxy(AnsiString& strRef, int index) : m_Ref(strRef), m_Index(index) {}
TCharProxy& operator=(char c) { m_Ref.Unique(); m_Ref.Data[m_Index-1] = c; return *this; }
operator char() const { return m_Ref.Data[m_Index-1]; }

protected:
AnsiString& m_Ref;
int m_Index;
};

public:
TCharProxy __fastcall operator [](const int idx)
{
ThrowIfOutOfRange(idx); // Should Range-checking be optional to avoid overhead ??
return TCharProxy(*this, idx);
}

#else

char& __fastcall operator [](const int idx)
{
ThrowIfOutOfRange(idx); // Should Range-checking be optional to avoid overhead ??
Unique(); // Ensure we're not ref-counted
return Data[idx-1];
}

#endif

// Concatenation
AnsiString __fastcall operator +(const AnsiString& rhs) const;

// C string operator
char* __fastcall c_str() const { return (Data)? Data: "";}

// Read access to raw Data ptr. Will be NULL for an empty string.
const void* __fastcall data() const { return Data; }

// Query attributes of string
int __fastcall Length() const;
bool __fastcall IsEmpty() const { return Data == NULL; }

// Make string unique (refcnt == 1)
AnsiString& __fastcall Unique();

// Modify string
AnsiString& __fastcall Insert(const AnsiString& str, int index);
AnsiString& __fastcall Delete(int index, int count);
AnsiString& __fastcall SetLength(int newLength);

int __fastcall Pos(const AnsiString& subStr) const;
AnsiString __fastcall LowerCase() const;
AnsiString __fastcall UpperCase() const;
AnsiString __fastcall Trim() const;
AnsiString __fastcall TrimLeft() const;
AnsiString __fastcall TrimRight() const;
AnsiString __fastcall SubString(int index, int count) const;

int __fastcall ToInt() const;
int __fastcall ToIntDef(int defaultValue) const;
double __fastcall ToDouble() const;

// Convert to Unicode
int __fastcall WideCharBufSize() const;
wchar_t* __fastcall WideChar(wchar_t* dest, int destSize) const;

// MBCS support
enum TStringMbcsByteType
{mbSingleByte, mbLeadByte, mbTrailByte};

TStringMbcsByteType __fastcall ByteType(int index) const;
bool __fastcall IsLeadByte(int index) const;
bool __fastcall IsTrailByte(int index) const;
bool __fastcall IsDelimiter(const AnsiString& delimiters, int index) const;
bool __fastcall IsPathDelimiter(int index) const;
int __fastcall LastDelimiter(const AnsiString& delimiters) const;
int __fastcall AnsiPos(const AnsiString& subStr) const;
char* __fastcall AnsiLastChar() const;

protected:
void ThrowIfOutOfRange(int idx) const;

struct StrRec {
int allocSiz;
int refCnt;
int length;
};

const StrRec &GetRec() const;
StrRec &GetRec();

private:
// assert(offsetof(AnsiString, Data) == 0);
char *Data;
};

extern AnsiString __fastcall operator +(const char*, const AnsiString&);

#if defined(VCL_IOSTREAM)
// see <sysclass.h>
ostream& operator << (ostream& os, const AnsiString& arg);
istream& operator >> (istream& is, AnsiString& arg);
#endif

#if !defined(__CODEGUARD__)

// Codeguard is not very happy about our "reverse indexing" of the
// Data pointer. We'll address this by violating the ODR: when
// Codeguard compile checks are enabled, these methods will not be
// inlined. When building dstring.cpp, __DSTRING_INLINE will be
// defined to generate out-of-line implementations of these methods.

#if !defined(__DSTRING_INLINE)
#define __DSTRING_INLINE inline
#endif

__DSTRING_INLINE const AnsiString::StrRec &AnsiString::GetRec() const
{
return reinterpret_cast<const StrRec *>(Data)[-1];
}

__DSTRING_INLINE AnsiString::StrRec &AnsiString::GetRec()
{
return reinterpret_cast<StrRec *>(Data)[-1];
}

__DSTRING_INLINE int __fastcall AnsiString::Length() const
{
return (Data)? GetRec().length : 0;
}

#undef __DSTRING_INLINE
#endif // !defined(__CODEGUARD__)

/////////////////////////////////////////////////////////////////////////////
// SmallStringBase
/////////////////////////////////////////////////////////////////////////////
template <unsigned char sz> class SmallStringBase
{
protected:
unsigned char Len;
char Data[sz];
};


/////////////////////////////////////////////////////////////////////////////
// SmallString
/////////////////////////////////////////////////////////////////////////////
template <unsigned char sz> class SmallString : SmallStringBase<sz>
{

public:
__fastcall SmallString() { Len = 0; }
__fastcall SmallString(const SmallString& src);
__fastcall SmallString(const char* src);

__fastcall SmallString(const AnsiString& src)
{
long len = src.Length();
Len = (unsigned char)((len > sz)? sz: len);
strncpy(Data, src.c_str(), Len);
}

char& __fastcall operator [](const unsigned char idx)
{return Data[idx-1];}

SmallString& __fastcall operator =(const SmallString& rhs);

__fastcall operator AnsiString() const;
};

// used when SmallStrings are in unions (can't have a ctor)
// must cast DummySmallString to SmallString to do anything useful

template<unsigned char sz> __fastcall
SmallString<sz>::SmallString(const char* src)
{
long len = strlen(src);
Len = (unsigned char)((len > sz)? sz: len);
strncpy(Data, src, Len);
}

template<unsigned char sz> __fastcall
SmallString<sz>::SmallString(const SmallString& src)
{
Len = src.Len;
for (int i = 0; i < Len; i++)
Data[i] = src.Data[i];
}

template<unsigned char sz> SmallString<sz>& __fastcall
SmallString<sz>::operator =(const SmallString& rhs)
{
if (this != &rhs)
{
Len = rhs.Len;
for (int i = 0; i < Len; i++)
Data[i] = rhs.Data[i];
}
return *this;
}

template<unsigned char sz>
inline __fastcall SmallString<sz>::operator AnsiString() const
{
return AnsiString(Data, Len);
}

#if defined(VCL_IOSTREAM)
// see sysclass.h
template<unsigned char sz>
ostream& operator <<(ostream& os, const SmallString<sz>& arg);

template<unsigned char sz>
istream& operator >>(istream& is, SmallString<sz>& arg);
#endif

}
using namespace System;

// The following is provided for backward compatibility.
// Otherwise, the new IntToStr(__int64) causes ambiguity for old code
// that used other integral types.
//
namespace Sysutils
{
extern PACKAGE AnsiString __fastcall IntToStr(int Value)/* overload */;
extern PACKAGE AnsiString __fastcall IntToStr(__int64 Value)/* overload */;
}

#pragma option push -w-inl

inline AnsiString __fastcall IntToStr(bool value)
{
return Sysutils::IntToStr(int(value));
}
inline AnsiString __fastcall IntToStr(unsigned int value)
{
return Sysutils::IntToStr(int(value));
}
inline AnsiString __fastcall IntToStr(long value)
{
return Sysutils::IntToStr(int(value));
}
inline AnsiString __fastcall IntToStr(unsigned long value)
{
return Sysutils::IntToStr(int(value));
}

#pragma option pop

#pragma delphiheader end.

#endif // DSTRING_H


//第一个的是.cpp
//第二个是.h
holyfire 2001-08-01
  • 打赏
  • 举报
回复
// dstring.cpp - support for delphi strings in cpp
// $Revision: 1.24.1.7 $
// Copyright (c) 1997, 1999 Borland International

#pragma inline
#define __DSTRING_INLINE

#include <windows.hpp>
#include <sysutils.hpp>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <limits.h>

#include <dstring.h>

#ifdef near
#undef near
#endif

static void dummy()
{
// extern all asm symbols used here
asm
{
extrn @System@@LStrAsg$qqrv:near
extrn @System@@LStrCat$qqrv:near
extrn @System@@LStrCat3$qqrv:near
extrn @System@@LStrClr$qqrr17System@AnsiString:near
extrn @System@@LStrCmp$qqrv:near
extrn @System@@LStrCopy$qqrv:near
extrn @System@@LStrDelete$qqrv:near
extrn @System@@LStrFromArray$qqrr17System@AnsiStringpci:near
extrn @System@@LStrFromWStr$qqrr17System@AnsiStringx17System@WideString:near
extrn @System@@LStrInsert$qqrv:near
extrn @System@@LStrFromPChar$qqrr17System@AnsiStringpc:near
extrn @System@@LStrLen$qqrv:near
extrn @System@@LStrPos$qqrv:near
extrn @System@@LStrSetLength$qqrv:near
}
}


namespace System
{
void AnsiString::ThrowIfOutOfRange(int idx) const
{
if (idx < 1 || idx > Length()) // NOTE: AnsiString are 1-based !!
throw ERangeError(Sysconst_SRangeError);
}

__fastcall AnsiString::AnsiString(const char*)
{
asm
{
xor ecx,ecx
mov eax, this
mov [eax], ecx
call @System@@LStrFromPChar$qqrr17System@AnsiStringpc
}
}

__fastcall AnsiString::AnsiString(const AnsiString&)
{
asm
{
mov edx,[edx]
xor ecx,ecx
mov eax, this
mov [eax],ecx
call @System@@LStrAsg$qqrv
}
}

__fastcall AnsiString::AnsiString(const WideString &)
{
asm
{
xor ecx, ecx
mov eax, this
mov [eax], ecx /* this->data = NULL */
mov edx, [edx] /* edx = src->data */
call @System@@LStrFromWStr$qqrr17System@AnsiStringx17System@WideString
}
}



__fastcall AnsiString::AnsiString(const char* src, unsigned int len) : Data(0)
{
// We only handle up to INT_MAX (the sign bit is ignored)
SetLength(int(len & INT_MAX));
memcpy(Data, src, int(len & INT_MAX));
}


__fastcall AnsiString::AnsiString(const wchar_t* src) : Data(0)
{
int len = WideCharToMultiByte(CP_ACP, 0, const_cast<wchar_t*>(src), -1, 0, 0, 0, 0);

if (len > 1)
{
SetLength(len - 1);
WideCharToMultiByte(CP_ACP, 0, const_cast<wchar_t*>(src), -1, Data, len, 0, 0);
}
}

__fastcall AnsiString::AnsiString(char src) : Data(0)
{
sprintf("%c", src);
}

__fastcall AnsiString::AnsiString(short src) : Data(0)
{
sprintf("%hd", src);
}

__fastcall AnsiString::AnsiString(unsigned short src) : Data(0)
{
sprintf("%hu", src);
}

__fastcall AnsiString::AnsiString(int src) : Data(0)
{
sprintf("%i", src);
}

__fastcall AnsiString::AnsiString(unsigned int src) : Data(0)
{
sprintf("%u", src);
}

__fastcall AnsiString::AnsiString(long src) : Data(0)
{
sprintf("%ld", src);
}

__fastcall AnsiString::AnsiString(unsigned long src) : Data(0)
{
sprintf("%lu", src);
}

__fastcall AnsiString::AnsiString(__int64 src) : Data(0)
{
sprintf("%Li", src);
}

__fastcall AnsiString::AnsiString(unsigned __int64 src) : Data(0)
{
sprintf("%Lu", src);
}

__fastcall AnsiString::AnsiString(double src) : Data(0)
{
*this = Sysutils::FloatToStr(src);
}

__fastcall AnsiString::~AnsiString()
{
asm
{
mov eax,this
call @System@@LStrClr$qqrr17System@AnsiString
}
}

AnsiString& __fastcall AnsiString::operator=(const AnsiString&)
{
asm
{
mov edx,[edx]
call @System@@LStrAsg$qqrv
}
return *this;
}

AnsiString& __fastcall AnsiString::operator+=(const AnsiString&)
{
asm
{
mov edx,[edx]
call @System@@LStrCat$qqrv
}
return *this;
}

AnsiString __fastcall AnsiString::operator+(const AnsiString& rhs) const
{
#if 0
//!JK Per Peter S., change to push 0 onto the stack
//!JK and use as the first parm
//!JK need to take out double contruction (return tmp)
#endif
AnsiString tmp;
AnsiString* ptmp = &tmp;
asm
{
mov edx, this
mov edx, [edx]
mov eax, ptmp
mov ecx, rhs
mov ecx, [ecx]
call @System@@LStrCat3$qqrv
}
return tmp;
}

#pragma option push -w-rvl

bool __fastcall AnsiString::operator==(const AnsiString&) const
{
asm
{
mov eax, [eax]
mov edx, [edx]
call @System@@LStrCmp$qqrv
sete al
and eax, 1
}
}

bool __fastcall AnsiString::operator!=(const AnsiString&) const
{
asm
{
mov eax, [eax]
mov edx, [edx]
call @System@@LStrCmp$qqrv
setne al
and eax, 1
}
}

bool __fastcall AnsiString::operator<(const AnsiString&) const
{
asm
{
mov eax, [eax]
mov edx, [edx]
call @System@@LStrCmp$qqrv
setb al
and eax, 1
}
}

bool __fastcall AnsiString::operator>(const AnsiString&) const
{
asm
{
mov eax, [eax]
mov edx, [edx]
call @System@@LStrCmp$qqrv
seta al
and eax, 1
}
}
#pragma option pop

bool __fastcall AnsiString::operator<=(const AnsiString& rhs) const
{
return !operator>(rhs);
}

bool __fastcall AnsiString::operator >=(const AnsiString& rhs) const
{
return !operator<(rhs);
}

int __fastcall AnsiString::AnsiCompare(const AnsiString& rhs) const
{
return Sysutils::AnsiCompareStr(*this, rhs);
}

int __fastcall AnsiString::AnsiCompareIC(const AnsiString& rhs) const
{
return Sysutils::AnsiCompareText(*this, rhs);
}


// Return AnsiString of count chars of value ch
AnsiString __fastcall AnsiString::StringOfChar(char ch, int count)
{
AnsiString tmp;
tmp.SetLength(count);
memset(tmp.Data, ch, count);
return tmp;
}

AnsiString __fastcall AnsiString::LoadStr(int ident)
{
return Sysutils::LoadStr(ident);
}

AnsiString __fastcall AnsiString::LoadStr(HINSTANCE hInstance, int ident)
{
AnsiString str;
str.LoadString(hInstance, ident);
return str;
}

AnsiString& __fastcall AnsiString::LoadString(HINSTANCE hInstance, int id)
{
HRSRC resHdl = ::FindResource(hInstance, MAKEINTRESOURCE(id/16+1), RT_STRING);
if (resHdl)
{
HGLOBAL gblHdl = ::LoadResource(hInstance, resHdl);
if (gblHdl)
{
WCHAR* resData = (WCHAR*)::LockResource(gblHdl);
if (resData)
{
unsigned int len;
for (int cnt = id % 16; len = *resData++, cnt--; resData += len)
;
if (len != 0)
{
SetLength(len);
len = ::WideCharToMultiByte(CP_ACP, 0, resData, len, Data, len, 0, 0);
if (len > 0)
Data[len] = 0;
}
/* Unnecessary in Win32
::UnlockResource(gblHdl);
*/
}
::FreeResource(resHdl);
}
}

return *this;
}

AnsiString __fastcall AnsiString::FmtLoadStr(int ident, const TVarRec* args, int size)
{
return Sysutils::FmtLoadStr(ident, args, size);
}

AnsiString __fastcall AnsiString::Format(const AnsiString& format, const TVarRec *args, int size)
{
return Sysutils::Format(format, args, size);
}

AnsiString __fastcall AnsiString::FormatFloat(const AnsiString& format, const long double& value)
{
return Sysutils::FormatFloat(format, value);
}


#undef vprintf
#undef printf
#undef sprintf

int __cdecl AnsiString::vprintf(const char* format, va_list paramList)
{
int size = vsnprintf(NULL, 0, format, paramList);
SetLength(size);
return vsnprintf(Data, size, format, paramList);
}

int __cdecl AnsiString::cat_vprintf(const char* format, va_list paramList)
{
int size = vsnprintf(NULL, 0, format, paramList);
int len = Length();
SetLength(len + size);
return vsnprintf(Data + len, len + size, format, paramList);
}


int __cdecl AnsiString::printf(const char* format, ...)
{
int rc;
va_list paramList;
va_start(paramList, format);
rc = vprintf(format, paramList);
va_end(paramList);
return rc;
}

AnsiString& __cdecl AnsiString::sprintf(const char* format, ...)
{
va_list paramList;
va_start(paramList, format);
vprintf(format, paramList);
va_end(paramList);
return *this;
}


int __cdecl AnsiString::cat_printf(const char* format, ...)
{
int rc;
va_list paramList;
va_start(paramList, format);
rc = cat_vprintf(format, paramList);
va_end(paramList);
return rc;
}

AnsiString& __cdecl AnsiString::cat_sprintf(const char* format, ...)
{
va_list paramList;
va_start(paramList, format);
cat_vprintf(format, paramList);
va_end(paramList);
return *this;
}


AnsiString __fastcall AnsiString::FloatToStrF(long double value, TStringFloatFormat format, int precision, int digits)
{
#if 0
//!JK this code requires TStringFloatFormat and TFloatFormat to be identical
#endif
return Sysutils::FloatToStrF(value, TFloatFormat(format), precision, digits);
}

AnsiString __fastcall AnsiString::IntToHex(int value, int digits)
{
return Sysutils::IntToHex(value, digits);
}

AnsiString __fastcall AnsiString::CurrToStr(Currency value)
{
return ::CurrToStr(value);
}

AnsiString __fastcall AnsiString::CurrToStrF(Currency value, TStringFloatFormat format, int digits)
{
#if 0
//!JK this code requires TStringFloatFormat and TFloatFormat to be identical
#endif
return Sysutils::CurrToStrF(value, TFloatFormat(format), digits);
}

int __fastcall AnsiString::WideCharBufSize() const
{
// return size of buffer required to call WideChar()
return MultiByteToWideChar(CP_ACP,0,(Data)? Data: (const PChar)"", -1, 0,0);
}

//Convert to Unicode
wchar_t* __fastcall AnsiString::WideChar(wchar_t* dest, int destSize) const
{
MultiByteToWideChar(CP_ACP,0,(Data)?Data: (const PChar)"",-1,dest,destSize);
return dest;
}

AnsiString& __fastcall AnsiString::Unique()
{
System::UniqueString(*this);
return *this;
}

AnsiString& __fastcall AnsiString::Insert(const String& source, int index)
{
asm
{
// edx must be a pointer to the characters
mov edx, this
// eax must be the characters themselves
mov eax, source
mov eax, [eax]
mov ecx, index
call @System@@LStrInsert$qqrv
}
return *this;
}

AnsiString& __fastcall AnsiString::Delete(int index, int count)
{
asm
{
// eax must be a pointer to the characters
mov eax, this
mov edx, index
mov ecx, count
call @System@@LStrDelete$qqrv
}
return *this;
}

AnsiString& __fastcall AnsiString::SetLength(int newLength)
{
asm
{
// eax must be a pointer to the characters
mov eax, this
mov edx, newLength
call @System@@LStrSetLength$qqrv
}
return *this;
}

int __fastcall AnsiString::Pos(const AnsiString& subStr) const
{
asm
{
// edx must be the characters themselves
mov edx, this
mov edx, [edx]
// eax must be the characters themselves!
mov eax, subStr
mov eax, [eax]
call @System@@LStrPos$qqrv
//Result left in eax
}
return _EAX;
}

AnsiString __fastcall AnsiString::LowerCase() const
{
return Sysutils::AnsiLowerCase(*this);
}

AnsiString __fastcall AnsiString::UpperCase() const
{
return Sysutils::AnsiUpperCase(*this);
}

AnsiString __fastcall AnsiString::Trim() const
{
return Sysutils::Trim(*this);
}

AnsiString __fastcall AnsiString::TrimLeft() const
{
return Sysutils::TrimLeft(*this);
}

AnsiString __fastcall AnsiString::TrimRight() const
{
return Sysutils::TrimRight(*this);
}

AnsiString __fastcall AnsiString::SubString(int index, int count) const
{
// Emulate Pascal's _LStrCopy: if 'index' is bogus, or the 'count' is negative,
// return an empty string.
if (index < 1 || index > Length() || count < 0)
return AnsiString();

// If 'count' is too large, copy the rest of the string.
int n = Length() - index + 1;
if (n > count)
n = count;
return AnsiString(Data + index - 1, n);
}

int __fastcall AnsiString::ToInt() const
{
return Sysutils::StrToInt(*this);
}

int __fastcall AnsiString::ToIntDef(int defaultValue) const
{
return Sysutils::StrToIntDef(*this, defaultValue);
}

double __fastcall AnsiString::ToDouble() const
{
#if 0
//!JK change this to return a long double when the compiler properly
//!JK promotes/demotes long doubles/doubles
#endif
return Sysutils::StrToFloat(*this);
}

bool __fastcall AnsiString::IsDelimiter(const AnsiString& delimiters, int index) const
{
return Sysutils::IsDelimiter(delimiters, *this, index);
}

int __fastcall AnsiString::AnsiPos(const AnsiString& subStr) const
{
return Sysutils::AnsiPos(subStr, *this);
}

bool __fastcall AnsiString::IsPathDelimiter(int index) const
{
return Sysutils::IsPathDelimiter(*this, index);
}

int __fastcall AnsiString::LastDelimiter(const AnsiString& delimiters) const
{
return Sysutils::LastDelimiter(delimiters, *this);
}

AnsiString::TStringMbcsByteType __fastcall AnsiString::ByteType(int index) const
{
//!GCD this code requires TStringMbcsByteType and TMbcsByteType to be identical
return TStringMbcsByteType(Sysutils::ByteType(*this, index));
}

bool __fastcall AnsiString::IsLeadByte(int index) const
{
return ByteType(index) == mbLeadByte;
}

bool __fastcall AnsiString::IsTrailByte(int index) const
{
return ByteType(index) == mbTrailByte;
}

char* __fastcall AnsiString::AnsiLastChar() const
{
return Sysutils::AnsiLastChar(*this);
}

AnsiString __fastcall operator+(const char* lhs, const AnsiString& rhs)
{
AnsiString tmp(lhs);
AnsiString* ptmp = &tmp;
asm
{
mov eax,ptmp
mov edx,rhs
mov edx,[edx]
call @System@@LStrCat$qqrv
}
return tmp;
}


} // System Namespace
BCB 2001-08-01
  • 打赏
  • 举报
回复
替我找找,我找不到,要求能见到它的完整定义;
BCB 2001-08-01
  • 打赏
  • 举报
回复
你给我找一下,贴出来,给分!!!!!!!!!!!
holyfire 2001-08-01
  • 打赏
  • 举报
回复
安装BCB时,选择安装VCL源代码就有了
holyfire 2001-08-01
  • 打赏
  • 举报
回复
看Delphi的VCL源代码就知道了啊

13,825

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder相关内容讨论区
社区管理员
  • 基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧