1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\r
6 # define _MSGSTREAM_H
\r
9 # include "stringtool.h"
\r
10 # include "multithread.h"
\r
13 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\r
18 <p>Before writing to omsgstream, you must acquire lock by calling
\r
19 <code>acquire()</code>. Then after completion of writing, you
\r
20 must call <code>release()</code>.</p>
\r
22 <p>Omsgbuf calls <code>PostMessage(hwnd, messageid, 0,
\r
23 (LPARAM)omsgbuf)</code> to notify that string is ready to get.
\r
24 When the window (<code>hwnd</code>) get the message, you can get
\r
25 the string containd in the omsgbuf by calling
\r
26 <code>acquireString()</code>. After calling
\r
27 <code>acquireString()</code>, you must / call releaseString().</p>
\r
31 template<class T, size_t SIZE = 1024,
\r
32 class TR = std::char_traits<T>, class A = std::allocator<T> >
\r
33 class basic_msgbuf : public std::basic_streambuf<T, TR>, public SyncObject
\r
36 typedef std::basic_string<T, TR, A> String; ///
\r
37 typedef std::basic_streambuf<T, TR> Super; ///
\r
40 HWND m_hwnd; /** window handle for
\r
42 UINT m_messageId; /// messageid for notification
\r
43 T *m_buf; /// for streambuf
\r
44 String m_str; /// for notification
\r
45 CriticalSection m_cs; /// lock
\r
46 A m_allocator; /// allocator
\r
49 if ( m_msgDebugLevel <= m_debugLevel ), message is displayed
\r
52 int m_msgDebugLevel; ///
\r
55 basic_msgbuf(const basic_msgbuf &); /// disable copy constructor
\r
59 basic_msgbuf(UINT i_messageId, HWND i_hwnd = 0)
\r
61 m_messageId(i_messageId),
\r
62 m_buf(m_allocator.allocate(SIZE, 0)),
\r
64 m_msgDebugLevel(0) {
\r
66 setp(m_buf, m_buf + SIZE);
\r
72 m_allocator.deallocate(m_buf, SIZE);
\r
75 /// attach/detach a window
\r
76 basic_msgbuf* attach(HWND i_hwnd) {
\r
78 ASSERT( !m_hwnd && i_hwnd );
\r
81 PostMessage(m_hwnd, m_messageId, 0, (LPARAM)this);
\r
86 basic_msgbuf* detach() {
\r
93 /// get window handle
\r
94 HWND getHwnd() const {
\r
98 /// is a window attached ?
\r
99 int is_open() const {
\r
103 /// acquire string and release the string
\r
104 const String &acquireString() {
\r
110 void releaseString() {
\r
115 /// set debug level
\r
116 void setDebugLevel(int i_debugLevel) {
\r
117 m_debugLevel = i_debugLevel;
\r
121 int getDebugLevel() const {
\r
122 return m_debugLevel;
\r
126 typename Super::int_type overflow(typename Super::int_type i_c = TR::eof()) {
\r
127 if (sync() == TR::eof()) // sync before new buffer created below
\r
130 if (i_c != TR::eof()) {
\r
131 *pptr() = TR::to_char_type(i_c);
\r
135 return TR::not_eof(i_c); // return something other than EOF if successful
\r
140 T *begin = pbase();
\r
143 for (i = begin; i < end; ++ i)
\r
147 if (m_msgDebugLevel <= m_debugLevel)
\r
148 m_str += String(begin, end - begin);
\r
149 setp(m_buf, m_buf + SIZE);
\r
150 } else { // end < i
\r
151 if (m_msgDebugLevel <= m_debugLevel)
\r
152 m_str += String(begin, end - begin - 1);
\r
153 m_buf[0] = end[-1];
\r
154 setp(m_buf, m_buf + SIZE);
\r
157 return TR::not_eof(0);
\r
163 virtual void acquire() {
\r
168 virtual void acquire(int i_msgDebugLevel) {
\r
170 m_msgDebugLevel = i_msgDebugLevel;
\r
174 virtual void release() {
\r
175 if (!m_str.empty())
\r
176 PostMessage(m_hwnd, m_messageId, 0, reinterpret_cast<LPARAM>(this));
\r
177 m_msgDebugLevel = m_debugLevel;
\r
184 template<class T, size_t SIZE = 1024,
\r
185 class TR = std::char_traits<T>, class A = std::allocator<T> >
\r
186 class basic_omsgstream : public std::basic_ostream<T, TR>, public SyncObject
\r
189 typedef std::basic_ostream<T, TR> Super; ///
\r
190 typedef basic_msgbuf<T, SIZE, TR, A> StreamBuf; ///
\r
191 typedef std::basic_string<T, TR, A> String; ///
\r
194 StreamBuf m_streamBuf; ///
\r
198 explicit basic_omsgstream(UINT i_messageId, HWND i_hwnd = 0)
\r
199 : Super(&m_streamBuf), m_streamBuf(i_messageId, i_hwnd) {
\r
203 virtual ~basic_omsgstream() {
\r
207 StreamBuf *rdbuf() const {
\r
208 return const_cast<StreamBuf *>(&m_streamBuf);
\r
211 /// attach a msg control
\r
212 void attach(HWND i_hwnd) {
\r
213 m_streamBuf.attach(i_hwnd);
\r
216 /// detach a msg control
\r
218 m_streamBuf.detach();
\r
221 /// get window handle of the msg control
\r
222 HWND getHwnd() const {
\r
223 return m_streamBuf.getHwnd();
\r
226 /// is the msg control attached ?
\r
227 int is_open() const {
\r
228 return m_streamBuf.is_open();
\r
231 /// set debug level
\r
232 void setDebugLevel(int i_debugLevel) {
\r
233 m_streamBuf.setDebugLevel(i_debugLevel);
\r
237 int getDebugLevel() const {
\r
238 return m_streamBuf.getDebugLevel();
\r
241 /// acquire string and release the string
\r
242 const String &acquireString() {
\r
243 return m_streamBuf.acquireString();
\r
247 void releaseString() {
\r
248 m_streamBuf->releaseString();
\r
254 virtual void acquire() {
\r
255 m_streamBuf.acquire();
\r
259 virtual void acquire(int i_msgDebugLevel) {
\r
260 m_streamBuf.acquire(i_msgDebugLevel);
\r
264 virtual void release() {
\r
265 m_streamBuf.release();
\r
270 typedef basic_omsgstream<_TCHAR> tomsgstream;
\r
273 #endif // !_MSGSTREAM_H
\r