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

ariaUtil.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 <sys/types.h>
00030 #include <sys/stat.h>
00031 #include <stdio.h>
00032 #include <string.h>
00033 #include <math.h>
00034 #include <ctype.h>
00035 #ifndef WIN32
00036 #include <sys/time.h>
00037 #include <stdarg.h>
00038 #include <unistd.h>
00039 #endif
00040 
00041 #include "ariaTypedefs.h"
00042 #include "ariaUtil.h"
00043 
00044 #ifdef WIN32
00045 const char *ArUtil::COM1 = "COM1";
00046 const char *ArUtil::COM2 = "COM2";
00047 const char *ArUtil::COM3 = "COM3";
00048 const char *ArUtil::COM4 = "COM4";
00049 #else // ifndef WIN32
00050 const char *ArUtil::COM1 = "/dev/ttyS0";
00051 const char *ArUtil::COM2 = "/dev/ttyS1";
00052 const char *ArUtil::COM3 = "/dev/ttyS2";
00053 const char *ArUtil::COM4 = "/dev/ttyS3";
00054 #endif  // WIN32
00055 
00056 const char *ArUtil::TRUESTRING = "true";
00057 const char *ArUtil::FALSESTRING = "false";
00058 
00076 void ArUtil::sleep(unsigned int ms)
00077 {
00078 #ifdef WIN32
00079   Sleep(ms);
00080 #endif // WIN32
00081 #ifdef linux
00082   if (ms > 10)
00083     ms -= 10;
00084   usleep(ms * 1000);
00085 #endif // linux
00086 
00087 }
00088 
00094 unsigned int ArUtil::getTime(void)
00095 {
00096 #ifdef WIN32
00097   return timeGetTime();
00098 #endif // WIN32
00099 
00100 #ifndef WIN32
00101   struct timeval tv;
00102   gettimeofday(&tv,NULL);
00103   return tv.tv_usec/1000 + (tv.tv_sec % 1000000)*1000;
00104 #endif
00105 }
00106 
00107 /*
00108    Takes a string and splits it into a list of words. It appends the words
00109    to the outList. If there is nothing found, it will not touch the outList.
00110    @param inString the input string to split
00111    @param outList the list in which to store the words that are found
00112 */
00113 /*
00114 void ArUtil::splitString(std::string inString,
00115                                   std::list<std::string> &outList)
00116 {
00117   const char *start, *end;
00118 
00119   // Strip off leading white space
00120   for (end=inString.c_str(); *end && isspace(*end); ++end)
00121     ;
00122   while (*end)
00123   {
00124     // Mark start of the word then find end
00125     for (start=end; *end && !isspace(*end); ++end)
00126       ;
00127     // Store the word
00128     if (*start && ((*end && isspace(*end)) || !*end))
00129       outList.push_back(std::string(start, (int)(end-start)));
00130     for (; *end && isspace(*end); ++end)
00131       ;
00132   }
00133 }
00134 */
00135 #ifdef WIN32
00136 
00141 long ArUtil::sizeFile(std::string fileName)
00142 {
00143   struct _stat buf;
00144 
00145   if (_stat(fileName.c_str(), &buf) < 0)
00146     return(-1);
00147 
00148   if (!(buf.st_mode | _S_IFREG))
00149     return(-1);
00150 
00151   return(buf.st_size);
00152 }
00153 
00158 long ArUtil::sizeFile(const char * fileName)
00159 {
00160   struct _stat buf;
00161 
00162   if (_stat(fileName, &buf) < 0)
00163     return(-1);
00164 
00165   if (!(buf.st_mode | _S_IFREG))
00166     return(-1);
00167 
00168   return(buf.st_size);
00169 }
00170 
00171 #else // WIN32
00172 
00173 long ArUtil::sizeFile(std::string fileName)
00174 {
00175   struct stat buf;
00176 
00177   if (stat(fileName.c_str(), &buf) < 0)
00178   {
00179     perror("stat");
00180     return(-1);
00181   }
00182 
00183   if (!S_ISREG(buf.st_mode))
00184     return(-1);
00185 
00186   return(buf.st_size);
00187 }
00188 
00189 
00194 long ArUtil::sizeFile(const char * fileName)
00195 {
00196   struct stat buf;
00197 
00198   if (stat(fileName, &buf) < 0)
00199   {
00200     perror("stat");
00201     return(-1);
00202   }
00203 
00204   if (!S_ISREG(buf.st_mode))
00205     return(-1);
00206 
00207   return(buf.st_size);
00208 }
00209 
00210 #endif // WIN32
00211 
00216 bool ArUtil::findFile(const char *fileName)
00217 {
00218   FILE *fp;
00219 
00220   if ((fp=fopen(fileName, "r")))
00221   {
00222     fclose(fp);
00223     return(true);
00224   }
00225   else
00226     return(false);
00227 }
00228 
00229 /*
00230    Works for \ and /. Returns true if something was actualy done. Sets
00231    fileOut to be what ever the answer is.
00232    @return true if the path contains a file
00233    @param fileIn input path/fileName
00234    @param fileOut output fileName
00235 */
00236 /*bool ArUtil::stripDir(std::string fileIn, std::string &fileOut)
00237 {
00238   const char *ptr;
00239 
00240   for (ptr=fileIn.c_str(); *ptr; ++ptr)
00241     ;
00242   for (--ptr; (ptr > fileIn.c_str()) && (*ptr != '/') && (*ptr != '\\'); --ptr)
00243     ;
00244   if ((*ptr == '/') || (*ptr == '\\'))
00245   {
00246     fileOut=ptr+1;
00247     return(true);
00248   }
00249   else
00250   {
00251     fileOut=fileIn;
00252     return(false);
00253   }
00254 }
00255 */
00256 /*
00257    Works for \ and /. Returns true if something was actualy done. Sets
00258    fileOut to be what ever the answer is.
00259    @return true if the file contains a path
00260    @param fileIn input path/fileName
00261    @param fileOut output path
00262 */
00263 /*
00264 bool ArUtil::stripFile(std::string fileIn, std::string &fileOut)
00265 {
00266   const char *start, *end;
00267 
00268   for (start=end=fileIn.c_str(); *end; ++end)
00269   {
00270     if ((*end == '/') || (*end == '\\'))
00271     {
00272       start=end;
00273       for (; *end && ((*end == '/') || (*end == '\\')); ++end)
00274         ;
00275     }
00276   }
00277 
00278   if (start < end)
00279   {
00280     fileOut.assign(fileIn, 0, start-fileIn.c_str());
00281     return(true);
00282   }
00283 
00284   fileOut=fileIn;
00285   return(false);
00286 }
00287 */
00288 bool ArUtil::stripQuotes(char *dest, const char *src, size_t destLen)
00289 {
00290   size_t srcLen = strlen(src);
00291   if (destLen < srcLen + 1)
00292   {
00293     ArLog::log(ArLog::Normal, "ArUtil::stripQuotes: destLen isn't long enough to fit copy its %d should be %d", destLen, srcLen + 1);
00294     return false;
00295   }
00296   // if there are no quotes to strip just copy and return
00297   if (srcLen < 2 || 
00298       (src[0] != '"' || src[srcLen - 1] != '"'))
00299   {
00300     strcpy(dest, src);
00301     return true;
00302   }
00303   // we have quotes so chop of the first and last char
00304   strncpy(dest, &src[1], srcLen - 1);
00305   dest[srcLen - 2] = '\0';
00306   return true;
00307 }
00308 
00316 void ArUtil::appendSlash(char *path, size_t pathLength)
00317 {
00318   // first check boundary
00319   size_t len;
00320   len = strlen(path);
00321   if (len > pathLength - 2)
00322     return;
00323 
00324   if (len == 0 || (path[len - 1] != '\\' && path[len - 1] != '/'))
00325   {
00326 #ifdef WIN32
00327     path[len] = '\\';
00328 #else
00329     path[len] = '/';
00330 #endif
00331     path[len + 1] = '\0';
00332   }
00333 }
00334 
00339 void ArUtil::fixSlashes(char *path, size_t pathLength)
00340 {
00341 #ifdef WIN32
00342   fixSlashesBackward(path, pathLength);
00343 #else
00344   fixSlashesForward(path, pathLength);
00345 #endif
00346 }
00347 
00352 void ArUtil::fixSlashesBackward(char *path, size_t pathLength)
00353 {
00354   for (size_t i=0; path[i] != '\0' && i < pathLength; i++)
00355   {
00356     if (path[i] == '/')
00357       path[i]='\\';
00358   }
00359 }
00360 
00365 void ArUtil::fixSlashesForward(char *path, size_t pathLength)
00366 {
00367 
00368   for (size_t i=0; path[i] != '\0' && i < pathLength; i++)
00369   {
00370     if (path[i] == '\\')
00371       path[i]='/';
00372   }
00373 }
00374 
00387 void ArUtil::addDirectories(char *dest, size_t destLength, 
00388                                      const char *baseDir,
00389                                      const char *insideDir)
00390 {
00391   // start it off
00392   strncpy(dest, baseDir, destLength - 1);
00393   // make sure we have a null term
00394   dest[destLength - 1] = '\0';
00395   // toss on that slash
00396   appendSlash(dest, destLength);
00397   // put on the inside dir
00398   strncat(dest, insideDir, destLength - strlen(dest) - 1);
00399   // now toss on that slash
00400   appendSlash(dest, destLength);
00401   // and now fix up all the slashes
00402   fixSlashes(dest, destLength);
00403 }
00404 
00414 int ArUtil::strcmp(std::string str, std::string str2)
00415 {
00416   return ::strcmp(str.c_str(), str2.c_str());
00417 }
00418 
00428 int ArUtil::strcmp(std::string str, const char *str2)
00429 {
00430   return ::strcmp(str.c_str(), str2);
00431 }
00432 
00442 int ArUtil::strcmp(const char *str, std::string str2)
00443 {
00444   return ::strcmp(str, str2.c_str());
00445 }
00446 
00456 int ArUtil::strcmp(const char *str, const char *str2)
00457 {
00458   return ::strcmp(str, str2);
00459 }
00460 
00461 
00470 int ArUtil::strcasecmp(std::string str, std::string str2)
00471 {
00472   return ::strcasecmp(str.c_str(), str2.c_str());
00473 }
00474 
00483 int ArUtil::strcasecmp(std::string str, const char *str2)
00484 {
00485   return ::strcasecmp(str.c_str(), str2);
00486 }
00487 
00496 int ArUtil::strcasecmp(const char *str, std::string str2)
00497 {
00498   return ::strcasecmp(str, str2.c_str());
00499 }
00500 
00509 int ArUtil::strcasecmp(const char *str, const char *str2)
00510 {
00511   return ::strcasecmp(str, str2);
00512 }
00513 
00520 void ArUtil::escapeSpaces(char *dest, const char *src, size_t maxLen)
00521 {
00522   size_t i, adj, len;
00523 
00524   len = strlen(src);
00525   // walk it, when we find one toss in the slash and incr adj so the
00526   // next characters go in the right space
00527   for (i = 0, adj = 0; i < len && i + adj < maxLen; i++)
00528   {
00529     if (src[i] == ' ')
00530     {
00531       dest[i+adj] = '\\';
00532       adj++;
00533     }
00534     dest[i+adj] = src[i];
00535   }
00536   // make sure its null terminated
00537   dest[i+adj] = '\0';
00538 }
00539 
00545 void ArUtil::lower(char *dest, const char *src, size_t maxLen)
00546 {
00547   size_t i;
00548   size_t len;
00549   
00550   len = strlen(src);
00551   for (i = 0; i < len && i < maxLen; i++)
00552     dest[i] = tolower(src[i]);
00553   dest[i] = '\0';
00554 
00555 }
00556 
00557 
00558 bool ArUtil::isOnlyAlphaNumeric(const char *str)
00559 {
00560   unsigned int ui;
00561   unsigned int len;
00562   if (str == NULL)
00563     return true;
00564   for (ui = 0, len = sizeof(str); ui < len; ui++)
00565   {
00566     if (!isalpha(str[ui]) && !isdigit(str[ui]) && str[ui] != '\0')
00567       return false;
00568   }
00569   return true;
00570 }
00571 
00572 
00573 const char *ArUtil::convertBool(int val)
00574 {
00575   if (val)
00576     return TRUESTRING;
00577   else
00578     return FALSESTRING;
00579 }
00580 
00581 double ArUtil::atof(const char *nptr)
00582 {
00583   if (strcasecmp(nptr, "inf") == 0)
00584     return HUGE_VAL;
00585   else if (strcasecmp(nptr, "-inf") == 0)
00586     return -HUGE_VAL;
00587   else
00588         return ::atof(nptr);
00589 }
00590 
00591 void ArUtil::functorPrintf(ArFunctor1<const char *> *functor,
00592                                     char *str, ...)
00593 {
00594   char buf[2048];
00595   va_list ptr;
00596   va_start(ptr, str);
00597   vsprintf(buf, str, ptr);
00598   functor->invoke(buf);
00599   va_end(ptr);
00600 }
00601 
00602 void ArUtil::writeToFile(const char *str, FILE *file)
00603 {
00604   fprintf(file, str);
00605 }
00606 
00607 
00620 bool ArUtil::getStringFromFile(const char *fileName, 
00621                                         char *str, size_t strLen)
00622 {
00623   FILE *strFile;
00624   unsigned int i;
00625 
00626   if ((strFile = fopen(fileName, "r")) != NULL)
00627   {
00628     fgets(str, strLen, strFile);
00629     for (i = 0; i < strLen; i++)
00630     {
00631       if (str[i] == '\r' || str[i] == '\n' || str[i] == '\0')
00632       {
00633         str[i] = '\0';
00634         break;
00635       }
00636     }
00637   }
00638   else
00639   {
00640     str[0] = '\0';
00641     return false;
00642   }
00643   return true;
00644 }
00645 
00664 bool ArUtil::getStringFromRegistry(REGKEY root,
00665                                                    const char *key,
00666                                                    const char *value,
00667                                                    char *str,
00668                                                    int len)
00669 {
00670 #ifndef WIN32
00671   return false;
00672 #else // WIN32
00673 
00674   HKEY hkey;
00675   int err;
00676   int i;
00677   unsigned long numKeys;
00678   unsigned long longestKey;
00679   unsigned long numValues;
00680   unsigned long longestValue;
00681   unsigned long longestDataLength;
00682   char *valueName;
00683   unsigned long valueLength;
00684   unsigned long type;
00685   char *data;
00686   unsigned long dataLength;
00687   HKEY rootKey;
00688 
00689 
00690   switch (root)
00691   {
00692   case REGKEY_CLASSES_ROOT:
00693     rootKey = HKEY_CLASSES_ROOT;
00694     break;
00695   case REGKEY_CURRENT_CONFIG:
00696     rootKey = HKEY_CURRENT_CONFIG;
00697     break;
00698   case REGKEY_CURRENT_USER:
00699     rootKey = HKEY_CURRENT_USER;
00700     break;
00701   case REGKEY_LOCAL_MACHINE:
00702     rootKey = HKEY_LOCAL_MACHINE;
00703     break;
00704   case REGKEY_USERS:
00705     rootKey=HKEY_USERS;
00706     break;
00707   default:
00708     ArLog::log(ArLog::Terse, 
00709                "ArUtil::getStringFromRegistry: Bad root key given.");
00710     return false;
00711   }
00712 
00713 
00714   if ((err = RegOpenKeyEx(rootKey, key, 0, KEY_READ, &hkey)) == ERROR_SUCCESS)
00715   {
00716     //printf("Got a key\n");
00717     if (RegQueryInfoKey(hkey, NULL, NULL, NULL, &numKeys, &longestKey, NULL, 
00718                         &numValues, &longestValue, &longestDataLength, NULL, NULL) == ERROR_SUCCESS)
00719     {
00720         /*
00721       printf("Have %d keys longest is %d, have %d values longest name is %d, longest data is %d\n",
00722              numKeys, longestKey, numValues, longestValue, longestDataLength);
00723         */       
00724       data = new char[longestDataLength+2];
00725       valueName = new char[longestValue+2];
00726       for (i = 0; i < numValues; ++i)
00727       {
00728         dataLength = longestDataLength+1;
00729         valueLength = longestValue+1;
00730         if ((err = RegEnumValue(hkey, i, valueName, &valueLength, NULL, 
00731                                 &type, (unsigned char *)data, &dataLength)) == ERROR_SUCCESS)
00732         {
00733                 //printf("Enumed value %d, name is %s, value is %s\n", i, valueName, data);
00734           if (strcmp(value, valueName) == 0)
00735           {
00736             if (len < dataLength)
00737             {
00738               ArLog::log(ArLog::Terse,"ArUtil::getStringFromRegistry: str passed in not long enough for data.");
00739               delete data;
00740               delete valueName;
00741               return false;
00742             }
00743             strncpy(str, data, len);
00744             delete data;
00745             delete valueName;
00746             return true;
00747           }
00748         }
00749         /*
00750         else
00751                 printf("Couldn't enum value %d cause %d\n",i,  err);
00752                 */
00753             }
00754       delete data;
00755       delete valueName;
00756     }
00757         /*
00758     else
00759       printf("QueryInfoKey failed\n");
00760           */
00761   }
00762   /*
00763   else
00764     printf("No key %d\n", err);
00765   */
00766   return false;
00767 #endif
00768 }
00769 
00770 ArRunningAverage::ArRunningAverage(size_t numToAverage)
00771 {
00772   myNumToAverage = numToAverage;
00773   myTotal = 0;
00774   myNum = 0;
00775 }
00776 
00777 ArRunningAverage::~ArRunningAverage()
00778 {
00779 
00780 }
00781 
00782 double ArRunningAverage::getAverage(void) const
00783 {
00784   return myTotal / myNum;
00785 }
00786 
00787 void ArRunningAverage::add(double val)
00788 {
00789   myTotal += val;
00790   myNum++;
00791   myVals.push_front(val);
00792   if (myVals.size() > myNumToAverage || myNum > myNumToAverage)
00793   {
00794     myTotal -= myVals.back();
00795     myNum--;
00796     myVals.pop_back();
00797   }
00798 }
00799 
00800 void ArRunningAverage::clear(void)
00801 {
00802   while (myVals.size() > 0)
00803     myVals.pop_back();
00804   myNum = 0;
00805   myTotal = 0;
00806 }
00807 
00808 size_t ArRunningAverage::getNumToAverage(void) const
00809 {
00810   return myNumToAverage;
00811 }
00812 
00813 void ArRunningAverage::setNumToAverage(size_t numToAverage)
00814 {
00815   myNumToAverage = numToAverage;
00816   while (myVals.size() > myNumToAverage)
00817   {
00818     myTotal -= myVals.back();
00819     myNum--;
00820     myVals.pop_back();
00821   }
00822 }
00823 
00824 #ifndef WIN32
00825 
00826 ArDaemonizer::ArDaemonizer(int *argc, char **argv) :
00827   myParser(argc, argv)
00828 {
00829   myIsDaemonized = false;
00830 }
00831 
00832 ArDaemonizer::~ArDaemonizer()
00833 {
00834 
00835 }
00836 
00837 bool ArDaemonizer::daemonize(void)
00838 {
00839   if (myParser.checkArgument("-daemonize") ||
00840       myParser.checkArgument("-d"))
00841   {
00842     return forceDaemonize();
00843   }
00844   else
00845     return true;
00846 
00847 }
00848 
00853 bool ArDaemonizer::forceDaemonize(void)
00854 {
00855     switch (fork())
00856     {
00857     case 0: // child process just return
00858       myIsDaemonized = true;
00859       fclose(stdout);
00860       fclose(stderr);
00861       return true;
00862     case -1: // error.... fail
00863       printf("Can't fork");
00864       ArLog::log(ArLog::Terse, "ArDaemonizer: Can't fork");
00865       return false;
00866     default: // parent process
00867       printf("Daemon started\n");
00868       exit(0);
00869     }
00870 }
00871 
00872 void ArDaemonizer::logOptions(void)
00873 {
00874   ArLog::log(ArLog::Terse, "Options for Daemonizing:");
00875   ArLog::log(ArLog::Terse, "-daemonize");
00876   ArLog::log(ArLog::Terse, "-d");
00877   ArLog::log(ArLog::Terse, "");
00878 }
00879 
00880 #endif // WIN32
00881 
00882 
00883 std::map<ArPriority::Priority, std::string> ArPriority::ourPriorityNames;
00884 std::string ArPriority::ourUnknownPriorityName;
00885 bool ArPriority::ourStringsInited = false;
00886 
00887 const char *ArPriority::getPriorityName(Priority priority) 
00888 {
00889 
00890   if (!ourStringsInited)
00891   {
00892     ourPriorityNames[IMPORTANT] = "Important";
00893     ourPriorityNames[NORMAL] = "Normal";
00894     ourPriorityNames[TRIVIAL] = "Detailed";
00895     ourPriorityNames[DETAILED] = "Detailed";
00896     ourUnknownPriorityName = "Unknown";
00897     ourStringsInited = true;
00898   }
00899   return ourPriorityNames[priority].c_str();
00900 }
00901 
00902 
00903 
00904 

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