Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

XMLCannedInput Class Reference

A class of canned input producer that uses XML syntax to specify the canned input. More...

Inheritance diagram for XMLCannedInput:

CannedInput List of all members.

Public Methods

 XMLCannedInput (const string &filename, istream &is)
 Initializes the XMLTokenizer member variable with the given input stream.

bool execute_one_event (Drawing *)
 Executes one event from the XML input; most work is done here.


Private Attributes

XMLTokenizer t

Detailed Description

A class of canned input producer that uses XML syntax to specify the canned input.

This is a subclass of CannedInput that reads from XML files; this is the concrete class used by CannedInput to accomplish its tasks.


Constructor & Destructor Documentation

XMLCannedInput::XMLCannedInput const string &    filename,
istream &    is
 

Initializes the XMLTokenizer member variable with the given input stream.

If the next token is XMLTokenizer::END, the input stream is empty and an exception is thrown. If this test is passed, it checks to make sure the file starts with an tag before returning. If the file doesn't start with an tag, an exception is thrown.

00055   : CannedInput(filename), t(is)
00056 {
00057   // If EOF immediately, stop.
00058   if (t.next_token() == XMLTokenizer::END)
00059     throw runtime_error("file is empty");
00060 
00061   if (t.curr_token != XMLTokenizer::OPEN ||
00062       t.curr_name != "input" ||
00063       t.next_token() != XMLTokenizer::CLOSE) {
00064     throw runtime_error("Canned input file does not start with <input> tag.");
00065   }
00066 }  


Member Function Documentation

bool XMLCannedInput::execute_one_event Drawing   drawing [virtual]
 

Executes one event from the XML input; most work is done here.

In a loop, it reads the next token from the XMLTokenizer, and then takes one of several actions. If the token is one of END, ERROR, TEXT, or a value not covered by other cases, an error is printed to cerr and the function returns false. If the next token is ETAG, it checks to make sure it matches the opening tag, then returns false. If the token is OPEN, then it checks the contents of the command against the possible commands. It executes the command using Drawing member functions on the parameter it's passed, then sets a timer in drawing's canvas so that the next event will be read.

Implements CannedInput.

00083 {
00084   for (;;) {
00085     switch (t.next_token()) {
00086     case XMLTokenizer::END:
00087       cerr << "Input file ended before </input> tag" << endl;
00088       return false;
00089     case XMLTokenizer::ERROR:
00090       cerr << filename << ":" << t.get_line_number() << ":"
00091            << t.curr_text;
00092       cerr << "  Stopped reading input file." << endl;
00093       return false;
00094     case XMLTokenizer::OPEN: {
00095       string command = t.curr_name;
00096       // do various things depending on command
00097       if (command == "toolbar:click" || command == "click") {
00098         if (t.next_token() != XMLTokenizer::ATTR ||
00099             t.curr_name != "position") {
00100           cerr << filename << ":" << t.get_line_number() << ":"
00101                << (t.curr_token == XMLTokenizer::ERROR ? t.curr_text :
00102                    string("Expected position attribute"))
00103                << ".  Stopped reading input file." << endl;
00104           return false;
00105         }
00106         Position p;
00107         if (Utilities::from_string(t.curr_text,p)) {
00108           drawing->click(p, command == "toolbar:click");
00109           cout << " clicked " << Utilities::to_string(p)
00110                << (command == "toolbar:click" ? " in tool bar." : ".")
00111                << endl;
00112           drawing->get_canvas()->StartTimer(10);
00113         } else {
00114           cerr << filename << ":" << t.get_line_number() << ":"
00115                << "Malformed position"
00116                << ".  Stopped reading input file." << endl;
00117           return false;
00118         }
00119       } else if (command == "sleep") {
00120         if (t.next_token() != XMLTokenizer::ATTR || t.curr_name != "seconds") {
00121           cerr << filename << ":" << t.get_line_number() << ":"
00122                << (t.curr_token == XMLTokenizer::ERROR ? t.curr_text :
00123                    string("Expected seconds attribute"))
00124                << ".  Stopped reading input file." << endl;
00125           return false;
00126         }
00127         int sec;
00128         if (Utilities::from_string(t.curr_text,sec) && sec > 0) {
00129           drawing->get_canvas()->StartTimer(sec*1000);
00130         } else {
00131           cerr << filename << ":" << t.get_line_number() << ":"
00132                << "Seconds must be a positive integer"
00133                << ".  Stopped reading input file." << endl;
00134           return false;
00135         }
00136       } else if (command == "echo") {
00137         if (t.next_token() != XMLTokenizer::ATTR || t.curr_name != "text") {
00138           cerr << filename << ":" << t.get_line_number() << ":"
00139                << (t.curr_token == XMLTokenizer::ERROR ? t.curr_text :
00140                    string("Expected 'text' attribute"))
00141                << ".  Stopped reading input file." << endl;
00142           return false;
00143         }
00144         cout << t.curr_text << endl;
00145         drawing->get_canvas()->StartTimer(10);
00146       } else if (command == "quit") {
00147         Terminate();
00148       } else {
00149         cerr << filename << ":" << t.get_line_number() << ":"
00150              << "Unknown command " << command
00151              << ".  Stopped reading input file." << endl;
00152         return false;
00153       }
00154       // permit /> or ></command>
00155       if (t.next_token() != XMLTokenizer::ECLOSE &&
00156           (t.curr_token != XMLTokenizer::CLOSE ||
00157            t.next_token() != XMLTokenizer::ETAG ||
00158            t.curr_name != command)) {
00159         // We can't return false here, because
00160         // the time has already been set.  Instead,
00161         // we leave an ERROR token in the input:
00162         if (t.curr_token != XMLTokenizer::ERROR) {
00163           t.curr_text = "Expected </" + command + ">";
00164           t.curr_token = XMLTokenizer::ERROR;
00165         }
00166         t.save_token();
00167       }
00168       return true;
00169     }
00170     case XMLTokenizer::ETAG:
00171       if (t.curr_name != "input") {
00172         cerr << filename << ":" << t.get_line_number() << ":"
00173              << "<input> tag matched with </" << t.curr_name << "> end tag."
00174              << "  Stopped reading input file." << endl;
00175         return false;
00176       }
00177       if (t.next_token() != XMLTokenizer::END) {
00178         cerr << filename << ":" << t.get_line_number() << ":"
00179              << "Extra text after </input> tag." << endl;
00180       }
00181       return false;
00182     case XMLTokenizer::TEXT:
00183       cerr << filename << ":" << t.get_line_number() << ":"
00184            << "Stray text in input file.  Stopped reading input file." << endl;
00185       return false;
00186     default:
00187       cerr << filename << ":" << t.get_line_number() << ":"
00188            << "Internal error 1-" << t.curr_token 
00189            << ".  Stopped reading input file." << endl;
00190       return false;
00191     }
00192   }
00193 }


Member Data Documentation

XMLTokenizer XMLCannedInput::t [private]
 


The documentation for this class was generated from the following file:
Generated on Fri Nov 8 10:52:33 2002 for Draw by doxygen1.2.17