Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

FP.H

Go to the documentation of this file.
00001 // Copyright (C) 2001, Compaq Computer Corporation
00002 // 
00003 // This file is part of Vesta.
00004 // 
00005 // Vesta is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public
00007 // License as published by the Free Software Foundation; either
00008 // version 2.1 of the License, or (at your option) any later version.
00009 // 
00010 // Vesta is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // Lesser General Public License for more details.
00014 // 
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with Vesta; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 
00019 // Last modified on Fri Apr 22 16:37:51 EDT 2005 by irina.furman@intel.com 
00020 //      modified on Fri Jul 16 15:08:20 EDT 2004 by ken@xorian.net        
00021 //      modified on Fri Sep 19 13:31:08 PDT 1997 by heydon
00022 
00023 // FP -- fingerprints and fingerprint tags
00024 
00025 #ifndef _FP_H
00026 #define _FP_H
00027 
00028 /* A {\it fingerprint} is a 128-bit representation of a byte string. The
00029    representation is chosen so that identical strings have identical
00030    fingerprints, and so that different strings have different fingerprints
00031    with high probability. When the exact probability of a collision can be
00032    bounded, the fingerprint is said to satisfy the {\it probabilistic
00033    guarantee}.
00034 
00035    A fingerprint is simply the value of a string S viewed as a polynomial
00036    with coefficients in the field GF(2) modulo some irreducible polynomial P
00037    of degree 128. Unfortunately, fingerprints have the property that taking
00038    the fingerprint of the bytes comprising a fingerprint produces a
00039    fingerprint that no longer satisfies the probabilistic guarantee.
00040 
00041    However, a fingerprint can be scrambled by a random permutation to produce
00042    another 128-bit value called a {\it tag}. Tags have the property that tags
00043    of tags are secure with respect to the probabilistic guarantee. Hence,
00044    given strings "s1" and "s2", the following are all legal ways of combining
00045    the strings to form a single tag:
00046 
00047 |    1. Tag t1(s1 + s2);           // where + denotes string concatenation
00048 |    2. Tag t1(s1); t1.Extend(s2);
00049 |    3. Tag t1(s1), t2(s2); t1.Extend(t2);
00050 |    4. Tag t1(s1), t2(s2), t0(""); t0.Extend(t1); t0.Extend(t2);
00051 
00052    Techniques (1) and (2) produce equivalent tags. Techniques (3) and (4)
00053    are also legal. Technique (3) is probably the most convenient way to
00054    combine two tags.
00055 
00056    This interface exports a tagged fingerprint type "FP::Tag", a method for
00057    constructing tags from byte strings, and a function for extending an
00058    existing tag by a byte string. It also exports a type "FP::List" that
00059    represents a list of tagged fingerprints.
00060 
00061    IMPORTANT: Use of this interface assumes you are linking your application
00062    program with a garbage collector! Also, none of these classes defines an
00063    assignment operator, so objects are copied field-wise by default. This
00064    means that use of the assignment operator will produce aliases for those
00065    fields that are pointer types. */
00066 
00067 #include <Basics.H>
00068 #include <FS.H>
00069 #include <SRPC.H>
00070 #include <VestaLog.H>
00071 #include <Recovery.H>
00072 #include "Poly.H"
00073 
00074 namespace FP {
00075   class Tag;
00076 }
00077 
00078 int Compare(const FP::Tag& fp1, const FP::Tag& fp2) throw ();
00079 
00080 namespace FP {
00081     enum { ByteCnt = PolyVal::ByteCnt }; // tag bytes
00082     enum { WordCnt = PolyVal::WordCnt }; // tag words
00083 
00084     // True fingerprint type
00085     class Tag {
00086       public:
00087         /*** Constructors ***/
00088 
00089         Tag() throw () { /*SKIP*/ };
00090         /* Constructs a default (uninitialized) tag. WARNING: When this
00091            constructor is used, the bytes of the tag are undefined! To
00092            get the tag of the empty string, use 'Tag("", 0)'. */
00093 
00094         Tag(const char *s, int len = -1) throw ()
00095             { if (len < 0) len = strlen(s); Init(s, len); }
00096         /* Constructs a new tag from the "len" bytes pointed to by "s". If
00097            "len" is negative (defaulted), "s" is assumed to point to a
00098            null-terminated string, and the length of that string is used 
00099            as the size of the buffer. */
00100 
00101         Tag(const Text &t) throw () { Init(t.cchars(), t.Length()); }
00102         /* Constructs a new tag from the characters of "t". */
00103 
00104         Tag(RecoveryReader &rd) throw (VestaLog::Error, VestaLog::Eof)
00105             { Recover(rd); }
00106 
00107       Tag(std::istream &ifs) throw (FS::Failure, FS::EndOfFile)
00108             { Read(ifs); }
00109 
00110         Tag(SRPC &srpc) throw (SRPC::failure)
00111             { Recv(srpc); }
00112 
00113         /*** Extending Tags ***/
00114 
00115         Tag& Extend(const char *s, int len = -1) throw ();
00116         /* Destructively extend this tag by the "len" bytes pointed to by
00117            "s" and return the resulting tag. A negative value for "len" is
00118            treated as described in the constructor above. */
00119 
00120         Tag& Extend(const Text &t) throw ()
00121             { return this->Extend(t.cchars()); }
00122         /* Destructively extend this tag by the characters of "t". */
00123 
00124         Tag& Extend(const Tag &tag) throw ()
00125             {
00126               unsigned char bytes[FP::ByteCnt];
00127               tag.ToBytes(bytes);
00128               return this->Extend((char *)bytes,
00129                                   sizeof_assert(bytes, FP::ByteCnt));
00130             }
00131         /* Destructively extend this tag by the bytes of "tag". */
00132 
00133         Tag& Extend(char c) throw ();
00134         /* Destructively extend this tag by the single character "c". */
00135 
00136         /*** Extending Raw Fingerprints ***/
00137 
00138         void Unpermute(/*OUT*/ RawFP &fp) const throw ();
00139         /* Destructively set "fp" to the raw fingerprint of this tag. */
00140 
00141         static void ExtendRaw(/*INOUT*/ RawFP &fp, const char *s, int len = -1)
00142           throw ();
00143         static void ExtendRaw(/*INOUT*/ RawFP &fp, const Text &t) throw ()
00144             { ExtendRaw(/*INOUT*/ fp, t.cchars()); }
00145         static void ExtendRaw(/*INOUT*/ RawFP &fp, const Tag &tag) throw ()
00146             {
00147               unsigned char bytes[FP::ByteCnt];
00148               tag.ToBytes(bytes);
00149               ExtendRaw(/*INOUT*/ fp, (char *)(bytes),
00150                         sizeof_assert(bytes, FP::ByteCnt));
00151             }
00152         static void ExtendRaw(/*INOUT*/ RawFP &fp, char c) throw ();
00153         /* Extend the raw fingerprint "fp" by the bytes of "s", the characters
00154             of "t", the bytes of "tag", and the character "c", respectively. */
00155 
00156         void Permute(const RawFP &f) throw ();
00157         /* Destructively set this "FP::Tag" to the tag of the raw
00158            fingerprint "f". */
00159 
00160         /* If you need to extend a tag by several byte sequences in a row,
00161            it is more efficient to unscramble the tag into its raw fingerprint
00162            once, extend the raw fingerprint many times, and then scramble
00163            the raw fingerprint back into a tag once. These methods allow
00164            clients to do that. It is an unchecked error for these procedures
00165            to be used in any way other than a sequence of calls of the form:
00166 
00167              Unpermute  (ExtendRaw)+  Permute
00168         */
00169 
00170         /*** Logging/Recovery ***/
00171 
00172         void Log(VestaLog& log) const throw (VestaLog::Error)
00173             {
00174               unsigned char bytes[FP::ByteCnt];
00175               this->ToBytes(bytes);
00176               log.write((char *)bytes, FP::ByteCnt);
00177             }
00178         /* Append this tag to "log". Requires "log" to be
00179            in the "logging" state. */
00180  
00181         void Recover(RecoveryReader &rd) throw (VestaLog::Error, VestaLog::Eof)
00182             {
00183               unsigned char bytes[FP::ByteCnt];
00184               rd.readAll((char *)bytes, FP::ByteCnt);
00185               this->FromBytes(bytes);
00186             }
00187         /* Recover this fingerprint from "rd". */
00188 
00189         /*** Write/Read ***/
00190 
00191         /* Write/read this fingerprint to/from the given stream. */
00192         void Write(std::ostream &ofs) const throw (FS::Failure)
00193             {
00194               unsigned char bytes[FP::ByteCnt];
00195               this->ToBytes(bytes);
00196               FS::Write(ofs, (char *)(bytes), sizeof(bytes));
00197             }
00198         void Read(std::istream &ifs) throw (FS::EndOfFile, FS::Failure)
00199             {
00200               unsigned char bytes[FP::ByteCnt];
00201               FS::Read(ifs, (char *)(bytes), sizeof(bytes));
00202               this->FromBytes(bytes);
00203             }
00204 
00205         /*** Send/Receive ***/
00206 
00207         /* Send/receive the fingerprint to/from "srpc". */
00208         void Send(SRPC &srpc) const throw (SRPC::failure)
00209             {
00210               unsigned char bytes[FP::ByteCnt];
00211               this->ToBytes(bytes);
00212               srpc.send_bytes((char *)(bytes),
00213                               sizeof_assert(bytes, FP::ByteCnt));
00214             }
00215         void Recv(SRPC &srpc) throw (SRPC::failure)
00216             { 
00217               unsigned char bytes[FP::ByteCnt];
00218               int len = sizeof(bytes);
00219               srpc.recv_bytes_here((char *)(bytes), len);
00220               assert(len == FP::ByteCnt);
00221               this->FromBytes(bytes);
00222             }
00223 
00224         Word Hash() const throw ();
00225         /* Return a hash value for this fingerprint. */
00226 
00227         void Print(std::ostream &os, const char *word_separator = " ")
00228           const throw ();
00229         /* Print an ASCII representation of this tag. */
00230 
00231         // operators
00232         bool operator == (const Tag &other) const throw ();
00233         bool operator != (const Tag &other)const  throw ();
00234 
00235         // comparison
00236         friend int ::Compare(const Tag& fp1, const Tag& fp2) throw ();
00237         /* Return -1, 0, or 1 as "fp1" is less than, equal to, or greater
00238            than "fp2". */
00239 
00240         // size
00241         int Size() const throw () { return FP::ByteCnt; }
00242 
00243         // Convert a tag to a sequence of bytes, or fill in a tag from
00244         // a sequence of bytes.  These functions should be used rather
00245         // than Words below for portability.
00246         void ToBytes(unsigned char *buffer) const throw ();
00247         void FromBytes(const unsigned char *buffer) throw ();
00248 
00249         // accessor (should not be used by most clients)
00250         Word *Words() throw () { return this->w; }
00251         Word Word0() const throw () { return this->w[0]; }
00252         Word Word1() const throw () { return this->w[1]; }
00253 
00254       protected:
00255         // representation -- two 64-bit words
00256         // clients should treat this field as read-only
00257         Word w[WordCnt];
00258 
00259       private:
00260         void Init(const char *s, int len) throw ();
00261         /* Initialize this tag from the "len" bytes pointed to by "s". */
00262     };
00263 
00264     // a list of tags
00265     class List {
00266       public:
00267         // data fields
00268         FP::Tag *fp;                    // array of fingerprint values
00269         int len;                        // size of "fp" array
00270 
00271         // constructors/destructor
00272         List() throw ()
00273             { len = 0; fp = (FP::Tag *)NULL; }
00274         List(int len) throw ()
00275             {
00276               this->len = len;
00277               fp = NEW_PTRFREE_ARRAY(FP::Tag, len);
00278             }
00279         List(RecoveryReader &rd) throw (VestaLog::Error, VestaLog::Eof)
00280             { Recover(rd); }
00281         List(std::istream &ifs) throw (FS::EndOfFile, FS::Failure)
00282             { Read(ifs); }
00283         List(SRPC &srpc) throw (SRPC::failure)
00284             { Recv(srpc); }
00285 
00286         // size
00287         int Size() const throw ()
00288             { return sizeof(this->len) + (this->len * sizeof(FP::Tag)); }
00289 
00290         // log/recover
00291         void Log(VestaLog& log) const throw (VestaLog::Error);
00292         void Recover(RecoveryReader &rd)
00293           throw (VestaLog::Error, VestaLog::Eof);
00294 
00295         // write/read
00296         void Write(std::ostream &ofs) const throw (FS::Failure);
00297         void Read(std::istream &ifs) throw (FS::EndOfFile, FS::Failure);
00298 
00299         // send/receive
00300         void Send(SRPC &srpc) const throw (SRPC::failure);
00301         void Recv(SRPC &srpc) throw (SRPC::failure);
00302 
00303         // print
00304         void Print(std::ostream &os, int indent) const throw ();
00305         /* Print a list of fingerprints, each on its own line and indented by
00306            "indent" spaces. */
00307       private:
00308         // hide the copy constructor from clients
00309         List(const List&);
00310     };
00311 
00312   void FileContents(std::istream &ifs, /*INOUT*/ FP::Tag &fp)
00313     throw (FS::Failure);
00314   /* Extend the fingerprint tag "fp" with the bytes of the stream "ifs".
00315      "ifs" is read until end-of-file is encountered. */
00316 }
00317 
00318 inline std::ostream& operator << (std::ostream &os, const FP::Tag &fp) throw ()
00319 {
00320   fp.Print(os);
00321   return os;
00322 }
00323 
00324 #endif // _FP_H

Generated on Mon May 8 00:48:41 2006 for Vesta by  doxygen 1.4.2