1 // =================================
  2 // Copyright (c) 2021 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System;
  7 using System.Collections;
  8 
  9 namespace System.Xml.Serialization
 10 {
 11     // XmlPtrBase contains an object id (UUID) of an object it points to.
 12     // The Resolve member function retrieves a proxy object from an XML container,
 13     // obtains an object pointer from the proxy and calls the SetPtr member function
 14     // of the derived class.
 15     //
 16     // Each derived class implements the SetPtr member function that sets the pointer contained by the derived class.
 17 
 18     public abstract class XmlPtrBase
 19     {
 20         public nothrow XmlPtrBase() : targetObjectId(Uuid())
 21         {
 22         }
 23         public virtual ~XmlPtrBase()
 24         {
 25         }
 26         public nothrow const Uuid& TargetObjectId() const
 27         {
 28             return targetObjectId;
 29         }
 30         public nothrow void SetTargetObjectId(const Uuid& targetObjectId_)
 31         {
 32             targetObjectId = targetObjectId_;
 33         }
 34         public abstract nothrow XmlSerializable Interface() const;
 35         public nothrow void Resolve(XmlContainer* container)
 36         {
 37             XmlSerializableProxy* proxy = container->Get(targetObjectId);
 38             if (proxy != null)
 39             {
 40                 SetPtr(proxy->Object());
 41             }
 42         }
 43         public abstract nothrow void* GetPtr() const;
 44         public abstract nothrow void SetPtr(void* p);
 45         private Uuid targetObjectId;
 46     }
 47 
 48     // XmlPtr<T> is like an ordinary pointer with no ownership semantics,
 49     // but it derives from the XmlPtrBase that contains an object id for the pointed-to object.
 50 
 51     public class XmlPtr<T> : XmlPtrBase
 52     {
 53         private typedef XmlPtr<T> Self;
 54 
 55         public nothrow XmlPtr() : base()ptr(null)
 56         {
 57         }
 58         public explicit nothrow XmlPtr(T* ptr_) : base()ptr(ptr_)
 59         {
 60             SetId();
 61         }
 62         public nothrow void operator=(T* ptr_)
 63         {
 64             ptr = ptr_;
 65             SetId();
 66         }
 67         public nothrow void Reset(T* ptr_)
 68         {
 69             ptr = ptr_;
 70             SetId();
 71         }
 72         public nothrow void Reset()
 73         {
 74             ptr = null;
 75             SetId();
 76         }
 77         public inline nothrow T* Get() const
 78         {
 79             return ptr;
 80         }
 81         public inline nothrow bool IsNull() const
 82         {
 83             return ptr == null;
 84         }
 85         public inline nothrow T* operator->()
 86         {
 87             return ptr;
 88         }
 89         public inline nothrow const T* operator->() const
 90         {
 91             return ptr;
 92         }
 93         public inline nothrow T& operator*()
 94         {
 95             return *ptr;
 96         }
 97         public inline nothrow const T& operator*() const
 98         {
 99             return *ptr;
100         }
101         public override nothrow void* GetPtr() const
102         {
103             return ptr;
104         }
105         public override nothrow void SetPtr(void* p)
106         {
107             ptr = cast<T*>(p);
108         }
109         public override nothrow XmlSerializable Interface() const
110         {
111             XmlSerializable intf = *Get();
112             return intf;
113         }
114         private nothrow void SetId()
115         {
116             if (!IsNull())
117             {
118                 XmlSerializable intf = *Get();
119                 SetTargetObjectId(intf.ObjectId());
120             }
121             else
122             {
123                 SetTargetObjectId(Uuid());
124             }
125         }
126         private T* ptr;
127     }
128 
129     public nothrow bool operator==<T>(const XmlPtr<T>& leftconst XmlPtr<T>& right)
130     {
131         return left.Get() == right.Get();
132     }
133 
134     public nothrow bool operator<<T>(const XmlPtr<T>& leftconst XmlPtr<T>& right)
135     {
136         return left.Get() < right.Get();
137     }
138 
139     // UniqueXmlPtr<T> is like a UniquePtr<T> but in addition it derives from the XmlPtrBase,
140     // that contains an object id for the pointed-to object.
141 
142     public class UniqueXmlPtr<T> : XmlPtrBase
143     {
144         private typedef UniqueXmlPtr<T> Self;
145 
146         public nothrow UniqueXmlPtr() : ptr()
147         {
148         }
149         public explicit nothrow UniqueXmlPtr(T* ptr_) : ptr(ptr_)
150         {
151             SetIdAndOwned();
152         }
153         suppress UniqueXmlPtr(const Self&);
154         public nothrow void operator=(T* ptr_)
155         {
156             ptr = ptr_;
157             SetIdAndOwned();
158         }
159         suppress void operator=(const Self&);
160         public nothrow void Reset()
161         {
162             ptr.Reset();
163             SetIdAndOwned();
164         }
165         public nothrow void Reset(T* ptr_)
166         {
167             ptr.Reset(ptr_);
168             SetIdAndOwned();
169         }
170         public inline nothrow T* Get()
171         {
172             return ptr.Get();
173         }
174         public inline nothrow T* Release()
175         {
176             T* p = ptr.Release();
177             if (p != null)
178             {
179                 XmlSerializable intf = *p;
180                 intf.ResetOwned();
181             }
182             SetIdAndOwned();
183             return p;
184         }
185         public inline nothrow bool IsNull() const
186         {
187             return ptr.IsNull();
188         }
189         public inline nothrow T* operator->()
190         {
191             return ptr.Get();
192         }
193         public inline nothrow const T* operator->() const
194         {
195             return ptr.Get();
196         }
197         public inline nothrow T& operator*()
198         {
199             return *ptr;
200         }
201         public inline nothrow const T& operator*() const
202         {
203             return *ptr;
204         }
205         public override nothrow void* GetPtr() const
206         {
207             return ptr.Get();
208         }
209         public override nothrow void SetPtr(void* p)
210         {
211             ptr.Reset(cast<T*>(p));
212             if (p != null)
213             {
214                 XmlSerializable intf = *Get();
215                 intf.SetOwned();
216             }
217         }
218         public override nothrow XmlSerializable Interface() const
219         {
220             XmlSerializable intf = *Get();
221             return intf;
222         }
223         private nothrow void SetIdAndOwned()
224         {
225             if (!IsNull())
226             {
227                 XmlSerializable intf = *Get();
228                 SetTargetObjectId(intf.ObjectId());
229                 intf.SetOwned();
230             }
231             else
232             {
233                 SetTargetObjectId(Uuid());
234             }
235         }
236         private UniquePtr<T> ptr;
237     }
238 
239     public nothrow bool operator==<T>(const UniqueXmlPtr<T>& leftconst UniqueXmlPtr<T>& right)
240     {
241         return left.Get() == right.Get();
242     }
243 
244     public nothrow bool operator<<T>(const UniqueXmlPtr<T>& leftconst UniqueXmlPtr<T>& right)
245     {
246         return left.Get() < right.Get();
247     }
248 }
249