# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

common.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2001 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 #include "stdmisc.h"
00027 
00028 #ifdef NL_OS_WINDOWS
00029 #include <windows.h>
00030 #elif defined NL_OS_UNIX
00031 #include <unistd.h>
00032 #include <string.h>
00033 #include <errno.h>
00034 #endif
00035 
00036 #include "nel/misc/command.h"
00037 
00038 using namespace std;
00039 
00040 #ifdef NL_OS_WINDOWS
00041 #  ifdef __STL_DEBUG
00042 #    define STL_MODE "debug"
00043 #  else
00044 #    define STL_MODE "normal"
00045 #  endif // __STL_DEBUG
00046 #  if(__SGI_STL_PORT < 0x400)
00047 #    define STL_STR_VER "< 4.0"
00048 #  elif(__SGI_STL_PORT == 0x400)
00049 #    define STL_STR_VER "4.0"
00050 #  elif(__SGI_STL_PORT == 0x450)
00051 #    define STL_STR_VER "4.5"
00052 #  elif(__SGI_STL_PORT > 0x450)
00053 #    define STL_STR_VER "> 4.5"
00054 #  endif // __SGI_STL_PORT
00055 #  pragma message("Using STLport version "STL_STR_VER" in "STL_MODE" mode")
00056 #endif // NL_OS_WINDOWS
00057 
00058 namespace       NLMISC
00059 {
00060 
00061 /*
00062  * Portable Sleep() function that suspends the execution of the calling thread for a number of milliseconds.
00063  * Note: the resolution of the timer is system-dependant and may be more than 1 millisecond.
00064  */
00065 void nlSleep( uint32 ms )
00066 {
00067 #ifdef NL_OS_WINDOWS
00068 
00070 #ifdef NL_DEBUG
00071         ms = max(ms, (uint32)1);
00072 #endif
00073 
00074         Sleep( ms );
00075 
00076 #elif defined NL_OS_UNIX
00077         usleep( ms*1000 );
00078 #endif
00079 }
00080 
00081 
00082 /*
00083  * Returns Thread Id (note: on Linux, Process Id is the same as the Thread Id)
00084  */
00085 uint getThreadId()
00086 {
00087 #ifdef NL_OS_WINDOWS
00088         return GetCurrentThreadId();
00089 #elif defined NL_OS_UNIX
00090         return getpid();
00091 #endif
00092 
00093 }
00094 
00095 
00096 /*
00097  * Returns a readable string from a vector of bytes. '\0' are replaced by ' '
00098  */
00099 string stringFromVector( const vector<uint8>& v, bool limited )
00100 {
00101         string s;
00102 
00103         if (!v.empty())
00104         {
00105                 int size = v.size ();
00106                 if (limited && size > 1000)
00107                 {
00108                         string middle = "...<buf too big,skip middle part>...";
00109                         s.resize (1000 + middle.size());
00110                         memcpy (&*s.begin(), &*v.begin(), 500);
00111                         memcpy (&*s.begin()+500, &*middle.begin(), middle.size());
00112                         memcpy (&*s.begin()+500+middle.size(), &*v.begin()+size-500, 500);
00113                 }
00114                 else
00115                 {
00116                         s.resize (size);
00117                         memcpy( &*s.begin(), &*v.begin(), v.size() );
00118                 }
00119 
00120                 // Replace '\0' characters
00121                 string::iterator is;
00122                 for ( is=s.begin(); is!=s.end(); ++is )
00123                 {
00124                         // remplace non printable char and % with '?' chat
00125                         if ( ! isprint((uint8)(*is)) || (*is) == '%')
00126                         {
00127                                 (*is) = '?';
00128                         }
00129                 }
00130         }
00131 /*
00132         if ( ! v.empty() )
00133         {
00134                 // Copy contents
00135                 s.resize( v.size() );
00136                 memcpy( &*s.begin(), &*v.begin(), v.size() );
00137 
00138                 // Replace '\0' characters
00139                 string::iterator is;
00140                 for ( is=s.begin(); is!=s.end(); ++is )
00141                 {
00142                         // remplace non printable char and % with '?' chat
00143                         if ( ! isprint((*is)) || (*is) == '%')
00144                         {
00145                                 (*is) = '?';
00146                         }
00147                 }
00148         }
00149 */      return s;
00150 }
00151 
00152 
00153 sint smprintf( char *buffer, size_t count, const char *format, ... )
00154 {
00155         sint ret;
00156 
00157         va_list args;
00158         va_start( args, format );
00159         ret = vsnprintf( buffer, count, format, args );
00160         if ( ret == -1 )
00161         {
00162                 buffer[count-1] = '\0';
00163         }
00164         va_end( args );
00165 
00166         return( ret );
00167 }
00168 
00169 
00170 sint64 atoiInt64 (const char *ident, sint64 base)
00171 {
00172         sint64 number = 0;
00173         bool neg = false;
00174 
00175         // NULL string
00176         nlassert (ident != NULL);
00177 
00178         // empty string
00179         if (*ident == '\0') goto end;
00180         
00181         // + sign
00182         if (*ident == '+') ident++;
00183 
00184         // - sign
00185         if (*ident == '-') { neg = true; ident++; }
00186 
00187         while (*ident != '\0')
00188         {
00189                 if (isdigit(*ident))
00190                 {
00191                         number *= base;
00192                         number += (*ident)-'0';
00193                 }
00194                 else if (base > 10 && islower(*ident))
00195                 {
00196                         number *= base;
00197                         number += (*ident)-'a'+10;
00198                 }
00199                 else if (base > 10 && isupper(*ident))
00200                 {
00201                         number *= base;
00202                         number += (*ident)-'A'+10;
00203                 }
00204                 else
00205                 {
00206                         goto end;
00207                 }
00208                 ident++;
00209         }
00210 end:
00211         if (neg) number = -number;
00212         return number;
00213 
00215 /*      uint64 k = 0;
00216 
00217         while (*ident != '\0')
00218         {
00219                 switch(*(ident++))
00220                 {
00221                 case '0':
00222                         k +=0;
00223                         break;
00224                 case '1':
00225                         k +=1;
00226                         break;
00227                 case '2':
00228                         k +=2;
00229                         break;
00230                 case '3':
00231                         k +=3;
00232                         break;
00233                 case '4':
00234                         k +=4;
00235                         break;
00236                 case '5':
00237                         k +=5;
00238                         break;
00239                 case '6':
00240                         k +=6;
00241                         break;
00242                 case '7':
00243                         k +=7;
00244                         break;
00245                 case '8':
00246                         k +=8;
00247                         break;
00248                 case '9':
00249                         k +=9;
00250                         break;
00251                 case 'a':
00252                         k +=10;
00253                         break;
00254                 case 'b':
00255                         k +=11;
00256                         break;
00257                 case 'c':
00258                         k +=12;
00259                         break;
00260                 case 'd':
00261                         k +=13;
00262                         break;
00263                 case 'e':
00264                         k +=14;
00265                         break;
00266                 case 'f':
00267                         k +=15;
00268                         break;
00269 
00270                 case 'A':
00271                         k +=10;
00272                         break;
00273                 case 'B':
00274                         k +=11;
00275                         break;
00276                 case 'C':
00277                         k +=12;
00278                         break;
00279                 case 'D':
00280                         k +=13;
00281                         break;
00282                 case 'E':
00283                         k +=14;
00284                         break;
00285                 case 'F':
00286                         k +=15;
00287                         break;
00288 
00289                 case 0:
00290                         return k;
00291                         break;
00292                 }
00293                 if(*ident != 0) k *= base;
00294         }
00295 
00296         return k;
00297 */
00298 }
00299 
00300 void itoaInt64 (sint64 number, char *str, sint64 base)
00301 {
00302         str[0] = '\0';
00303         char b[256];
00304         if(!number)
00305         {
00306                 str[0] = '0';
00307                 str[1] = '\0';
00308                 return;
00309         }
00310         memset(b,'\0',255);
00311         memset(b,'0',64);
00312         sint n;
00313         sint64 x = number;
00314         if (x < 0) x = -x;
00315         char baseTable[] = "0123456789abcdefghijklmnopqrstuvwyz";
00316         for(n = 0; n < 64; n ++)
00317         {
00318                 sint num = (sint)(x % base);
00319                 b[64 - n] = baseTable[num];
00320                 if(!x) 
00321                 {
00322                         int k;
00323                         int j = 0;
00324         
00325                         if (number < 0)
00326                         {
00327                                 str[j++] = '-';
00328                         }
00329 
00330                         for(k = 64 - n + 1; k <= 64; k++)       
00331                         {
00332                                 str[j ++] = b[k];
00333                         }
00334                         str[j] = '\0';
00335                         break;
00336                 }
00337                 x /= base;
00338         }
00339 }
00340 
00341 uint raiseToNextPowerOf2(uint v)
00342 {
00343         uint    res=1;
00344         while(res<v)
00345                 res<<=1;
00346         
00347         return res;
00348 }
00349 
00350 uint    getPowerOf2(uint v)
00351 {
00352         uint    res=1;
00353         uint    ret=0;
00354         while(res<v)
00355         {
00356                 ret++;
00357                 res<<=1;
00358         }
00359         
00360         return ret;
00361 }
00362 
00363 bool isPowerOf2(sint32 v)
00364 {
00365         while(v)
00366         {
00367                 if(v&1)
00368                 {
00369                         v>>=1;
00370                         if(v)
00371                                 return false;
00372                 }
00373                 else
00374                         v>>=1;
00375         }
00376 
00377         return true;
00378 }
00379 
00380 string bytesToHumanReadable (uint32 bytes)
00381 {
00382         static char *divTable[]= { "b", "kb", "mb", "gb", "tb" };
00383         uint div = 0;
00384         float res = (float)bytes;
00385         float newres = res;
00386         while (true)
00387         {
00388                 newres /= 1024;
00389                 if(newres < 1.0f || div > 4)
00390                         break;
00391                 div++;
00392                 res = newres;
00393         }
00394         int ires = (int) res;
00395         if (res-(float)ires < .01f)
00396                 return toString ("%.0f%s", res, divTable[div]);
00397         else
00398                 return toString ("%.2f%s", res, divTable[div]);
00399 }
00400 
00401 NLMISC_COMMAND(bthr, "Convert a bytes number into an human readable", "<int>")
00402 {
00403         if (args.size() != 1)
00404                 return false;
00405         
00406         log.displayNL("%d -> %s", atoi(args[0].c_str()), bytesToHumanReadable(atoi(args[0].c_str())).c_str());
00407 
00408         return true;
00409 }
00410 
00411 std::string strlwr ( const std::string &str )
00412 {
00413         string res;
00414         res.reserve (str.size());
00415         for (uint i=0; i<str.size(); i++)
00416         {
00417                 if ( (str[i] >= 'A') && (str[i] <= 'Z') )
00418                         res += str[i] - 'A' + 'a';
00419                 else
00420                         res += str[i];
00421         }
00422 
00423         return res;
00424 }
00425 
00426 std::string &strlwr ( std::string &str )
00427 {
00428         for (int i=str.size()-1; i>=0; i--)
00429         {
00430                 if ( (str[i] >= 'A') && (str[i] <= 'Z') )
00431                 {
00432                         str[i] = str[i] - 'A' + 'a';
00433                 }
00434         }
00435 
00436         return (str);
00437 }
00438 
00439 char *strlwr ( char *str )
00440 {
00441         if (str == NULL)
00442                 return (NULL);
00443 
00444         while (*str != '\0')
00445         {
00446                 if ( (*str >= 'A') && (*str <= 'Z') )
00447                 {
00448                         *str = *str - 'A' + 'a';
00449                 }
00450                 str++;
00451         }
00452 
00453         return (str);
00454 }
00455 
00456 std::string &strupr ( std::string &str )
00457 {
00458         for (int i=str.size()-1; i>=0; i--)
00459         {
00460                 if ( (str[i] >= 'a') && (str[i] <= 'z') )
00461                 {
00462                         str[i] = str[i] - 'a' + 'A';
00463                 }
00464         }
00465 
00466         return (str);
00467 }
00468 
00469 char *strupr ( char *str )
00470 {
00471         if (str == NULL)
00472                 return (NULL);
00473 
00474         while (*str != '\0')
00475         {
00476                 if ( (*str >= 'a') && (*str <= 'z') )
00477                 {
00478                         *str = *str - 'a' + 'A';
00479                 }
00480                 str++;
00481         }
00482 
00483         return (str);
00484 }
00485 
00486 sint nlstricmp(const char *lhs,const char *rhs)
00487 {
00488         nlassert(lhs);
00489         nlassert(rhs);
00490         uint lchar, rchar;
00491         while (*lhs != '\0' && *rhs != '\0')
00492         {
00493                 lchar = ::toupper(*lhs);
00494                 rchar = ::toupper(*rhs);
00495                 if (lchar != rchar) return lchar - rchar;
00496                 ++lhs;
00497                 ++rhs;
00498         }
00499         if (*lhs != 0) return 1;
00500         if (*rhs != 0) return -1;
00501         return 0;
00502 }
00503 
00504 sint nlstricmp(const std::string &lhs,const std::string &rhs)
00505 {
00506         return nlstricmp(lhs.c_str(), rhs.c_str());
00507 }
00508 
00509 
00510 
00511 //
00512 // Exceptions
00513 //
00514 
00515 Exception::Exception() : _Reason("Unknown Exception")
00516 {
00517 //      nlinfo("Exception will be launched: %s", _Reason.c_str());
00518 }
00519 
00520 Exception::Exception(const std::string &reason) : _Reason(reason)
00521 {
00522         nlinfo("Exception will be launched: %s", _Reason.c_str());
00523 }
00524 
00525 Exception::Exception(const char *format, ...)
00526 {
00527         NLMISC_CONVERT_VARGS (_Reason, format, NLMISC::MaxCStringSize);
00528         nlinfo("Exception will be launched: %s", _Reason.c_str());
00529 }
00530 
00531 const char      *Exception::what() const throw()
00532 {
00533         return _Reason.c_str();
00534 }
00535 
00536 bool launchProgram (const std::string &programName, const std::string &arguments)
00537 {
00538 
00539 #ifdef NL_OS_WINDOWS
00540 
00541         SECURITY_ATTRIBUTES sa;
00542         sa.nLength = sizeof (sa);
00543         sa.lpSecurityDescriptor = NULL;
00544         sa.bInheritHandle = FALSE;
00545 
00546         STARTUPINFO si;
00547         si.cb = sizeof (si);
00548         si.lpReserved = NULL;
00549         si.lpDesktop = NULL;
00550         si.lpTitle = NULL;
00551         si.dwFlags = STARTF_USESHOWWINDOW;
00552         si.cbReserved2 = 0;
00553         si.wShowWindow = SW_MINIMIZE;
00554         si.lpReserved2 = NULL;
00555 
00556         PROCESS_INFORMATION pi;
00557 
00558         BOOL res = CreateProcess(programName.c_str(), (char*)arguments.c_str(), &sa, &sa, FALSE, 0, NULL, NULL, &si, &pi);
00559 
00560         if (res)
00561         {
00562                 nldebug("Successful launch '%s' with arg '%s'", programName.c_str(), arguments.c_str());
00563                 return true;
00564         }
00565         else
00566         {
00567                 LPVOID lpMsgBuf;
00568                 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL);
00569                 nlwarning("Failed launched '%s' with arg '%s' err %d: '%s'", programName.c_str(), arguments.c_str(), GetLastError (), lpMsgBuf);
00570                 LocalFree(lpMsgBuf);
00571         }
00572 
00573 #elif defined(NL_OS_UNIX)
00574 
00575         int status = vfork ();
00576         if (status == -1)
00577         {
00578                 char *err = strerror (errno);
00579                 nlwarning("Failed launched '%s' with arg '%s' err %d: '%s'", programName.c_str(), arguments.c_str(), errno, err);
00580         }
00581         else if (status == 0)
00582     {
00583                 status = execlp(programName.c_str(), programName.c_str(), arguments.c_str(), 0);
00584                 if (status == -1)
00585                 {
00586                         perror("Failed launched");
00587                         _exit(EXIT_FAILURE);
00588                 }
00589         }
00590         else
00591         {
00592                 nldebug("Successful launch '%s' with arg '%s'", programName.c_str(), arguments.c_str());
00593                 return true;
00594         }
00595 #else
00596         nlwarning ("launchProgram() not implemented");
00597 #endif
00598 
00599         return false;
00600 
00601 }
00602 
00603 } // NLMISC