00001 #ifndef LUX_UTIL_H
00002 #define LUX_UTIL_H
00003
00004
00005
00006 #include "luxconfig.h"
00007 #include "types.h"
00008 #include <sys/stat.h>
00009 #include <fcntl.h>
00010 #include <sys/mman.h>
00011 #include <errno.h>
00012 #include <string>
00013 #include <iostream>
00014 #include <unistd.h>
00015
00016 #ifdef USE_ZLIB
00017 #include <zlib.h>
00018 #endif
00019
00020 #define MIN_COMPRESS_LENGTH 50
00021
00022 #ifdef DEBUG
00023 #define error_log(msg) \
00024 std::cerr << "[error] " << msg \
00025 << " in " << __FILE__ << ":" << __LINE__ \
00026 << std::endl;
00027 #else
00028 #define error_log(msg)
00029 #endif
00030
00031
00032 #ifdef DEBUG_VINFO
00033 #define vinfo_log(msg) \
00034 std::cerr << "[info] " << msg \
00035 << std::endl;
00036 #else
00037 #define vinfo_log(msg)
00038 #endif
00039
00040 namespace Lux {
00041
00042 static inline void _mkdir(const char *str)
00043 {
00044 std::string str_(str);
00045 std::size_t n = 0;
00046 while (1) {
00047 n = str_.find_first_of('/', n+1);
00048 if (n == std::string::npos) {
00049 break;
00050 }
00051 std::string dir = str_.substr(0, n);
00052
00053 ::mkdir(dir.c_str(), 0755);
00054 }
00055 }
00056
00057 static inline int _open(const char *pathname, int flags, mode_t mode)
00058 {
00059 int oflags = O_RDONLY;
00060
00061 if (flags & DB_RDWR) {
00062 oflags |= O_RDWR;
00063 }
00064 if (flags & DB_CREAT) {
00065 oflags |= O_CREAT | O_RDWR;
00066 _mkdir(pathname);
00067 }
00068 if (flags & DB_TRUNC) {
00069 oflags |= O_TRUNC;
00070 }
00071 return ::open(pathname, oflags, mode);
00072 }
00073
00074 static inline ssize_t _read(int fd, void *buf, size_t count)
00075 {
00076 char *p = reinterpret_cast<char *>(buf);
00077 const char * const end_p = p + count;
00078
00079 while (p < end_p) {
00080 const int num_bytes = read(fd, p, end_p - p);
00081 if (num_bytes < 0) {
00082 if (errno == EINTR) {
00083 continue;
00084 }
00085 perror("read failed");
00086 break;
00087 }
00088 p += num_bytes;
00089 }
00090
00091 if (p != end_p) {
00092 return -1;
00093 }
00094 return count;
00095 }
00096
00097 static inline ssize_t _write(int fd, const void *buf, size_t count)
00098 {
00099 const char *p = reinterpret_cast<const char *>(buf);
00100 const char * const end_p = p + count;
00101
00102 while (p < end_p) {
00103 const int num_bytes = write(fd, p, end_p - p);
00104 if (num_bytes < 0) {
00105 if (errno == EINTR) continue;
00106 perror("write failed");
00107 break;
00108 }
00109 p += num_bytes;
00110 }
00111
00112 if (p != end_p) {
00113 return -1;
00114 }
00115 return count;
00116 }
00117
00118 static inline bool _pwrite(int fd, const void *buf, size_t nbyte, off_t offset)
00119 {
00120 if (pwrite(fd, buf, nbyte, offset) < 0) {
00121 perror("pwrite failed");
00122 return false;
00123 }
00124
00125
00126
00127
00128
00129
00130
00131
00132 return true;
00133 }
00134
00135 static inline bool _pread(int fd, void *buf, size_t nbyte, off_t offset)
00136 {
00137 if (pread(fd, buf, nbyte, offset) < 0) {
00138 perror("pread failed");
00139 return false;
00140 }
00141
00142
00143
00144
00145
00146
00147
00148
00149 return true;
00150 }
00151
00152 static inline void *_mmap(int fd, size_t size, int flags)
00153 {
00154 int prot = PROT_READ;
00155 if (flags & DB_RDWR || flags & DB_CREAT) {
00156 prot |= PROT_WRITE;
00157 }
00158
00159 void *p = mmap(0, size, prot, MAP_SHARED, fd, 0);
00160 if (p == MAP_FAILED) {
00161 perror("mmap failed.");
00162 return NULL;
00163 }
00164 return p;
00165 }
00166
00167 #ifdef USE_ZLIB
00168 static inline
00169 char *_compress(char *src, uint32_t slen, uint32_t *dlen)
00170 {
00171 *dlen = slen * 120 / 100 + 12;
00172 char *dest = new char[*dlen];
00173 int res = ::compress((Bytef *) dest, (uLongf *) dlen,
00174 (const Bytef *) src, (uLong) slen);
00175 if (res != Z_OK) {
00176 delete [] dest;
00177 if (res == Z_MEM_ERROR) {
00178 error_log("out of memory");
00179 } else if (res == Z_BUF_ERROR) {
00180 error_log("no enough buffer");
00181 }
00182 return NULL;
00183 }
00184 if (*dlen > slen) {
00185 *dlen = 0;
00186 delete [] dest;
00187 return NULL;
00188 }
00189 return dest;
00190 }
00191
00192 static inline
00193 char *compress(char *src, uint32_t slen, uint32_t *dlen)
00194 {
00195 if (slen < MIN_COMPRESS_LENGTH) {
00196 *dlen = 0;
00197 return NULL;
00198 }
00199 return _compress(src, slen, dlen);
00200 }
00201
00202 static inline
00203 char *uncompress(char *src, uint32_t slen, uint32_t *dlen)
00204 {
00205 char *dest = new char[*dlen+1];
00206 memset(dest, 0, *dlen+1);
00207 int res = ::uncompress((Bytef *) dest, (uLongf *) dlen,
00208 (const Bytef *) src, (uLong) slen);
00209 if (res != Z_OK) {
00210 delete [] dest;
00211 if (res == Z_MEM_ERROR) {
00212 error_log("out of memory");
00213 } else if (res == Z_BUF_ERROR) {
00214 error_log("no enough buffer");
00215 }
00216 return NULL;
00217 }
00218 return dest;
00219 }
00220 #endif
00221
00222 }
00223
00224 #endif