Go to the documentation of this file.00001 #ifndef MEGATREE_LONG_ID_H
00002 #define MEGATREE_LONG_ID_H
00003
00004 #include <cstdio>
00005 #include <boost/cstdint.hpp>
00006 #include <assert.h>
00007 #include <iostream>
00008 #include <math.h>
00009
00010 namespace megatree
00011 {
00012
00013 template <int num>
00014 class LongId
00015 {
00016 public:
00017 LongId<num>(uint64_t value=0)
00018 {
00019
00020 for (int i=0; i<num-1; i++)
00021 ints[i] = 0;
00022 ints[num-1] = value;
00023
00024
00025 id_level = 0;
00026 while (value != 0)
00027 {
00028 value >>= 3;
00029 id_level++;
00030 }
00031 }
00032
00033
00034 bool operator < (const LongId<num>& value) const
00035 {
00036 for (int i=0; i<num; i++)
00037 {
00038 if (ints[i] < value.ints[i])
00039 return true;
00040 else if (ints[i] > value.ints[i])
00041 return false;
00042 }
00043
00044
00045 return false;
00046 }
00047
00048 bool operator == (const LongId<num>& value) const
00049 {
00050 if (id_level != value.id_level)
00051 return false;
00052
00053 for (int i=0; i<num; i++)
00054 {
00055 if (ints[i] != value.ints[i])
00056 return false;
00057 }
00058
00059
00060 return true;
00061 }
00062
00063 LongId<num> &operator=(const LongId<num> &o)
00064 {
00065 id_level = o.id_level;
00066 for (int i = 0; i < num; ++i)
00067 ints[i] = o.ints[i];
00068 return *this;
00069 }
00070
00071
00072 bool operator != (const LongId<num>& value) const
00073 {
00074 return !(*this == value);
00075 }
00076
00077
00078
00079 unsigned int level() const
00080 {
00081 return id_level;
00082 }
00083
00084
00085 bool isRoot() const
00086 {
00087 return (id_level == 1);
00088 }
00089 bool isRootFile() const
00090 {
00091 return id_level == 0;
00092 }
00093
00094 bool isValid() const
00095 {
00096 return (id_level != 0);
00097 }
00098
00099
00100 uint8_t getChildNr() const
00101 {
00102 return ints[num-1] & 7;
00103 }
00104
00105 int getBit(int bit) const
00106 {
00107 assert(bit <= 63);
00108 return (ints[num-1] >> bit) & 1;
00109 }
00110
00111 int getBits(uint8_t nr_bits) const
00112 {
00113 return (ints[num-1] & ((1 << nr_bits)-1));
00114 }
00115
00116
00117 std::string toString() const
00118 {
00119 LongId<num> id = *this;
00120 std::string s;
00121 s.resize(level()+1);
00122 int i = s.size();
00123 while (id.isValid())
00124 {
00125 s[--i] = (char)((int)'0'+(id.ints[num-1] & 7));
00126 id = id.getParent();
00127 }
00128 s[--i] = '0';
00129 return s;
00130 }
00131
00132 void toPath(unsigned folder_depth, std::string& path, std::string& file) const
00133 {
00134 LongId<num> id = *this;
00135 int file_size = level()%folder_depth;
00136 int path_size = (level() - file_size);
00137
00138
00139 file.resize(file_size+1);
00140 for (int i=file_size; i>0; i--)
00141 {
00142 file[i] = (char)((int)'0'+(id.ints[num-1] & 7));
00143 id = id.getParent();
00144 }
00145 file[0] = 'f';
00146
00147
00148 path.resize(path_size + path_size/folder_depth);
00149 int count = path.size();
00150 for (int i=0; i<path_size; i++)
00151 {
00152 if (i%folder_depth == 0)
00153 path[--count] = '/';
00154 path[--count] = (char)((int)'0'+(id.ints[num-1] & 7));
00155 id = id.getParent();
00156 }
00157
00158
00159
00160 }
00161
00162
00163 unsigned getMaxDepth() const
00164 {
00165 unsigned bits = num*64-1;
00166 return (bits - (bits % 3)) / 3;
00167 }
00168
00169
00170 LongId<num> getParent(unsigned int generations=1) const
00171 {
00172
00173 if (generations >= id_level)
00174 return LongId<num>();
00175
00176 assert(3*generations < 64);
00177 unsigned int shift = 3*generations;
00178
00179 LongId<num> parent;
00180
00181 for (int i = num - 1; i > 0; i--)
00182 {
00183 parent.ints[i] = (ints[i] >> shift) + ((ints[i-1] & ((1 << shift)-1)) << (64-shift));
00184 }
00185 parent.ints[0] = ints[0] >> shift;
00186
00187
00188 parent.id_level = id_level - generations;
00189
00190 return parent;
00191 }
00192
00193
00194
00195 LongId<num> getChild(int child_nr) const
00196 {
00197 LongId<num> child;
00198
00199 uint64_t oct = 7;
00200 oct <<= 61;
00201 for (int i=0; i<num-1; i++)
00202 {
00203 child.ints[i] = (ints[i] << 3) + ((ints[i+1] & oct) >> 61);
00204 }
00205 child.ints[num-1] = (ints[num-1] << 3) + child_nr;
00206 child.id_level = id_level+1;
00207
00208 assert(id_level < num*64/3);
00209
00210 return child;
00211 }
00212
00213
00214 int size() const
00215 {
00216 return num;
00217 }
00218
00219 uint64_t ints[num];
00220 unsigned int id_level;
00221
00222 };
00223
00224
00225 template <int num>
00226 std::ostream& operator << (std::ostream& os, const LongId<num>& value)
00227 {
00228 for (int i=0; i<(int)value.size(); i++)
00229 os << value.toString();
00230 return os;
00231 }
00232
00233
00234 typedef LongId<2> IdType;
00235
00236
00237
00238
00239
00240
00241
00242 }
00243
00244 #include <tr1/unordered_map>
00245 namespace std {
00246 namespace tr1 {
00247 template <>
00248 struct hash<megatree::LongId<2> >
00249 {
00250 std::size_t operator()(const megatree::LongId<2>& li) const {
00251 std::tr1::hash<uint64_t> hasher;
00252 return hasher(li.ints[0] ^ li.ints[1]);
00253 }
00254 };
00255 }
00256 }
00257
00258 #endif