long_id.h
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     // initialize the value of the node
00020     for (int i=0; i<num-1; i++)
00021       ints[i] = 0;
00022     ints[num-1] = value;
00023 
00024     // compute the level of this node
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     // equal
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     // equal
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     // get filename
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     // get path
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     //printf("level %d, file_size %d, path_size %d\n", level(), file_size, path_size);    
00159     //printf("Id %s gets path %s and file %s\n", toString().c_str(), path.c_str(), file.c_str());
00160   }
00161 
00162 
00163   unsigned getMaxDepth() const
00164   {
00165     unsigned bits = num*64-1;
00166     return (bits - (bits % 3)) / 3;
00167   }
00168 
00169   // Returns the id of the parent, moving up the tree by "generations" number of steps.
00170   LongId<num> getParent(unsigned int generations=1) const
00171   {
00172     // The parent doesn't exist, so it returns the invalid id.
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     // Computes the parent's level.
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 } // namespace
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


megatree_cpp
Author(s): Stuart Glaser
autogenerated on Thu Nov 28 2013 11:30:34