Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages | Examples

ArArgumentBuilder.cpp

00001 /*
00002 MobileRobots Advanced Robotics Interface for Applications (ARIA)
00003 Copyright (C) 2004, 2005 ActivMedia Robotics LLC
00004 Copyright (C) 2006, 2007 MobileRobots Inc.
00005 
00006      This program is free software; you can redistribute it and/or modify
00007      it under the terms of the GNU General Public License as published by
00008      the Free Software Foundation; either version 2 of the License, or
00009      (at your option) any later version.
00010 
00011      This program is distributed in the hope that it will be useful,
00012      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014      GNU General Public License for more details.
00015 
00016      You should have received a copy of the GNU General Public License
00017      along with this program; if not, write to the Free Software
00018      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 If you wish to redistribute ARIA under different terms, contact 
00021 MobileRobots for information about a commercial version of ARIA at 
00022 robots@mobilerobots.com or 
00023 MobileRobots Inc, 19 Columbia Drive, Amherst, NH 03031; 800-639-9481
00024 */
00025 
00026 #include "ArExport.h"
00027 #include "ariaOSDef.h"
00028 #include "ArArgumentBuilder.h"
00029 #include "ArLog.h"
00030 #include <stdarg.h>
00031 #include <ctype.h>
00032 #include <math.h>
00033 
00040 AREXPORT ArArgumentBuilder::ArArgumentBuilder(size_t argvLen, 
00041                           char extraSpaceChar)
00042 {
00043   myArgc = 0;
00044   myOrigArgc = 0;
00045   myArgvLen = argvLen;
00046   myArgv = new char *[myArgvLen];
00047   myFirstAdd = true;
00048   myExtraSpace = extraSpaceChar;
00049 }
00050 
00051 AREXPORT ArArgumentBuilder::ArArgumentBuilder(const ArArgumentBuilder & builder)
00052 {
00053   size_t i;
00054   myFullString = builder.myFullString;
00055   myExtraString = builder.myExtraString;
00056   myArgc = builder.getArgc();
00057   myArgvLen = builder.getArgvLen();
00058   myOrigArgc = myArgc;
00059   myArgv = new char *[myArgvLen];
00060   for (i = 0; i < myArgc; i++)
00061     myArgv[i] = strdup(builder.getArg(i));
00062 }
00063 
00064 AREXPORT ArArgumentBuilder::~ArArgumentBuilder()
00065 {
00066   size_t i;
00067   if (myOrigArgc > 0)
00068   {
00069     for (i = 0; i < myOrigArgc; ++i)
00070       delete[] myArgv[i];
00071   }
00072   delete[] myArgv;
00073 }
00074 
00075 
00076 AREXPORT void ArArgumentBuilder::removeArg(size_t which)
00077 {
00078   size_t i;
00079   char *temp;
00080 
00081   if (which > myArgc - 1)
00082   {
00083     ArLog::log(ArLog::Terse, "ArArgumentBuilder::removeArg: %d is greater than the number of arguments which is %d", which, myArgc);
00084     return;
00085   }
00086 
00087   temp = myArgv[which];
00088   //delete[] myArgv[which]; 
00089   for (i = which; i < myArgc - 1; i++)
00090     myArgv[i] = myArgv[i+1];
00091   myArgc -= 1;
00092   myArgv[i] = temp;
00093   // delete the one off the end
00094 }
00095 
00096 AREXPORT void ArArgumentBuilder::add(const char *str, ...)
00097 {
00098   char buf[2048];
00099   va_list ptr;
00100   va_start(ptr, str);
00101   vsprintf(buf, str, ptr);
00102   internalAdd(buf, -1);
00103   va_end(ptr);
00104 }
00105 
00115 AREXPORT void ArArgumentBuilder::internalAdd(const char *str, int position)
00116 {
00117   char buf[2048];
00118   int i;
00119   int j;
00120   size_t k;
00121   bool findingSpace = true;
00122   int startNonSpace;
00123   int len;
00124   bool addAtEnd;
00125   //size_t startingArgc = getArgc();
00126 
00127   if (position < 0 || (size_t)position > myArgc)
00128     addAtEnd = true;
00129   else
00130     addAtEnd = false;
00131   
00132   strncpy(buf, str, sizeof(buf));
00133   len = strlen(buf);
00134 
00135   // can do whatever you want with the buf now
00136   // first we advance to non-space
00137   for (i = 0; i < len; ++i)
00138   {
00139     if (!isspace(buf[i]) || (myExtraSpace != '\0' && buf[i] == myExtraSpace))
00140       break;
00141   }
00142   // see if we're done
00143   if (i == len)
00144   {
00145     ArLog::log(ArLog::Verbose, "All white space add for argument builder.");
00146     return;
00147   }
00148 
00149 
00150   // walk through the line until we get to the end of the buffer...
00151   // we keep track of if we're looking for white space or non-white...
00152   // if we're looking for white space when we find it we have finished
00153   // one argument, so we toss that into argv, reset pointers and moveon
00154   for (startNonSpace = i; ; ++i)
00155   {
00156     // take out the slash of escaped spaces
00157     if (buf[i] == '\\' && i + 1 < len && buf[i + 1] == ' ')
00158     {
00159       for (j = i; j < len && j != '\0'; j++)
00160       {
00161     buf[j] = buf[j + 1];
00162       }
00163       --len;
00164     }
00165     // if we're not finding space and we see a non space (or the end),
00166     // set us into finding space mode and denote where it started
00167     else if (!findingSpace && 
00168          !(i == len || isspace(buf[i]) || buf[i] == '\0' || 
00169            (myExtraSpace != '\0' && buf[i] == myExtraSpace)))        
00170     {
00171       startNonSpace = i;
00172       findingSpace = true;
00173     }
00174     // if we're finding space, and we see it (or the end), we're at
00175     // the end of one arg, so toss it into the list
00176     else if (findingSpace && 
00177          (i == len || isspace(buf[i]) || buf[i] == '\0' || 
00178           (myExtraSpace != '\0' && buf[i] == myExtraSpace)))
00179     {
00180       // see if we have room in our argvLen
00181       if (myArgc + 1 >= myArgvLen)
00182       {
00183     ArLog::log(ArLog::Terse, "ArArgumentBuilder::Add: could not add argument since argc (%u) has grown beyond the argv given in the conbufuctor (%u)", myArgc, myArgvLen);
00184       }
00185       else
00186       {
00187     // if we're adding at the end just put it there, also put it
00188     // at the end if its too far out
00189     if (addAtEnd)
00190     {
00191       myArgv[myArgc] = new char[i - startNonSpace + 1];
00192       strncpy(myArgv[myArgc], &buf[startNonSpace], i - startNonSpace);
00193       myArgv[myArgc][i - startNonSpace] = '\0';
00194       // add to our full string
00195       // if its not our first add a space (or whatever our space char is)
00196       if (!myFirstAdd && myExtraSpace == '\0')
00197         myFullString += " ";
00198       else if (!myFirstAdd)
00199         myFullString += myExtraSpace;
00200       
00201       myFullString += myArgv[myArgc];
00202       myFirstAdd = false;
00203       
00204       myArgc++;
00205       myOrigArgc = myArgc;
00206     }
00207         // otherwise stick it where we wanted it if we can or just 
00208     else
00209     {
00210       // first move things down
00211       for (k = myArgc + 1; k > (size_t)position; k--)
00212       {
00213         myArgv[k] = myArgv[k - 1];
00214       }
00215       myArgc++;
00216       myOrigArgc = myArgc;
00217 
00218       myArgv[position] = new char[i - startNonSpace + 1];
00219       strncpy(myArgv[position], &buf[startNonSpace], i - startNonSpace);
00220       myArgv[position][i - startNonSpace] = '\0';
00221       position++;
00222       // now rebuild the full string
00223       myFullString = "";
00224       for (k = 0; k < myArgc; k++)
00225       {
00226         myFullString += myArgv[k];
00227         myFullString += " ";
00228       }
00229       myFirstAdd = false;
00230     }
00231 
00232       }
00233       findingSpace = false;
00234     }
00235     // if we're at the end or its a null, we're at the end of the buf
00236     if (i == len || buf[i] == '\0')
00237       break;
00238   }
00239 }
00240 
00248 AREXPORT void ArArgumentBuilder::addPlain(const char *str, int position)
00249 {
00250   internalAdd(str, position);
00251 }
00252 
00260 AREXPORT void ArArgumentBuilder::addStrings(char **argv, int argc,
00261                         int position)
00262 {
00263   addStrings(argc, argv, position);
00264 }
00265 
00273 AREXPORT void ArArgumentBuilder::addStrings(int argc, char **argv, 
00274                         int position)
00275 {
00276   int i;
00277   for (i = 0; i < argc; i++)
00278     add(argv[i], position + i);
00279 }
00280 
00288 AREXPORT void ArArgumentBuilder::addStringsAsIs(int argc, char **argv, 
00289                         int position)
00290 {
00291   int i;
00292   for (i = 0; i < argc; i++)
00293     internalAddAsIs(argv[i], position + i);
00294 }
00295 
00303 AREXPORT void ArArgumentBuilder::addPlainAsIs(const char *str, int position)
00304 {
00305   internalAddAsIs(str, position);
00306 }
00307 
00308 AREXPORT void ArArgumentBuilder::internalAddAsIs(const char *str, int position)
00309 {
00310   myArgv[myArgc] = new char[strlen(str) + 1];
00311   strcpy(myArgv[myArgc], str);
00312   myArgv[myArgc][strlen(str)] = '\0';
00313 
00314   // add to our full string
00315   // if its not our first add a space (or whatever our space char is)
00316   if (!myFirstAdd && myExtraSpace == '\0')
00317     myFullString += " ";
00318   else if (!myFirstAdd)
00319     myFullString += myExtraSpace;
00320   
00321   myFullString += myArgv[myArgc];
00322   myFirstAdd = false;
00323   
00324   myArgc++;
00325   myOrigArgc = myArgc;
00326 }
00327 
00328 AREXPORT size_t ArArgumentBuilder::getArgc(void) const
00329 {
00330   return myArgc;
00331 }
00332 
00333 AREXPORT char** ArArgumentBuilder::getArgv(void) const
00334 {
00335   return myArgv;
00336 }
00337 
00338 AREXPORT const char *ArArgumentBuilder::getFullString(void) const
00339 {
00340   return myFullString.c_str();
00341 }
00342 
00343 AREXPORT const char *ArArgumentBuilder::getExtraString(void) const
00344 {
00345   return myExtraString.c_str();
00346 }
00347 
00348 AREXPORT void ArArgumentBuilder::setExtraString(const char *str)
00349 {
00350   myExtraString = str;
00351 }
00352 
00353 AREXPORT void ArArgumentBuilder::setFullString(const char *str)
00354 {
00355   myFullString = str;
00356 }
00357 
00358 AREXPORT const char* ArArgumentBuilder::getArg(size_t whichArg) const
00359 {
00360   if (whichArg >= myArgc)
00361     return NULL;
00362   else
00363     return myArgv[whichArg];
00364 }
00365 
00366 AREXPORT void ArArgumentBuilder::log(void) const
00367 {
00368   size_t i;
00369   ArLog::log(ArLog::Terse, "Num arguments: %d", myArgc);
00370   for (i = 0; i < myArgc; ++i)
00371     ArLog::log(ArLog::Terse, "Arg %d: %s", i, myArgv[i]);
00372 }
00373 
00374 AREXPORT bool ArArgumentBuilder::isArgBool(size_t whichArg) const
00375 {
00376   if (whichArg > myArgc || getArg(whichArg) == NULL)
00377     return false;
00378 
00379   if (strcasecmp(getArg(whichArg), "true") == 0 || 
00380       strcasecmp(getArg(whichArg), "1") == 0 || 
00381       strcasecmp(getArg(whichArg), "false") == 0 || 
00382       strcasecmp(getArg(whichArg), "0") == 0)
00383     return true;
00384   else
00385     return false;
00386 }
00387 
00388 AREXPORT bool ArArgumentBuilder::getArgBool(size_t whichArg) const
00389 {
00390   if (whichArg > myArgc || getArg(whichArg) == NULL)
00391     return false;
00392 
00393   if (strcasecmp(getArg(whichArg), "true") == 0 || 
00394       strcasecmp(getArg(whichArg), "1") == 0)
00395     return true;
00396   else
00397     return false;
00398 }
00399 
00400 AREXPORT bool ArArgumentBuilder::isArgInt(size_t whichArg) const
00401 {
00402   const char *str;
00403   int ret;
00404   char *endPtr;
00405   if (whichArg > myArgc || getArg(whichArg) == NULL)
00406     return false;
00407 
00408   str = getArg(whichArg);
00409   ret = strtol(str, &endPtr, 10);
00410   if (endPtr[0] == '\0' && endPtr != str)
00411     return true;
00412   else
00413     return false;
00414 }
00415 
00416 AREXPORT int ArArgumentBuilder::getArgInt(size_t whichArg) const
00417 {
00418   const char *str;
00419   int ret;
00420   char *endPtr;
00421   if (whichArg > myArgc || getArg(whichArg) == NULL)
00422     return 0;
00423 
00424   str = getArg(whichArg);
00425   ret = strtol(str, &endPtr, 10);
00426   if (endPtr[0] == '\0' && endPtr != str)
00427     return ret;
00428   else
00429     return 0;
00430 }
00431 
00432 AREXPORT bool ArArgumentBuilder::isArgDouble(size_t whichArg) const
00433 {
00434   const char *str;
00435   double ret;
00436   char *endPtr;
00437   if (whichArg > myArgc || getArg(whichArg) == NULL)
00438     return false;
00439 
00440   str = getArg(whichArg);
00441   if (strcmp(str, "-INF") == 0)
00442   {
00443     return true;
00444   }
00445   else if (strcmp(str, "INF") == 0)
00446   {
00447     return true;
00448   }
00449   else
00450   {
00451     ret = strtod(str, &endPtr);
00452     if (endPtr[0] == '\0' && endPtr != str)
00453       return true;
00454     else
00455       return false;
00456   }
00457 
00458 }
00459 
00460 AREXPORT double ArArgumentBuilder::getArgDouble(size_t whichArg) const
00461 {
00462   const char *str;
00463   double ret;
00464   char *endPtr;
00465   if (whichArg > myArgc || getArg(whichArg) == NULL)
00466     return 0;
00467 
00468   str = getArg(whichArg);
00469   if (strcmp(str, "-INF") == 0)
00470   {
00471     ret = -HUGE_VAL;
00472     return ret;
00473   }
00474   else if (strcmp(str, "INF") == 0)
00475   {
00476     ret = HUGE_VAL;
00477     return ret;
00478   }
00479   else
00480   {  
00481     ret = strtod(str, &endPtr);
00482     if (endPtr[0] == '\0' && endPtr != str)
00483       return ret;
00484     else
00485       return 0;
00486   }
00487 }
00488 
00489 AREXPORT void ArArgumentBuilder::compressQuoted(bool stripQuotationMarks)
00490 {
00491   size_t argLen;
00492   size_t i;
00493   std::string myNewArg;
00494 
00495   for (i = 0; i < myArgc; i++)
00496   {
00497     argLen = strlen(myArgv[i]);
00498     if (stripQuotationMarks && argLen >= 2 && 
00499     myArgv[i][0] == '"' && myArgv[i][argLen - 1] == '"')
00500     {
00501       myNewArg = &myArgv[i][1];
00502       myNewArg[myNewArg.size() - 1] = '\0';
00503       delete myArgv[i];
00504       // but replacing ourself with the new arg
00505       myArgv[i] = strdup(myNewArg.c_str());
00506       continue;
00507     }
00508     // if this arg begins with a quote but doesn't end with one
00509     if (argLen >= 2 && myArgv[i][0] == '"' && myArgv[i][argLen - 1] != '"')
00510     {
00511       // start the new value for this arg, if stripping quotations
00512       // then start after the quote
00513       if (stripQuotationMarks)
00514     myNewArg = &myArgv[i][1];
00515       else
00516     myNewArg = myArgv[i];
00517 
00518       bool isEndQuoteFound = false;
00519 
00520       // now while the end char of the next args isn't the end of our
00521       // start quote we toss things into this arg
00522       while ((i + 1 < myArgc) && !isEndQuoteFound) {
00523           
00524         int nextArgLen = strlen(myArgv[i+1]);
00525 
00526         // Check whether the next arg contains the ending quote...
00527         if ((nextArgLen > 0) &&
00528         (myArgv[i+1][nextArgLen - 1] == '"')) 
00529     {
00530           isEndQuoteFound = true;
00531         }
00532     
00533         // Concatenate the next arg to this one...
00534         myNewArg += " ";
00535         myNewArg += myArgv[i+1];
00536     // if we are striping quotes off then replace the quote
00537     if (stripQuotationMarks && myNewArg.size() > 0 && isEndQuoteFound)
00538       myNewArg[myNewArg.size() - 1] = '\0';
00539         // removing those next args
00540         removeArg(i+1);
00541         // and ourself
00542         delete myArgv[i];
00543 
00544         // but replacing ourself with the new arg
00545         myArgv[i] = strdup(myNewArg.c_str());
00546       }
00547     }
00548   }
00549 }

Generated on Tue Feb 20 10:51:38 2007 for Aria by  doxygen 1.4.0