Modifying exception throwing in Sync::Digest

Now there are more diagnostic information attached to each exception
diff --git a/model/sync-diff-leaf.cc b/model/sync-diff-leaf.cc
index 59e0fc1..0790ec7 100644
--- a/model/sync-diff-leaf.cc
+++ b/model/sync-diff-leaf.cc
@@ -21,6 +21,8 @@
  */
 
 #include "sync-diff-leaf.h"
+#include <boost/throw_exception.hpp>
+typedef boost::error_info<struct tag_errmsg, std::string> errmsg_info; 
 
 namespace Sync {
 
@@ -36,4 +38,35 @@
 {
 }
 
+std::ostream &
+operator << (std::ostream &os, Operation op)
+{
+  switch (op)
+    {
+    case UPDATE:
+      os << "update";
+      break;
+    case REMOVE:
+      os << "remove";
+      break;
+    }
+  return os;
+}
+
+std::istream &
+operator >> (std::istream &is, Operation &op)
+{
+  std::string operation;
+  is >> operation;
+  if (operation == "update")
+    op = UPDATE;
+  else if (operation == "remove")
+    op = REMOVE;
+  else
+    BOOST_THROW_EXCEPTION (SyncDiffLeafOperationParseError () << errmsg_info (operation));
+
+  return is;
+}
+
+
 }
diff --git a/model/sync-diff-leaf.h b/model/sync-diff-leaf.h
index 084b5fc..a4b6538 100644
--- a/model/sync-diff-leaf.h
+++ b/model/sync-diff-leaf.h
@@ -24,6 +24,7 @@
 #define SYNC_DIFF_LEAF_H
 
 #include "sync-leaf.h"
+#include <boost/exception/all.hpp>
 
 namespace Sync {
 
@@ -74,6 +75,14 @@
 
 typedef boost::shared_ptr<DiffLeaf> DiffLeafPtr;
 
+std::ostream &
+operator << (std::ostream &os, Operation op);
+
+std::istream &
+operator >> (std::istream &is, Operation &op);
+
+struct SyncDiffLeafOperationParseError : virtual boost::exception, virtual std::exception { };
+
 } // Sync
 
 #endif // SYNC_DIFF_LEAF_H
diff --git a/model/sync-digest.cc b/model/sync-digest.cc
index 621b52b..d8dda5c 100644
--- a/model/sync-digest.cc
+++ b/model/sync-digest.cc
@@ -24,7 +24,9 @@
 #include <string.h>
 
 #include <boost/assert.hpp>
-#include <boost/exception/errinfo_at_line.hpp>
+#include <boost/throw_exception.hpp>
+typedef boost::error_info<struct tag_errmsg, std::string> errmsg_info_str; 
+typedef boost::error_info<struct tag_errmsg, int> errmsg_info_int; 
 
 // for printing, may be disabled in optimized build
 
@@ -86,7 +88,7 @@
     if ((unsigned)ch < 128)
       value = lookup_table [(unsigned)ch];
     if (value == -1)
-      throw Sync::DigestCalculationError () << errinfo_at_line (__LINE__);
+      BOOST_THROW_EXCEPTION (Sync::DigestCalculationError () << errmsg_info_int ((int)ch));
     
     return value;
   }
@@ -137,7 +139,9 @@
 
   int ok = EVP_DigestInit_ex (m_context, HASH_FUNCTION (), 0);
   if (!ok)
-    throw DigestCalculationError () << errinfo_at_line (__LINE__);
+    BOOST_THROW_EXCEPTION (DigestCalculationError ()
+                           << errmsg_info_str ("EVP_DigestInit_ex returned error")
+                           << errmsg_info_int (ok));
 }
 
 
@@ -151,7 +155,9 @@
   int ok = EVP_DigestFinal_ex (m_context,
 			       m_buffer, &m_hashLength);
   if (!ok)
-    throw DigestCalculationError () << errinfo_at_line (__LINE__);
+    BOOST_THROW_EXCEPTION (DigestCalculationError ()
+                           << errmsg_info_str ("EVP_DigestFinal_ex returned error")
+                           << errmsg_info_int (ok));
 }
   
 std::size_t
@@ -161,7 +167,9 @@
     finalize ();
 
   if (sizeof (std::size_t) > m_hashLength)
-    throw DigestCalculationError () << errinfo_at_line (__LINE__);
+    BOOST_THROW_EXCEPTION (DigestCalculationError ()
+                           << errmsg_info_str ("Hash length is less than size_t")
+                           << errmsg_info_int (m_hashLength));
   
   // just getting first sizeof(std::size_t) bytes
   // not ideal, but should work pretty well
@@ -171,10 +179,19 @@
 bool
 Digest::operator == (const Digest &digest) const
 {
-  if (m_buffer == 0 || digest.m_buffer == 0)
-    throw DigestCalculationError () << errinfo_at_line (__LINE__);
-  
-  BOOST_ASSERT (m_hashLength == digest.m_hashLength);
+  if (m_buffer == 0)
+    BOOST_THROW_EXCEPTION (DigestCalculationError ()
+                           << errmsg_info_str ("Digest1 is empty"));
+
+  if (digest.m_buffer == 0)
+    BOOST_THROW_EXCEPTION (DigestCalculationError ()
+                           << errmsg_info_str ("Digest2 is empty"));
+
+  if (m_hashLength != digest.m_hashLength)
+    BOOST_THROW_EXCEPTION (DigestCalculationError ()
+                           << errmsg_info_str ("Digest lengths are not the same")
+                           << errmsg_info_int (m_hashLength)
+                           << errmsg_info_int (digest.m_hashLength));
 
   return memcmp (m_buffer, digest.m_buffer, m_hashLength) == 0;
 }
@@ -187,11 +204,14 @@
   
   // cannot update Digest when it has been finalized
   if (m_buffer != 0)
-    throw DigestCalculationError () << errinfo_at_line (__LINE__);
+    BOOST_THROW_EXCEPTION (DigestCalculationError ()
+                           << errmsg_info_str ("Digest has been already finalized"));
 
   bool ok = EVP_DigestUpdate (m_context, buffer, size);
   if (!ok)
-    throw DigestCalculationError () << errinfo_at_line (__LINE__);
+    BOOST_THROW_EXCEPTION (DigestCalculationError ()
+                           << errmsg_info_str ("EVP_DigestUpdate returned error")
+                           << errmsg_info_int (ok));
 }
 
 
@@ -199,7 +219,8 @@
 Digest::operator << (const Digest &src)
 {
   if (src.m_buffer == 0) 
-    throw DigestCalculationError () << errinfo_at_line (__LINE__);
+    BOOST_THROW_EXCEPTION (DigestCalculationError ()
+                           << errmsg_info_str ("Digest has not been yet finalized"));
 
   update (src.m_buffer, src.m_hashLength);
 
@@ -227,14 +248,16 @@
   is >> str; // read string first
 
   if (str.size () == 0)
-    throw DigestCalculationError () << errinfo_at_line (__LINE__);
+    BOOST_THROW_EXCEPTION (DigestCalculationError ()
+                           << errmsg_info_str ("Input is empty"));
   
   // uint8_t padding = (3 - str.size () % 3) % 3;
   // for (uint8_t i = 0; i < padding; i++) str.push_back ('=');
 
   // only empty digest object can be used for reading
   if (digest.m_buffer != 0)
-    throw DigestCalculationError () << errinfo_at_line (__LINE__);
+    BOOST_THROW_EXCEPTION (DigestCalculationError ()
+                           << errmsg_info_str ("Digest has been already finalized"));
 
   digest.m_buffer = new uint8_t [EVP_MAX_MD_SIZE];
   uint8_t *end = copy (string_to_binary (str.begin ()),
diff --git a/model/sync-digest.h b/model/sync-digest.h
index 52072d2..04e6d13 100644
--- a/model/sync-digest.h
+++ b/model/sync-digest.h
@@ -130,7 +130,7 @@
   uint32_t m_hashLength;
 };
 
-struct DigestCalculationError : virtual boost::exception { };
+struct DigestCalculationError : virtual boost::exception, virtual std::exception { };
 
 typedef boost::shared_ptr<Digest> DigestPtr;
 typedef boost::shared_ptr<const Digest> DigestConstPtr;