3 * wxbDataParser, class that receives and analyses data
5 * Nicolas Boichat, April-July 2004
10 Copyright (C) 2004-2006 Kern Sibbald
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License
14 version 2 as amended with additional clauses defined in the
15 file LICENSE in the main source directory.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 the file LICENSE for additional details.
24 /* Windows debug builds set _DEBUG which is used by wxWidgets to select their
25 * debug memory allocator. Unfortunately it conflicts with Bacula's SmartAlloc.
26 * So we turn _DEBUG off since we aren't interested in things it enables.
35 #include "wxbmainframe.h"
39 #include "wxbtableparser.h"
41 /* A macro named Yield is defined under MinGW */
44 bool wxbUtils::inited = false;
46 wxString wxbUtils::ConvertToPrintable(wxString& str) {
47 /* FIXME : Unicode support should be added to fix this problem */
48 #if (wxUSE_UNICODE == 0) && __WXGTK20__
50 /* Convert the string to something printable without unicode */
51 for (unsigned int i = 0; i < strnew.Length(); i++) {
52 /* If the character is not ASCII, print a ? */
53 if (((unsigned char)strnew[i] > (unsigned char)127)) {
63 /* Sleeps during milliseconds (wrapper for wxUsleep (2.4) or wxMilliSleep (2.6)) */
64 void wxbUtils::MilliSleep(unsigned long milliseconds) {
65 #if wxCHECK_VERSION(2, 6, 0)
66 ::wxMilliSleep(milliseconds);
68 ::wxUsleep(milliseconds);
73 void wxbUtils::Init() {
78 void wxbUtils::Reset() {
82 /* Parse a table in tableParser */
83 wxbTableParser* wxbUtils::CreateAndWaitForParser(wxString cmd) {
84 wxbTableParser* tableParser = new wxbTableParser();
86 wxbMainFrame::GetInstance()->Send(cmd);
88 //time_t base = wxDateTime::Now().GetTicks();
89 while (!tableParser->hasFinished()) {
90 //innerThread->Yield();
91 wxTheApp->Yield(true);
92 wxbUtils::MilliSleep(100);
93 //if (base+15 < wxDateTime::Now().GetTicks()) break;
98 /* Run a command, and waits until prompt result is fully received,
99 * if keepresults is true, returns a valid pointer to a wxbPromptParser
100 * containing the data. */
101 wxbPromptParser* wxbUtils::WaitForPrompt(wxString cmd, bool keepresults) {
102 wxbPromptParser* promptParser = new wxbPromptParser();
104 wxbMainFrame::GetInstance()->Send(cmd);
106 //time_t base = wxDateTime::Now().GetTicks();
107 while (!promptParser->hasFinished()) {
108 //innerThread->Yield();
109 wxTheApp->Yield(true);
110 wxbUtils::MilliSleep(100);
111 //if (base+15 < wxDateTime::Now().GetTicks()) break;
123 /* Run a command, and waits until result is fully received. */
124 wxbDataTokenizer* wxbUtils::WaitForEnd(wxString cmd, bool keepresults, bool linebyline) {
125 wxbDataTokenizer* datatokenizer = new wxbDataTokenizer(linebyline);
127 wxbMainFrame::GetInstance()->Send(cmd);
129 //wxbMainFrame::GetInstance()->Print("(<WFE)", CS_DEBUG);
131 //time_t base = wxDateTime::Now().GetTicks();
132 while (!datatokenizer->hasFinished()) {
133 //innerThread->Yield();
134 wxTheApp->Yield(true);
135 wxbUtils::MilliSleep(100);
136 //if (base+15 < wxDateTime::Now().GetTicks()) break;
139 //wxbMainFrame::GetInstance()->Print("(>WFE)", CS_DEBUG);
142 return datatokenizer;
145 delete datatokenizer;
151 /* Creates a new wxbDataParser, and register it in wxbMainFrame */
152 wxbDataParser::wxbDataParser(bool lineanalysis) {
153 wxbMainFrame::GetInstance()->Register(this);
154 this->lineanalysis = lineanalysis;
158 /* Destroy a wxbDataParser, and unregister it in wxbMainFrame */
159 wxbDataParser::~wxbDataParser() {
160 wxbMainFrame::GetInstance()->Unregister(this);
164 * Receives director information, forwarded by wxbMainFrame, and sends it
165 * line by line to the virtual function Analyse.
167 bool wxbDataParser::Print(wxString str, int status) {
170 bool allnewline = true;
171 for (unsigned int i = 0; i < str.Length(); i++) {
172 if (!(allnewline = (str.GetChar(i) == '\n')))
177 ret = Analyse(buffer << wxT("\n"), CS_DATA);
179 for (unsigned int i = 1; i < str.Length(); i++) {
180 ret = Analyse(wxT("\n"), status);
184 wxStringTokenizer tkz(str, wxT("\n"),
185 (wxStringTokenizerMode)(wxTOKEN_RET_DELIMS | wxTOKEN_RET_EMPTY | wxTOKEN_RET_EMPTY_ALL));
187 while ( tkz.HasMoreTokens() ) {
188 buffer << tkz.GetNextToken();
189 if (buffer.Length() != 0) {
190 if ((buffer.GetChar(buffer.Length()-1) == '\n') ||
191 (buffer.GetChar(buffer.Length()-1) == '\r')) {
192 ret = Analyse(buffer, status);
199 if (buffer == wxT("$ ")) { // Restore console
200 ret = Analyse(buffer, status);
204 if (status != CS_DATA) {
205 if (buffer.Length() != 0) {
206 ret = Analyse(buffer, CS_DATA);
209 ret = Analyse(wxT(""), status);
213 ret = Analyse(wxString(str), status);
218 /* Creates a new wxbDataTokenizer */
219 wxbDataTokenizer::wxbDataTokenizer(bool linebyline): wxbDataParser(linebyline), wxArrayString() {
223 /* Destroy a wxbDataTokenizer */
224 wxbDataTokenizer::~wxbDataTokenizer() {
229 * Receives director information, forwarded by wxbMainFrame.
231 bool wxbDataTokenizer::Analyse(wxString str, int status) {
232 finished = ((status == CS_END) || (status == CS_PROMPT) || (status == CS_DISCONNECTED));
234 if (str != wxT("")) {
240 /* Returns true if the last signal received was an end signal,
241 * indicating that no more data is available */
242 bool wxbDataTokenizer::hasFinished() {
246 /* Creates a new wxbDataTokenizer */
247 wxbPromptParser::wxbPromptParser(): wxbDataParser(false) {
253 questionStr = wxT("");
256 /* Destroy a wxbDataTokenizer */
257 wxbPromptParser::~wxbPromptParser() {
264 * Receives director information, forwarded by wxbMainFrame.
266 bool wxbPromptParser::Analyse(wxString str, int status) {
267 if (status == CS_DATA) {
268 if (finished || prompt) { /* New question */
276 questionStr = wxT("");
282 if (((i = str.Find(wxT(": "))) > 0) && (str.Mid(0, i).Trim(false).ToLong(&num))) { /* List element */
284 choices = new wxArrayString();
285 choices->Add(wxT("")); /* index 0 is never used by multiple choice questions */
289 if ((long)choices->GetCount() != num) { /* new choice has begun */
291 choices = new wxArrayString();
292 choices->Add(wxT(""), num); /* fill until this number */
296 choices->Add(str.Mid(i+2).RemoveLast());
298 else if (!choices) { /* Introduction, no list received yet */
299 introStr << questionStr;
300 questionStr = wxString(str);
302 else { /* List receveived, get the question now */
303 introStr << questionStr;
304 questionStr = wxString(str);
308 finished = ((status == CS_PROMPT) || (status == CS_END) || (status == CS_DISCONNECTED));
309 if (prompt = ((status == CS_PROMPT) && (questionStr != wxT("$ ")))) { // && (str.Find(": ") == str.Length())
310 if (introStr.Last() == '\n') {
311 introStr.RemoveLast();
313 if ((introStr != wxT("")) && (questionStr == wxT(""))) {
314 questionStr = introStr;
318 if ((!choices) && (questionStr.Find(wxT("(yes/mod/no)")) > -1)) {
319 choices = new wxArrayString();
320 choices->Add(wxT("yes"));
321 choices->Add(wxT("mod"));
322 choices->Add(wxT("no"));
328 else { /* ended or (dis)connected */
334 questionStr = wxT("");
341 /* Returns true if the last signal received was an prompt signal,
342 * indicating that the answer must be sent */
343 bool wxbPromptParser::hasFinished() {
347 /* Returns true if the last message received is a prompt message */
348 bool wxbPromptParser::isPrompt() {
352 /* Returns multiple choice question's introduction */
353 wxString wxbPromptParser::getIntroString() {
357 /* Returns question string */
358 wxString wxbPromptParser::getQuestionString() {
362 /* Returns a wxArrayString containing the indexed choices we have
363 * to answer the question, or NULL if this question is not a multiple
365 wxArrayString* wxbPromptParser::getChoices() {
369 /* Returns true if the expected answer to the choice list is a number,
370 * false if it is a string (for example yes/mod/no). */
371 bool wxbPromptParser::isNumericalChoice() {