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_LEVEL_H
19 #define _LOG4CXX_LEVEL_H
20 
21 
22 #include <log4cxx/logstring.h>
23 #include <limits.h>
24 #include <log4cxx/helpers/objectimpl.h>
25 #include <log4cxx/helpers/objectptr.h>
26 
27 #if defined(_MSC_VER)
28 	#pragma warning ( push )
29 	#pragma warning ( disable: 4251 )
30 #endif
31 
32 namespace log4cxx
33 {
34 /**
35  * LOG4CXX_PTR_DEF can't be used to get a smart pointer for Level because we need to override
36  * the comparison operator and this doesn't work if the template has alread been initialized,
37  * which is what the macro does on some platforms. The overriding takes place underneath the
38  * definition of Level because we need one of it's methods.
39  *
40  * https://issues.apache.org/jira/browse/LOGCXX-394
41  */
42 class Level;
43 typedef log4cxx::helpers::ObjectPtrT<Level> LevelPtr;
44 
45 /**
46 Defines the minimum set of levels recognized by the system, that is
47 <code>OFF</code>, <code>FATAL</code>, <code>ERROR</code>,
48 <code>WARN</code>, <code>INFO</code>, <code>DEBUG</code> and
49 <code>ALL</code>.
50 <p>The <code>Level</code> class may be subclassed to define a larger
51 level set.
52 */
53 class LOG4CXX_EXPORT Level : public helpers::ObjectImpl
54 {
55 	public:
56 		class LOG4CXX_EXPORT LevelClass : public helpers::Class
57 		{
58 			public:
LevelClass()59 				LevelClass() : helpers::Class() {}
60 
getName()61 				virtual LogString getName() const
62 				{
63 					return LOG4CXX_STR("Level");
64 				}
65 
toLevel(const LogString & sArg)66 				virtual LevelPtr toLevel(const LogString& sArg) const
67 				{
68 					return Level::toLevelLS(sArg);
69 				}
70 
toLevel(int val)71 				virtual LevelPtr toLevel(int val) const
72 				{
73 					return Level::toLevel(val);
74 				}
75 		};
76 
77 		DECLARE_LOG4CXX_OBJECT_WITH_CUSTOM_CLASS(Level, LevelClass)
78 		BEGIN_LOG4CXX_CAST_MAP()
79 		LOG4CXX_CAST_ENTRY(Level)
80 		END_LOG4CXX_CAST_MAP()
81 
82 		/**
83 		Instantiate a Level object.
84 		*/
85 		Level(int level,
86 			const LogString& name,
87 			int syslogEquivalent);
88 
89 		/**
90 		Convert the string passed as argument to a level. If the
91 		conversion fails, then this method returns DEBUG.
92 		* @param sArg level name.
93 		*/
94 		static LevelPtr toLevel(const std::string& sArg);
95 		/**
96 		Convert the string passed as argument to a level. If the
97 		conversion fails, then this method returns the value of
98 		<code>defaultLevel</code>.
99 		* @param sArg level name.
100 		* @param defaultLevel level to return if no match.
101 		* @return
102 		*/
103 		static LevelPtr toLevel(const std::string& sArg,
104 			const LevelPtr& defaultLevel);
105 		/**
106 		 *  Get the name of the level in the current encoding.
107 		 *  @param name buffer to which name is appended.
108 		 */
109 		void toString(std::string& name) const;
110 
111 #if LOG4CXX_WCHAR_T_API
112 		/**
113 		Convert the string passed as argument to a level. If the
114 		conversion fails, then this method returns DEBUG.
115 		* @param sArg level name.
116 		*/
117 		static LevelPtr toLevel(const std::wstring& sArg);
118 		/**
119 		Convert the string passed as argument to a level. If the
120 		conversion fails, then this method returns the value of
121 		<code>defaultLevel</code>.
122 		* @param sArg level name.
123 		* @param defaultLevel level to return if no match.
124 		* @return
125 		*/
126 		static LevelPtr toLevel(const std::wstring& sArg,
127 			const LevelPtr& defaultLevel);
128 		/**
129 		 *  Get the name of the level.
130 		 *  @param name buffer to which name is appended.
131 		 */
132 		void toString(std::wstring& name) const;
133 #endif
134 #if LOG4CXX_UNICHAR_API
135 		/**
136 		Convert the string passed as argument to a level. If the
137 		conversion fails, then this method returns DEBUG.
138 		* @param sArg level name.
139 		*/
140 		static LevelPtr toLevel(const std::basic_string<UniChar>& sArg);
141 		/**
142 		Convert the string passed as argument to a level. If the
143 		conversion fails, then this method returns the value of
144 		<code>defaultLevel</code>.
145 		* @param sArg level name.
146 		* @param defaultLevel level to return if no match.
147 		* @return
148 		*/
149 		static LevelPtr toLevel(const std::basic_string<UniChar>& sArg,
150 			const LevelPtr& defaultLevel);
151 		/**
152 		 *  Get the name of the level.
153 		 *  @param name buffer to which name is appended.
154 		 */
155 		void toString(std::basic_string<UniChar>& name) const;
156 #endif
157 #if LOG4CXX_CFSTRING_API
158 		/**
159 		Convert the string passed as argument to a level. If the
160 		conversion fails, then this method returns DEBUG.
161 		* @param sArg level name.
162 		*/
163 		static LevelPtr toLevel(const CFStringRef& sArg);
164 		/**
165 		Convert the string passed as argument to a level. If the
166 		conversion fails, then this method returns the value of
167 		<code>defaultLevel</code>.
168 		* @param sArg level name.
169 		* @param defaultLevel level to return if no match.
170 		* @return
171 		*/
172 		static LevelPtr toLevel(const CFStringRef& sArg,
173 			const LevelPtr& defaultLevel);
174 		/**
175 		 *  Get the name of the level.
176 		 *  @param name buffer to which name is appended.
177 		 */
178 		void toString(CFStringRef& name) const;
179 #endif
180 		/**
181 		Convert the string passed as argument to a level. If the
182 		conversion fails, then this method returns DEBUG.
183 		* @param sArg level name.
184 		*/
185 		static LevelPtr toLevelLS(const LogString& sArg);
186 		/**
187 		Convert the string passed as argument to a level. If the
188 		conversion fails, then this method returns the value of
189 		<code>defaultLevel</code>.
190 		* @param sArg level name.
191 		* @param defaultLevel level to return if no match.
192 		* @return
193 		*/
194 		static LevelPtr toLevelLS(const LogString& sArg,
195 			const LevelPtr& defaultLevel);
196 		/**
197 		Returns the string representation of this level.
198 		* @return level name.
199 		*/
200 		LogString toString() const;
201 
202 		/**
203 		Convert an integer passed as argument to a level. If the
204 		conversion fails, then this method returns DEBUG.
205 		*/
206 		static LevelPtr toLevel(int val);
207 
208 		/**
209 		Convert an integer passed as argument to a level. If the
210 		conversion fails, then this method returns the specified default.
211 		*/
212 		static LevelPtr toLevel(int val, const LevelPtr& defaultLevel);
213 
214 		enum
215 		{
216 			OFF_INT = INT_MAX,
217 			FATAL_INT = 50000,
218 			ERROR_INT = 40000,
219 			WARN_INT = 30000,
220 			INFO_INT = 20000,
221 			DEBUG_INT = 10000,
222 			TRACE_INT = 5000,
223 			ALL_INT = INT_MIN
224 		};
225 
226 
227 		static LevelPtr getAll();
228 		static LevelPtr getFatal();
229 		static LevelPtr getError();
230 		static LevelPtr getWarn();
231 		static LevelPtr getInfo();
232 		static LevelPtr getDebug();
233 		static LevelPtr getTrace();
234 		static LevelPtr getOff();
235 
236 
237 		/**
238 		Two levels are equal if their level fields are equal.
239 		*/
240 		virtual bool equals(const LevelPtr& level) const;
241 
242 		inline bool operator==(const Level& level1) const
243 		{
244 			return (this->level == level1.level);
245 		}
246 
247 		inline bool operator!=(const Level& level1) const
248 		{
249 			return (this->level != level1.level);
250 		}
251 
252 		/**
253 		Return the syslog equivalent of this level as an integer.
254 		*/
getSyslogEquivalent()255 		inline int getSyslogEquivalent() const
256 		{
257 			return syslogEquivalent;
258 		}
259 
260 
261 		/**
262 		Returns <code>true</code> if this level has a higher or equal
263 		level than the level passed as argument, <code>false</code>
264 		otherwise.
265 
266 		<p>You should think twice before overriding the default
267 		implementation of <code>isGreaterOrEqual</code> method.
268 
269 		*/
270 		virtual bool isGreaterOrEqual(const LevelPtr& level) const;
271 
272 
273 		/**
274 		Returns the integer representation of this level.
275 		*/
toInt()276 		inline int toInt() const
277 		{
278 			return level;
279 		}
280 
281 	private:
282 		int level;
283 		LogString name;
284 		int syslogEquivalent;
285 		Level(const Level&);
286 		Level& operator=(const Level&);
287 };
288 
289 /**
290  * We need to double some logic from LOG4CXX_PTR_DEF or else we are unable to override the
291  * comparison operator, which we need to properly fix LOGCXX-394.
292  *
293  * https://issues.apache.org/jira/browse/LOGCXX-394
294  */
295 namespace helpers
296 {
297 
298 /** @class log4cxx::helpers::ObjectPtr */
299 template<> inline bool LevelPtr::operator==(const LevelPtr& rhs) const
300 {
301 	return (*this)->equals(rhs);
302 }
303 template<> inline bool LevelPtr::operator!=(const LevelPtr& rhs) const
304 {
305 	return !(*this == rhs);
306 }
307 #if defined(_MSC_VER) && !defined(LOG4CXX_STATIC) && defined(LOG4CXX)
308 	template class LOG4CXX_EXPORT log4cxx::helpers::ObjectPtrT<Level>;
309 #elif defined(_MSC_VER) && !defined(LOG4CXX_STATIC)
310 	#pragma warning(push)
311 	#pragma warning(disable: 4231)
312 	extern template class LOG4CXX_EXPORT log4cxx::helpers::ObjectPtrT<Level>;
313 	#pragma warning(pop)
314 #endif
315 
316 }
317 
318 }
319 
320 #define DECLARE_LOG4CXX_LEVEL(level)\
321 	public:\
322 	class Class##level : public Level::LevelClass\
323 	{\
324 		public:\
325 			Class##level() : Level::LevelClass() {}\
326 			virtual LogString getName() const { return LOG4CXX_STR(#level); } \
327 			virtual LevelPtr toLevel(const LogString& sArg) const\
328 			{ return level::toLevelLS(sArg); }\
329 			virtual LevelPtr toLevel(int val) const\
330 			{ return level::toLevel(val); }\
331 	};\
332 	DECLARE_LOG4CXX_OBJECT_WITH_CUSTOM_CLASS(level, Class##level)
333 
334 #define IMPLEMENT_LOG4CXX_LEVEL(level) \
335 	IMPLEMENT_LOG4CXX_OBJECT_WITH_CUSTOM_CLASS(level, Class##level)
336 
337 #if defined(_MSC_VER)
338 	#pragma warning (pop)
339 #endif
340 
341 #endif //_LOG4CXX_LEVEL_H
342