1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 #ifndef _LOG4CXX_HELPERS_CACHED_DATE_FORMAT_H 19 #define _LOG4CXX_HELPERS_CACHED_DATE_FORMAT_H 20 21 #include <log4cxx/helpers/dateformat.h> 22 23 #if defined(_MSC_VER) 24 #pragma warning ( push ) 25 #pragma warning ( disable: 4251 ) 26 #endif 27 28 namespace log4cxx 29 { 30 namespace pattern 31 { 32 class LOG4CXX_EXPORT CachedDateFormat : public log4cxx::helpers::DateFormat 33 { 34 public: 35 enum 36 { 37 /* 38 * Constant used to represent that there was no change 39 * observed when changing the millisecond count. 40 */ 41 NO_MILLISECONDS = -2, 42 /* 43 * Constant used to represent that there was an 44 * observed change, but was an expected change. 45 */ 46 UNRECOGNIZED_MILLISECONDS = -1 47 }; 48 49 private: 50 /** 51 * Supported digit set. If the wrapped DateFormat uses 52 * a different unit set, the millisecond pattern 53 * will not be recognized and duplicate requests 54 * will use the cache. 55 */ 56 static const logchar digits[]; 57 58 59 /** 60 * First magic number (in microseconds) used to detect 61 * the millisecond position. 62 */ 63 static const int magic1; 64 65 66 /** 67 * Expected representation of first magic number in milliseconds. 68 */ 69 static const logchar magicString1[]; 70 71 72 /** 73 * Second magic number (in microseconds) used to detect 74 * the millisecond position. 75 */ 76 static const int magic2; 77 78 79 /** 80 * Expected representation of second magic number in milliseconds. 81 */ 82 static const logchar magicString2[]; 83 84 85 /** 86 * Expected representation of 0 milliseconds. 87 */ 88 static const logchar zeroString[]; 89 90 /** 91 * Wrapped formatter. 92 */ 93 log4cxx::helpers::DateFormatPtr formatter; 94 95 /** 96 * Index of initial digit of millisecond pattern or 97 * UNRECOGNIZED_MILLISECONDS or NO_MILLISECONDS. 98 */ 99 mutable int millisecondStart; 100 101 /** 102 * Integral second preceding the previous convered Date. 103 */ 104 mutable log4cxx_time_t slotBegin; 105 106 107 /** 108 * Cache of previous conversion. 109 */ 110 mutable LogString cache; 111 112 113 /** 114 * Maximum validity period for the cache. 115 * Typically 1, use cache for duplicate requests only, or 116 * 1000000, use cache for requests within the same integral second. 117 */ 118 const int expiration; 119 120 /** 121 * Date requested in previous conversion. 122 */ 123 mutable log4cxx_time_t previousTime; 124 125 public: 126 /** 127 * Creates a new CachedDateFormat object. 128 * @param dateFormat Date format, may not be null. 129 * @param expiration maximum cached range in microseconds. 130 * If the dateFormat is known to be incompatible with the 131 * caching algorithm, use a value of 0 to totally disable 132 * caching or 1 to only use cache for duplicate requests. 133 */ 134 CachedDateFormat(const log4cxx::helpers::DateFormatPtr& dateFormat, int expiration); 135 136 /** 137 * Finds start of millisecond field in formatted time. 138 * @param time long time, must be integral number of seconds 139 * @param formatted String corresponding formatted string 140 * @param formatter DateFormat date format 141 * @param pool pool. 142 * @return int position in string of first digit of milliseconds, 143 * -1 indicates no millisecond field, -2 indicates unrecognized 144 * field (likely RelativeTimeDateFormat) 145 */ 146 static int findMillisecondStart( 147 log4cxx_time_t time, const LogString& formatted, 148 const log4cxx::helpers::DateFormatPtr& formatter, 149 log4cxx::helpers::Pool& pool); 150 151 /** 152 * Formats a Date into a date/time string. 153 * 154 * @param date the date to format. 155 * @param sbuf the string buffer to write to. 156 * @param p memory pool. 157 */ 158 virtual void format(LogString& sbuf, 159 log4cxx_time_t date, 160 log4cxx::helpers::Pool& p) const; 161 162 private: 163 /** 164 * Formats a count of milliseconds (0-999) into a numeric representation. 165 * @param millis Millisecond coun between 0 and 999. 166 * @buf String buffer, may not be null. 167 * @offset Starting position in buffer, the length of the 168 * buffer must be at least offset + 3. 169 */ 170 static void millisecondFormat(int millis, 171 LogString& buf, 172 int offset); 173 174 175 public: 176 /** 177 * Set timezone. 178 * 179 * @remarks Setting the timezone using getCalendar().setTimeZone() 180 * will likely cause caching to misbehave. 181 * @param zone TimeZone new timezone 182 */ 183 virtual void setTimeZone(const log4cxx::helpers::TimeZonePtr& zone); 184 185 /** 186 * Format an integer consistent with the format method. 187 * @param s string to which the numeric string is appended. 188 * @param n integer value. 189 * @param p memory pool used during formatting. 190 */ 191 virtual void numberFormat(LogString& s, 192 int n, 193 log4cxx::helpers::Pool& p) const; 194 195 /** 196 * Gets maximum cache validity for the specified SimpleDateTime 197 * conversion pattern. 198 * @param pattern conversion pattern, may not be null. 199 * @returns Duration in microseconds from an integral second 200 * that the cache will return consistent results. 201 */ 202 static int getMaximumCacheValidity(const LogString& pattern); 203 204 private: 205 CachedDateFormat(const CachedDateFormat&); 206 CachedDateFormat& operator=(const CachedDateFormat&); 207 208 /** 209 * Tests if two string regions are equal. 210 * @param target target string. 211 * @param toffset character position in target to start comparison. 212 * @param other other string. 213 * @param ooffset character position in other to start comparison. 214 * @param len length of region. 215 * @return true if regions are equal. 216 */ 217 static bool regionMatches( 218 const LogString& target, 219 size_t toffset, 220 const LogString& other, 221 size_t ooffset, 222 size_t len); 223 224 }; 225 226 227 228 } // namespace helpers 229 } // namespace log4cxx 230 231 #if defined(_MSC_VER) 232 #pragma warning (pop) 233 #endif 234 235 #endif // _LOG4CXX_HELPERS_SIMPLE_DATE_FORMAT_H 236