Skip to content
Snippets Groups Projects
Unverified Commit 8f5737a2 authored by kaldoran's avatar kaldoran
Browse files

Add some commentary

And move function around
parent e2797284
No related branches found
No related tags found
No related merge requests found
...@@ -47,6 +47,18 @@ struct Prefix { ...@@ -47,6 +47,18 @@ struct Prefix {
content_.push_back(p.content_[size_/8] & (0xFF << (8 - rem))); content_.push_back(p.content_[size_/8] & (0xFF << (8 - rem)));
} }
/**
* Get a sub prefix of the Prefix
*
* @param len lenght of the prefix to get, could be negative
* if len is negativ then you will get the prefix
* of size of the previous prefix minus len
*
* @return Sub-prefix of size len or if len is negative sub-prefix of size
* of prefix minus len
*
* @throw out_of_range if len is larger than size of the content
*/
Prefix getPrefix(ssize_t len) const { Prefix getPrefix(ssize_t len) const {
if ((size_t)std::abs(len) >= content_.size() * 8) if ((size_t)std::abs(len) >= content_.size() * 8)
throw std::out_of_range("len larger than prefix size."); throw std::out_of_range("len larger than prefix size.");
...@@ -57,16 +69,18 @@ struct Prefix { ...@@ -57,16 +69,18 @@ struct Prefix {
} }
/** /**
* Method for getting the state of the bit at the position pos. * Flags are considered as active if flag is empty or if the flag
* @param pos : Pos of the needed bit * at pos 'pos' is active
* @return : true if the bit is at 1 ee *
* false otherwise * @see isActiveBit in private function
* @throw out_of_range Throw out of range if the bit at 'pos' does not exist
*/ */
bool isFlagActive(size_t pos) const { bool isFlagActive(size_t pos) const {
return flags_.empty() or isActiveBit(flags_, pos); return flags_.empty() or isActiveBit(flags_, pos);
} }
/**
* @see isActiveBit in private function
*/
bool isContentBitActive(size_t pos) const { bool isContentBitActive(size_t pos) const {
return isActiveBit(content_, pos); return isActiveBit(content_, pos);
} }
...@@ -92,20 +106,6 @@ struct Prefix { ...@@ -92,20 +106,6 @@ struct Prefix {
return InfoHash::get(copy); return InfoHash::get(copy);
} }
std::string toString() const {
std::stringstream ss;
ss << "Prefix : " << std::endl << "\tContent_ : ";
ss << blobToString(content_);
ss << std::endl;
ss << "\tFlags_ : ";
ss << blobToString(flags_);
ss << std::endl;
return ss.str();
}
/** /**
* This method count total of bit in common between 2 prefix * This method count total of bit in common between 2 prefix
* *
...@@ -141,63 +141,64 @@ struct Prefix { ...@@ -141,63 +141,64 @@ struct Prefix {
return 8 * i + j; return 8 * i + j;
} }
/**
* @see doc of swap private function
*/
void swapContentBit(size_t bit) { void swapContentBit(size_t bit) {
swapBit(content_, bit); swapBit(content_, bit);
} }
/** /**
* This method swap the bit a the position 'bit' * @see doc of swap private function
*
* @param bit Position of the bit to swap
* @return The prefix with the bit at position 'bit' swapped
* @throw out_of_range Throw out of range if bit does not exist
*/ */
void swapFlagBit(size_t bit) { void swapFlagBit(size_t bit) {
swapBit(flags_, bit); swapBit(flags_, bit);
} }
/**
* @see doc of addPadding private function
*/
void addPaddingContent(size_t size) { void addPaddingContent(size_t size) {
content_ = addPadding(content_, size); content_ = addPadding(content_, size);
} }
void updateFlags() { void updateFlags() {
// Fill first known bit /* Fill first known bit */
auto csize = size_ - flags_.size() * 8; auto csize = size_ - flags_.size() * 8;
while(csize >= 8) { while(csize >= 8) {
flags_.push_back(0xFF); flags_.push_back(0xFF);
csize -= 8; csize -= 8;
} }
// if needed fill remaining bit /* if needed fill remaining bit */
if ( csize ) if ( csize )
flags_.push_back(0xFF << (8 - csize)); flags_.push_back(0xFF << (8 - csize));
// Complet vector space missing /* Complet vector space missing */
for ( auto i = flags_.size(); i < content_.size(); i++ ) for ( auto i = flags_.size(); i < content_.size(); i++ )
flags_.push_back(0xFF); flags_.push_back(0xFF);
} }
std::string toString() const;
size_t size_ {0}; size_t size_ {0};
/* Will contain flags according to content_.
If flags_[i] == 0, then content_[i] is unknown
else if flags_[i] == 1, then content_[i] is known */
Blob flags_ {}; Blob flags_ {};
Blob content_ {}; Blob content_ {};
private: private:
std::string blobToString(const Blob &bl) const { /**
std::stringstream ss; * Add a padding to the input blob
auto bn = bl.size() % 8; *
auto n = bl.size() / 8; * @param toP : Prefix where to add a padding
* @param size : Final size of the prefix with padding
for (size_t i = 0; i < bl.size(); i++) *
ss << std::bitset<8>(bl[i]) << " "; * @return Copy of the input Blob but with a padding
if (bn) */
for (unsigned b=0; b < bn; b++)
ss << (char)((bl[n] & (1 << (7 - b))) ? '1':'0');
return ss.str();
}
Blob addPadding(Blob toP, size_t size) { Blob addPadding(Blob toP, size_t size) {
Blob copy = toP; Blob copy = toP;
for ( auto i = copy.size(); i < size; i++ ) for ( auto i = copy.size(); i < size; i++ )
...@@ -207,6 +208,16 @@ private: ...@@ -207,6 +208,16 @@ private:
return copy; return copy;
} }
/**
* Check if the bit a pos 'pos' is active, i.e. equal to 1
*
* @param b : Blob to check
* @param pos : Position to check
*
* @return true if the bit is equal to 1, false otherwise
*
* @throw out_of_range if bit is superior to blob size * 8
*/
bool isActiveBit(const Blob &b, size_t pos) const { bool isActiveBit(const Blob &b, size_t pos) const {
if ( pos >= content_.size() * 8 ) if ( pos >= content_.size() * 8 )
throw std::out_of_range("Can't detect active bit at pos, pos larger than prefix size or empty prefix"); throw std::out_of_range("Can't detect active bit at pos, pos larger than prefix size or empty prefix");
...@@ -214,6 +225,16 @@ private: ...@@ -214,6 +225,16 @@ private:
return ((b[pos / 8] >> (7 - (pos % 8)) ) & 1) == 1; return ((b[pos / 8] >> (7 - (pos % 8)) ) & 1) == 1;
} }
/**
* Swap bit at position bit [from 0 to 1 and vice-versa]
*
* @param b : Blob to swap
* @param bit : Bit to swap on b
*
* @return the input prefix with the bit at pos 'bit' swapped
*
* @throw out_of_range if bit is superior to blob size * 8
*/
void swapBit(Blob &b, size_t bit) { void swapBit(Blob &b, size_t bit) {
if ( bit >= b.size() * 8 ) if ( bit >= b.size() * 8 )
throw std::out_of_range("bit larger than prefix size."); throw std::out_of_range("bit larger than prefix size.");
...@@ -259,6 +280,7 @@ public: ...@@ -259,6 +280,7 @@ public:
/* A key for a an index entry */ /* A key for a an index entry */
using Key = std::map<std::string, Blob>; using Key = std::map<std::string, Blob>;
/* Specifications of the keys. It defines the number, the length and the /* Specifications of the keys. It defines the number, the length and the
* serialization order of fields. */ * serialization order of fields. */
using KeySpec = std::map<std::string, size_t>; using KeySpec = std::map<std::string, size_t>;
...@@ -397,6 +419,13 @@ private: ...@@ -397,6 +419,13 @@ private:
std::shared_ptr<unsigned> max_common_prefix_len, std::shared_ptr<unsigned> max_common_prefix_len,
int start = -1, bool all_values = false); int start = -1, bool all_values = false);
/**
* Apply the zcurve algorithm on the list of input prefix
*
* @param all_prefix : Vector of prefix to interleave
*
* @return The output prefix where all flags and content are interleaves
*/
Prefix zcurve(const std::vector<Prefix>& all_prefix) const; Prefix zcurve(const std::vector<Prefix>& all_prefix) const;
/** /**
......
...@@ -4,6 +4,41 @@ ...@@ -4,6 +4,41 @@
namespace dht { namespace dht {
namespace indexation { namespace indexation {
/**
* Output the blob into string and readable way
*
* @param bl : Blob to print
*
* @return string that represent the blob into a readable way
*/
static std::string blobToString(const Blob &bl) {
std::stringstream ss;
auto bn = bl.size() % 8;
auto n = bl.size() / 8;
for (size_t i = 0; i < bl.size(); i++)
ss << std::bitset<8>(bl[i]) << " ";
if (bn)
for (unsigned b=0; b < bn; b++)
ss << (char)((bl[n] & (1 << (7 - b))) ? '1':'0');
return ss.str();
}
std::string Prefix::toString() const {
std::stringstream ss;
ss << "Prefix : " << std::endl << "\tContent_ : ";
ss << blobToString(content_);
ss << std::endl;
ss << "\tFlags_ : ";
ss << blobToString(flags_);
ss << std::endl;
return ss.str();
}
void Pht::Cache::insert(const Prefix& p) { void Pht::Cache::insert(const Prefix& p) {
size_t i = 0; size_t i = 0;
auto now = clock::now(); auto now = clock::now();
...@@ -312,27 +347,39 @@ Prefix Pht::zcurve(const std::vector<Prefix>& all_prefix) const { ...@@ -312,27 +347,39 @@ Prefix Pht::zcurve(const std::vector<Prefix>& all_prefix) const {
if ( all_prefix.size() == 1 ) if ( all_prefix.size() == 1 )
return all_prefix[0]; return all_prefix[0];
for ( size_t j = 0, bit = 0; j < all_prefix[0].content_.size(); j++) { /* All prefix got the same size (thanks to padding) */
size_t prefix_size = all_prefix[0].content_.size();
/* Loop on all uint8_t of the input prefix */
for ( size_t j = 0, bit = 0; j < prefix_size; j++) {
uint8_t mask = 0x80; uint8_t mask = 0x80;
/* For each of the 8 bits of the input uint8_t */
for ( int i = 0; i < 8; ) { for ( int i = 0; i < 8; ) {
uint8_t flags = 0; uint8_t flags = 0;
uint8_t content = 0; uint8_t content = 0;
for ( int k = 0 ; k < 8; k++, bit++ ) { /* For each bit of the output uint8_t */
for ( int k = 0 ; k < 8; k++ ) {
auto diff = k - i; auto diff = k - i;
auto x = all_prefix[bit].content_[j] & mask; /*get the content 'c', and the flag 'f' of the input prefix */
auto y = all_prefix[bit].flags_[j] & mask; auto c = all_prefix[bit].content_[j] & mask;
auto f = all_prefix[bit].flags_[j] & mask;
content |= ( diff >= 0 ) ? x >> diff : x << std::abs(diff); /* Move this bit at the right position according to the diff
flags |= ( diff >= 0 ) ? y >> diff : y << std::abs(diff); and merge it into content and flags in the same way */
content |= ( diff >= 0 ) ? c >> diff : c << std::abs(diff);
flags |= ( diff >= 0 ) ? f >> diff : f << std::abs(diff);
if ( bit == all_prefix.size() - 1 ) { bit = -1; ++i; mask >>= 1; } /* If we are on the last prefix of the vector get back to the first and
,move the mask in order to get the n + 1nth bit */
if ( ++bit == all_prefix.size() ) { bit = 0; ++i; mask >>= 1; }
} }
/* Add the next flags + content to the output prefix */
p.content_.push_back(content); p.content_.push_back(content);
p.flags_.push_back(flags); p.flags_.push_back(flags);
p.size_ += 8; p.size_ += 8;
...@@ -348,6 +395,7 @@ Prefix Pht::linearize(Key k) const { ...@@ -348,6 +395,7 @@ Prefix Pht::linearize(Key k) const {
std::vector<Prefix> all_prefix; std::vector<Prefix> all_prefix;
all_prefix.reserve(k.size()); all_prefix.reserve(k.size());
/* Get the max size of the keyspec and take it for size limit (for padding) */
auto max = std::max_element(keySpec_.begin(), keySpec_.end(), auto max = std::max_element(keySpec_.begin(), keySpec_.end(),
[](const std::pair<std::string, size_t>& a, const std::pair<std::string, size_t>& b) { [](const std::pair<std::string, size_t>& a, const std::pair<std::string, size_t>& b) {
return a.second < b.second; return a.second < b.second;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment