Index: examples/Makefile.am =================================================================== RCS file: /home/cvs/logging-log4cxx/examples/Makefile.am,v retrieving revision 1.3 diff -u -r1.3 Makefile.am --- examples/Makefile.am 13 Aug 2004 12:27:45 -0000 1.3 +++ examples/Makefile.am 7 Oct 2004 18:29:13 -0000 @@ -1,4 +1,4 @@ -noinst_PROGRAMS = trivial delayedloop +noinst_PROGRAMS = trivial delayedloop stream INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include @@ -7,6 +7,9 @@ delayedloop_SOURCES = delayedloop.cpp delayedloop_LDADD = $(top_builddir)/src/liblog4cxx.la + +stream_SOURCES = stream.cpp +stream_LDADD = $(top_builddir)/src/liblog4cxx.la Index: src/Makefile.am =================================================================== RCS file: /home/cvs/logging-log4cxx/src/Makefile.am,v retrieving revision 1.17 diff -u -r1.17 Makefile.am --- src/Makefile.am 13 Aug 2004 12:27:47 -0000 1.17 +++ src/Makefile.am 7 Oct 2004 18:29:13 -0000 @@ -36,6 +36,7 @@ levelrangefilter.cpp \ loader.cpp\ locale.cpp\ + locationinfo.cpp\ logger.cpp \ loggingevent.cpp \ loglog.cpp \ Index: log4cxx/stream.h =================================================================== RCS file: log4cxx/stream.h diff -N log4cxx/stream.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ log4cxx/stream.h 7 Oct 2004 18:32:26 -0000 @@ -0,0 +1,243 @@ +/* + * Copyright 2004 The Apache Software Foundation. + * + * Licensed 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. + */ + +#ifndef _LOG4CXX_STREAM_H +#define _LOG4CXX_STREAM_H + +#include +#include +#include + +namespace log4cxx +{ + /** + * Implements an STL streambuf for use by logging streams. + */ + template > + class basic_logstreambuf : public ::std::basic_stringbuf { + public: + /** + * Constructor. + * + */ + basic_logstreambuf(const ::log4cxx::LoggerPtr& logger, + const ::log4cxx::LevelPtr& level) : + ::std::basic_stringbuf(::std::ios_base::out), + logger(logger), + level(level) { + isLoggerEnabled = logger->isEnabledFor(level); + } + + /** + * Gets whether logger is currently enabled for the specified level. + * @returns true if enabled + */ + bool isEnabled() const { + return isLoggerEnabled; + } + + /** + * Sets the call site location. + * @param location call site location + */ + void setLocation(const ::log4cxx::spi::location::LocationInfo& location) { + this->location = location; + } + + /** + * Sets the level. + * @param level level + */ + void setLevel(const ::log4cxx::LevelPtr& level) { + this->level = level; + isLoggerEnabled = logger->isEnabledFor(level); + } + + protected: + /** + * Synchronizes the stream and logger. + * + */ + int sync() { + isLoggerEnabled = logger->isEnabledFor(level); + if (isLoggerEnabled) { + ::std::basic_string msg(str()); + if (msg.length() > 0) { + logger->forcedLog(level, + msg, + location.getFileName(), + location.getLineNumber()); + } + } + location.clear(); + // + // reset the stream buffer + seekoff(0, ::std::ios_base::beg, ::std::ios_base::out); + return 0; + } + + private: + /** + * logger. + */ + ::log4cxx::LoggerPtr logger; + /** + * level. + */ + ::log4cxx::LevelPtr level; + /** + * location. + */ + ::log4cxx::spi::location::LocationInfo location; + + /** + * State of logger at last sync or level changes. + */ + bool isLoggerEnabled; + + }; + + /** + * This template provides an stream interface layer to + * log4cxx. + */ + template > + class basic_logstream : public ::std::basic_ostream { + + public: + /** + * Constructor. + */ + basic_logstream(const ::log4cxx::LoggerPtr& logger, + const ::log4cxx::LevelPtr& level) : + ::std::basic_ostream(&buffer), + buffer(logger, level) { + } + + /** + * Constructor. + */ + basic_logstream(const char* logName, + ::log4cxx::LevelPtr& level) : + ::std::basic_ostream(&buffer), + buffer(::log4cxx::Logger::getLogger(logName), level) { + } + + + /** + * Sets the call site location. + * @param location call site location + */ + void setLocation(const ::log4cxx::spi::location::LocationInfo& location) { + buffer.setLocation(location); + } + + + /** + * Set the level. + * @param level level + */ + void setLevel(const ::log4cxx::LevelPtr& level) { + buffer.setLevel(level); + } + + bool isEnabled() const { + return buffer.isEnabled(); + } + + + private: + basic_logstreambuf buffer; + }; + + typedef basic_logstream logstream; + typedef basic_logstream wlogstream; +} // namespace log4cxx + +/** +* Insertion operator for LocationInfo. +* +*/ +template +::log4cxx::basic_logstream& operator<<( + ::log4cxx::basic_logstream& lhs, + const ::log4cxx::spi::location::LocationInfo& rhs) { + lhs.setLocation(rhs); + return lhs; +} + +/** +* Insertion operator for LocationInfo. +* +*/ +template +::log4cxx::basic_logstream& operator<<( + ::log4cxx::basic_logstream& lhs, + const ::log4cxx::LevelPtr& rhs) { + lhs.setLevel(rhs); + return lhs; +} + + +#define LOG4CXX_STREAM_DEFINE_INSERTION(InsType) \ +template \ +::log4cxx::basic_logstream& operator<<( \ + ::log4cxx::basic_logstream& lhs, \ + InsType rhs) { \ + if (lhs.isEnabled()) { \ + ((::std::basic_ostream&) lhs) << rhs; \ + } \ + return lhs; \ +} + +/* +* Insertion operators for common types. +* Can't use template or would get ambiguities. +* If attempting to insert a type without a matching +* logstream specific insertion operator, the type +* will be formatted, but may get discarded. +* +*/ +LOG4CXX_STREAM_DEFINE_INSERTION(bool) +LOG4CXX_STREAM_DEFINE_INSERTION(signed char) +LOG4CXX_STREAM_DEFINE_INSERTION(unsigned char) +LOG4CXX_STREAM_DEFINE_INSERTION(signed short) +LOG4CXX_STREAM_DEFINE_INSERTION(unsigned short) +LOG4CXX_STREAM_DEFINE_INSERTION(signed int) +LOG4CXX_STREAM_DEFINE_INSERTION(unsigned int) +LOG4CXX_STREAM_DEFINE_INSERTION(signed long) +LOG4CXX_STREAM_DEFINE_INSERTION(unsigned long) +LOG4CXX_STREAM_DEFINE_INSERTION(float) +LOG4CXX_STREAM_DEFINE_INSERTION(double) +LOG4CXX_STREAM_DEFINE_INSERTION(const Elem*) + +template +::log4cxx::basic_logstream& operator<<( + ::log4cxx::basic_logstream& lhs, + const ::std::basic_string& rhs) { + if (lhs.isEnabled()) { + ((::std::basic_ostream&) lhs) << rhs; + } + return lhs; +} + + +#if !defined(LOG4CXX_ENDL) +#define LOG4CXX_ENDMSG LOG4CXX_LOCATION << ::std::flush +#endif + + +#endif //_LOG4CXX_STREAM_H Index: log4cxx/spi/location/locationinfo.h =================================================================== RCS file: log4cxx/spi/location/locationinfo.h diff -N log4cxx/spi/location/locationinfo.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ log4cxx/spi/location/locationinfo.h 7 Oct 2004 18:32:26 -0000 @@ -0,0 +1,184 @@ +/* + * Copyright 2004 The Apache Software Foundation. + * + * Licensed 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. + */ + +#ifndef _LOG4CXX_SPI_LOCATION_LOCATIONINFO_H + #define _LOG4CXX_SPI_LOCATION_LOCATIONINFO_H + + #include + +namespace log4cxx +{ + namespace spi + { + namespace location + { + /** + * This class represents the location of a logging statement. + * + * @remarks This class currently only used by the experimental (and optional) log4cxx::stream class. + */ + class LocationInfo + { + public: + + + + /** + * When location information is not available the constant + * NA is returned. Current value of this string constant is ?. + */ + static const char * const NA; + + + /** + * NA_LOCATION_INFO when real location info is not available. + */ + static LocationInfo NA_LOCATION_INFO; + + + /** + * Constructor. + * @remarks Used by LOG4CXX_LOCATION to generate + * location info for current code site + */ + LocationInfo( const char * const fileName, + const char * const className, + const char * const methodName, + int lineNumber ) + : fileName( fileName ), + className( className ), + methodName( methodName ), + lineNumber( lineNumber ) + { + } + + /** + * Default constructor. + */ + LocationInfo() + : fileName(LocationInfo::NA), + className(LocationInfo::NA), + methodName(LocationInfo::NA), + lineNumber(-1) { + } + + /** + * Copy constructor. + * @param src source location + */ + LocationInfo( const LocationInfo & src ) + : fileName( src.fileName ), + className( src.className ), + methodName( src.methodName ), + lineNumber( src.lineNumber ) + { + } + + /** + * Assignment operator. + * @param src source location + */ + LocationInfo & operator = ( const LocationInfo & src ) + { + fileName = src.fileName; + className = src.className; + methodName = src.methodName; + lineNumber = src.lineNumber; + return * this; + } + + /** + * Resets location info to default state. + */ + void clear() { + fileName = NA; + className = NA; + methodName = NA; + lineNumber = -1; + } + + + /** Return the class name of the call site. */ + const std::string getClassName() const; + + /** + * Return the file name of the caller. + * @returns file name, may be null. + */ + const char * getFileName() const + { + return fileName; + } + + /** + * Returns the line number of the caller. + * @returns line number, -1 if not available. + */ + int getLineNumber() const + { + return lineNumber; + } + + /** Returns the method name of the caller. */ + const char * getMethodName() const + { + return methodName; + } + + /** Formatted representation of location */ + const std::string getFullInfo() const; + + private: + /** Caller's line number. */ + int lineNumber; + + /** Caller's file name. */ + const char * fileName; + + /** Caller's fully qualified class name. */ + const char * className; + + /** Caller's method name. */ + const char * methodName; + + + }; + } + } +} + + #if !defined(LOG4CXX_LOCATION) + #if defined(_GCC_VER) + #define LOG4CXX_LOCATION ::log4cxx::spi::location::LocationInfo(__FILE__, \ + __PRETTY_FUNCTION__, \ + __func__, \ + __LINE__) + #else + #if defined(_MSC_VER) + #define LOG4CXX_LOCATION ::log4cxx::spi::location::LocationInfo(__FILE__, \ + __FUNCSIG__, \ + __FUNCTION__, \ + __LINE__) + #else + #define LOG4CXX_LOCATION ::log4cxx::spi::location::LocationInfo(__FILE__, \ + ::log4cxx::spi::location::LocationInfo::NA, \ + __func__, \ + __LINE__) + #endif + #endif + #endif + +#endif //_LOG4CXX_SPI_LOCATION_LOCATIONINFO_H Index: Makefile.am =================================================================== RCS file: /home/cvs/logging-log4cxx/src/Makefile.am,v retrieving revision 1.17 diff -u -r1.17 Makefile.am --- Makefile.am 13 Aug 2004 12:27:47 -0000 1.17 +++ Makefile.am 7 Oct 2004 18:35:29 -0000 @@ -36,6 +36,7 @@ levelrangefilter.cpp \ loader.cpp\ locale.cpp\ + locationinfo.cpp\ logger.cpp \ loggingevent.cpp \ loglog.cpp \ Index: locationinfo.cpp =================================================================== RCS file: locationinfo.cpp diff -N locationinfo.cpp --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ locationinfo.cpp 7 Oct 2004 18:35:29 -0000 @@ -0,0 +1,64 @@ +/* + * Copyright 2004 The Apache Software Foundation. + * + * Licensed 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 + #include + + using namespace ::log4cxx::spi::location; + /** + When location information is not available the constant + NA is returned. Current value of this string + constant is ?. */ + const char* const LocationInfo::NA = "?"; + + + /** + * NA_LOCATION_INFO is used in conjunction with deserialized LoggingEvents + * without real location info available. + */ +LocationInfo LocationInfo::NA_LOCATION_INFO; + +const std::string LocationInfo::getClassName() const { + if (className == NULL) { + return NA; + } + if (strchr(className, ':') == NULL) { + return className; + } + std::string tmp(className); + size_t colonPos = tmp.find("::"); + if (colonPos != std::string::npos) { + size_t spacePos = tmp.find_last_of(' ', colonPos); + if (spacePos != std::string::npos) { + tmp.erase(colonPos); + tmp.erase(0, spacePos + 1); + } + } + return tmp; +} + +const std::string LocationInfo::getFullInfo() const { + std::ostringstream os; + os << getClassName() + << '.' + << getMethodName() + << '(' + << getFileName() + << ':' + << getLineNumber() + << ')'; + return os.str(); +} Index: Makefile.am =================================================================== RCS file: /home/cvs/logging-log4cxx/examples/Makefile.am,v retrieving revision 1.3 diff -u -r1.3 Makefile.am --- Makefile.am 13 Aug 2004 12:27:45 -0000 1.3 +++ Makefile.am 7 Oct 2004 18:38:52 -0000 @@ -1,4 +1,4 @@ -noinst_PROGRAMS = trivial delayedloop +noinst_PROGRAMS = trivial delayedloop stream INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include @@ -7,6 +7,9 @@ delayedloop_SOURCES = delayedloop.cpp delayedloop_LDADD = $(top_builddir)/src/liblog4cxx.la + +stream_SOURCES = stream.cpp +stream_LDADD = $(top_builddir)/src/liblog4cxx.la Index: stream.cpp =================================================================== RCS file: stream.cpp diff -N stream.cpp --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ stream.cpp 7 Oct 2004 18:38:52 -0000 @@ -0,0 +1,53 @@ +/* + * Copyright 2003,2004 The Apache Software Foundation. + * + * Licensed 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 +#include +#include +#include +#include + +using namespace log4cxx; +using namespace log4cxx::helpers; + +int main() +{ + int result = EXIT_SUCCESS; + try + { + BasicConfigurator::configure(); + LoggerPtr rootLogger = Logger::getRootLogger(); + + NDC::push(_T("trivial context")); + + log4cxx::logstream logstream(rootLogger, Level::DEBUG); + logstream << "debug message" << LOG4CXX_ENDMSG; + logstream.setLevel(Level::INFO); + logstream << "info message" << LOG4CXX_ENDMSG; + logstream << Level::WARN << "warn message" << LOG4CXX_ENDMSG; + logstream << Level::ERROR << "error message" << LOG4CXX_ENDMSG; + logstream << Level::FATAL << "fatal message" << LOG4CXX_ENDMSG; + + + NDC::pop(); + } + catch(Exception&) + { + result = EXIT_FAILURE; + } + + return result; +}