in src/main/cpp/cacheddateformat.cpp [155:237]
int CachedDateFormat::findMillisecondStart(
log4cxx_time_t time, const LogString& formatted,
const DateFormatPtr& formatter,
Pool& pool)
{
apr_time_t slotBegin = (time / 1000000) * 1000000;
if (slotBegin > time)
{
slotBegin -= 1000000;
}
int millis = (int) (time - slotBegin) / 1000;
// the magic numbers are in microseconds
int magic = magic1;
LogString magicString(magicString1);
if (millis == magic1 / 1000)
{
magic = magic2;
magicString = magicString2;
}
LogString plusMagic;
formatter->format(plusMagic, slotBegin + magic, pool);
/**
* If the string lengths differ then
* we can't use the cache except for duplicate requests.
*/
if (plusMagic.length() != formatted.length())
{
return UNRECOGNIZED_MILLISECONDS;
}
else
{
// find first difference between values
for (LogString::size_type i = 0; i < formatted.length(); i++)
{
if (formatted[i] != plusMagic[i])
{
//
// determine the expected digits for the base time
const logchar abc[] = { 0x41, 0x42, 0x43, 0 };
LogString formattedMillis(abc);
millisecondFormat(millis, formattedMillis, 0);
LogString plusZero;
formatter->format(plusZero, slotBegin, pool);
// Test if the next 1..3 characters match the magic string, main problem is that magic
// available millis in formatted can overlap. Therefore the current i is not always the
// index of the first millis char, but may be already within the millis. Besides that
// the millis can occur everywhere in formatted. See LOGCXX-420 and following.
size_t magicLength = magicString.length();
size_t overlapping = magicString.find(plusMagic[i]);
int possibleRetVal = int(i - overlapping);
if (plusZero.length() == formatted.length()
&& regionMatches(magicString, 0, plusMagic, possibleRetVal, magicLength)
&& regionMatches(formattedMillis, 0, formatted, possibleRetVal, magicLength)
&& regionMatches(zeroString, 0, plusZero, possibleRetVal, magicLength)
// The following will and should fail for patterns with more than one SSS because
// we only seem to be able to change one SSS in e.g. format and need to reformat the
// whole string in other cases.
&& (formatted.length() == possibleRetVal + magicLength
|| plusZero.compare(possibleRetVal + magicLength,
LogString::npos, plusMagic, possibleRetVal + magicLength, LogString::npos) == 0))
{
return possibleRetVal;
}
else
{
return UNRECOGNIZED_MILLISECONDS;
}
}
}
}
return NO_MILLISECONDS;
}