| /* | |
| * Licensed to the Apache Software Foundation (ASF) under one or more | |
| * contributor license agreements. See the NOTICE file distributed with | |
| * this work for additional information regarding copyright ownership. | |
| * The ASF licenses this file to You under the Apache License, Version 2.0 | |
| * (the "License"); you may not use this file except in compliance with | |
| * the License. You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| #include <log4cxx/pattern/nameabbreviator.h> | |
| #include <log4cxx/helpers/exception.h> | |
| #include <log4cxx/helpers/stringhelper.h> | |
| #include <log4cxx/helpers/loglog.h> | |
| #include <vector> | |
| #include <limits.h> | |
| #include <stdexcept> | |
| using namespace LOG4CXX_NS; | |
| using namespace LOG4CXX_NS::pattern; | |
| using namespace LOG4CXX_NS::helpers; | |
| IMPLEMENT_LOG4CXX_OBJECT(NameAbbreviator) | |
| NameAbbreviator::NameAbbreviator() | |
| { | |
| } | |
| NameAbbreviator::~NameAbbreviator() | |
| { | |
| } | |
| namespace LOG4CXX_NS | |
| { | |
| namespace pattern | |
| { | |
| /** | |
| * Abbreviator that simply appends full name to buffer. | |
| */ | |
| class NOPAbbreviator : public NameAbbreviator | |
| { | |
| public: | |
| DECLARE_ABSTRACT_LOG4CXX_OBJECT(NOPAbbreviator) | |
| BEGIN_LOG4CXX_CAST_MAP() | |
| LOG4CXX_CAST_ENTRY(NOPAbbreviator) | |
| LOG4CXX_CAST_ENTRY_CHAIN(NameAbbreviator) | |
| END_LOG4CXX_CAST_MAP() | |
| /** | |
| * Constructor. | |
| */ | |
| NOPAbbreviator() | |
| { | |
| } | |
| /** | |
| * {@inheritDoc} | |
| */ | |
| void abbreviate(LogString::size_type /* nameStart */, LogString& /* buf */) const override | |
| { | |
| } | |
| }; | |
| /** | |
| * Abbreviator that drops starting path elements. | |
| */ | |
| class MaxElementAbbreviator : public NameAbbreviator | |
| { | |
| /** | |
| * Maximum number of path elements to output. | |
| */ | |
| const int count; | |
| public: | |
| DECLARE_ABSTRACT_LOG4CXX_OBJECT(MaxElementAbbreviator) | |
| BEGIN_LOG4CXX_CAST_MAP() | |
| LOG4CXX_CAST_ENTRY(MaxElementAbbreviator) | |
| LOG4CXX_CAST_ENTRY_CHAIN(NameAbbreviator) | |
| END_LOG4CXX_CAST_MAP() | |
| /** | |
| * Create new instance. | |
| * @param count maximum number of path elements to output. | |
| */ | |
| MaxElementAbbreviator(const int count1) : count(count1 < 1 ? 1 : count1) | |
| { | |
| } | |
| /** | |
| * {@inheritDoc} | |
| */ | |
| void abbreviate(LogString::size_type nameStart, LogString& buf) const override | |
| { | |
| logchar separ = 0x2E; // '.' | |
| LogString::size_type end = buf.length(); | |
| for (LogString::size_type i = count; nameStart < end && 0 < i; --i) | |
| { | |
| end = buf.rfind(separ, end - 1); | |
| if (LogString::npos == end) | |
| { | |
| return; | |
| } | |
| } | |
| if (nameStart < end + 1 && end + 1 < buf.length()) | |
| buf.erase(buf.begin() + nameStart, buf.begin() + (end + 1)); | |
| } | |
| }; | |
| /** | |
| * Fragment of an pattern abbreviator. | |
| * | |
| */ | |
| class PatternAbbreviatorFragment | |
| { | |
| /** | |
| * Count of initial characters of element to output. | |
| */ | |
| LogString::size_type charCount; | |
| /** | |
| * Character used to represent dropped characters. | |
| * '\0' indicates no representation of dropped characters. | |
| */ | |
| logchar ellipsis; | |
| public: | |
| /** | |
| * Creates a PatternAbbreviatorFragment. | |
| * @param charCount number of initial characters to preserve. | |
| * @param ellipsis character to represent elimination of characters, | |
| * '\0' if no ellipsis is desired. | |
| */ | |
| PatternAbbreviatorFragment( | |
| const int charCount1, const logchar ellipsis1) | |
| : charCount(charCount1), ellipsis(ellipsis1) | |
| { | |
| } | |
| PatternAbbreviatorFragment() : charCount(0), ellipsis(0) | |
| { | |
| } | |
| PatternAbbreviatorFragment(const PatternAbbreviatorFragment& src) | |
| : charCount(src.charCount), ellipsis(src.ellipsis) | |
| { | |
| } | |
| PatternAbbreviatorFragment& operator=(const PatternAbbreviatorFragment& src) | |
| { | |
| charCount = src.charCount; | |
| ellipsis = src.ellipsis; | |
| return *this; | |
| } | |
| /** | |
| * Abbreviate element of name. | |
| * @param buf buffer to receive element. | |
| * @param startPos starting index of name element. | |
| * @return starting index of next element. | |
| */ | |
| LogString::size_type abbreviate(LogString& buf, LogString::size_type startPos) const | |
| { | |
| LogString::size_type nextDot = buf.find(0x2E /* '.' */, startPos); | |
| if (nextDot != LogString::npos) | |
| { | |
| if ((nextDot - startPos) > charCount) | |
| { | |
| buf.erase(buf.begin() + (startPos + charCount), buf.begin() + nextDot); | |
| nextDot = startPos + charCount; | |
| if (ellipsis != 0x00) | |
| { | |
| buf.insert(nextDot, 1, ellipsis); | |
| nextDot++; | |
| } | |
| } | |
| nextDot++; | |
| } | |
| return nextDot; | |
| } | |
| /** | |
| * Abbreviate all '.' separated elements of \c buf from \c startPos. | |
| * @param buf buffer to receive element. | |
| * @param startPos starting index of name element. | |
| */ | |
| void abbreviateAll(LogString& buf, LogString::size_type startPos) const | |
| { | |
| logchar separ = 0x2E; /* '.' */ | |
| LogString abbreviation; | |
| abbreviation.reserve(buf.length()); | |
| auto pos = startPos; | |
| LogString::size_type nextDot; | |
| while (pos < buf.length() && buf.npos != (nextDot = buf.find(separ, pos))) | |
| { | |
| if (pos + charCount < nextDot) | |
| { | |
| abbreviation.append(buf.begin() + pos, buf.begin() + (pos + charCount)); | |
| if (ellipsis != 0x00) | |
| abbreviation.append(1, ellipsis); | |
| } | |
| else | |
| abbreviation.append(buf.begin() + pos, buf.begin() + nextDot); | |
| abbreviation.append(1, separ); | |
| pos = nextDot + 1; | |
| } | |
| if (pos < buf.length()) | |
| abbreviation.append(buf.begin() + pos, buf.end()); | |
| buf.erase(buf.begin() + startPos, buf.end()); | |
| buf.append(abbreviation); | |
| } | |
| }; | |
| /** | |
| * Pattern abbreviator. | |
| * | |
| * | |
| */ | |
| class PatternAbbreviator : public NameAbbreviator | |
| { | |
| /** | |
| * Element abbreviation patterns. | |
| */ | |
| std::vector<PatternAbbreviatorFragment> fragments; | |
| public: | |
| DECLARE_ABSTRACT_LOG4CXX_OBJECT(PatternAbbreviator) | |
| BEGIN_LOG4CXX_CAST_MAP() | |
| LOG4CXX_CAST_ENTRY(PatternAbbreviator) | |
| LOG4CXX_CAST_ENTRY_CHAIN(NameAbbreviator) | |
| END_LOG4CXX_CAST_MAP() | |
| /** | |
| * Create PatternAbbreviator. | |
| * | |
| * @param fragments element abbreviation patterns. | |
| */ | |
| PatternAbbreviator(const std::vector<PatternAbbreviatorFragment>& fragments1) : | |
| fragments(fragments1) | |
| { | |
| if (fragments1.size() == 0) | |
| { | |
| throw IllegalArgumentException(LOG4CXX_STR("fragments parameter must contain at least one element")); | |
| } | |
| } | |
| /** | |
| * {@inheritDoc} | |
| */ | |
| void abbreviate(LogString::size_type nameStart, LogString& buf) const override | |
| { | |
| // | |
| // all non-terminal patterns are executed once | |
| // | |
| LogString::size_type pos = nameStart; | |
| for (LogString::size_type i = 0; (i < (fragments.size() - 1)) && (pos < buf.length()); | |
| i++) | |
| { | |
| pos = fragments[i].abbreviate(buf, pos); | |
| } | |
| // | |
| // apply the last pattern to all the remaining name parts | |
| // | |
| if (pos < buf.length()) | |
| fragments.back().abbreviateAll(buf, pos); | |
| } | |
| }; | |
| } | |
| } | |
| IMPLEMENT_LOG4CXX_OBJECT(NOPAbbreviator) | |
| IMPLEMENT_LOG4CXX_OBJECT(MaxElementAbbreviator) | |
| IMPLEMENT_LOG4CXX_OBJECT(PatternAbbreviator) | |
| NameAbbreviatorPtr NameAbbreviator::getAbbreviator(const LogString& pattern) | |
| { | |
| if (pattern.length() > 0) | |
| { | |
| // if pattern is just spaces and numbers then | |
| // use MaxElementAbbreviator | |
| LogString trimmed(StringHelper::trim(pattern)); | |
| if (trimmed.length() == 0) | |
| { | |
| return getDefaultAbbreviator(); | |
| } | |
| LogString::size_type i = 0; | |
| while ( | |
| (i < trimmed.length()) && (trimmed[i] >= 0x30 /* '0' */) | |
| && (trimmed[i] <= 0x39 /* '9' */)) | |
| { | |
| i++; | |
| } | |
| // | |
| // if all blanks and digits | |
| // | |
| if (i == trimmed.length()) | |
| { | |
| int len = 256; | |
| try | |
| { | |
| len = StringHelper::toInt(trimmed); | |
| } | |
| catch (const std::out_of_range& ex) | |
| { | |
| LogLog::warn(LOG4CXX_STR("Invalid name abreviator pattern: ") + pattern, ex); | |
| } | |
| if(len > 256){ | |
| len = 256; | |
| }else if( len < 0 ){ | |
| len = 0; | |
| } | |
| return std::make_shared<MaxElementAbbreviator>(len); | |
| } | |
| std::vector<PatternAbbreviatorFragment> fragments; | |
| logchar ellipsis; | |
| int charCount; | |
| LogString::size_type pos = 0; | |
| while (pos < trimmed.length()) | |
| { | |
| LogString::size_type ellipsisPos = pos; | |
| if (trimmed[pos] == 0x2A /* '*' */) | |
| { | |
| charCount = INT_MAX; | |
| ellipsisPos++; | |
| } | |
| else | |
| { | |
| if ((trimmed[pos] >= 0x30 /* '0' */) | |
| && (trimmed[pos] <= 0x39 /* '9' */)) | |
| { | |
| charCount = trimmed[pos] - 0x30 /* '0' */; | |
| ellipsisPos++; | |
| } | |
| else | |
| { | |
| charCount = 0; | |
| } | |
| } | |
| ellipsis = 0; | |
| if (ellipsisPos < trimmed.length()) | |
| { | |
| ellipsis = trimmed[ellipsisPos]; | |
| if (ellipsis == 0x2E /* '.' */) | |
| { | |
| ellipsis = 0; | |
| } | |
| } | |
| fragments.push_back(PatternAbbreviatorFragment(charCount, ellipsis)); | |
| pos = trimmed.find(0x2E /* '.' */, pos); | |
| if (pos == LogString::npos) | |
| { | |
| break; | |
| } | |
| pos++; | |
| } | |
| return std::make_shared<PatternAbbreviator>(fragments); | |
| } | |
| // | |
| // no matching abbreviation, return defaultAbbreviator | |
| // | |
| return getDefaultAbbreviator(); | |
| } | |
| /** | |
| * Gets default abbreviator. | |
| * | |
| * @return default abbreviator. | |
| */ | |
| NameAbbreviatorPtr NameAbbreviator::getDefaultAbbreviator() | |
| { | |
| static WideLife<NameAbbreviatorPtr> def = std::make_shared<NOPAbbreviator>(); | |
| return def; | |
| } | |