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