1 /*  $Id: objlist.cpp 450705 2014-10-29 19:41:05Z vasilche $
2 * ===========================================================================
3 *
4 *                            PUBLIC DOMAIN NOTICE
5 *               National Center for Biotechnology Information
6 *
7 *  This software/database is a "United States Government Work" under the
8 *  terms of the United States Copyright Act.  It was written as part of
9 *  the author's official duties as a United States Government employee and
10 *  thus cannot be copyrighted.  This software/database is freely available
11 *  to the public for use. The National Library of Medicine and the U.S.
12 *  Government have not placed any restriction on its use or reproduction.
13 *
14 *  Although all reasonable efforts have been taken to ensure the accuracy
15 *  and reliability of the software and data, the NLM and the U.S.
16 *  Government do not and cannot warrant the performance or results that
17 *  may be obtained by using this software or data. The NLM and the U.S.
18 *  Government disclaim all warranties, express or implied, including
19 *  warranties of performance, merchantability or fitness for any particular
20 *  purpose.
21 *
22 *  Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Author: Eugene Vasilchenko
27 *
28 * File Description:
29 *   !!! PUT YOUR DESCRIPTION HERE !!!
30 *
31 */
32 
33 #include <ncbi_pch.hpp>
34 #include <corelib/ncbistd.hpp>
35 #include <serial/exception.hpp>
36 #include <serial/impl/objlist.hpp>
37 #include <serial/typeinfo.hpp>
38 #include <serial/impl/member.hpp>
39 #include <serial/impl/typeinfoimpl.hpp>
40 
41 #undef _TRACE
42 #define _TRACE(arg) ((void)0)
43 
44 BEGIN_NCBI_SCOPE
45 
CWriteObjectList(void)46 CWriteObjectList::CWriteObjectList(void)
47 {
48 }
49 
~CWriteObjectList(void)50 CWriteObjectList::~CWriteObjectList(void)
51 {
52 }
53 
Clear(void)54 void CWriteObjectList::Clear(void)
55 {
56     m_Objects.clear();
57     m_ObjectsByPtr.clear();
58 }
59 
RegisterObject(TTypeInfo typeInfo)60 void CWriteObjectList::RegisterObject(TTypeInfo typeInfo)
61 {
62     m_Objects.push_back(CWriteObjectInfo(typeInfo, NextObjectIndex()));
63 }
64 
65 #if _DEBUG
66 static inline
EndOf(TConstObjectPtr objectPtr,TTypeInfo objectType)67 TConstObjectPtr EndOf(TConstObjectPtr objectPtr, TTypeInfo objectType)
68 {
69     return CRawPointer::Add(objectPtr, TPointerOffsetType(objectType->GetSize()));
70 }
71 #endif
72 
73 const CWriteObjectInfo*
RegisterObject(TConstObjectPtr object,TTypeInfo typeInfo)74 CWriteObjectList::RegisterObject(TConstObjectPtr object, TTypeInfo typeInfo)
75 {
76     _TRACE("CWriteObjectList::RegisterObject("<<NStr::PtrToString(object)<<
77            ", "<<typeInfo->GetName()<<") size: "<<typeInfo->GetSize()<<
78            ", end: "<<NStr::PtrToString(EndOf(object, typeInfo)));
79     TObjectIndex index = NextObjectIndex();
80     CWriteObjectInfo info(object, typeInfo, index);
81 
82     if ( info.GetObjectRef() ) {
83         // special case with cObjects
84         if ( info.GetObjectRef()->ReferencedOnlyOnce() ) {
85             // unique reference -> do not remember pointer
86             // in debug mode check for absence of other references
87 #if _DEBUG
88             pair<TObjectsByPtr::iterator, bool> ins =
89                 m_ObjectsByPtr.insert(TObjectsByPtr::value_type(object, index));
90             if ( !ins.second ) {
91                 // not inserted -> already have the same object pointer
92                 // as reference counter is one -> error
93                 NCBI_THROW(CSerialException,eIllegalCall,
94                              "double write of CObject with counter == 1");
95             }
96 #endif
97             // new object
98             m_Objects.push_back(info);
99             return 0;
100         }
101         else if ( info.GetObjectRef()->Referenced() ) {
102             // multiple reference -> normal processing
103         }
104         else {
105             // not referenced -> error
106             NCBI_THROW(CSerialException,eIllegalCall,
107                          "registering non referenced CObject");
108         }
109     }
110 
111     pair<TObjectsByPtr::iterator, bool> ins =
112         m_ObjectsByPtr.insert(TObjectsByPtr::value_type(object, index));
113 
114     if ( !ins.second ) {
115         // not inserted -> already have the same object pointer
116         TObjectIndex oldIndex = ins.first->second;
117         CWriteObjectInfo& objectInfo = m_Objects[oldIndex];
118         _ASSERT(objectInfo.GetTypeInfo() == typeInfo);
119         return &objectInfo;
120     }
121 
122     // new object
123     m_Objects.push_back(info);
124 
125 #if _DEBUG
126     // check for overlapping with previous object
127     TObjectsByPtr::iterator check = ins.first;
128     if ( check != m_ObjectsByPtr.begin() ) {
129         --check;
130         if ( EndOf(check->first,
131                    m_Objects[check->second].GetTypeInfo()) > object )
132             NCBI_THROW(CSerialException,eFail, "overlapping objects");
133     }
134 
135     // check for overlapping with next object
136     check = ins.first;
137     if ( ++check != m_ObjectsByPtr.end() ) {
138         if ( EndOf(object, typeInfo) > check->first )
139             NCBI_THROW(CSerialException,eFail, "overlapping objects");
140     }
141 #endif
142 
143     return 0;
144 }
145 
ForgetObjects(TObjectIndex from,TObjectIndex to)146 void CWriteObjectList::ForgetObjects(TObjectIndex from, TObjectIndex to)
147 {
148     _ASSERT(from <= to);
149     _ASSERT(to <= GetObjectCount());
150     for ( TObjectIndex i = from; i < to; ++i ) {
151         CWriteObjectInfo& info = m_Objects[i];
152         TConstObjectPtr objectPtr = info.GetObjectPtr();
153         if ( objectPtr ) {
154             m_ObjectsByPtr.erase(objectPtr);
155             info.ResetObjectPtr();
156         }
157     }
158 }
159 
CReadObjectList(void)160 CReadObjectList::CReadObjectList(void)
161 {
162 }
163 
~CReadObjectList(void)164 CReadObjectList::~CReadObjectList(void)
165 {
166 }
167 
Clear(void)168 void CReadObjectList::Clear(void)
169 {
170     m_Objects.clear();
171 }
172 
RegisterObject(TTypeInfo typeInfo)173 void CReadObjectList::RegisterObject(TTypeInfo typeInfo)
174 {
175     m_Objects.push_back(CReadObjectInfo(typeInfo));
176 }
177 
RegisterObject(TObjectPtr objectPtr,TTypeInfo typeInfo)178 void CReadObjectList::RegisterObject(TObjectPtr objectPtr, TTypeInfo typeInfo)
179 {
180     m_Objects.push_back(CReadObjectInfo(objectPtr, typeInfo));
181 }
182 
183 const CReadObjectInfo&
GetRegisteredObject(TObjectIndex index) const184 CReadObjectList::GetRegisteredObject(TObjectIndex index) const
185 {
186     if ( index >= GetObjectCount() )
187         NCBI_THROW(CSerialException,eFail, "invalid object index");
188     return m_Objects[index];
189 }
190 
ForgetObjects(TObjectIndex from,TObjectIndex to)191 void CReadObjectList::ForgetObjects(TObjectIndex from, TObjectIndex to)
192 {
193     _ASSERT(from <= to);
194     _ASSERT(to <= GetObjectCount());
195     for ( TObjectIndex i = from; i < to; ++i ) {
196         m_Objects[i].ResetObjectPtr();
197     }
198 }
199 
200 END_NCBI_SCOPE
201