OSDN Git Service

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