00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef IRCMESSAGE_H
00017 #define IRCMESSAGE_H
00018
00019 #ifndef USE_PCH
00020 #include <map>
00021 #include <string>
00022 #include <vector>
00023 #include "debug.h"
00024 #include <libcw/dbstreambuf.h>
00025 #ifdef CWDEBUG
00026 #include <libcwd/buf2str.h>
00027 #endif
00028 #endif
00029
00030 #include "Keyword.h"
00031 #include "Prefix.h"
00032
00033 class ClientSession;
00034 class ServerSession;
00035 class MsgPart;
00036
00037
00038
00039
00040
00041 class MessageIn {
00042 public:
00043
00044 class Part {
00045 private:
00046 char const* M_ptr;
00047 size_t M_len;
00048 public:
00049
00050 Part(void) { }
00051
00052 Part(char const* start, char const* end) : M_ptr(start), M_len(end - start) { }
00053
00054 void set(char const* start, char const* end) { M_ptr = start; M_len = end - start; }
00055
00056 void clear(void) { M_ptr = NULL; }
00057
00058 char const* start(void) const { return M_ptr; }
00059
00060 char const* end(void) const { return M_ptr + M_len; }
00061
00062 size_t len(void) const { return M_len; }
00063 #ifdef CWDEBUG
00064
00065 friend std::ostream& operator<<(std::ostream& os, Part const& part)
00066 { return os << '"' << libcwd::buf2str(part.M_ptr, part.M_len) << '"'; }
00067 #endif
00068 };
00069
00070 public:
00071 typedef std::vector<Part> params_type;
00072
00073 private:
00074 msg_block_ct M_msg_block;
00075 char const* M_end;
00076 Part M_prefix;
00077 Part M_command;
00078 int M_key;
00079 Keyword const* M_keyword_ptr;
00080 params_type M_params;
00081
00082 protected:
00083
00084 MessageIn(void);
00085
00086 public:
00087
00088 void init(msg_block_ct msg_block);
00089
00090
00091 bool uninitialized(void) const { return M_msg_block.get_size() == 0; }
00092
00093
00094 bool is_numeric(void) const { return M_command.start() && std::isdigit(*M_command.start()); }
00095
00096
00097 int numeric(void) const { ASSERT(is_numeric()); return M_key; }
00098
00099
00100 int key(void) const { return M_key; }
00101
00102
00103 params_type::size_type params_size(void) const { return M_params.size(); }
00104
00105
00106 params_type const& params(void) const { return M_params; }
00107
00108
00109 std::string param(size_t n) const
00110 {
00111 std::string result;
00112 if (n < M_params.size())
00113 result.assign(M_params[n].start(), M_params[n].len());
00114 return result;
00115 }
00116
00117
00118 MsgPart params(size_t n) const;
00119
00120
00121 bool has_prefix(void) const { return M_prefix.start(); }
00122
00123
00124 std::string prefix_str(void) const { ASSERT(has_prefix()); return std::string(M_prefix.start(), M_prefix.len()); }
00125
00126
00127 Part prefix_part(void) const { ASSERT(has_prefix()); return M_prefix; }
00128
00129
00130 Prefix prefix(void) const
00131 { return has_prefix() ? (is_server_message() ? Prefix(priv_server_session(), prefix_str()) : Prefix(priv_client_session(), prefix_str())) : Prefix(); }
00132
00133
00134 std::string command_str(void) const { return M_command.start() ? std::string(M_command.start(), M_command.len()) : ""; }
00135
00136
00137 Part const& command_part(void) const { return M_command; }
00138
00139
00140 char const* uppercase_command(void) const { ASSERT(M_key < 0); return M_keyword_ptr->name; }
00141
00142
00143 char const* end(void) const { return M_end; }
00144
00145 protected:
00146
00147 virtual bool is_server_message(void) const = 0;
00148
00149
00150 virtual ServerSession& priv_server_session(void) const = 0;
00151
00152 virtual ClientSession& priv_client_session(void) const = 0;
00153 };
00154
00155
00156
00157
00158 class MsgPart : public MessageIn::Part {
00159 private:
00160 msg_block_ct M_msg_block;
00161 public:
00162
00163 MsgPart(msg_block_ct const& msg_block) : M_msg_block(msg_block) { }
00164
00165 MsgPart(msg_block_ct const& msg_block, Part const& part) : MessageIn::Part(part), M_msg_block(msg_block) { }
00166 };
00167
00168 inline MsgPart MessageIn::params(size_t n) const
00169 {
00170 MsgPart result(M_msg_block);
00171 if (n < M_params.size())
00172 {
00173 char const* start = M_params[n].start();
00174 if (n == M_params.size() - 1 && start[-1] == ':')
00175 --start;
00176 result.set(start, M_end);
00177 }
00178 else
00179 result.clear();
00180 return result;
00181 }
00182
00183
00184
00185
00186
00187 class ClientMessageIn : public MessageIn {
00188 private:
00189 ClientSession* M_client_session;
00190 public:
00191
00192 ClientMessageIn(ClientSession* client_session) : M_client_session(client_session) { }
00193 #ifdef CWDEBUG
00194
00195 ClientMessageIn(ClientMessageIn const& msg) : MessageIn(msg), M_client_session(msg.M_client_session)
00196 { Dout(dc::objects, "Copy-constructing ClientMessageIn from " << msg); }
00197
00198 ~ClientMessageIn() { Dout(dc::objects, "Destructing ClientMessageIn " << *this); }
00199 #endif
00200
00201
00202 ClientSession& client_session(void) const { return *M_client_session; }
00203
00204 protected:
00205 virtual bool is_server_message(void) const { return false; }
00206
00207 virtual ClientSession& priv_client_session(void) const { return client_session(); }
00208 virtual ServerSession& priv_server_session(void) const { DoutFatal(dc::core, "Calling MessageIn::server_session() for ClientMessageIn"); }
00209 };
00210
00211
00212
00213
00214
00215 class ServerMessageIn : public MessageIn {
00216 private:
00217 ServerSession* M_server_session;
00218 public:
00219
00220 ServerMessageIn(ServerSession* server_session) : M_server_session(server_session) { }
00221 #ifdef CWDEBUG
00222
00223 ServerMessageIn(ServerMessageIn const& msg) : MessageIn(msg), M_server_session(msg.M_server_session)
00224 { Dout(dc::objects, "Copy-constructing ServerMessageIn from " << msg); }
00225 #endif
00226
00227 ~ServerMessageIn() { Dout(dc::objects, "Destructing ServerMessageIn " << *this); }
00228
00229
00230
00231
00232
00233
00234 ServerSession& server_session(void) const { return *M_server_session; }
00235
00236 protected:
00237 virtual bool is_server_message(void) const { return true; }
00238
00239 virtual ClientSession& priv_client_session(void) const { DoutFatal(dc::core, "Calling ServerMessageIn::priv_client_session()"); }
00240 virtual ServerSession& priv_server_session(void) const { return server_session(); }
00241 };
00242
00243 #endif // IRCMESSAGE_H