pathhook.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:9k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: pathhook.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 19:41:30  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.2
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: pathhook.cpp,v 1000.1 2004/06/01 19:41:30 gouriano Exp $
  10. * ===========================================================================
  11. *
  12. *                            PUBLIC DOMAIN NOTICE
  13. *               National Center for Biotechnology Information
  14. *
  15. *  This software/database is a "United States Government Work" under the
  16. *  terms of the United States Copyright Act.  It was written as part of
  17. *  the author's official duties as a United States Government employee and
  18. *  thus cannot be copyrighted.  This software/database is freely available
  19. *  to the public for use. The National Library of Medicine and the U.S.
  20. *  Government have not placed any restriction on its use or reproduction.
  21. *
  22. *  Although all reasonable efforts have been taken to ensure the accuracy
  23. *  and reliability of the software and data, the NLM and the U.S.
  24. *  Government do not and cannot warrant the performance or results that
  25. *  may be obtained by using this software or data. The NLM and the U.S.
  26. *  Government disclaim all warranties, express or implied, including
  27. *  warranties of performance, merchantability or fitness for any particular
  28. *  purpose.
  29. *
  30. *  Please cite the author in any work or product based on this material.
  31. *
  32. * ===========================================================================
  33. *
  34. * Author: Andrei Gourianov
  35. *
  36. * File Description:
  37. *   Helper classes to set serialization hooks by stack path
  38. */
  39. #include <ncbi_pch.hpp>
  40. #include <serial/pathhook.hpp>
  41. #include <serial/objstack.hpp>
  42. #include <serial/item.hpp>
  43. #include <serial/classinfob.hpp>
  44. BEGIN_NCBI_SCOPE
  45. static const char
  46.     s_Separator = '.',
  47.     s_One       = '?',
  48.     s_Many      = '*',
  49.     s_All       = '*';
  50. static const string&
  51.     s_RootStr   = "*.",
  52.     s_AllStr    = "?";
  53. CPathHook::CPathHook(void)
  54. {
  55.     m_Empty = true;
  56.     m_Regular = m_All = m_Wildcard = false;
  57. }
  58. CPathHook::~CPathHook(void)
  59. {
  60. }
  61. bool CPathHook::SetHook(CObjectStack* stk, const string& path, CObject* hook)
  62. {
  63.     bool state = false;
  64.     iterator it = find(stk);
  65.     for ( ;it != end() && it->first == stk; ++it) {
  66.         if ((it->second).first == path) {
  67.             if ((it->second).second == hook) {
  68.                 return state; // this hook already set - do nothing
  69.             }
  70.             erase(it); // erase existing hook
  71.             state = !state;
  72.         }
  73.     }
  74.     if (hook) { // set the new one
  75.         insert(pair<CObjectStack* const, pair<string, CRef<CObject> > >(
  76.             stk,pair<string, CRef<CObject> >(path,CRef<CObject>(hook))));
  77.         state = !state;
  78.     }
  79.     bool wildcard = path.find(s_One)  != string::npos ||
  80.                     path.find(s_Many) != string::npos;
  81.     bool all = (path == s_AllStr);
  82.     m_Regular = m_Regular || !wildcard;
  83.     m_All = m_All || all;
  84.     m_Wildcard = m_Wildcard || (wildcard && !all);
  85.     m_Empty = empty();
  86.     return state;
  87. }
  88. CObject* CPathHook::GetHook(CObjectStack& stk) const
  89. {
  90.     CObject* hook;
  91.     if (m_All) {
  92.         hook = x_Get(stk,s_AllStr);
  93.         if (hook) {
  94.             return hook;
  95.         }
  96.     }
  97.     const string& path = stk.GetStackPath();
  98.     if (m_Regular) {
  99.         hook = x_Get(stk,path);
  100.         if (hook) {
  101.             return hook;
  102.         }
  103.     }
  104.     if (m_Wildcard) {
  105.         for (CObjectStack* stmp = &stk; ; stmp = 0) {
  106.             const_iterator it;
  107.             for (it = find(stmp); it != end() && it->first == stmp; ++it) {
  108.                 if (CPathHook::Match((it->second).first,path)) {
  109.                     return const_cast<CObject*>((it->second).second.GetPointer());
  110.                 }
  111.             }
  112.             if (!stmp) {
  113.                 break;
  114.             }
  115.         }
  116.     }
  117.     return 0;
  118. }
  119. CObject* CPathHook::x_Get(CObjectStack& stk, const string& path) const
  120. {
  121.     for (CObjectStack* stmp = &stk; ; stmp = 0) {
  122.         const_iterator it;
  123.         for ( it = find(stmp); it != end() && it->first == stmp; ++it) {
  124.             if ((it->second).first == path) {
  125.                 return const_cast<CObject*>((it->second).second.GetPointer());
  126.             }
  127.         }
  128.         if (!stmp) {
  129.             break;
  130.         }
  131.     }
  132.     return 0;
  133. }
  134. bool CPathHook::Match(const string& mask, const string& path)
  135. {
  136. // Path is current stack path
  137. // Mask contains one or more wildcards (if we are here, it does)
  138. // so, for example:
  139. //      mask="A.?.?.D" and path="A.B.C.D" match
  140. //      mask="A.*.D"   and path="A.B.C.D" match
  141.     const char *m00 = mask.c_str();
  142.     const char *p00 = path.c_str();
  143.     const char *m1 = m00 + mask.length() - 1;
  144.     const char *p1 = p00 + path.length() - 1;
  145.     const char *m0;
  146.     const char *p0;
  147.     for ( ; m1 >= m00 && p1 >= p00; --m1, --p1) {
  148.         if (*m1 == s_One) {
  149.             for ( --m1; m1 >= m00 && *m1 != s_Separator; --m1)
  150.                 ; // skip "s_One" wildcard
  151.             for (; p1 >= p00 && *p1 != s_Separator; --p1)
  152.                 ; // skip one level
  153.         } else if (*m1 == s_Many) {
  154.             for ( --m1; m1 >= m00 && *m1 != s_Separator; --m1)
  155.                 ; // skip "s_Many" wildcard
  156.             if (m1 < m00) {
  157.                 return true;
  158.             }
  159.             for (; p1 >= p00 && *p1 != s_Separator; --p1)
  160.                 ; // skip one level ("many" means "1 or more")
  161.             if (p1 < p00) {
  162.                 return false;
  163.             }
  164.             for (m0 = m1-1; m0 >= m00 && *m0 != s_Separator; --m0)
  165.                 ; // find level name
  166.             if (m0 < m00) {
  167.                 m0 = m00;
  168.             }
  169.             for (p0 = p1-1; p0 >= p00; p1 = p0) {
  170.                 for (p0 = p1-1; p0 >= p00 && *p0 != s_Separator; --p0)
  171.                     ; // next level name
  172.                 if (p0 < p00) {
  173.                     p0 = p00;
  174.                 }
  175.                 if (!strncmp(p0,m0,m1-m0+1)) {
  176.                     m1 = m0;
  177.                     p1 = p0;
  178.                     break; // level found, keep looking
  179.                 }
  180.                 if (p0 == p00) {
  181.                     return false; // no match
  182.                 }
  183.             }
  184.         } else if (*m1 != *p1) {
  185.             return false;
  186.         }
  187.     }
  188.     return m1 <= m00 && p1 <= p00;
  189. }
  190. CStreamPathHookBase::CStreamPathHookBase(void)
  191. {
  192.     m_Regular = m_All = m_Member = m_Wildcard = false;
  193. }
  194. CStreamPathHookBase::~CStreamPathHookBase(void)
  195. {
  196. }
  197. bool CStreamPathHookBase::SetHook(const string& path, CObject* hook)
  198. {
  199.     bool state = false;
  200.     iterator it = find(path);
  201.     if (it != end()) {
  202.         if (hook == it->second) {
  203.             return state;
  204.         }
  205.         erase(it);
  206.         state = !state;
  207.     }
  208.     if (hook) {
  209.         insert(pair<string,CRef<CObject> >(path,CRef<CObject>(hook)));
  210.         state = !state;
  211.     }
  212.     bool wildcard = path.find(s_One)  != string::npos ||
  213.                     path.find(s_Many) != string::npos;
  214.     bool all = (path == s_AllStr);
  215.     m_Regular = m_Regular || !wildcard;
  216.     m_All = m_All || all;
  217.     m_Wildcard = m_Wildcard || (wildcard && !all);
  218.     m_Empty = empty();
  219.     return state;
  220. }
  221. CObject* CStreamPathHookBase::GetHook(CObjectStack& stk) const
  222. {
  223.     CObject* hook;
  224.     if (m_All) {
  225.         hook = x_Get(s_AllStr);
  226.         if (hook) {
  227.             return hook;
  228.         }
  229.     }
  230.     const string& path = stk.GetStackPath();
  231.     if (m_Regular) {
  232.         hook = x_Get(path);
  233.         if (hook) {
  234.             return hook;
  235.         }
  236.     }
  237.     if (m_Wildcard) {
  238.         for (const_iterator it = begin(); it != end(); ++it) {
  239.             if (CPathHook::Match(it->first,path)) {
  240.                 return const_cast<CObject*>(it->second.GetPointer());
  241.             }
  242.         }
  243.     }
  244.     return 0;
  245. }
  246. CObject* CStreamPathHookBase::x_Get(const string& path) const
  247. {
  248.     const_iterator it = find(path);
  249.     return it != end() ? const_cast<CObject*>(it->second.GetPointer()) : 0;
  250. }
  251. CTypeInfo* CStreamPathHookBase::FindType(const CObjectStack& stk)
  252. {
  253.     CItemInfo* item = FindItem(stk);
  254.     return item ? const_cast<CTypeInfo*>(item->GetTypeInfo()) : 0;
  255. }
  256. CItemInfo* CStreamPathHookBase::FindItem(const CObjectStack& stk)
  257. {
  258.     if (stk.TopFrame().HasMemberId()) {
  259.         for (size_t i = 0; i < stk.GetStackDepth(); ++i) {
  260.             const CObjectStackFrame& frame = stk.FetchFrameFromTop(i);
  261.             if (!frame.HasTypeInfo()) {
  262.                 continue;
  263.             }
  264.             const CClassTypeInfoBase* classInfo =
  265.                 dynamic_cast<const CClassTypeInfoBase*>(frame.GetTypeInfo());
  266.             if (classInfo) {
  267.                 return const_cast<CItemInfo*>(classInfo->GetItemInfo(
  268.                     stk.TopFrame().GetMemberId().GetName()));
  269.             }
  270.             break;
  271.         }
  272.     }
  273.     return 0;
  274. }
  275. END_NCBI_SCOPE
  276. /* ---------------------------------------------------------------------------
  277. * $Log: pathhook.cpp,v $
  278. * Revision 1000.1  2004/06/01 19:41:30  gouriano
  279. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.2
  280. *
  281. * Revision 1.2  2004/05/17 21:03:03  gorelenk
  282. * Added include of PCH ncbi_pch.hpp
  283. *
  284. * Revision 1.1  2004/01/05 14:25:22  gouriano
  285. * Added possibility to set serialization hooks by stack path
  286. *
  287. *
  288. * ===========================================================================
  289. */