OSDN Git Service

separate intermediate directories for each projects to avoid confliction of dependenc...
[yamy/yamy.git] / msgstream.h
1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2 // msgstream.h
3
4
5 #ifndef _MSGSTREAM_H
6 #  define _MSGSTREAM_H
7
8 #  include "misc.h"
9 #  include "stringtool.h"
10 #  include "multithread.h"
11
12
13 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
14 // msgstream
15
16 /** msgstream.
17
18     <p>Before writing to omsgstream, you must acquire lock by calling
19     <code>acquire()</code>.  Then after completion of writing, you
20     must call <code>release()</code>.</p>
21     
22     <p>Omsgbuf calls <code>PostMessage(hwnd, messageid, 0,
23     (LPARAM)omsgbuf)</code> to notify that string is ready to get.
24     When the window (<code>hwnd</code>) get the message, you can get
25     the string containd in the omsgbuf by calling
26     <code>acquireString()</code>.  After calling
27     <code>acquireString()</code>, you must / call releaseString().</p>
28
29 */
30
31 template<class T, size_t SIZE = 1024,
32   class TR = std::char_traits<T>, class A = std::allocator<T> >
33 class basic_msgbuf : public std::basic_streambuf<T, TR>, public SyncObject
34 {
35 public:
36   typedef std::basic_string<T, TR, A> String;   /// 
37   typedef std::basic_streambuf<T, TR> Super;    ///
38   
39 private:
40   HWND m_hwnd;                                  /** window handle for
41                                                     notification */
42   UINT m_messageId;                             /// messageid for notification
43   T *m_buf;                                     /// for streambuf
44   String m_str;                                 /// for notification
45   CriticalSection m_cs;                         /// lock
46   A m_allocator;                                /// allocator
47   
48   /** debug level.
49       if ( m_msgDebugLevel &lt;= m_debugLevel ), message is displayed
50   */
51   int m_debugLevel;
52   int m_msgDebugLevel;                          ///
53
54 private:
55   basic_msgbuf(const basic_msgbuf &);           /// disable copy constructor
56
57 public:
58   ///
59   basic_msgbuf(UINT i_messageId, HWND i_hwnd = 0)
60     : m_hwnd(i_hwnd),
61       m_messageId(i_messageId),
62       m_buf(m_allocator.allocate(SIZE, 0)),
63       m_debugLevel(0),
64       m_msgDebugLevel(0)
65   {
66     ASSERT(m_buf);
67     setp(m_buf, m_buf + SIZE);
68   }
69   
70   ///
71   ~basic_msgbuf()
72   {
73     sync();
74     m_allocator.deallocate(m_buf, SIZE);
75   }
76   
77   /// attach/detach a window
78   basic_msgbuf* attach(HWND i_hwnd)
79   {
80     Acquire a(&m_cs);
81     ASSERT( !m_hwnd && i_hwnd );
82     m_hwnd = i_hwnd;
83     if (!m_str.empty())
84       PostMessage(m_hwnd, m_messageId, 0, (LPARAM)this);
85     return this;
86   }
87   
88   ///
89   basic_msgbuf* detach()
90   {
91     Acquire a(&m_cs);
92     sync();
93     m_hwnd = 0;
94     return this;
95   }
96   
97   /// get window handle
98   HWND getHwnd() const { return m_hwnd; }
99   
100   /// is a window attached ?
101   int is_open() const { return !!m_hwnd; }
102   
103   /// acquire string and release the string
104   const String &acquireString()
105   {
106     m_cs.acquire();
107     return m_str;
108   }
109   
110   ///
111   void releaseString()
112   {
113     m_str.resize(0);
114     m_cs.release();
115   }
116
117   /// set debug level
118   void setDebugLevel(int i_debugLevel)
119   {
120     m_debugLevel = i_debugLevel;
121   }
122   
123   ///
124   int getDebugLevel() const { return m_debugLevel; }
125   
126   // for stream
127   typename Super::int_type overflow(typename Super::int_type i_c = TR::eof())
128   {
129     if (sync() == TR::eof()) // sync before new buffer created below
130       return TR::eof();
131     
132     if (i_c != TR::eof())
133     {
134       *pptr() = TR::to_char_type(i_c);
135       pbump(1);
136       sync();
137     }
138     return TR::not_eof(i_c); // return something other than EOF if successful
139   }
140   
141   // for stream
142   int sync()
143   {
144     T *begin = pbase();
145     T *end = pptr();
146     T *i;
147     for (i = begin; i < end; ++ i)
148       if (_istlead(*i))
149         ++ i;
150     if (i == end)
151     {
152       if (m_msgDebugLevel <= m_debugLevel)
153         m_str += String(begin, end - begin);
154       setp(m_buf, m_buf + SIZE);
155     }
156     else // end < i
157     {
158       if (m_msgDebugLevel <= m_debugLevel)
159         m_str += String(begin, end - begin - 1);
160       m_buf[0] = end[-1];
161       setp(m_buf, m_buf + SIZE);
162       pbump(1);
163     }
164     return TR::not_eof(0);
165   }
166
167   // sync object
168   
169   /// begin writing
170   virtual void acquire()
171   {
172     m_cs.acquire();
173   }
174
175   /// begin writing
176   virtual void acquire(int i_msgDebugLevel)
177   {
178     m_cs.acquire();
179     m_msgDebugLevel = i_msgDebugLevel;
180   }
181   
182   /// end writing
183   virtual void release()
184   {
185     if (!m_str.empty())
186       PostMessage(m_hwnd, m_messageId, 0, reinterpret_cast<LPARAM>(this));
187     m_msgDebugLevel = m_debugLevel;
188     m_cs.release();
189   }
190 };
191
192
193 ///
194 template<class T, size_t SIZE = 1024,
195   class TR = std::char_traits<T>, class A = std::allocator<T> >
196 class basic_omsgstream : public std::basic_ostream<T, TR>, public SyncObject
197 {
198 public:
199   typedef std::basic_ostream<T, TR> Super;      /// 
200   typedef basic_msgbuf<T, SIZE, TR, A> StreamBuf; /// 
201   typedef std::basic_string<T, TR, A> String;   /// 
202   
203 private:
204   StreamBuf m_streamBuf;                        /// 
205
206 public:
207   ///
208   explicit basic_omsgstream(UINT i_messageId, HWND i_hwnd = 0)
209     : Super(&m_streamBuf), m_streamBuf(i_messageId, i_hwnd)
210   {
211   }
212   
213   ///
214   virtual ~basic_omsgstream()
215   {
216   }
217   
218   ///
219   StreamBuf *rdbuf() const
220   {
221     return const_cast<StreamBuf *>(&m_streamBuf);
222   }
223
224   /// attach a msg control
225   void attach(HWND i_hwnd)
226   {
227     m_streamBuf.attach(i_hwnd);
228   }
229
230   /// detach a msg control
231   void detach()
232   {
233     m_streamBuf.detach();
234   }
235
236   /// get window handle of the msg control
237   HWND getHwnd() const
238   {
239     return m_streamBuf.getHwnd();
240   }
241
242   /// is the msg control attached ?
243   int is_open() const
244   {
245     return m_streamBuf.is_open();
246   }
247
248   /// set debug level
249   void setDebugLevel(int i_debugLevel)
250   {
251     m_streamBuf.setDebugLevel(i_debugLevel);
252   }
253   
254   ///
255   int getDebugLevel() const
256   {
257     return m_streamBuf.getDebugLevel();
258   }
259
260   /// acquire string and release the string
261   const String &acquireString()
262   {
263     return m_streamBuf.acquireString();
264   }
265   
266   ///
267   void releaseString()
268   {
269     m_streamBuf->releaseString();
270   }
271
272   // sync object
273   
274   /// begin writing
275   virtual void acquire()
276   {
277     m_streamBuf.acquire();
278   }
279   
280   /// begin writing
281   virtual void acquire(int i_msgDebugLevel)
282   {
283     m_streamBuf.acquire(i_msgDebugLevel);
284   }
285   
286   /// end writing
287   virtual void release()
288   {
289     m_streamBuf.release();
290   }
291 };
292
293 ///
294 typedef basic_omsgstream<_TCHAR> tomsgstream;
295
296
297 #endif // !_MSGSTREAM_H