00001
00002
00003
00004
00005
00006
00007
00009
00016 #include "utils.h"
00017
00018
00019
00020 #ifdef _WIN32
00021 #include <direct.h>
00022 #else
00023 #include <dirent.h>
00024 #endif
00025
00026 #include <sys/stat.h>
00027 #include "socket.h"
00028
00029 using namespace std;
00030 using namespace hoa_socket;
00031
00032 namespace hoa_utils {
00033
00034 bool UTILS_DEBUG = false;
00035
00039
00040 uint32 RoundUpPow2(uint32 x) {
00041 x -= 1;
00042 x |= x >> 1;
00043 x |= x >> 2;
00044 x |= x >> 4;
00045 x |= x >> 8;
00046 x |= x >> 16;
00047 return x + 1;
00048 }
00049
00050
00051
00052 bool IsPowerOfTwo(uint32 x) {
00053 return ((x & (x-1)) == 0);
00054 }
00055
00056
00057
00058 bool IsOddNumber(uint32 x) {
00059
00060 return (x & 0x00000001);
00061 }
00062
00063
00064
00065 bool IsFloatInRange(float value, float lower, float upper) {
00066 return (value >= lower && value <= upper);
00067 }
00068
00069
00070 float FloorToFloatMultiple (const float value, const float multiple)
00071 {
00072 return multiple * floor(value / multiple);
00073 }
00074
00075
00076
00080
00081 const size_t ustring::npos = ~0;
00082
00083
00084
00085 ustring::ustring() {
00086 _str.push_back(0);
00087 }
00088
00089
00090
00091 ustring::ustring(const uint16 *s) {
00092 _str.clear();
00093
00094 if (!s) {
00095 _str.push_back(0);
00096 return;
00097 }
00098
00099 while (*s != 0) {
00100 _str.push_back(*s);
00101 ++s;
00102 }
00103
00104 _str.push_back(0);
00105 }
00106
00107
00108
00109 ustring ustring::substr(size_t pos, size_t n) const
00110 {
00111 size_t len = length();
00112
00113 if (pos >= len)
00114 throw std::out_of_range("pos passed to substr() was too large");
00115
00116 ustring s;
00117 while (n > 0 && pos < len) {
00118 s += _str[pos];
00119 ++pos;
00120 --n;
00121 }
00122
00123 return s;
00124 }
00125
00126
00127
00128 ustring & ustring::operator + (const ustring& s)
00129 {
00130
00131 if (s.empty())
00132 return *this;
00133
00134
00135 _str[length()] = s[0];
00136
00137
00138 size_t len = s.length();
00139 for (size_t j = 1; j < len; ++j) {
00140 _str.push_back(s[j]);
00141 }
00142
00143
00144 _str.push_back(0);
00145
00146 return *this;
00147 }
00148
00149
00150
00151 ustring & ustring::operator += (uint16 c) {
00152 _str[length()] = c;
00153 _str.push_back(0);
00154
00155 return *this;
00156 }
00157
00158
00159
00160 ustring & ustring::operator += (const ustring &s) {
00161
00162 if (s.empty())
00163 return *this;
00164
00165
00166 _str[length()] = s[0];
00167
00168
00169 size_t len = s.length();
00170 for (size_t j = 1; j < len; ++j) {
00171 _str.push_back(s[j]);
00172 }
00173
00174
00175 _str.push_back(0);
00176
00177 return *this;
00178 }
00179
00180
00181
00182 ustring & ustring::operator = (const ustring &s) {
00183 clear();
00184 operator += (s);
00185
00186 return *this;
00187 }
00188
00189
00190
00191 size_t ustring::find(uint16 c, size_t pos) const {
00192 size_t len = length();
00193
00194 for (size_t j = pos; j < len; ++j) {
00195 if (_str[j] == c)
00196 return j;
00197 }
00198
00199 return npos;
00200 }
00201
00202
00203
00204 size_t ustring::find(const ustring &s, size_t pos) const {
00205 size_t len = length();
00206 size_t total_chars = s.length();
00207 size_t chars_found = 0;
00208
00209 for (size_t j = pos; j < len; ++j) {
00210 if (_str[j] == s[chars_found]) {
00211 ++chars_found;
00212 if (chars_found == total_chars) {
00213 return (j - chars_found + 1);
00214 }
00215 }
00216 else {
00217 chars_found = 0;
00218 }
00219 }
00220
00221 return npos;
00222 }
00223
00227
00228
00229 bool IsStringNumeric(const string& text) {
00230 if (text.empty())
00231 return false;
00232
00233
00234 bool decimal_allowed = true;
00235
00236 size_t len = text.length();
00237
00238
00239 for (size_t c = 0; c < len; ++c) {
00240
00241 bool numeric_char = (isdigit(static_cast<int32>(text[c]))) || (c==0 && (text[c] == '-' || text[c] == '+'));
00242
00243 if (!numeric_char) {
00244
00245 if (decimal_allowed && text[c] == '.') {
00246 decimal_allowed = false;
00247 }
00248 else {
00249 return false;
00250 }
00251 }
00252 }
00253
00254 return true;
00255 }
00256
00257
00258
00259 ustring MakeUnicodeString(const string& text) {
00260 int32 length = static_cast<int32>(text.length());
00261 uint16 *ubuff = new uint16[length+1];
00262 ubuff[length] = static_cast<uint16>('\0');
00263
00264 for (int32 c = 0; c < length; ++c) {
00265 ubuff[c] = static_cast<uint16>(text[c]);
00266 }
00267
00268 ustring new_ustr(ubuff);
00269 delete[] ubuff;
00270
00271 return new_ustr;
00272 }
00273
00274
00275
00276 string MakeStandardString(const ustring& text) {
00277 int32 length = static_cast<int32>(text.length());
00278
00279 unsigned char *strbuff = new unsigned char[length+1];
00280 strbuff[length] = '\0';
00281
00282 for (int32 c = 0; c < length; ++c) {
00283 uint16 curr_char = text[c];
00284
00285 if(curr_char > 0xff)
00286 strbuff[c] = '?';
00287 else
00288 strbuff[c] = static_cast<unsigned char>(curr_char);
00289 }
00290
00291 string new_str(reinterpret_cast<char*>(strbuff));
00292 delete [] strbuff;
00293
00294 return new_str;
00295 }
00296
00300
00301 float RandomFloat() {
00302 return (static_cast<float>(rand()) / static_cast<float>(RAND_MAX));
00303 }
00304
00305
00306
00307 int32 RandomBoundedInteger(int32 lower_bound, int32 upper_bound) {
00308 int32 range;
00309 float result;
00310
00311 range = upper_bound - lower_bound + 1;
00312 if (range < 0) {
00313 if (UTILS_DEBUG) cerr << "UTILS WARNING: Call to RandomNumber had bound arguments swapped." << endl;
00314 range = range * -1;
00315 }
00316
00317 result = range * RandomFloat();
00318 result = result + lower_bound;
00319
00320 return static_cast<int32>(result);
00321 }
00322
00323
00324
00325 int32 GaussianRandomValue(int32 mean, float std_dev, bool positive_value) {
00326 float x, y, r;
00327 float grv_unit;
00328 float result;
00329
00330
00331 if (std_dev < 0) {
00332 cerr << "UTILS WARNING: negative value for standard deviation argument in function GaussianValue" << endl;
00333 std_dev = -1.0f * std_dev;
00334 }
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345 do {
00346 x = 2.0f * RandomFloat() - 1.0f;
00347 y = 2.0f * RandomFloat() - 1.0f;
00348 r = x*x + y*y;
00349 } while (r > 1.0f || r == 0.0f);
00350 grv_unit = x * sqrt(-2.0f * log(r) / r);
00351
00352
00353 result = (grv_unit * std_dev) + mean;
00354
00355
00356 if (result < 0.0f && positive_value)
00357 return 0;
00358 else
00359 return static_cast<int32>(result);
00360 }
00361
00362
00363 bool Probability(uint32 chance) {
00364 uint32 value = static_cast<uint32>(RandomBoundedInteger(1, 100));
00365 if (value <= chance)
00366 return true;
00367 else
00368 return false;
00369 }
00370
00374
00375 bool DoesFileExist(const std::string& file_name) {
00376 struct stat buf;
00377 if (stat(file_name.c_str(), &buf) == 0)
00378 return true;
00379 else
00380 return false;
00381 }
00382
00383
00384
00385 bool MoveFile(const std::string& source_name, const std::string& destination_name) {
00386 return (rename(source_name.c_str(), destination_name.c_str()) == 0);
00387 }
00388
00389
00390
00391 bool MakeDirectory(const std::string& dir_name) {
00392
00393 struct stat buf;
00394 int32 i = stat(dir_name.c_str(), &buf);
00395 if (i == 0)
00396 return true;
00397
00398
00399
00400
00401 #ifdef _WIN32
00402 int32 success = mkdir(dir_name.c_str());
00403 #else
00404 int32 success = mkdir(dir_name.c_str(), S_IRWXG | S_IRWXO | S_IRWXU);
00405 #endif
00406
00407 if (success == -1) {
00408 cerr << "UTILS ERROR: could not create directory: " << dir_name.c_str() << endl;
00409 return false;
00410 }
00411
00412 return true;
00413 }
00414
00415
00416
00417 bool CleanDirectory(const std::string& dir_name) {
00418
00419 struct stat buf;
00420 int32 i = stat(dir_name.c_str(), &buf);
00421 if (i != 0)
00422 return true;
00423
00424 #ifdef _WIN32
00425
00426
00427
00428 char app_path[1024];
00429 GetCurrentDirectoryA(1024, app_path);
00430
00431 int32 app_path_len = static_cast<int32>(strlen(app_path));
00432 if (app_path_len <= 0)
00433 return false;
00434 if(app_path[app_path_len-1] == '\\')
00435 app_path[app_path_len-1] = '\0';
00436
00437 string full_path = app_path;
00438
00439 if (dir_name[0] == '/' || dir_name[0] == '\\') {
00440 full_path += dir_name;
00441 }
00442 else {
00443 full_path += "\\";
00444 full_path += dir_name;
00445 }
00446
00447 char file_found[1024];
00448 WIN32_FIND_DATAA info;
00449 HANDLE hp;
00450 sprintf(file_found, "%s\\*.*", full_path.c_str());
00451 hp = FindFirstFileA(file_found, &info);
00452
00453 if (hp != INVALID_HANDLE_VALUE) {
00454
00455 do {
00456 sprintf(file_found, "%s\\%s", full_path.c_str(), info.cFileName);
00457 DeleteFileA(file_found);
00458 } while(FindNextFileA(hp, &info));
00459 }
00460 FindClose(hp);
00461
00462 #else
00463
00464
00465 DIR *parent_dir;
00466 struct dirent *dir_file;
00467
00468 parent_dir = opendir(dir_name.c_str());
00469 if (!parent_dir) {
00470 cerr << "UTILS ERROR: failed to clean directory: " << dir_name << endl;
00471 return false;
00472 }
00473
00474 string base_dir = dir_name;
00475 if (base_dir[base_dir.length()-1] != '/')
00476 base_dir += "/";
00477
00478
00479 while ((dir_file = readdir(parent_dir))) {
00480 string file_name = base_dir + dir_file->d_name;
00481 remove(file_name.c_str());
00482 }
00483
00484 closedir(parent_dir);
00485
00486 #endif
00487
00488 return true;
00489 }
00490
00491
00492
00493 bool RemoveDirectory(const std::string& dir_name)
00494 {
00495
00496 struct stat buf;
00497 int32 i = stat(dir_name.c_str(), &buf);
00498 if (i != 0)
00499 return true;
00500
00501
00502 CleanDirectory(dir_name);
00503
00504
00505 int32 success = rmdir(dir_name.c_str());
00506
00507 if (success == -1) {
00508 cerr << "UTILS ERROR: could not delete directory: " << dir_name << endl;
00509 return false;
00510 }
00511
00512 return true;
00513 }
00514
00515 #define VERSION_HOST "rabidtinker.mine.nu"
00516 #define VERSION_PATH "/~alistair/allacrost-version.txt"
00517 #define ALLACROST_MAJOR_VERSION 0
00518 #define ALLACROST_MINOR_VERSION 1
00519 #define ALLACROST_PATCH 0
00520
00521 static std::string temp_version_str;
00522
00523 bool IsLatestVersion ()
00524 {
00525 uint32 rversionmajor;
00526 uint32 rversionminor;
00527 uint32 rpatch;
00528
00529
00530
00531
00532
00533
00534
00535 Socket conn;
00536 conn.Connect ( VERSION_HOST, 80 );
00537 if (!conn.IsConnected())
00538 return true;
00539 conn.Write ( "GET http://%s%s\r\n", VERSION_HOST, VERSION_PATH );
00540 conn.IsQueued ( 300 );
00541 conn.ScanLine ( "%d.%d.%d", &rversionmajor, &rversionminor, &rpatch );
00542 conn.Disconnect();
00543
00544 char vstring[255];
00545 sprintf ( vstring, "%d.%d.%d", rversionmajor, rversionminor, rpatch );
00546 temp_version_str = vstring;
00547
00548 if (rversionmajor > ALLACROST_MAJOR_VERSION)
00549 return false;
00550 else if (rversionmajor == ALLACROST_MAJOR_VERSION)
00551 {
00552 if (rversionminor > ALLACROST_MINOR_VERSION)
00553 return false;
00554 else if (rversionminor == ALLACROST_MINOR_VERSION)
00555 {
00556 if (rpatch > ALLACROST_PATCH)
00557 return false;
00558 }
00559 }
00560 return true;
00561 }
00562
00563 string GetLatestVersion ()
00564 {
00565 return temp_version_str;
00566 }
00567
00568 }