basix_doc 0.1
|
00001 00002 /****************************************************************************** 00003 * MODULE : port.hpp 00004 * DESCRIPTION: Input and output ports 00005 * COPYRIGHT : (C) 2010 Joris van der Hoeven 00006 ******************************************************************************* 00007 * This software falls under the GNU general public license and comes WITHOUT 00008 * ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details. 00009 * If you don't have this file, write to the Free Software Foundation, Inc., 00010 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00011 ******************************************************************************/ 00012 00013 #ifndef __PORT_HPP 00014 #define __PORT_HPP 00015 #include <basix/string.hpp> 00016 00018 00019 namespace mmx { 00020 00021 extern bool texmacs_mode; 00022 extern bool math_mode; 00023 00024 string string_as_mmx (const string& g); 00025 string output_as_mmx (const generic& g); 00026 00027 /****************************************************************************** 00028 * The port class 00029 ******************************************************************************/ 00030 00031 class port; 00032 class port_rep: public rep_struct { 00033 public: 00034 virtual syntactic expression () const = 0; 00035 virtual bool is_output_port (); 00036 virtual bool is_input_port (); 00037 virtual bool error_flag (); 00038 virtual string error_message (); 00039 virtual bool busy (); 00040 virtual nat can_write (); 00041 virtual nat can_read (); 00042 virtual void write (const char* s, nat n); 00043 virtual void read (char* s, nat n); 00044 virtual void flush (); 00045 virtual bool wait (int msecs); 00046 virtual port accept (); 00047 virtual port component (const string& name); 00048 virtual void format (const print_format& fm); 00049 00050 public: 00051 inline port_rep () {} 00052 inline virtual ~port_rep () {} 00053 }; 00054 00055 class port { 00056 INDIRECT_PROTO (port, port_rep) 00057 port (); 00058 }; 00059 INDIRECT_IMPL (port, port_rep) 00060 00061 HARD_TO_EXACT_IDENTITY_SUGAR(,port) 00062 HARD_TO_TRUE_IDENTITY_SUGAR(,port) 00063 00064 inline syntactic flatten (const port& p) { return p->expression (); } 00065 00066 /****************************************************************************** 00067 * Public port constructors 00068 ******************************************************************************/ 00069 00070 extern port mmin; 00071 extern port mmout; 00072 extern port mmerr; 00073 00074 port input_string_port (const string& s); 00075 port output_string_port (string& s); 00076 port input_output_string_port (string& s); 00077 port input_file_port (const string& name); 00078 port output_file_port (const string& name); 00079 port input_output_file_port (const string& name); 00080 port socket_server_port (const string& host, int port); 00081 port socket_client_port (const string& host, int port); 00082 port pipe_port (const string& cmd); 00083 port composite_port (const vector<port>& ps); 00084 port composite_port (const vector<port>& ps, const vector<string>& names); 00085 port formatting_port (const port& p); 00086 port error_port (const string& message); 00087 00088 /****************************************************************************** 00089 * Public routines for ports 00090 ******************************************************************************/ 00091 00092 inline bool is_input_port (const port& p) { 00093 return inside (p)->is_input_port (); } 00094 inline bool is_output_port (const port& p) { 00095 return inside (p)->is_output_port (); } 00096 inline bool error_flag (const port& p) { 00097 return inside (p)->error_flag (); } 00098 string error_message (const port& p); 00099 inline bool busy (const port& p) { 00100 return inside (p)->busy (); } 00101 inline nat can_write (const port& p) { 00102 return inside (p)->can_write (); } 00103 inline nat can_read (const port& p) { 00104 return inside (p)->can_read (); } 00105 inline void write (const port& p, const char* s, nat n) { 00106 inside (p)->write (s, n); } 00107 inline void write (const port& p, const string& s) { 00108 inside (p)->write (inside (s, 0), N(s)); } 00109 inline void read (const port& p, char* s, nat n) { 00110 inside (p)->read (s, n); } 00111 inline string read (const port& p, nat n) { 00112 string r (n); inside (p)->read (inside (r, 0), n); return r; } 00113 inline void flush (const port& p) { 00114 inside (p)->flush (); } 00115 inline bool wait (const port& p, int msec) { 00116 return inside (p)->wait (msec); } 00117 inline port accept (const port& p) { 00118 return inside (p)->accept (); } 00119 port component (const port& p, const string& name); 00120 00121 nat wait_port_event (int msecs); 00122 00123 /****************************************************************************** 00124 * Standard << and >> operators 00125 ******************************************************************************/ 00126 00127 typedef char* charp; 00128 typedef const char* const_charp; 00129 00130 template<typename C> inline port 00131 operator << (const port& out, const C& x) { 00132 write (out, output_as_mmx (as<generic> (x))); 00133 return out; 00134 } 00135 00136 inline port 00137 operator << (const port& out, const string& s) { 00138 write (out, string_as_mmx (s)); 00139 return out; 00140 } 00141 00142 inline port 00143 operator << (const port& out, const charp& s) { 00144 write (out, string_as_mmx (s)); 00145 return out; 00146 } 00147 00148 inline port 00149 operator << (const port& out, const const_charp& s) { 00150 write (out, string_as_mmx (s)); 00151 return out; 00152 } 00153 00154 inline port 00155 operator << (const port& out, const char& c) { 00156 write (out, string_as_mmx (c)); 00157 return out; 00158 } 00159 00160 inline port 00161 operator << (const port& out, const print_format& fm) { 00162 inside (out) -> format (fm); 00163 return out; 00164 } 00165 00166 inline port 00167 operator >> (const port& in, char& c) { 00168 read (in, &c, 1); 00169 return in; 00170 } 00171 00172 /****************************************************************************** 00173 * Binary serialization 00174 ******************************************************************************/ 00175 00176 template<typename C> generic binary_disassemble (const C& x); 00177 template<typename C> C binary_assemble (const generic& x); 00178 template<typename C> void binary_write (const port& out, const C& x); 00179 template<typename C> C binary_read (const port& in); 00180 00181 template<typename C> 00182 struct void_binary_helper { 00183 static inline string short_type_name () { return "?"; } 00184 static inline generic full_type_name () { return "?"; } 00185 static inline nat size (const C& x) { 00186 return vector_size (disassemble (x)); } 00187 static inline generic access (const C& x, nat i) { 00188 return vector_access (disassemble (x), i); } 00189 static inline generic disassemble (const C& x) { 00190 return as<generic> (x); } 00191 static inline C assemble (const generic& x) { 00192 return as<C> (x); } 00193 static inline void write (const port& out, const C& x) { 00194 generic d= binary_disassemble<C> (x); 00195 ASSERT (is<string> (d) || !is<C> (d), "binary write not implemented"); 00196 binary_write<generic> (out, d); } 00197 static inline C read (const port& in) { 00198 return binary_assemble<C> (binary_read<generic> (in)); } 00199 }; 00200 00201 template<typename C> 00202 struct binary_helper: 00203 public void_binary_helper<C> {}; 00204 00205 template<typename C> nat 00206 binary_size (const C& x) { 00207 return binary_helper<C>::size (x); 00208 } 00209 00210 template<typename C> generic 00211 binary_access (const C& x, nat i) { 00212 return binary_helper<C>::access (x, i); 00213 } 00214 00215 template<typename C> generic 00216 binary_disassemble (const C& x) { 00217 return binary_helper<C>::disassemble (x); 00218 } 00219 00220 template<typename C> C 00221 binary_assemble (const generic& x) { 00222 return binary_helper<C>::assemble (x); 00223 } 00224 00225 template<typename C> void 00226 binary_write (const port& out, const C& x) { 00227 binary_helper<C>::write (out, x); 00228 } 00229 00230 template<typename C> C 00231 binary_read (const port& in) { 00232 return binary_helper<C>::read (in); 00233 } 00234 00235 template<typename C> port 00236 binary_ll (const port& out, const C& x) { 00237 binary_helper<C>::write (out, x); 00238 return out; 00239 } 00240 00241 template<typename C> port 00242 binary_rr (const port& in, C& x) { 00243 x= binary_helper<C>::read (in); 00244 return in; 00245 } 00246 00247 #define Short_type_name(T) binary_helper<T >::short_type_name () 00248 #define Full_type_name(T) binary_helper<T >::full_type_name () 00249 00250 /****************************************************************************** 00251 * Binary serialization of generic objects 00252 ******************************************************************************/ 00253 00254 typedef generic (*unary_generic) (const generic&); 00255 00256 void attach_generic_binary_assembler (const generic&, unary_generic); 00257 generic binary_type_generic (const generic& g); 00258 generic binary_disassemble_generic (const generic& g); 00259 generic binary_assemble_generic (const generic& tp, const generic& val); 00260 00261 template<typename T> generic 00262 binary_assemble_generic_via (const generic& x) { 00263 return as<generic> (binary_assemble<T> (x)); 00264 } 00265 00266 template<typename T> inline void 00267 attach_generic_binary_assembler () { 00268 attach_generic_binary_assembler (binary_helper<T>::full_type_name (), 00269 binary_assemble_generic_via<T>); 00270 } 00271 00272 void attach_generic_binary_reader (const string&, unary_generic); 00273 void binary_write_generic (const port& out, const generic& g); 00274 generic binary_read_generic (const port& in); 00275 00276 template<typename T> generic 00277 binary_read_generic (const generic& in) { 00278 return as<generic> (binary_read<T> (as<port> (in))); 00279 } 00280 00281 template<typename T> inline void 00282 attach_generic_binary_reader () { 00283 attach_generic_binary_reader (binary_helper<T>::short_type_name (), 00284 binary_read_generic<T>); 00285 } 00286 00287 template<> 00288 struct binary_helper<generic> { 00289 static inline string short_type_name () { return "Gen"; } 00290 static inline generic full_type_name () { return "Generic"; } 00291 static inline nat size (const generic& g) { (void) g; return 2; } 00292 static inline generic access (const generic& x, nat i) { 00293 if (i == 0) return binary_type_generic (x); 00294 else if (i == 1) return binary_disassemble_generic (x); 00295 else ERROR ("index out of range"); } 00296 static inline generic disassemble (const generic& x) { 00297 return gen_vec (access (x, 0), access (x, 1)); } 00298 static inline generic assemble (const generic& x) { 00299 return binary_assemble_generic (vector_access (x, 0), 00300 vector_access (x, 1)); } 00301 static inline void write (const port& out, const generic& g) { 00302 binary_write_generic (out, g); } 00303 static generic read (const port& in) { 00304 return binary_read_generic (in); } 00305 }; 00306 00307 inline generic generic_disassemble (const generic& x) { 00308 return binary_disassemble<generic> (x); } 00309 inline generic generic_assemble (const generic& x) { 00310 return binary_assemble<generic> (x); } 00311 00312 /****************************************************************************** 00313 * Binary serialization of standard numeric types 00314 ******************************************************************************/ 00315 00316 #define NUMERIC_BINARY_HELPER(TMPL,C,name,fname) \ 00317 TMPL \ 00318 struct binary_helper< C >: public void_binary_helper< C > { \ 00319 static inline string short_type_name () { return name; } \ 00320 static inline generic full_type_name () { return fname; } \ 00321 static inline generic disassemble (const C& x) { \ 00322 return as<generic> (numeric_as_string (x)); } \ 00323 static inline C assemble (const generic& x) { \ 00324 return string_as_numeric<C> (as<string> (x)); } \ 00325 static inline void write (const port& out, const C& x) { \ 00326 mmx::write (out, (const char*) ((const void*) (&x)), sizeof (C)); } \ 00327 static inline C read (const port& in) { \ 00328 C x; mmx::read (in, (char*) ((void*) (&x)), sizeof (C)); return x; } \ 00329 }; 00330 00331 NUMERIC_BINARY_HELPER(STMPL,char,"C","Char") 00332 NUMERIC_BINARY_HELPER(STMPL,uchar,"Uc","Uchar") 00333 NUMERIC_BINARY_HELPER(STMPL,short,"Sh","Short") 00334 NUMERIC_BINARY_HELPER(STMPL,ushort,"Us","Ushort") 00335 NUMERIC_BINARY_HELPER(STMPL,int,"I","Int") 00336 NUMERIC_BINARY_HELPER(STMPL,nat,"N","Uint") 00337 NUMERIC_BINARY_HELPER(STMPL,long,"Lo","Long") 00338 NUMERIC_BINARY_HELPER(STMPL,ulong,"Ul","Ulong") 00339 NUMERIC_BINARY_HELPER(STMPL,float,"F","Float") 00340 NUMERIC_BINARY_HELPER(STMPL,double,"D","Double") 00341 00342 /****************************************************************************** 00343 * Binary serialization of other basic types 00344 ******************************************************************************/ 00345 00346 template<> 00347 struct binary_helper<bool>: public void_binary_helper<bool> { 00348 static inline string short_type_name () { return "B"; } 00349 static inline generic full_type_name () { return "Boolean"; } 00350 static inline generic disassemble (const bool& b) { 00351 return as<generic> (b? string ("true"): string ("false")); } 00352 static inline bool assemble (const generic& x) { 00353 return is<string> (x) && as<string> (x) == "true"; } 00354 static inline void write (const port& out, const bool& b) { 00355 mmx::write (out, b? "t": "f", 1); } 00356 static inline bool read (const port& in) { 00357 char s[1]; mmx::read (in, s, 1); return s[0] == 't'; } 00358 }; 00359 00360 template<> 00361 struct binary_helper<string>: public void_binary_helper<string> { 00362 static inline string short_type_name () { return "S"; } 00363 static inline generic full_type_name () { return "String"; } 00364 static inline void write (const port& out, const string& s) { 00365 binary_write<nat> (out, N(s)); 00366 mmx::write (out, s); } 00367 static inline string read (const port& in) { 00368 nat n= binary_read<nat> (in); 00369 return mmx::read (in, n); } 00370 }; 00371 00372 template<> 00373 struct binary_helper<syntactic>: public void_binary_helper<syntactic> { 00374 static inline string short_type_name () { return "Y"; } 00375 static inline generic full_type_name () { return "Syntactic"; } 00376 static inline generic disassemble (const syntactic& x) { 00377 return *x; } 00378 static inline syntactic assemble (const generic& x) { 00379 return as_syntactic (x); } 00380 static inline void write (const port& out, const syntactic& s) { 00381 binary_write<generic> (out, *s); } 00382 static inline syntactic read (const port& in) { 00383 return as_syntactic (binary_read<generic> (in)); } 00384 }; 00385 00386 template<> 00387 struct binary_helper<exception>: public void_binary_helper<exception> { 00388 static inline string short_type_name () { return "Exc"; } 00389 static inline generic full_type_name () { return "Exception"; } 00390 static inline generic disassemble (const exception& x) { 00391 return *x; } 00392 static inline exception assemble (const generic& x) { 00393 return exception (x); } 00394 static inline void write (const port& out, const exception& e) { 00395 binary_write<generic> (out, *e); } 00396 static inline exception read (const port& in) { 00397 return exception (binary_read<generic> (in)); } 00398 }; 00399 00400 template<typename FT, typename T> 00401 struct format_binary_helper { 00402 static inline void write (const port& out, const format<T>& fm) { 00403 binary_write<T> (out, get_sample (fm)); } 00404 static inline format<T> read (const port& in) { 00405 return get_format (binary_read<T> (in)); } 00406 }; 00407 00408 template<typename T> 00409 struct format_binary_helper<empty_format,T> { 00410 static inline void write (const port&, const format<T>&) {} 00411 static inline format<T> read (const port&) { return format<T> (); } 00412 }; 00413 00414 template<typename T> 00415 struct binary_helper<format<T> >: public void_binary_helper<format<T> > { 00416 typedef typename format<T>::FT FT; 00417 static inline string short_type_name () { 00418 return "Fm" * Short_type_name (T); } 00419 static inline generic full_type_name () { 00420 return gen ("Format", Full_type_name (T)); } 00421 static inline generic disassemble (const format<T>& fm) { 00422 return binary_disassemble (get_sample (fm)); } 00423 static inline format<T> assemble (const generic& x) { 00424 return get_format (binary_assemble<T> (x)); } 00425 static inline void write (const port& out, const format<T>& fm) { 00426 format_binary_helper<FT,T>::write (out, fm); } 00427 static inline format<T> read (const port& in) { 00428 return format_binary_helper<FT,T>::read (in); } 00429 }; 00430 00431 } // namespace mmx 00432 #endif // __PORT_HPP