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

ArArgumentBuilder.cpp

00001 /*
00002 ActivMedia Robotics Interface for Applications (ARIA)
00003 Copyright (C) 2004,2005 ActivMedia Robotics, LLC
00004 
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 ActivMedia Robotics for information about a commercial version of ARIA at 
00022 robots@activmedia.com or 
00023 ActivMedia Robotics, 19 Columbia Drive, Amherst, NH 03031; 800-639-9481
00024 
00025 */
00026 
00027 #include "ArExport.h"
00028 #include "ariaOSDef.h"
00029 #include "ArArgumentBuilder.h"
00030 #include "ArLog.h"
00031 #include <stdarg.h>
00032 #include <ctype.h>
00033 #include <math.h>
00034 
00035 ArArgumentBuilder::ArArgumentBuilder(size_t argvLen)
00036 {
00037   myArgc = 0;
00038   myOrigArgc = 0;
00039   myArgvLen = argvLen;
00040   myArgv = new char *[myArgvLen];
00041   myFirstAdd = true;
00042 }
00043 
00044 ArArgumentBuilder::ArArgumentBuilder(const ArArgumentBuilder & builder)
00045 {
00046   size_t i;
00047   myFullString = builder.myFullString;
00048   myExtraString = builder.myExtraString;
00049   myArgc = builder.getArgc();
00050   myArgvLen = builder.getArgvLen();
00051   myOrigArgc = myArgc;
00052   myArgv = new char *[myArgvLen];
00053   for (i = 0; i < myArgc; i++)
00054     myArgv[i] = strdup(builder.getArg(i));
00055 }
00056 
00057 ArArgumentBuilder::~ArArgumentBuilder()
00058 {
00059   size_t i;
00060   if (myOrigArgc > 0)
00061   {
00062     for (i = 0; i < myOrigArgc; ++i)
00063       delete[] myArgv[i];
00064   }
00065   delete[] myArgv;
00066 }
00067 
00068 
00069 void ArArgumentBuilder::removeArg(size_t which)
00070 {
00071   size_t i;
00072   char *temp;
00073 
00074   if (which > myArgc - 1)
00075   {
00076     ArLog::log(ArLog::Terse, "ArArgumentBuilder::removeArg: %d is greater than the number of arguments which is %d", which, myArgc);
00077     return;
00078   }
00079 
00080   temp = myArgv[which];
00081   //delete[] myArgv[which]; 
00082   for (i = which; i < myArgc - 1; i++)
00083     myArgv[i] = myArgv[i+1];
00084   myArgc -= 1;
00085   myArgv[i] = temp;
00086   // delete the one off the end
00087 }
00088 
00089 void ArArgumentBuilder::add(const char *str, ...)
00090 {
00091   char buf[2048];
00092   va_list ptr;
00093   va_start(ptr, str);
00094   vsprintf(buf, str, ptr);
00095   internalAdd(buf, -1);
00096   va_end(ptr);
00097 }
00098 
00108 void ArArgumentBuilder::internalAdd(const char *str, int position)
00109 {
00110   char buf[2048];
00111   int i;
00112   int j;
00113   size_t k;
00114   bool findingSpace = true;
00115   int startNonSpace;
00116   int len;
00117   bool addAtEnd;
00118   //size_t startingArgc = getArgc();
00119 
00120   if (position < 0 || (size_t)position > myArgc)
00121     addAtEnd = true;
00122   else
00123     addAtEnd = false;
00124   
00125   strncpy(buf, str, sizeof(buf));
00126   len = strlen(buf);
00127 
00128   // can do whatever you want with the buf now
00129   // first we advance to non-space
00130   for (i = 0; i < len; ++i)
00131   {
00132     if (!isspace(buf[i]))
00133       break;
00134   }
00135   // see if we're done
00136   if (i == len)
00137   {
00138     ArLog::log(ArLog::Verbose, "All white space add for argument builder.");
00139     return;
00140   }
00141 
00142 
00143   // walk through the line until we get to the end of the buffer...
00144   // we keep track of if we're looking for white space or non-white...
00145   // if we're looking for white space when we find it we have finished
00146   // one argument, so we toss that into argv, reset pointers and moveon
00147   for (startNonSpace = i; ; ++i)
00148   {
00149     // take out the slash of escaped spaces
00150     if (buf[i] == '\\' && i + 1 < len && buf[i + 1] == ' ')
00151     {
00152       for (j = i; j < len && j != '\0'; j++)
00153       {
00154         buf[j] = buf[j + 1];
00155       }
00156       --len;
00157     }
00158     // if we're not finding space and we see a non space (or the end),
00159     // set us into finding space mode and denote where it started
00160     else if (!findingSpace && 
00161              !(i == len || isspace(buf[i]) || buf[i] == '\0'))
00162     {
00163       startNonSpace = i;
00164       findingSpace = true;
00165     }
00166     // if we're finding space, and we see it (or the end), we're at
00167     // the end of one arg, so toss it into the list
00168     else if (findingSpace && 
00169              (i == len || isspace(buf[i]) || buf[i] == '\0'))
00170     {
00171       // see if we have room in our argvLen
00172       if (myArgc + 1 >= myArgvLen)
00173       {
00174         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);
00175       }
00176       else
00177       {
00178         // if we're adding at the end just put it there, also put it
00179         // at the end if its too far out
00180         if (addAtEnd)
00181         {
00182           myArgv[myArgc] = new char[i - startNonSpace + 1];
00183           strncpy(myArgv[myArgc], &buf[startNonSpace], i - startNonSpace);
00184           myArgv[myArgc][i - startNonSpace] = '\0';
00185           // add to our full string
00186           // if its not our first add a space
00187           if (!myFirstAdd)
00188             myFullString += " ";
00189           
00190           myFullString += myArgv[myArgc];
00191           myFirstAdd = false;
00192           
00193           myArgc++;
00194           myOrigArgc = myArgc;
00195         }
00196         // otherwise stick it where we wanted it if we can or just 
00197         else
00198         {
00199           // first move things down
00200           for (k = myArgc + 1; k > (size_t)position; k--)
00201           {
00202             myArgv[k] = myArgv[k - 1];
00203           }
00204           myArgc++;
00205           myOrigArgc = myArgc;
00206 
00207           myArgv[position] = new char[i - startNonSpace + 1];
00208           strncpy(myArgv[position], &buf[startNonSpace], i - startNonSpace);
00209           myArgv[position][i - startNonSpace] = '\0';
00210           position++;
00211           // now rebuild the full string
00212           myFullString = "";
00213           for (k = 0; k < myArgc; k++)
00214           {
00215             myFullString += myArgv[k];
00216             myFullString += " ";
00217           }
00218           myFirstAdd = false;
00219         }
00220 
00221       }
00222       findingSpace = false;
00223     }
00224     // if we're at the end or its a null, we're at the end of the buf
00225     if (i == len || buf[i] == '\0')
00226       break;
00227   }
00228 }
00229 
00237 void ArArgumentBuilder::addPlain(const char *str, int position)
00238 {
00239   internalAdd(str, position);
00240 }
00241 
00249 void ArArgumentBuilder::addStrings(char **argv, int argc,
00250                                             int position)
00251 {
00252   addStrings(argc, argv, position);
00253 }
00254 
00262 void ArArgumentBuilder::addStrings(int argc, char **argv, 
00263                                             int position)
00264 {
00265   int i;
00266   for (i = 0; i < argc; i++)
00267     add(argv[i], position + i);
00268 }
00269 
00270 size_t ArArgumentBuilder::getArgc(void) const
00271 {
00272   return myArgc;
00273 }
00274 
00275 char** ArArgumentBuilder::getArgv(void) const
00276 {
00277   return myArgv;
00278 }
00279 
00280 const char *ArArgumentBuilder::getFullString(void) const
00281 {
00282   return myFullString.c_str();
00283 }
00284 
00285 const char *ArArgumentBuilder::getExtraString(void) const
00286 {
00287   return myExtraString.c_str();
00288 }
00289 
00290 void ArArgumentBuilder::setExtraString(const char *str)
00291 {
00292   myExtraString = str;
00293 }
00294 
00295 void ArArgumentBuilder::setFullString(const char *str)
00296 {
00297   myFullString = str;
00298 }
00299 
00300 const char* ArArgumentBuilder::getArg(size_t whichArg) const
00301 {
00302   if (whichArg >= myArgc)
00303     return NULL;
00304   else
00305     return myArgv[whichArg];
00306 }
00307 
00308 void ArArgumentBuilder::log(void) const
00309 {
00310   size_t i;
00311   ArLog::log(ArLog::Terse, "Num arguments: %d", myArgc);
00312   for (i = 0; i < myArgc; ++i)
00313     ArLog::log(ArLog::Terse, "Arg %d: %s", i, myArgv[i]);
00314 }
00315 
00316 bool ArArgumentBuilder::isArgBool(size_t whichArg) const
00317 {
00318   if (whichArg > myArgc || getArg(whichArg) == NULL)
00319     return false;
00320 
00321   if (strcasecmp(getArg(whichArg), "true") == 0 || 
00322       strcasecmp(getArg(whichArg), "1") == 0 || 
00323       strcasecmp(getArg(whichArg), "false") == 0 || 
00324       strcasecmp(getArg(whichArg), "0") == 0)
00325     return true;
00326   else
00327     return false;
00328 }
00329 
00330 bool ArArgumentBuilder::getArgBool(size_t whichArg) const
00331 {
00332   if (whichArg > myArgc || getArg(whichArg) == NULL)
00333     return false;
00334 
00335   if (strcasecmp(getArg(whichArg), "true") == 0 || 
00336       strcasecmp(getArg(whichArg), "1") == 0)
00337     return true;
00338   else
00339     return false;
00340 }
00341 
00342 bool ArArgumentBuilder::isArgInt(size_t whichArg) const
00343 {
00344   const char *str;
00345   int ret;
00346   char *endPtr;
00347   if (whichArg > myArgc || getArg(whichArg) == NULL)
00348     return false;
00349 
00350   str = getArg(whichArg);
00351   ret = strtol(str, &endPtr, 10);
00352   if (endPtr[0] == '\0' && endPtr != str)
00353     return true;
00354   else
00355     return false;
00356 }
00357 
00358 int ArArgumentBuilder::getArgInt(size_t whichArg) const
00359 {
00360   const char *str;
00361   int ret;
00362   char *endPtr;
00363   if (whichArg > myArgc || getArg(whichArg) == NULL)
00364     return 0;
00365 
00366   str = getArg(whichArg);
00367   ret = strtol(str, &endPtr, 10);
00368   if (endPtr[0] == '\0' && endPtr != str)
00369     return ret;
00370   else
00371     return 0;
00372 }
00373 
00374 bool ArArgumentBuilder::isArgDouble(size_t whichArg) const
00375 {
00376   const char *str;
00377   double ret;
00378   char *endPtr;
00379   if (whichArg > myArgc || getArg(whichArg) == NULL)
00380     return false;
00381 
00382   str = getArg(whichArg);
00383   if (strcmp(str, "-INF") == 0)
00384   {
00385         return true;
00386   }
00387   else if (strcmp(str, "INF") == 0)
00388   {
00389         return true;
00390   }
00391   else
00392   {
00393     ret = strtod(str, &endPtr);
00394     if (endPtr[0] == '\0' && endPtr != str)
00395       return true;
00396     else
00397       return false;
00398   }
00399 
00400 }
00401 
00402 double ArArgumentBuilder::getArgDouble(size_t whichArg) const
00403 {
00404   const char *str;
00405   double ret;
00406   char *endPtr;
00407   if (whichArg > myArgc || getArg(whichArg) == NULL)
00408     return 0;
00409 
00410   str = getArg(whichArg);
00411   if (strcmp(str, "-INF") == 0)
00412   {
00413         ret = -HUGE_VAL;
00414         return ret;
00415   }
00416   else if (strcmp(str, "INF") == 0)
00417   {
00418         ret = HUGE_VAL;
00419         return ret;
00420   }
00421   else
00422   {  
00423         ret = strtod(str, &endPtr);
00424     if (endPtr[0] == '\0' && endPtr != str)
00425       return ret;
00426     else
00427       return 0;
00428   }
00429 }
00430 
00431 void ArArgumentBuilder::compressQuoted(bool stripQuotationMarks)
00432 {
00433   size_t argLen;
00434   size_t i;
00435   std::string myNewArg;
00436 
00437   for (i = 0; i < myArgc; i++)
00438   {
00439     argLen = strlen(myArgv[i]);
00440     if (stripQuotationMarks && argLen >= 2 && 
00441         myArgv[i][0] == '"' && myArgv[i][argLen - 1] == '"')
00442     {
00443       myNewArg = &myArgv[i][1];
00444       myNewArg[myNewArg.size() - 1] = '\0';
00445       delete myArgv[i];
00446       // but replacing ourself with the new arg
00447       myArgv[i] = strdup(myNewArg.c_str());
00448       continue;
00449     }
00450     // if this arg begins with a quote but doesn't end with one
00451     if (argLen >= 2 && myArgv[i][0] == '"' && myArgv[i][argLen - 1] != '"')
00452     {
00453       // start the new value for this arg, if stripping quotations
00454       // then start after the quote
00455       if (stripQuotationMarks)
00456         myNewArg = &myArgv[i][1];
00457       else
00458         myNewArg = myArgv[i];
00459 
00460       bool isEndQuoteFound = false;
00461 
00462       // now while the end char of the next args isn't the end of our
00463       // start quote we toss things into this arg
00464       while ((i + 1 < myArgc) && !isEndQuoteFound) {
00465           
00466         int nextArgLen = strlen(myArgv[i+1]);
00467 
00468         // Check whether the next arg contains the ending quote...
00469         if ((nextArgLen > 0) &&
00470             (myArgv[i+1][nextArgLen - 1] == '"')) 
00471         {
00472               isEndQuoteFound = true;
00473         }
00474     
00475         // Concatenate the next arg to this one...
00476         myNewArg += " ";
00477         myNewArg += myArgv[i+1];
00478         // if we are striping quotes off then replace the quote
00479         if (stripQuotationMarks && myNewArg.size() > 0 && isEndQuoteFound)
00480           myNewArg[myNewArg.size() - 1] = '\0';
00481         // removing those next args
00482         removeArg(i+1);
00483         // and ourself
00484         delete myArgv[i];
00485 
00486         // but replacing ourself with the new arg
00487         myArgv[i] = strdup(myNewArg.c_str());
00488       }
00489     }
00490   }
00491 }

Generated on Wed Oct 19 12:56:34 2005 for Aria by  doxygen 1.4.0