|
SASC-NG
DVBSoftCAM
|
00001 /* 00002 * tools.h: Various tools 00003 * 00004 * See the main source file 'vdr.c' for copyright information and 00005 * how to reach the author. 00006 * 00007 * $Id: tools.h 1.103 2007/06/23 13:34:28 kls Exp $ 00008 */ 00009 00010 #ifndef __TOOLS_H 00011 #define __TOOLS_H 00012 00013 #include <dirent.h> 00014 #include <errno.h> 00015 #include <fcntl.h> 00016 #include <iconv.h> 00017 #include <poll.h> 00018 #include <stddef.h> 00019 #include <stdint.h> 00020 #include <stdio.h> 00021 #include <stdlib.h> 00022 #include <string.h> 00023 #include <syslog.h> 00024 #include <sys/stat.h> 00025 #include <sys/types.h> 00026 00027 typedef unsigned char uchar; 00028 00029 extern int SysLogLevel; 00030 00031 #define esyslog(a...) void( (SysLogLevel > 0) ? syslog_with_tid(LOG_ERR, a) : void() ) 00032 #define isyslog(a...) void( (SysLogLevel > 1) ? syslog_with_tid(LOG_INFO, a) : void() ) 00033 #define dsyslog(a...) void( (SysLogLevel > 2) ? syslog_with_tid(LOG_DEBUG, a) : void() ) 00034 00035 #define LOG_ERROR esyslog("ERROR (%s,%d): %m", __FILE__, __LINE__) 00036 #define LOG_ERROR_STR(s) esyslog("ERROR: %s: %m", s) 00037 00038 #define SECSINDAY 86400 00039 00040 #define KILOBYTE(n) ((n) * 1024) 00041 #define MEGABYTE(n) ((n) * 1024 * 1024) 00042 00043 #define MALLOC(type, size) (type *)malloc(sizeof(type) * (size)) 00044 00045 #define DELETENULL(p) (delete (p), p = NULL) 00046 00047 #define CHECK(s) { if ((s) < 0) LOG_ERROR; } // used for 'ioctl()' calls 00048 #define FATALERRNO (errno && errno != EAGAIN && errno != EINTR) 00049 00050 #ifndef __STL_CONFIG_H // in case some plugin needs to use the STL 00051 template<class T> inline T min(T a, T b) { return a <= b ? a : b; } 00052 template<class T> inline T max(T a, T b) { return a >= b ? a : b; } 00053 template<class T> inline int sgn(T a) { return a < 0 ? -1 : a > 0 ? 1 : 0; } 00054 template<class T> inline void swap(T &a, T &b) { T t = a; a = b; b = t; } 00055 #endif 00056 00057 void syslog_with_tid(int priority, const char *format, ...) __attribute__ ((format (printf, 2, 3))); 00058 00059 #define BCDCHARTOINT(x) (10 * ((x & 0xF0) >> 4) + (x & 0xF)) 00060 int BCD2INT(int x); 00061 00062 // Unfortunately there are no platform independent macros for unaligned 00063 // access. so we do it this way: 00064 00065 template<class T> inline T get_unaligned(T *p) 00066 { 00067 struct s { T v; } __attribute__((packed)); 00068 return ((s *)p)->v; 00069 } 00070 00071 template<class T> inline void put_unaligned(unsigned int v, T* p) 00072 { 00073 struct s { T v; } __attribute__((packed)); 00074 ((s *)p)->v = v; 00075 } 00076 00077 // When handling strings that might contain UTF-8 characters, it may be necessary 00078 // to process a "symbol" that consists of several actual character bytes. The 00079 // following functions allow transparently accessing a "char *" string without 00080 // having to worry about what character set is actually used. 00081 00082 int Utf8CharLen(const char *s); 00085 uint Utf8CharGet(const char *s, int Length = 0); 00089 int Utf8CharSet(uint c, char *s = NULL); 00093 int Utf8SymChars(const char *s, int Symbols); 00096 int Utf8StrLen(const char *s); 00099 char *Utf8Strn0Cpy(char *Dest, const char *Src, int n); 00104 int Utf8ToArray(const char *s, uint *a, int Size); 00108 int Utf8FromArray(const uint *a, char *s, int Size, int Max = -1); 00114 00115 // When allocating buffer space, make sure we reserve enough space to hold 00116 // a string in UTF-8 representation: 00117 00118 #define Utf8BufSize(s) ((s) * 4) 00119 00120 // The following macros automatically use the correct versions of the character 00121 // class functions: 00122 00123 #define Utf8to(conv, c) (cCharSetConv::SystemCharacterTable() ? to##conv(c) : tow##conv(c)) 00124 #define Utf8is(ccls, c) (cCharSetConv::SystemCharacterTable() ? is##ccls(c) : isw##ccls(c)) 00125 00126 class cCharSetConv { 00127 private: 00128 iconv_t cd; 00129 char *result; 00130 size_t length; 00131 static char *systemCharacterTable; 00132 public: 00133 cCharSetConv(const char *FromCode = NULL, const char *ToCode = NULL); 00137 ~cCharSetConv(); 00138 const char *Convert(const char *From, char *To = NULL, size_t ToLength = 0); 00148 static const char *SystemCharacterTable(void) { return systemCharacterTable; } 00149 static void SetSystemCharacterTable(const char *CharacterTable); 00150 }; 00151 00152 class cString { 00153 private: 00154 char *s; 00155 public: 00156 cString(const char *S = NULL, bool TakePointer = false); 00157 cString(const cString &String); 00158 virtual ~cString(); 00159 operator const char * () const { return s; } // for use in (const char *) context 00160 const char * operator*() const { return s; } // for use in (const void *) context (printf() etc.) 00161 cString &operator=(const cString &String); 00162 static cString sprintf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); 00163 }; 00164 00165 ssize_t safe_read(int filedes, void *buffer, size_t size); 00166 ssize_t safe_write(int filedes, const void *buffer, size_t size); 00167 void writechar(int filedes, char c); 00168 int WriteAllOrNothing(int fd, const uchar *Data, int Length, int TimeoutMs = 0, int RetryMs = 0); 00172 char *strcpyrealloc(char *dest, const char *src); 00173 char *strn0cpy(char *dest, const char *src, size_t n); 00174 char *strreplace(char *s, char c1, char c2); 00175 char *strreplace(char *s, const char *s1, const char *s2); 00176 char *skipspace(const char *s); 00177 char *stripspace(char *s); 00178 char *compactspace(char *s); 00179 cString strescape(const char *s, const char *chars); 00180 bool startswith(const char *s, const char *p); 00181 bool endswith(const char *s, const char *p); 00182 bool isempty(const char *s); 00183 int numdigits(int n); 00184 bool isnumber(const char *s); 00185 cString itoa(int n); 00186 cString AddDirectory(const char *DirName, const char *FileName); 00187 int FreeDiskSpaceMB(const char *Directory, int *UsedMB = NULL); 00188 bool DirectoryOk(const char *DirName, bool LogErrors = false); 00189 bool MakeDirs(const char *FileName, bool IsDirectory = false); 00190 bool RemoveFileOrDir(const char *FileName, bool FollowSymlinks = false); 00191 bool RemoveEmptyDirectories(const char *DirName, bool RemoveThis = false); 00192 int DirSizeMB(const char *DirName); 00193 char *ReadLink(const char *FileName); 00194 bool SpinUpDisk(const char *FileName); 00195 void TouchFile(const char *FileName); 00196 time_t LastModifiedTime(const char *FileName); 00197 cString WeekDayName(int WeekDay); 00198 cString WeekDayName(time_t t); 00199 cString WeekDayNameFull(int WeekDay); 00200 cString WeekDayNameFull(time_t t); 00201 cString DayDateTime(time_t t = 0); 00202 cString TimeToString(time_t t); 00203 cString DateString(time_t t); 00204 cString TimeString(time_t t); 00205 uchar *RgbToJpeg(uchar *Mem, int Width, int Height, int &Size, int Quality = 100); 00214 00215 class cBase64Encoder { 00216 private: 00217 const uchar *data; 00218 int length; 00219 int maxResult; 00220 int i; 00221 char *result; 00222 static const char *b64; 00223 public: 00224 cBase64Encoder(const uchar *Data, int Length, int MaxResult = 64); 00230 ~cBase64Encoder(); 00231 const char *NextLine(void); 00237 }; 00238 00239 class cTimeMs { 00240 private: 00241 uint64_t begin; 00242 public: 00243 cTimeMs(int Ms = 0); 00245 static uint64_t Now(void); 00246 void Set(int Ms = 0); 00247 bool TimedOut(void); 00248 uint64_t Elapsed(void); 00249 }; 00250 00251 class cReadLine { 00252 private: 00253 size_t size; 00254 char *buffer; 00255 public: 00256 cReadLine(void); 00257 ~cReadLine(); 00258 char *Read(FILE *f); 00259 }; 00260 00261 class cPoller { 00262 private: 00263 enum { MaxPollFiles = 16 }; 00264 pollfd pfd[MaxPollFiles]; 00265 int numFileHandles; 00266 public: 00267 cPoller(int FileHandle = -1, bool Out = false); 00268 bool Add(int FileHandle, bool Out); 00269 bool Poll(int TimeoutMs = 0); 00270 }; 00271 00272 class cReadDir { 00273 private: 00274 DIR *directory; 00275 struct dirent *result; 00276 union { // according to "The GNU C Library Reference Manual" 00277 struct dirent d; 00278 char b[offsetof(struct dirent, d_name) + NAME_MAX + 1]; 00279 } u; 00280 public: 00281 cReadDir(const char *Directory); 00282 ~cReadDir(); 00283 bool Ok(void) { return directory != NULL; } 00284 struct dirent *Next(void); 00285 }; 00286 00287 class cFile { 00288 private: 00289 static bool files[]; 00290 static int maxFiles; 00291 int f; 00292 public: 00293 cFile(void); 00294 ~cFile(); 00295 operator int () { return f; } 00296 bool Open(const char *FileName, int Flags, mode_t Mode = DEFFILEMODE); 00297 bool Open(int FileDes); 00298 void Close(void); 00299 bool IsOpen(void) { return f >= 0; } 00300 bool Ready(bool Wait = true); 00301 static bool AnyFileReady(int FileDes = -1, int TimeoutMs = 1000); 00302 static bool FileReady(int FileDes, int TimeoutMs = 1000); 00303 static bool FileReadyForWriting(int FileDes, int TimeoutMs = 1000); 00304 }; 00305 00306 class cSafeFile { 00307 private: 00308 FILE *f; 00309 char *fileName; 00310 char *tempName; 00311 public: 00312 cSafeFile(const char *FileName); 00313 ~cSafeFile(); 00314 operator FILE* () { return f; } 00315 bool Open(void); 00316 bool Close(void); 00317 }; 00318 00321 00322 class cUnbufferedFile { 00323 private: 00324 int fd; 00325 off_t curpos; 00326 off_t cachedstart; 00327 off_t cachedend; 00328 off_t begin; 00329 off_t lastpos; 00330 off_t ahead; 00331 size_t readahead; 00332 size_t written; 00333 size_t totwritten; 00334 int FadviseDrop(off_t Offset, off_t Len); 00335 public: 00336 cUnbufferedFile(void); 00337 ~cUnbufferedFile(); 00338 int Open(const char *FileName, int Flags, mode_t Mode = DEFFILEMODE); 00339 int Close(void); 00340 void SetReadAhead(size_t ra); 00341 off_t Seek(off_t Offset, int Whence); 00342 ssize_t Read(void *Data, size_t Size); 00343 ssize_t Write(const void *Data, size_t Size); 00344 static cUnbufferedFile *Create(const char *FileName, int Flags, mode_t Mode = DEFFILEMODE); 00345 }; 00346 00347 class cLockFile { 00348 private: 00349 char *fileName; 00350 int f; 00351 public: 00352 cLockFile(const char *Directory); 00353 ~cLockFile(); 00354 bool Lock(int WaitSeconds = 0); 00355 void Unlock(void); 00356 }; 00357 00358 class cListObject { 00359 private: 00360 cListObject *prev, *next; 00361 public: 00362 cListObject(void); 00363 virtual ~cListObject(); 00364 virtual int Compare(const cListObject &ListObject) const { return 0; } 00367 void Append(cListObject *Object); 00368 void Insert(cListObject *Object); 00369 void Unlink(void); 00370 int Index(void) const; 00371 cListObject *Prev(void) const { return prev; } 00372 cListObject *Next(void) const { return next; } 00373 }; 00374 00375 class cListBase { 00376 protected: 00377 cListObject *objects, *lastObject; 00378 cListBase(void); 00379 int count; 00380 public: 00381 virtual ~cListBase(); 00382 void Add(cListObject *Object, cListObject *After = NULL); 00383 void Ins(cListObject *Object, cListObject *Before = NULL); 00384 void Del(cListObject *Object, bool DeleteObject = true); 00385 virtual void Move(int From, int To); 00386 void Move(cListObject *From, cListObject *To); 00387 virtual void Clear(void); 00388 cListObject *Get(int Index) const; 00389 int Count(void) const { return count; } 00390 void Sort(void); 00391 }; 00392 00393 template<class T> class cList : public cListBase { 00394 public: 00395 T *Get(int Index) const { return (T *)cListBase::Get(Index); } 00396 T *First(void) const { return (T *)objects; } 00397 T *Last(void) const { return (T *)lastObject; } 00398 T *Prev(const T *object) const { return (T *)object->cListObject::Prev(); } // need to call cListObject's members to 00399 T *Next(const T *object) const { return (T *)object->cListObject::Next(); } // avoid ambiguities in case of a "list of lists" 00400 }; 00401 00402 template<class T> class cVector { 00403 private: 00404 mutable int allocated; 00405 mutable int size; 00406 mutable T *data; 00407 cVector(const cVector &Vector) {} // don't copy... 00408 cVector &operator=(const cVector &Vector) { return *this; } // ...or assign this! 00409 void Realloc(int Index) const 00410 { 00411 if (++Index > allocated) { 00412 data = (T *)realloc(data, Index * sizeof(T)); 00413 for (int i = allocated; i < Index; i++) 00414 data[i] = T(0); 00415 allocated = Index; 00416 } 00417 } 00418 public: 00419 cVector(int Allocated = 10) 00420 { 00421 allocated = 0; 00422 size = 0; 00423 data = NULL; 00424 Realloc(Allocated); 00425 } 00426 virtual ~cVector() { free(data); } 00427 T& At(int Index) const 00428 { 00429 Realloc(Index); 00430 if (Index >= size) 00431 size = Index + 1; 00432 return data[Index]; 00433 } 00434 const T& operator[](int Index) const 00435 { 00436 return At(Index); 00437 } 00438 T& operator[](int Index) 00439 { 00440 return At(Index); 00441 } 00442 int Size(void) const { return size; } 00443 virtual void Insert(T Data, int Before = 0) 00444 { 00445 if (Before < size) { 00446 Realloc(size); 00447 memmove(&data[Before + 1], &data[Before], (size - Before) * sizeof(T)); 00448 size++; 00449 data[Before] = Data; 00450 } 00451 else 00452 Append(Data); 00453 } 00454 virtual void Append(T Data) 00455 { 00456 if (size >= allocated) 00457 Realloc(allocated * 4 / 2); // increase size by 50% 00458 data[size++] = Data; 00459 } 00460 virtual void Clear(void) {} 00461 void Sort(__compar_fn_t Compare) 00462 { 00463 qsort(data, size, sizeof(T), Compare); 00464 } 00465 }; 00466 00467 inline int CompareStrings(const void *a, const void *b) 00468 { 00469 return strcmp(*(const char **)a, *(const char **)b); 00470 } 00471 00472 class cStringList : public cVector<char *> { 00473 public: 00474 cStringList(int Allocated = 10): cVector<char *>(Allocated) {} 00475 virtual ~cStringList(); 00476 int Find(const char *s) const; 00477 void Sort(void) { cVector<char *>::Sort(CompareStrings); } 00478 virtual void Clear(void); 00479 }; 00480 00481 class cFileNameList : public cStringList { 00482 public: 00483 cFileNameList(const char *Directory = NULL); 00484 bool Load(const char *Directory); 00485 }; 00486 00487 class cHashObject : public cListObject { 00488 friend class cHashBase; 00489 private: 00490 unsigned int id; 00491 cListObject *object; 00492 public: 00493 cHashObject(cListObject *Object, unsigned int Id) { object = Object; id = Id; } 00494 cListObject *Object(void) { return object; } 00495 }; 00496 00497 class cHashBase { 00498 private: 00499 cList<cHashObject> **hashTable; 00500 int size; 00501 unsigned int hashfn(unsigned int Id) const { return Id % size; } 00502 protected: 00503 cHashBase(int Size); 00504 public: 00505 virtual ~cHashBase(); 00506 void Add(cListObject *Object, unsigned int Id); 00507 void Del(cListObject *Object, unsigned int Id); 00508 void Clear(void); 00509 cListObject *Get(unsigned int Id) const; 00510 cList<cHashObject> *GetList(unsigned int Id) const; 00511 }; 00512 00513 #define HASHSIZE 512 00514 00515 template<class T> class cHash : public cHashBase { 00516 public: 00517 cHash(int Size = HASHSIZE) : cHashBase(Size) {} 00518 T *Get(unsigned int Id) const { return (T *)cHashBase::Get(Id); } 00519 }; 00520 00521 #endif //__TOOLS_H