Change the Preprocessor::getSpelling interface to let it be zero-copy in

the common case.

llvm-svn: 38671
This commit is contained in:
Chris Lattner 2006-07-04 22:33:12 +00:00
parent a3f827e0a6
commit ef9eae1c44
4 changed files with 23 additions and 14 deletions

View File

@ -297,9 +297,9 @@ void clang::DoPrintPreprocessedInput(Preprocessor &PP) {
}
if (Tok.getLength() < 256) {
unsigned Len = PP.getSpelling(Tok, Buffer);
Buffer[Len] = 0;
OutputString(Buffer, Len);
const char *TokPtr = Buffer;
unsigned Len = PP.getSpelling(Tok, TokPtr);
OutputString(TokPtr, Len);
} else {
std::string S = PP.getSpelling(Tok);
OutputString(&S[0], S.size());

View File

@ -360,7 +360,7 @@ FinishIdentifier:
II = PP.getIdentifierInfo(IdStart, IdEnd);
} else {
// Cleaning needed, alloca a buffer, clean into it, then use the buffer.
char *TmpBuf = (char*)alloca(Result.getLength());
const char *TmpBuf = (char*)alloca(Result.getLength());
unsigned Size = PP.getSpelling(Result, TmpBuf);
II = PP.getIdentifierInfo(TmpBuf, TmpBuf+Size);
}

View File

@ -218,10 +218,10 @@ std::string Preprocessor::getSpelling(const LexerToken &Tok) const {
if (!Tok.needsCleaning())
return std::string(TokStart, TokStart+Tok.getLength());
// Otherwise, hard case, relex the characters into the string.
std::string Result;
Result.reserve(Tok.getLength());
// Otherwise, hard case, relex the characters into the string.
for (const char *Ptr = TokStart, *End = TokStart+Tok.getLength();
Ptr != End; ) {
unsigned CharSize;
@ -237,7 +237,14 @@ std::string Preprocessor::getSpelling(const LexerToken &Tok) const {
/// preallocated buffer, instead of as an std::string. The caller is required
/// to allocate enough space for the token, which is guaranteed to be at least
/// Tok.getLength() bytes long. The actual length of the token is returned.
unsigned Preprocessor::getSpelling(const LexerToken &Tok, char *Buffer) const {
///
/// Note that this method may do two possible things: it may either fill in
/// the buffer specified with characters, or it may *change the input pointer*
/// to point to a constant buffer with the data already in it (avoiding a
/// copy). The caller is not allowed to modify the returned buffer pointer
/// if an internal buffer is returned.
unsigned Preprocessor::getSpelling(const LexerToken &Tok,
const char *&Buffer) const {
assert((int)Tok.getLength() >= 0 && "Token character range is bogus!");
const char *TokStart = SourceMgr.getCharacterData(Tok.getLocation());
@ -245,15 +252,11 @@ unsigned Preprocessor::getSpelling(const LexerToken &Tok, char *Buffer) const {
// If this token contains nothing interesting, return it directly.
if (!Tok.needsCleaning()) {
unsigned Size = Tok.getLength();
memcpy(Buffer, TokStart, Size);
return Size;
Buffer = TokStart;
return Tok.getLength();
}
// Otherwise, hard case, relex the characters into the string.
std::string Result;
Result.reserve(Tok.getLength());
char *OutBuf = Buffer;
char *OutBuf = const_cast<char*>(Buffer);
for (const char *Ptr = TokStart, *End = TokStart+Tok.getLength();
Ptr != End; ) {
unsigned CharSize;

View File

@ -365,7 +365,13 @@ public:
/// preallocated buffer, instead of as an std::string. The caller is required
/// to allocate enough space for the token, which is guaranteed to be at least
/// Tok.getLength() bytes long. The length of the actual result is returned.
unsigned getSpelling(const LexerToken &Tok, char *Buffer) const;
///
/// Note that this method may do two possible things: it may either fill in
/// the buffer specified with characters, or it may *change the input pointer*
/// to point to a constant buffer with the data already in it (avoiding a
/// copy). The caller is not allowed to modify the returned buffer pointer
/// if an internal buffer is returned.
unsigned getSpelling(const LexerToken &Tok, const char *&Buffer) const;
/// DumpToken - Print the token to stderr, used for debugging.
///