requiredSpaceEstimate = sz*2; // TODO: tune heuristics
space = rawSpace(requiredSpaceEstimate);
sz = vsnprintf(space, spaceSize(), fmt, vargs);
+ if (sz < 0) // output error in vsnprintf
+ throw TextException("output error in second-go vsnprintf",__FILE__,
+ __LINE__);
}
if (sz < 0) // output error in either vsnprintf
// data was appended, update internal state
len_ += sz;
-
/* C99 specifies that the final '\0' is not counted in vsnprintf's
* return value. Older compilers/libraries might instead count it */
/* check whether '\0' was appended and counted */
- static bool snPrintfTerminatorChecked = false,
- snPrintfTerminatorCounted = false;
+ static bool snPrintfTerminatorChecked = false;
+ static bool snPrintfTerminatorCounted = false;
if (!snPrintfTerminatorChecked) {
char testbuf[16];
snPrintfTerminatorCounted = snprintf(testbuf, sizeof(testbuf),
"%s", "1") == 2;
+ snPrintfTerminatorChecked = true;
}
if (snPrintfTerminatorCounted) {
--sz;
os << id
<< ": ";
store_->dump(os);
- os << ",offset:" << off_
- << ",len:" << len_
+ os << ", offset:" << off_
+ << ", len:" << len_
<< ") : '";
print(os);
os << '\'' << std::endl;
return os;
+# if 0
+ // alternate implementation, based on Raw() API.
+ os << Raw("SBuf", buf(), length()) <<
+ ". id: " << id <<
+ ", offset:" << off_ <<
+ ", len:" << len_ <<
+ ", store: ";
+ store_->dump(os);
+ os << std::endl;
+ return os;
+#endif
}
void
SBuf::compare(const SBuf &S, SBufCaseSensitive isCaseSensitive, size_type n) const
{
Must(n == npos || n >= 0);
- if (n != npos) {
- if (n > length())
- return compare(S.substr(0,n),isCaseSensitive);
+ if (n != npos)
return substr(0,n).compare(S.substr(0,n),isCaseSensitive);
- }
+
size_type byteCompareLen = min(S.length(), length());
++stats.compareSlow;
int rv = 0;
{
++stats.find;
- // for npos with char sd::string returns npos
- // this differs from how std::string handles 1-length string
- if (startPos == npos)
+ if (startPos == npos) // can't find anything if we look past end of SBuf
return npos;
// std::string returns npos if needle is outside hay
- if (startPos >= length())
+ if (startPos > length())
return npos;
// ignore invalid startPos
SBuf::size_type
SBuf::find(const SBuf &needle, size_type startPos) const
{
+ if (startPos == npos) { // can't find anything if we look past end of SBuf
+ ++stats.find;
+ return npos;
+ }
+
+ if (startPos < 0)
+ startPos = 0;
+
// std::string allows needle to overhang hay but not start outside
- if (startPos != npos && startPos > length()) {
+ if (startPos > length()) {
++stats.find;
return npos;
}
return startPos;
}
- // for npos with char* std::string scans entire hay
- // this differs from how std::string handles single char from npos
- if (startPos == npos)
- return npos;
-
// if needle length is 1 use the char search
if (needle.length() == 1)
return find(needle[0], startPos);
// on npos input std::string scans from the end of hay
if (endPos == npos || endPos > length())
- endPos=length();
+ endPos = length();
// on empty hay std::string returns npos
if (length() < needle.length())
return npos;
- // on empty needle std::string returns the position the search starts
+ // consistent with std::string: on empty needle return min(endpos,length())
if (needle.length() == 0)
return endPos;
-/* std::string permits needle to overhang endPos
- if (endPos <= needle.length())
- return npos;
-*/
-
char *bufBegin = buf();
char *cur = bufBegin+endPos;
char needleBegin = needle[0];
{
++stats.find;
- // on empty hay std::string returns size of hay
+ // shortcut: haystack is empty, can't find anything by definition
if (length() == 0)
return npos;
++endPos;
}
+ if (length() == 0)
+ return endPos;
+
const void *i = memrchr(buf(), (int)c, (size_type)endPos);
if (i == NULL)
if (startPos == npos)
return npos;
- if (startPos > length())
+ if (startPos >= length())
return npos;
if (startPos < 0)
if (isupper(c))
rv.setAt(j, tolower(c)); //will cow() if needed
}
- debugs(24, 8, "result: \"" << *this << "\"");
+ debugs(24, 8, "result: \"" << rv << "\"");
++stats.caseChange;
return rv;
}
if (islower(c))
rv.setAt(j, toupper(c)); //will cow() if needed
}
- debugs(24, 8, "result: \"" << *this << "\"");
+ debugs(24, 8, "result: \"" << rv << "\"");
++stats.caseChange;
return rv;
}
void
SBuf::reAlloc(size_type newsize)
{
- debugs(24, DBG_DATA, "new size: " << newsize);
+ debugs(24, 8, "new size: " << newsize);
if (newsize > maxSize)
throw SBufTooBigException(__FILE__, __LINE__);
MemBlob::Pointer newbuf = new MemBlob(newsize);
* copy-on-write: make sure that we are the only holder of the backing store.
* If not, reallocate. If a new size is specified, and it is greater than the
* current length, the backing store will be extended as needed
- * \retval false no grow was needed
- * \retval true had to copy
*/
-bool
+void
SBuf::cow(SBuf::size_type newsize)
{
- debugs(24, DBG_DATA, "new size:" << newsize);
+ debugs(24, 8, "new size:" << newsize);
if (newsize == npos || newsize < length())
newsize = length();
if (store_->LockCount() == 1 && newsize == length()) {
- debugs(24, DBG_DATA, "no cow needed");
+ debugs(24, 8, "no cow needed");
++stats.cowFast;
- return false;
+ return;
}
reAlloc(newsize);
- return true;
}