#pragma once #include #include #include #include #include "WGPLCryptor.h" #include "WGPLAllocator.h" namespace WGPL { static const size_t __rc = 11; // // T : ŸÀÔ // _checksum : trueÀ̸é, ¸Þ¸ð¸®°¡ º¯°æµÇ¾ú´Â Áö checksumÀ» µÎ°í °Ë»çÇÔ. º¸¾È °­·Â but ´À¸² // _replicaCount: ½ÇÁ¦ º¯¼ö Æ÷ÇÔÇØ¼­ ´õ¹Ì º¯¼ö¸¦ ¸î °³ ¸¸µé°ÇÁö (µðÆúÆ® 11 = ½ÇÁ¦ 1°³ + ´õ¹Ì 10°³) // template class Value { public: Value() : seed_(0), index_(0), check_(0) { #ifdef _DEBUG memset(map_, 0, sizeof(map_)); #endif }; ~Value() { // note: empty() °Ë»çÇÏÁö ¾ÊÀ¸¸é ¾²·¹±â°ªÀ» Áö¿ì°Ô µÇ¾î crash if (!empty()) { for (int i = 0; i < _replicaCount; i++) { Free(map_[i], sizeof(T)); } } }; inline bool empty() { return !seed_; } inline void Set(T val) { #ifdef _DEBUG debugVal_ = val; #endif if (empty()) { // index °»½Å renewIndex(); for (int i = 0; i < _replicaCount; i++) { T* p = (T*)Alloc(sizeof(T)); // ¾²·¹±â°ª µé¾î°¨ if (i == index_ || (_checksum && i == check_)) { // ¾Ïȣȭ *p = val; Encrypt(seed_ + i, (char *)p, sizeof(T)); } map_[i] = p; } } else { renewIndex(); T tmp[_replicaCount]; // ¾²·¹±â °ª for (int i = 0; i < _replicaCount; ++i) { T* p = map_[i]; if (i == index_ || (_checksum && i == check_)) { // ¾Ïȣȭ *p = val; // ½ÇÁ¦ °ªÀ¸·Î ¼ÂÆÃ Encrypt(seed_ + i, (char *)p, sizeof(T)); } else { // ¾²·¹±â °ª set, warning ¹«½Ã *p = tmp[i]; } } } } inline T Get() { if (empty()) { // note: T´Â primitive type¸¸ °¡´É return 0; } else { return getValue(); } } inline void Swap(Value& src) { swap(this->seed_, src.seed_); swap(this->index_, src.index_); swap(this->check_, src.check_); #ifdef _DEBUG swap(this->debugVal_, src.debugVal_); #endif // swap map T* tmp[_replicaCount]; memcpy(tmp, this->map_, sizeof(tmp)); memcpy(this->map_, src.map_, sizeof(tmp)); memcpy(src.map_, tmp, sizeof(tmp)); } private: inline T getValue() { assert(!empty()); T val = getValue(index_); #ifdef _DEBUG assert(debugVal_ == val); #endif if (_checksum) { T check = getValue(check_); // checksum °Ë»ç if (val != check) { // todo: ÇØÅ·!! //std::cout << "val = " << val << ", check = " << check << std::endl; //printf("getValue: index_ = %u, check_ = %u\n", index_, check_); if (_Callback_WGPL != NULL) { _Callback_WGPL(); } else { throw; } } } return val; } inline T getValue(unsigned int index) { T* p = map_[index]; T val; memcpy(&val, p, sizeof(T)); Decrypt(seed_ + index, (char *)&val, sizeof(T)); return val; } inline void renewIndex() { // seed ÀúÀå seed_ = GetTickCount(); // _replicaCount°¡ 1À̸é index¹Ù²Ù´Â °Ô ÀÇ¹Ì ¾øÀ½. if (_replicaCount <= 1) { return; } // ½ÇÁ¦ °ªÀÌ ÀúÀåµÈ index index_ = rand() % _replicaCount; if (_checksum) { // üũ¼¶ÀÇ index check_ = index_ + 1; check_ %= _replicaCount; } assert(index_ != check_); } template inline void swap(_ST& a, _ST& b) { _ST tmp = a; a = b; b = tmp; } private: unsigned int seed_; unsigned int index_; // ½ÇÁ¦ °ªÀÌ ÀúÀåµÈ index unsigned int check_; // ½ÇÁ¦ °ªÀÌ º¯°æµÇ¾ú´Â Áö °ËÁõÇÒ checksumÀÌ µé¾îÀÖ´Â index T* map_[_replicaCount]; #ifdef _DEBUG T debugVal_; // correct if _DEBUG is defined #endif }; }