1 /* $Id: objstack.cpp 570512 2018-09-10 18:52:20Z gouriano $ 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 #include <ncbi_pch.hpp> 33 #include <corelib/ncbistd.hpp> 34 #include <serial/impl/objstack.hpp> 35 #include <serial/impl/ptrinfo.hpp> 36 #include <serial/impl/continfo.hpp> 37 #include <serial/impl/classinfob.hpp> 38 39 BEGIN_NCBI_SCOPE 40 41 static const size_t KInitialStackSize = 16; 42 CObjectStack(void)43CObjectStack::CObjectStack(void) 44 { 45 TFrame* stack = m_Stack = m_StackPtr = new TFrame[KInitialStackSize]; 46 m_StackEnd = stack + KInitialStackSize; 47 for ( size_t i = 0; i < KInitialStackSize; ++i ) { 48 m_Stack[i].Reset(); 49 } 50 m_WatchPathHooks = m_PathValid = false; 51 } 52 ~CObjectStack(void)53CObjectStack::~CObjectStack(void) 54 { 55 delete[] m_Stack; 56 } 57 ResetState(void)58void CObjectStack::ResetState(void) 59 { 60 m_PathValid = false; 61 } 62 ResetPathHooks(void)63void CObjectStack::ResetPathHooks(void) 64 { 65 for (auto& h : m_PathHooks) { 66 h->Erase(this); 67 } 68 m_PathHooks.clear(); 69 } 70 UnendedFrame(void)71void CObjectStack::UnendedFrame(void) 72 { 73 } 74 ClearStack(void)75void CObjectStack::ClearStack(void) 76 { 77 m_StackPtr = m_Stack; 78 } 79 GetStackTraceASN(void) const80string CObjectStack::GetStackTraceASN(void) const 81 { 82 if (!GetStackDepth()) { 83 return "stack is empty"; 84 } 85 // _ASSERT(FetchFrameFromBottom(0).m_FrameType == TFrame::eFrameNamed); 86 // _ASSERT(FetchFrameFromBottom(0).m_TypeInfo); 87 string stack = FetchFrameFromBottom(0).HasTypeInfo() ? 88 FetchFrameFromBottom(0).m_TypeInfo->GetName() : "?"; 89 for ( size_t i = 1; i < GetStackDepth(); ++i ) { 90 const TFrame& frame = FetchFrameFromBottom(i); 91 switch ( frame.m_FrameType ) { 92 case TFrame::eFrameClassMember: 93 case TFrame::eFrameChoiceVariant: 94 { 95 if ( !frame.m_MemberId ) { 96 _ASSERT(i == GetStackDepth() - 1); 97 } 98 else { 99 const CMemberId& id = *frame.m_MemberId; 100 stack += '.'; 101 if ( !id.GetName().empty() ) { 102 stack += id.GetName(); 103 } 104 else { 105 stack += '['; 106 stack += NStr::IntToString(id.GetTag()); 107 stack += ']'; 108 } 109 } 110 } 111 break; 112 case TFrame::eFrameArrayElement: 113 stack += ".E"; 114 break; 115 default: 116 break; 117 } 118 } 119 return stack; 120 } 121 PushFrameLong(void)122CObjectStack::TFrame& CObjectStack::PushFrameLong(void) 123 { 124 size_t depth = m_StackPtr - m_Stack; 125 size_t oldSize = m_StackEnd - m_Stack; 126 size_t newSize = oldSize * 2; 127 TFrame* newStack = new TFrame[newSize]; 128 129 { 130 // copy old stack 131 for ( size_t i = 0; i < oldSize; ++i ) 132 newStack[i] = m_Stack[i]; 133 } 134 { 135 // clear new area of new stack 136 for ( size_t i = oldSize; i < newSize; ++i ) 137 newStack[i].Reset(); 138 } 139 140 delete[] m_Stack; 141 142 m_Stack = newStack; 143 m_StackEnd = newStack + newSize; 144 145 return *(m_StackPtr = (newStack + depth + 1)); 146 } 147 IsNsQualified(void)148bool CObjectStack::IsNsQualified(void) 149 { 150 if (StackIsEmpty()) { 151 return true; 152 } 153 ENsQualifiedMode mode; 154 if (TopFrame().HasTypeInfo()) { 155 if (!TopFrame().GetTypeInfo()->GetModuleName().empty()) { 156 return true; 157 } 158 } 159 size_t i, count = GetStackDepth(); 160 for (i=0; i<count; ++i) { 161 162 CObjectStack::TFrame& frame = FetchFrameFromTop(i); 163 mode = frame.IsNsQualified(); 164 if (mode != eNSQNotSet) { 165 return mode == eNSQualified; 166 } 167 168 if (frame.HasTypeInfo()) { 169 mode = frame.GetTypeInfo()->IsNsQualified(); 170 if (mode != eNSQNotSet) { 171 frame.SetNsQualified(mode); 172 return mode == eNSQualified; 173 } 174 } 175 176 if (frame.HasMemberId()) { 177 const CMemberId& mem = frame.GetMemberId(); 178 mode = mem.IsNsQualified(); 179 if (mode != eNSQNotSet) { 180 frame.SetNsQualified(mode); 181 return mode == eNSQualified; 182 } 183 if (mem.IsAttlist()) { 184 frame.SetNsQualified(eNSUnqualified); 185 return false; 186 } 187 } 188 } 189 TopFrame().SetNsQualified(eNSQualified); 190 return true; 191 } 192 IsCompressed(void) const193bool CObjectStack::IsCompressed(void) const 194 { 195 size_t i, count = GetStackDepth(); 196 for (i=0; i<count; ++i) { 197 const CObjectStack::TFrame& frame = FetchFrameFromTop(i); 198 if (frame.HasMemberId()) { 199 return frame.GetMemberId().IsCompressed(); 200 } 201 } 202 return false; 203 } 204 x_PushStackPath(void)205void CObjectStack::x_PushStackPath(void) 206 { 207 if (!m_WatchPathHooks) { 208 m_PathValid = false; 209 return; 210 } 211 if (!m_PathValid) { 212 GetStackPath(); 213 #if 0 214 for ( size_t i = 1; i < GetStackDepth(); ++i ) { 215 const TFrame& frame = FetchFrameFromTop(i); 216 if (frame.HasTypeInfo()) { 217 // there is no "root" symbol 218 m_MemberPath = frame.GetTypeInfo()->GetName(); 219 break; 220 } 221 } 222 #endif 223 } 224 const CMemberId& mem_id = TopFrame().GetMemberId(); 225 if (mem_id.HasNotag() || mem_id.IsAttlist()) { 226 return; 227 } 228 // member separator symbol is '.' 229 m_MemberPath += '.'; 230 const string& member = mem_id.GetName(); 231 if (!member.empty()) { 232 m_MemberPath += member; 233 } else { 234 m_MemberPath += NStr::IntToString(mem_id.GetTag()); 235 } 236 m_PathValid = true; 237 x_SetPathHooks(true); 238 } 239 x_PopStackPath(void)240void CObjectStack::x_PopStackPath(void) 241 { 242 if (!m_WatchPathHooks) { 243 m_PathValid = false; 244 return; 245 } 246 if (GetStackDepth() == 1) { 247 x_SetPathHooks(false); 248 m_PathValid = false; 249 } else { 250 const TFrame& top = TopFrame(); 251 if (top.HasMemberId()) { 252 const CMemberId& mem_id = top.GetMemberId(); 253 if (mem_id.HasNotag() || mem_id.IsAttlist()) { 254 return; 255 } 256 x_SetPathHooks(false); 257 // member separator symbol is '.' 258 m_MemberPath.erase(m_MemberPath.find_last_of('.')); 259 } 260 } 261 } 262 GetStackPath(void) const263const string& CObjectStack::GetStackPath(void) const 264 { 265 if (GetStackDepth()) { 266 // _ASSERT(FetchFrameFromBottom(0).m_FrameType == TFrame::eFrameNamed); 267 // _ASSERT(FetchFrameFromBottom(0).m_TypeInfo); 268 // m_MemberPath = FetchFrameFromBottom(0).GetTypeInfo()->GetName(); 269 // there is no "root" symbol 270 string path; 271 path = FetchFrameFromBottom(0).HasTypeInfo() ? 272 FetchFrameFromBottom(0).m_TypeInfo->GetName() : "?"; 273 for ( size_t i = 1; i < GetStackDepth(); ++i ) { 274 const TFrame& frame = FetchFrameFromBottom(i); 275 if (frame.HasMemberId()) { 276 const CMemberId& mem_id = frame.GetMemberId(); 277 if (mem_id.HasNotag() || mem_id.IsAttlist()) { 278 continue; 279 } 280 // member separator symbol is '.' 281 path += '.'; 282 const string& member = mem_id.GetName(); 283 if (!member.empty()) { 284 path += member; 285 } else { 286 path += NStr::IntToString(mem_id.GetTag()); 287 } 288 } 289 } 290 const_cast<CObjectStack*>(this)->m_PathValid = true; 291 const_cast<CObjectStack*>(this)->m_MemberPath = path; 292 } 293 return m_MemberPath; 294 } 295 PopErrorFrame(void)296void CObjectStack::PopErrorFrame(void) 297 { 298 try { 299 UnendedFrame(); 300 } 301 catch (...) { 302 PopFrame(); 303 throw; 304 } 305 PopFrame(); 306 } 307 IsKnownElement(const CTempString & name) const308bool CObjectStack::IsKnownElement(const CTempString& name) const 309 { 310 size_t s, depth = GetStackDepth(); 311 for (s=1; s < depth; ++s) { 312 const TFrame& frame = FetchFrameFromTop(s); 313 if (frame.GetFrameType() == CObjectStackFrame::eFrameClass || 314 frame.GetFrameType() == CObjectStackFrame::eFrameChoice) { 315 const CClassTypeInfoBase* type = dynamic_cast<const CClassTypeInfoBase*>(frame.GetTypeInfo()); 316 TMemberIndex i = type->GetItems().FindDeep(name); 317 if (i != kInvalidMember) { 318 return true; 319 } 320 } 321 else if (frame.HasTypeInfo() && !frame.GetTypeInfo()->GetName().empty()) { 322 break; 323 } 324 else if (!frame.GetNotag()) { 325 break; 326 } 327 } 328 return false; 329 } 330 GetRealTypeInfo(TTypeInfo typeInfo)331TTypeInfo CObjectStack::GetRealTypeInfo(TTypeInfo typeInfo) 332 { 333 if (typeInfo->GetTypeFamily() == eTypeFamilyPointer) { 334 const CPointerTypeInfo* ptr = 335 dynamic_cast<const CPointerTypeInfo*>(typeInfo); 336 if (ptr) { 337 typeInfo = ptr->GetPointedType(); 338 } 339 } 340 return typeInfo; 341 } 342 GetRealTypeFamily(TTypeInfo typeInfo)343ETypeFamily CObjectStack::GetRealTypeFamily(TTypeInfo typeInfo) 344 { 345 return GetRealTypeInfo( typeInfo )->GetTypeFamily(); 346 } 347 GetContainerElementTypeInfo(TTypeInfo typeInfo)348TTypeInfo CObjectStack::GetContainerElementTypeInfo(TTypeInfo typeInfo) 349 { 350 typeInfo = GetRealTypeInfo( typeInfo ); 351 _ASSERT(typeInfo->GetTypeFamily() == eTypeFamilyContainer); 352 const CContainerTypeInfo* ptr = 353 dynamic_cast<const CContainerTypeInfo*>(typeInfo); 354 return GetRealTypeInfo(ptr->GetElementType()); 355 } 356 GetContainerElementTypeFamily(TTypeInfo typeInfo)357ETypeFamily CObjectStack::GetContainerElementTypeFamily(TTypeInfo typeInfo) 358 { 359 typeInfo = GetRealTypeInfo( typeInfo ); 360 _ASSERT(typeInfo->GetTypeFamily() == eTypeFamilyContainer); 361 const CContainerTypeInfo* ptr = 362 dynamic_cast<const CContainerTypeInfo*>(typeInfo); 363 return GetRealTypeFamily(ptr->GetElementType()); 364 } 365 GetFrameTypeName(void) const366const char* CObjectStackFrame::GetFrameTypeName(void) const 367 { 368 const char* s; 369 switch (GetFrameType()) 370 { 371 default: s = "UNKNOWN"; break; 372 case eFrameOther: s = "eFrameOther"; break; 373 case eFrameNamed: s = "eFrameNamed"; break; 374 case eFrameArray: s = "eFrameArray"; break; 375 case eFrameArrayElement: s = "eFrameArrayElement"; break; 376 case eFrameClass: s = "eFrameClass"; break; 377 case eFrameClassMember: s = "eFrameClassMember"; break; 378 case eFrameChoice: s = "eFrameChoice"; break; 379 case eFrameChoiceVariant: s = "eFrameChoiceVariant"; break; 380 } 381 return s; 382 } 383 384 #if defined(NCBI_SERIAL_IO_TRACE) 385 TracePushFrame(bool push) const386void CObjectStack::TracePushFrame(bool push) const 387 { 388 cout << endl ; 389 int depth = (int)GetStackDepth(); 390 cout << depth; 391 for (; depth>0; --depth) { 392 cout.put(' '); 393 } 394 cout << (push ? "Enter " : "Leave ") << m_StackPtr->GetFrameTypeName(); 395 } 396 397 #endif 398 GetFrameInfo(void) const399string CObjectStackFrame::GetFrameInfo(void) const 400 { 401 string info(" Frame type= "); 402 info += GetFrameTypeName(); 403 if (m_TypeInfo) { 404 info += ", Object type= " + m_TypeInfo->GetName(); 405 } 406 if (m_MemberId) { 407 info += ", Member name= " + m_MemberId->GetName(); 408 } 409 return info; 410 } 411 412 GetFrameName(void) const413string CObjectStackFrame::GetFrameName(void) const 414 { 415 string info; 416 switch ( GetFrameType() ) { 417 case eFrameClassMember: 418 case eFrameChoiceVariant: 419 { 420 if ( m_MemberId ) { 421 const CMemberId& id = *m_MemberId; 422 // info = '.'; 423 if ( !id.GetName().empty() ) { 424 info += id.GetName(); 425 } 426 else { 427 info += '['; 428 info += NStr::IntToString(id.GetTag()); 429 info += ']'; 430 } 431 } 432 } 433 break; 434 case eFrameArrayElement: 435 info = "[]"; 436 break; 437 case eFrameArray: 438 info = "[]"; 439 break; 440 case eFrameNamed: 441 if (!GetNotag()) { 442 info = GetTypeInfo()->GetName(); 443 } 444 break; 445 default: 446 { 447 break; 448 } 449 } 450 return info; 451 } 452 453 454 END_NCBI_SCOPE 455