From b2b8dba6c149407d6657398a874c75629871d21a Mon Sep 17 00:00:00 2001
From: Boris Kolpackov <boris@codesynthesis.com>
Date: Mon, 18 Apr 2011 11:15:37 +0200
Subject: Fix loaded() function in lazy_ptr to conform to documentation

---
 odb/lazy-ptr-impl.hxx |  2 +-
 odb/lazy-ptr.hxx      | 16 ++++++++++++++++
 odb/lazy-ptr.ixx      |  6 ++++--
 odb/lazy-ptr.txx      | 20 ++++++++++++++++----
 odb/tr1/lazy-ptr.hxx  | 10 +++++++++-
 odb/tr1/lazy-ptr.ixx  |  6 ++++--
 odb/tr1/lazy-ptr.txx  | 20 ++++++++++++++++----
 7 files changed, 66 insertions(+), 14 deletions(-)

diff --git a/odb/lazy-ptr-impl.hxx b/odb/lazy-ptr-impl.hxx
index d51228a..58a1cd5 100644
--- a/odb/lazy-ptr-impl.hxx
+++ b/odb/lazy-ptr-impl.hxx
@@ -63,7 +63,7 @@ namespace odb
     typedef void* lazy_ptr_base::*unspecified_bool_type;
     operator unspecified_bool_type () const
     {
-      return id_ != 0 ? &lazy_ptr_base::id_ : 0;
+      return db_ != 0 ? &lazy_ptr_base::id_ : 0;
     }
 
     operator lazy_ptr_impl_ref ();
diff --git a/odb/lazy-ptr.hxx b/odb/lazy-ptr.hxx
index 9eb8af8..b181639 100644
--- a/odb/lazy-ptr.hxx
+++ b/odb/lazy-ptr.hxx
@@ -53,7 +53,15 @@ namespace odb
   public:
     typedef odb::database database_type;
 
+    //  NULL      loaded()
+    //
+    //  true       true      NULL pointer to transient object
+    //  false      true      valid pointer to persistent object
+    //  true       false     unloaded pointer to persistent object
+    //  false      false     valid pointer to transient object
+    //
     bool loaded () const;
+
     T* load () const;
 
     // Unload the pointer. For transient objects this function is
@@ -154,7 +162,15 @@ namespace odb
   public:
     typedef odb::database database_type;
 
+    //  NULL      loaded()
+    //
+    //  true       true      NULL pointer to transient object
+    //  false      true      valid pointer to persistent object
+    //  true       false     unloaded pointer to persistent object
+    //  false      false     valid pointer to transient object
+    //
     bool loaded () const;
+
     std::auto_ptr<T>& load () const;
 
     // Unload the pointer. For transient objects this function is
diff --git a/odb/lazy-ptr.ixx b/odb/lazy-ptr.ixx
index 8035923..d682ba5 100644
--- a/odb/lazy-ptr.ixx
+++ b/odb/lazy-ptr.ixx
@@ -108,7 +108,8 @@ namespace odb
   inline bool lazy_ptr<T>::
   loaded () const
   {
-    return p_ || !i_;
+    bool i (i_);
+    return (p_ == 0) != i; // !p_ XOR i
   }
 
   template <class T>
@@ -361,7 +362,8 @@ namespace odb
   inline bool lazy_auto_ptr<T>::
   loaded () const
   {
-    return p_.get () != 0 || !i_;
+    bool i (i_);
+    return (p_.get () == 0) != i; // XOR
   }
 
   template <class T>
diff --git a/odb/lazy-ptr.txx b/odb/lazy-ptr.txx
index 56f1473..0b7bbea 100644
--- a/odb/lazy-ptr.txx
+++ b/odb/lazy-ptr.txx
@@ -14,12 +14,24 @@ namespace odb
   bool lazy_ptr<T>::
   equal (const lazy_ptr<Y>& r) const
   {
-    if (loaded () && r.loaded ())
+    bool t1 ((p_ == 0) == loaded ());
+    bool t2 ((r.p_ == 0) == r.loaded ());
+
+    // If both are transient, then compare the underlying pointers.
+    //
+    if (t1 && t2)
       return p_ == r.p_;
 
-    // If one of the object is not loaded, then we compare databases and
-    // object ids. Note that NULL pointers cannot have non-NULL databases
-    // and if both of them are NULL, we wouldn't have gotten here.
+    // If one is transient and the other is persistent, then compare
+    // the underlying pointers but only if they are non NULL. Note
+    // that an unloaded persistent object is always unequal to a
+    // transient object.
+    //
+    if (t1 || t2)
+      return p_ == r.p_ && p_ != 0;
+
+    // If both objects are persistent, then we compare databases and
+    // object ids.
     //
     typedef typename object_traits<T>::object_type object_type1;
     typedef typename object_traits<Y>::object_type object_type2;
diff --git a/odb/tr1/lazy-ptr.hxx b/odb/tr1/lazy-ptr.hxx
index 0c2cbce..52b1b03 100644
--- a/odb/tr1/lazy-ptr.hxx
+++ b/odb/tr1/lazy-ptr.hxx
@@ -84,7 +84,15 @@ namespace odb
     public:
       typedef odb::database database_type;
 
+      //  NULL      loaded()
+      //
+      //  true       true      NULL pointer to transient object
+      //  false      true      valid pointer to persistent object
+      //  true       false     unloaded pointer to persistent object
+      //  false      false     valid pointer to transient object
+      //
       bool loaded () const;
+
       std::tr1::shared_ptr<T> load () const;
 
       // Unload the pointer. For transient objects this function is
@@ -186,7 +194,7 @@ namespace odb
       //  true       true      expired pointer to transient object
       //  false      true      valid pointer to persistent object
       //  true       false     expired pointer to persistent object
-      //  false      false     valid pointer to transiend object
+      //  false      false     valid pointer to transient object
       //
       bool loaded () const;
 
diff --git a/odb/tr1/lazy-ptr.ixx b/odb/tr1/lazy-ptr.ixx
index 5e99e98..3460e99 100644
--- a/odb/tr1/lazy-ptr.ixx
+++ b/odb/tr1/lazy-ptr.ixx
@@ -192,7 +192,8 @@ namespace odb
     inline bool lazy_shared_ptr<T>::
     loaded () const
     {
-      return p_ || !i_;
+      bool i (i_);
+      return !p_ != i; // !p_ XOR i_
     }
 
     template <class T>
@@ -524,7 +525,8 @@ namespace odb
     inline bool lazy_weak_ptr<T>::
     loaded () const
     {
-      return !expired () || !i_;
+      bool i (i_);
+      return expired () != i; // expired () XOR i_
     }
 
     template <class T>
diff --git a/odb/tr1/lazy-ptr.txx b/odb/tr1/lazy-ptr.txx
index 49c3799..bdce2b4 100644
--- a/odb/tr1/lazy-ptr.txx
+++ b/odb/tr1/lazy-ptr.txx
@@ -16,12 +16,24 @@ namespace odb
     bool lazy_shared_ptr<T>::
     equal (const lazy_shared_ptr<Y>& r) const
     {
-      if (loaded () && r.loaded ())
+      bool t1 (!p_ == loaded ());
+      bool t2 (!r.p_ == r.loaded ());
+
+      // If both are transient, then compare the underlying pointers.
+      //
+      if (t1 && t2)
         return p_ == r.p_;
 
-      // If one of the object is not loaded, then we compare databases and
-      // object ids. Note that NULL pointers cannot have non-NULL databases
-      // and if both of them are NULL, we wouldn't have gotten here.
+      // If one is transient and the other is persistent, then compare
+      // the underlying pointers but only if they are non NULL. Note
+      // that an unloaded persistent object is always unequal to a
+      // transient object.
+      //
+      if (t1 || t2)
+        return p_ == r.p_ && p_;
+
+      // If both objects are persistent, then we compare databases and
+      // object ids.
       //
       typedef typename object_traits<T>::object_type object_type1;
       typedef typename object_traits<Y>::object_type object_type2;
-- 
cgit v1.1