00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 #include "messageblock.hh"
00025 #include "message.hh"
00026 #include "msglexer.hh"
00027 #include "log.hh"
00028 
00029 #include "parsemessage_parser.h"
00030 
00031 #include <deque>
00032 
00033 using namespace VOS;
00034 
00035 MessageBlock::MessageBlock()
00036     : formattedString(0)
00037 {
00038     parsestate.m=this;
00039     parsestate.chars_read=0;
00040     parsestate.expected_length=0;
00041     parsestate.done=false;
00042     parsestate.extra=0;
00043     parsestate.read_quoted=0;
00044 }
00045 
00046 MessageBlock::~MessageBlock()
00047 {
00048     LOG("refcount", 5, "start deleting messageblock with messages:");
00049     if(formattedString) delete formattedString;
00050     for(deque<Message*>::iterator i = messages.begin(); i != messages.end(); i++) {
00051         LOG("refcount", 5, "msg: [" << (*i)->refcount_debug << "]  count " << (*i)->getCount());
00052         (*i)->release(); 
00053     }
00054     LOG("refcount", 5, "done deleting messageblock");
00055 }
00056 
00057 string MessageBlock::getName()
00058 {
00059     return name;
00060 }
00061 
00062 void MessageBlock::setName(const string& n)
00063 {
00064     name=n;
00065 }
00066 
00067 void MessageBlock::insertMessage(int n, Message* m)
00068 {
00069     m->acquire(); 
00070     if(messages.size() > 0 && n > -1 && (unsigned int)n >= messages.size()) n = n % (int)messages.size();
00071     if(n < 0) n = (int)messages.size() + n + 1;
00072     messages.insert(messages.begin() + n, m);
00073 }
00074 
00075 Message* MessageBlock::getMessage(int n)
00076 {
00077     if(n < 0) n = (int)messages.size() + n + 1;
00078     if(n < 0 || n >= (int)messages.size()) return 0;
00079     messages[n]->acquire(); 
00080     return messages[n];
00081 }
00082 
00083 Message* MessageBlock::lastMessage()
00084 {
00085     if(messages.size() == 0) return 0;
00086     messages.back()->acquire(); 
00087     return messages.back();
00088 }
00089 
00090 int MessageBlock::numMessages()
00091 {
00092     return (int)messages.size();
00093 }
00094 
00095 const string& MessageBlock::getString()
00096 {
00097     if(formattedString) delete formattedString;
00098 
00099     if(messages.size() == 1 && name == "") {
00100         formattedString = new string;
00101         *formattedString = lastMessage()->getFormattedString(true);
00102         return *formattedString;
00103     }
00104 
00105     string* s = new string();
00106 
00107     *s += "<messageblock length=\"\"";
00108     if(name != "") {
00109         *s += " name=\"";
00110         *s += name;
00111         *s += "\"";
00112     }
00113     *s += ">\n";
00114     for(deque<Message*>::const_iterator f = messages.begin();
00115         f != messages.end();
00116         f++) {
00117         *s += (*f)->getFormattedString(false) + "\n";
00118     }
00119     *s += "</messageblock>";
00120 
00121     unsigned int size = (unsigned int)s->size();
00122 
00123     char len[16];
00124     int width = snprintf(len, sizeof(len), "%i", size);
00125     size += (unsigned int)strlen(len);
00126     if(width < snprintf(len, sizeof(len), "%i", size)) snprintf(len, sizeof(len), "%i", size+1);
00127 
00128     
00129     s->insert(22, len);
00130 
00131     formattedString = s;
00132 
00133     return *s;
00134 }
00135 
00136 int MessageBlock::parseUpdate(const string& s)
00137 {
00138     unsigned int oldsize = (unsigned int)parse_buffer.size();
00139     parse_buffer.append(s);
00140 
00141     LOG("messageblock", 4, "parse_buffer.size() is " << (unsigned int)parse_buffer.size() << " and expected_length is " << parsestate.expected_length);
00142 
00143     if(parse_buffer.size() < parsestate.expected_length) return 0;
00144 
00145     msgFlexLexer fl(&parsestate);
00146     parsestate.extra=&fl;
00147 
00148 #ifdef USE_STRSTREAM
00149     istrstream ss(parse_buffer.c_str(), parse_buffer.length());
00150     char blah[1024];
00151     ostrstream os(blah, sizeof(blah));
00152 #else
00153     istringstream ss(parse_buffer);
00154     string blah;
00155     ostringstream os(blah);
00156 #endif
00157     LOG("parser", 5, "siccing the parser on " << parse_buffer);
00158     if(parse_buffer.size() > 1000) LOG("parser", 5, "ending is  " << parse_buffer.substr(parse_buffer.size() - 1000, 1000));
00159 
00160     parsestate.input = &ss;
00161 
00162     fl.switch_streams(&ss, &os);
00163     parsestate.chars_read=0;
00164     parsestate.read_quoted=0;
00165     msgparse(&parsestate);
00166 
00167     if(parsestate.done) {
00168         parse_buffer.erase(parse_buffer.begin(), parse_buffer.end());
00169         if(formattedString != 0) {
00170             delete formattedString;
00171             formattedString=0;
00172         }
00173         return (parsestate.chars_read - oldsize);
00174     } else {
00175         for(deque<Message*>::iterator i = messages.begin(); i != messages.end(); i++) {
00176             (*i)->release(); 
00177         }
00178         messages.resize(0);
00179         return 0;
00180     }
00181 }
00182 
00183 int VOS::msglex(char** lvalp, void* extra)
00184 {
00185     struct parse_state_t* ps=(parse_state_t*)extra;
00186 
00187     msgFlexLexer* fl=(msgFlexLexer*)ps->extra;
00188 
00189     if(! ps->done) {
00190         int ret;
00191         *lvalp = 0;
00192         do {
00193             ret=fl->yylex();
00194             if(ret < 255 || ret == SPACE || ret == COMMENT) *lvalp = (char*)fl->YYText();
00195             else *lvalp = strdup(fl->YYText());
00196             
00197 
00198             if(! ps->read_quoted) ps->chars_read += fl->YYLeng();
00199 
00200             LOG("lexer", 6, "lexer called, got a " << *lvalp << " (len " << fl->YYLeng()
00201                 << ") and returning " << ret);
00202         } while(ret == COMMENT);
00203         return ret;
00204     }
00205     return 0;
00206 }
00207 
00208 void VOS::msgerror(char* blah)
00209 {
00210     LOG("parser", 4, "Message parse error (probably because entire message has beeen received yet): " << blah);
00211 }