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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: Seq_loc.cpp,v $
  4.  * PRODUCTION Revision 1000.3  2004/06/01 19:34:35  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R6.42
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* $Id: Seq_loc.cpp,v 1000.3 2004/06/01 19:34:35 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:   Author:  Cliff Clausen, Eugene Vasilchenko
  35.  *
  36.  * File Description:
  37.  *   .......
  38.  *
  39.  * Remark:
  40.  *   This code was originally generated by application DATATOOL
  41.  *   using specifications from the ASN data definition file
  42.  *   'seqloc.asn'.
  43.  *
  44.  * ===========================================================================
  45.  */
  46. #include <ncbi_pch.hpp>
  47. #include <serial/enumvalues.hpp>
  48. #include <objects/general/Int_fuzz.hpp>
  49. #include <objects/seqloc/Seq_point.hpp>
  50. #include <objects/seqloc/Packed_seqint.hpp>
  51. #include <objects/seqloc/Packed_seqpnt.hpp>
  52. #include <objects/seqloc/Seq_loc_mix.hpp>
  53. #include <objects/seqloc/Seq_loc_equiv.hpp>
  54. #include <objects/seqloc/Seq_loc.hpp>
  55. #include <objects/seqfeat/Feat_id.hpp>
  56. BEGIN_NCBI_SCOPE
  57. BEGIN_objects_SCOPE // namespace ncbi::objects::
  58. // constructors
  59. CSeq_loc::CSeq_loc(E_Choice index)
  60. {
  61.     x_InvalidateCache();
  62.     switch ( index ) {
  63.     case e_Null:
  64.         {
  65.             SetNull();
  66.             break;
  67.         }
  68.     case e_Empty:
  69.         {
  70.             SetEmpty();
  71.             break;
  72.         }
  73.     case e_Whole:
  74.         {
  75.             SetWhole();
  76.             break;
  77.         }
  78.     case e_Int:
  79.         {
  80.             SetInt();
  81.             break;
  82.         }
  83.     case e_Packed_int:
  84.         {
  85.             SetPacked_int();
  86.             break;
  87.         }
  88.     case e_Pnt:
  89.         {
  90.             SetPnt();
  91.             break;
  92.         }
  93.     case e_Packed_pnt:
  94.         {
  95.             SetPacked_pnt();
  96.             break;
  97.         }
  98.     case e_Mix:
  99.         {
  100.             SetMix();
  101.             break;
  102.         }
  103.     case e_Equiv:
  104.         {
  105.             SetEquiv();
  106.             break;
  107.         }
  108.     case e_Bond:
  109.         {
  110.             SetBond();
  111.             break;
  112.         }
  113.     case e_Feat:
  114.         {
  115.             SetFeat();
  116.             break;
  117.         }
  118.     case e_not_set:
  119.     default:
  120.         break;
  121.     }
  122. }
  123. CSeq_loc::CSeq_loc(TId& id, TPoint point, TStrand strand)
  124. {
  125.     x_InvalidateCache();
  126.     SetPnt(*new CSeq_point(id, point, strand));
  127. }
  128. CSeq_loc::CSeq_loc(TId& id, const TPoints& points, TStrand strand)
  129. {
  130.     x_InvalidateCache();
  131.     if ( points.size() == 1 ) {
  132.         SetPnt(*new CSeq_point(id, points.front(), strand));
  133.     } else {
  134.         SetPacked_pnt(*new CPacked_seqpnt(id, points, strand));
  135.     }
  136. }
  137. CSeq_loc::CSeq_loc(TId& id, TPoint from, TPoint to, TStrand strand)
  138. {
  139.     x_InvalidateCache();
  140.     SetInt(*new CSeq_interval(id, from, to, strand));
  141. }
  142. CSeq_loc::CSeq_loc(TId& id, TRanges ranges, TStrand strand)
  143. {
  144.     x_InvalidateCache();
  145.     if ( ranges.size() == 1 ) {
  146.         SetInt(*new CSeq_interval(id,
  147.             ranges.front().GetFrom(), ranges.front().GetTo(), strand));
  148.     } else {
  149.         SetPacked_int(*new CPacked_seqint(id, ranges, strand));
  150.     }
  151. }
  152. // destructor
  153. CSeq_loc::~CSeq_loc(void)
  154. {
  155. }
  156. inline
  157. void x_Assign(CInt_fuzz& dst, const CInt_fuzz& src)
  158. {
  159.     switch ( src.Which() ) {
  160.     case CInt_fuzz::e_not_set:
  161.         dst.Reset();
  162.         break;
  163.     case CInt_fuzz::e_P_m:
  164.         dst.SetP_m(src.GetP_m());
  165.         break;
  166.     case CInt_fuzz::e_Range:
  167.         dst.SetRange().SetMin(src.GetRange().GetMin());
  168.         dst.SetRange().SetMax(src.GetRange().GetMax());
  169.         break;
  170.     case CInt_fuzz::e_Pct:
  171.         dst.SetPct(src.GetPct());
  172.         break;
  173.     case CInt_fuzz::e_Lim:
  174.         dst.SetLim(src.GetLim());
  175.         break;
  176.     case CInt_fuzz::e_Alt:
  177.         dst.SetAlt() = src.GetAlt();
  178.         break;
  179.     default:
  180.         NCBI_THROW(CException, eUnknown,
  181.             "Invalid Int-fuzz variant");
  182.     }
  183. }
  184. inline
  185. void x_Assign(CSeq_interval& dst, const CSeq_interval& src)
  186. {
  187.     dst.SetFrom(src.GetFrom());
  188.     dst.SetTo(src.GetTo());
  189.     if ( src.IsSetStrand() ) {
  190.         dst.SetStrand(src.GetStrand());
  191.     }
  192.     else {
  193.         dst.ResetStrand();
  194.     }
  195.     dst.SetId().Assign(src.GetId());
  196.     if ( src.IsSetFuzz_from() ) {
  197.         x_Assign(dst.SetFuzz_from(), src.GetFuzz_from());
  198.     }
  199.     else {
  200.         dst.ResetFuzz_from();
  201.     }
  202.     if ( src.IsSetFuzz_to() ) {
  203.         x_Assign(dst.SetFuzz_to(), src.GetFuzz_to());
  204.     }
  205.     else {
  206.         dst.ResetFuzz_to();
  207.     }
  208. }
  209. inline
  210. void x_Assign(CSeq_point& dst, const CSeq_point& src)
  211. {
  212.     dst.SetPoint(src.GetPoint());
  213.     if ( src.IsSetStrand() ) {
  214.         dst.SetStrand(src.GetStrand());
  215.     }
  216.     else {
  217.         dst.ResetStrand();
  218.     }
  219.     dst.SetId().Assign(src.GetId());
  220.     if ( src.IsSetFuzz() ) {
  221.         x_Assign(dst.SetFuzz(), src.GetFuzz());
  222.     }
  223.     else {
  224.         dst.ResetFuzz();
  225.     }
  226. }
  227. inline
  228. void x_Assign(CPacked_seqint& dst, const CPacked_seqint& src)
  229. {
  230.     CPacked_seqint::Tdata& data = dst.Set();
  231.     data.clear();
  232.     ITERATE ( CPacked_seqint::Tdata, i, src.Get() ) {
  233.         data.push_back(CRef<CSeq_interval>(new CSeq_interval));
  234.         x_Assign(*data.back(), **i);
  235.     }
  236. }
  237. inline
  238. void x_Assign(CPacked_seqpnt& dst, const CPacked_seqpnt& src)
  239. {
  240.     if ( src.IsSetStrand() ) {
  241.         dst.SetStrand(src.GetStrand());
  242.     }
  243.     else {
  244.         dst.ResetStrand();
  245.     }
  246.     dst.SetId().Assign(src.GetId());
  247.     if ( src.IsSetFuzz() ) {
  248.         x_Assign(dst.SetFuzz(), src.GetFuzz());
  249.     }
  250.     else {
  251.         dst.ResetFuzz();
  252.     }
  253.     dst.SetPoints() = src.GetPoints();
  254. }
  255. inline
  256. void x_Assign(CSeq_bond& dst, const CSeq_bond& src)
  257. {
  258.     x_Assign(dst.SetA(), src.GetA());
  259.     if ( src.IsSetB() ) {
  260.         x_Assign(dst.SetB(), src.GetB());
  261.     }
  262.     else {
  263.         dst.ResetB();
  264.     }
  265. }
  266. inline
  267. void x_Assign(CSeq_loc_mix& dst, const CSeq_loc_mix& src)
  268. {
  269.     CSeq_loc_mix::Tdata& data = dst.Set();
  270.     data.clear();
  271.     ITERATE ( CSeq_loc_mix::Tdata, i, src.Get() ) {
  272.         data.push_back(CRef<CSeq_loc>(new CSeq_loc));
  273.         data.back()->Assign(**i);
  274.     }
  275. }
  276. inline
  277. void x_Assign(CSeq_loc_equiv& dst, const CSeq_loc_equiv& src)
  278. {
  279.     CSeq_loc_equiv::Tdata& data = dst.Set();
  280.     data.clear();
  281.     ITERATE ( CSeq_loc_equiv::Tdata, i, src.Get() ) {
  282.         data.push_back(CRef<CSeq_loc>(new CSeq_loc));
  283.         data.back()->Assign(**i);
  284.     }
  285. }
  286. void CSeq_loc::Assign(const CSerialObject& obj, ESerialRecursionMode how)
  287. {
  288.     if ( GetTypeInfo() == obj.GetThisTypeInfo() ) {
  289.         const CSeq_loc& loc = static_cast<const CSeq_loc&>(obj);
  290.         switch ( loc.Which() ) {
  291.         case CSeq_loc::e_not_set:
  292.             Reset();
  293.             return;
  294.         case CSeq_loc::e_Null:
  295.             SetNull();
  296.             return;
  297.         case CSeq_loc::e_Empty:
  298.             SetEmpty().Assign(loc.GetEmpty());
  299.             return;
  300.         case CSeq_loc::e_Whole:
  301.             SetWhole().Assign(loc.GetWhole());
  302.             return;
  303.         case CSeq_loc::e_Int:
  304.             x_Assign(SetInt(), loc.GetInt());
  305.             return;
  306.         case CSeq_loc::e_Pnt:
  307.             x_Assign(SetPnt(), loc.GetPnt());
  308.             return;
  309.         case CSeq_loc::e_Packed_int:
  310.             x_Assign(SetPacked_int(), loc.GetPacked_int());
  311.             return;
  312.         case CSeq_loc::e_Packed_pnt:
  313.             x_Assign(SetPacked_pnt(), loc.GetPacked_pnt());
  314.             return;
  315.         case CSeq_loc::e_Mix:
  316.             x_Assign(SetMix(), loc.GetMix());
  317.             return;
  318.         case CSeq_loc::e_Equiv:
  319.             x_Assign(SetEquiv(), loc.GetEquiv());
  320.             return;
  321.         case CSeq_loc::e_Bond:
  322.             x_Assign(SetBond(), loc.GetBond());
  323.             return;
  324.         case CSeq_loc::e_Feat:
  325.             SetFeat().Assign(loc.GetFeat());
  326.             return;
  327.         }
  328.     }
  329.     CSerialObject::Assign(obj, how);
  330. }
  331. CSeq_loc::TRange CSeq_loc::x_UpdateTotalRange(void) const
  332. {
  333.     TRange range = m_TotalRangeCache;
  334.     if ( range.GetFrom() == TSeqPos(kDirtyCache) ) {
  335.         const CSeq_id* id = 0;
  336.         range = m_TotalRangeCache = x_CalculateTotalRangeCheckId(id);
  337.         m_IdCache = id;
  338.     }
  339.     return range;
  340. }
  341. void CSeq_loc::x_UpdateId(const CSeq_id*& total_id, const CSeq_id* id) const
  342. {
  343.     if ( total_id == id ) {
  344.         return;
  345.     }
  346.     
  347.     if ( !total_id ) {
  348.         total_id = id;
  349.     } else if ( (id  &&  !total_id->Equals(*id))  ||  !id ) {
  350.         NCBI_THROW(CException, eUnknown, "CSeq_loc -- multiple seq-ids");
  351.     }
  352. // returns enclosing location range
  353. // the total range is meaningless if there are several seq-ids
  354. // in the location
  355. CSeq_loc::TRange CSeq_loc::x_CalculateTotalRangeCheckId(const CSeq_id*& id) const
  356. {
  357.     TRange total_range;
  358.     switch ( Which() ) {
  359.     case CSeq_loc::e_not_set:
  360.     case CSeq_loc::e_Null:
  361.         {
  362.             // Ignore locations without id
  363.             total_range = TRange::GetEmpty();
  364.             break;
  365.         }
  366.     case CSeq_loc::e_Empty:
  367.         {
  368.             x_UpdateId(id, &GetEmpty());
  369.             total_range = TRange::GetEmpty();
  370.             break;
  371.         }
  372.     case CSeq_loc::e_Whole:
  373.         {
  374.             x_UpdateId(id, &GetWhole());
  375.             total_range = TRange::GetWhole();
  376.             break;
  377.         }
  378.     case CSeq_loc::e_Int:
  379.         {
  380.             const CSeq_interval& loc = GetInt();
  381.             x_UpdateId(id, &loc.GetId());
  382.             total_range.Set(loc.GetFrom(), loc.GetTo());
  383.             break;
  384.         }
  385.     case CSeq_loc::e_Pnt:
  386.         {
  387.             const CSeq_point& pnt = GetPnt();
  388.             x_UpdateId(id, &pnt.GetId());
  389.             TSeqPos pos = pnt.GetPoint();
  390.             total_range.Set(pos, pos);
  391.             break;
  392.         }
  393.     case CSeq_loc::e_Packed_int:
  394.         {
  395.             // Check ID of each interval
  396.             const CPacked_seqint& ints = GetPacked_int();
  397.             total_range = TRange::GetEmpty();
  398.             ITERATE ( CPacked_seqint::Tdata, ii, ints.Get() ) {
  399.                 const CSeq_interval& loc = **ii;
  400.                 x_UpdateId(id, &loc.GetId());
  401.                 total_range += TRange(loc.GetFrom(), loc.GetTo());
  402.             }
  403.             break;
  404.         }
  405.     case CSeq_loc::e_Packed_pnt:
  406.         {
  407.             const CPacked_seqpnt& pnts = GetPacked_pnt();
  408.             x_UpdateId(id, &pnts.GetId());
  409.             total_range = TRange::GetEmpty();
  410.             ITERATE( CPacked_seqpnt::TPoints, pi, pnts.GetPoints() ) {
  411.                 TSeqPos pos = *pi;
  412.                 total_range += TRange(pos, pos);
  413.             }
  414.             break;
  415.         }
  416.     case CSeq_loc::e_Mix:
  417.         {
  418.             // Check ID of each sub-location.
  419.             const CSeq_loc_mix& mix = GetMix();
  420.             total_range = TRange::GetEmpty();
  421.             ITERATE( CSeq_loc_mix::Tdata, li, mix.Get() ) {
  422.                 // instead of Get... to be able to check ID
  423.                 total_range += (*li)->x_CalculateTotalRangeCheckId(id);
  424.             }
  425.             break;
  426.         }
  427.     case CSeq_loc::e_Equiv:
  428. /*
  429.         {
  430.             // Does it make any sense to GetTotalRange() from an equiv?
  431.             total_range = TRange::GetEmpty();
  432.             ITERATE(CSeq_loc_equiv::Tdata, li, GetEquiv().Get()) {
  433.                 total_range += (*li)->GetTotalRange();
  434.             }
  435.             break;
  436.         }
  437. */
  438.     case CSeq_loc::e_Bond:
  439. /*
  440.         {
  441.             // Does it make any sense to GetTotalRange() from a bond?
  442.             const CSeq_bond& loc = GetBond();
  443.             TSeqPos pos = loc.GetA().GetPoint();
  444.             total_range = TRange(pos, pos);
  445.             if ( loc.IsSetB() ) {
  446.                 pos = loc.GetB().GetPoint();
  447.                 total_range += TRange(pos, pos);
  448.             }
  449.             break;
  450.         }
  451. */
  452.     case CSeq_loc::e_Feat:
  453.     default:
  454.         {
  455.             NCBI_THROW(CException, eUnknown,
  456.                        "CSeq_loc::CalculateTotalRange -- "
  457.                        "unsupported location type");
  458.         }
  459.     }
  460.     return total_range;
  461. }
  462. TSeqPos CSeq_loc::GetStart(TSeqPos seq_len) const
  463. {
  464.     if (seq_len == kInvalidSeqPos) {
  465.         return GetTotalRange().GetFrom();
  466.     }
  467.     switch ( Which() ) {
  468.     case CSeq_loc::e_not_set:
  469.     case CSeq_loc::e_Null:
  470.     case CSeq_loc::e_Empty:
  471.         {
  472.             return kInvalidSeqPos;
  473.         }
  474.     case CSeq_loc::e_Whole:
  475.         {
  476.             return TRange::GetWhole().GetFrom();
  477.         }
  478.     case CSeq_loc::e_Int:
  479.         {
  480.             return GetInt().GetFrom();
  481.         }
  482.     case CSeq_loc::e_Pnt:
  483.         {
  484.             return GetPnt().GetPoint();
  485.         }
  486.     case CSeq_loc::e_Packed_int:
  487.         {
  488.             return (*GetPacked_int().Get().begin())->GetFrom();
  489.         }
  490.     case CSeq_loc::e_Packed_pnt:
  491.         {
  492.             return *GetPacked_pnt().GetPoints().begin();
  493.         }
  494.     case CSeq_loc::e_Mix:
  495.         {
  496.             return (*GetMix().Get().begin())->GetStart(seq_len);
  497.         }
  498.     case CSeq_loc::e_Equiv:
  499.     case CSeq_loc::e_Bond:
  500.     case CSeq_loc::e_Feat:
  501.     default:
  502.         {
  503.             NCBI_THROW(CException, eUnknown,
  504.                        "CSeq_loc::GetStart -- "
  505.                        "unsupported location type");
  506.         }
  507.     }
  508. }
  509. TSeqPos CSeq_loc::GetEnd(TSeqPos seq_len) const
  510. {
  511.     if (seq_len == kInvalidSeqPos) {
  512.         return GetTotalRange().GetTo();
  513.     }
  514.     switch ( Which() ) {
  515.     case CSeq_loc::e_not_set:
  516.     case CSeq_loc::e_Null:
  517.     case CSeq_loc::e_Empty:
  518.         {
  519.             return kInvalidSeqPos;
  520.         }
  521.     case CSeq_loc::e_Whole:
  522.         {
  523.             return TRange::GetWhole().GetTo();
  524.         }
  525.     case CSeq_loc::e_Int:
  526.         {
  527.             return GetInt().GetTo();
  528.         }
  529.     case CSeq_loc::e_Pnt:
  530.         {
  531.             return GetPnt().GetPoint();
  532.         }
  533.     case CSeq_loc::e_Packed_int:
  534.         {
  535.             return (*GetPacked_int().Get().rbegin())->GetTo();
  536.         }
  537.     case CSeq_loc::e_Packed_pnt:
  538.         {
  539.             return *GetPacked_pnt().GetPoints().rbegin();
  540.         }
  541.     case CSeq_loc::e_Mix:
  542.         {
  543.             return (*GetMix().Get().rbegin())->GetEnd(seq_len);
  544.         }
  545.     case CSeq_loc::e_Equiv:
  546.     case CSeq_loc::e_Bond:
  547.     case CSeq_loc::e_Feat:
  548.     default:
  549.         {
  550.             NCBI_THROW(CException, eUnknown,
  551.                        "CSeq_loc::GetEnd -- "
  552.                        "unsupported location type");
  553.         }
  554.     }
  555. }
  556. TSeqPos CSeq_loc::GetCircularLength(TSeqPos seq_len) const
  557. {
  558.     if (seq_len == kInvalidSeqPos) {
  559.         return GetTotalRange().GetLength();
  560.     }
  561.     TSeqPos start = GetStart(seq_len);
  562.     TSeqPos stop = GetEnd(seq_len);
  563.     return start > stop ? seq_len - start + stop + 1 : stop - start + 1;
  564. }
  565. // CSeq_loc_CI implementation
  566. CSeq_loc_CI::CSeq_loc_CI(void)
  567.     : m_Location(0),
  568.       m_EmptyFlag(eEmpty_Skip)
  569. {
  570.     m_CurLoc = m_LocList.end();
  571. }
  572. CSeq_loc_CI::CSeq_loc_CI(const CSeq_loc& loc, EEmptyFlag empty_flag)
  573.     : m_Location(&loc),
  574.       m_EmptyFlag(empty_flag)
  575. {
  576.     x_ProcessLocation(loc);
  577.     m_CurLoc = m_LocList.begin();
  578. }
  579. CSeq_loc_CI::CSeq_loc_CI(const CSeq_loc_CI& iter)
  580. {
  581.     *this = iter;
  582. }
  583. CSeq_loc_CI::~CSeq_loc_CI()
  584. {
  585. }
  586. CSeq_loc_CI& CSeq_loc_CI::operator= (const CSeq_loc_CI& iter)
  587. {
  588.     if (this == &iter)
  589.         return *this;
  590.     m_LocList.clear();
  591.     m_Location = iter.m_Location;
  592.     m_EmptyFlag = iter.m_EmptyFlag;
  593.     ITERATE(TLocList, li, iter.m_LocList) {
  594.         TLocList::iterator tmp = m_LocList.insert(m_LocList.end(), *li);
  595.         if (iter.m_CurLoc == li)
  596.             m_CurLoc = tmp;
  597.     }
  598.     return *this;
  599. }
  600. void CSeq_loc_CI::x_ThrowNotValid(const char* where) const
  601. {
  602.     string msg;
  603.     msg += "CSeq_loc_CI::";
  604.     msg += where;
  605.     msg += " -- iterator is not valid";
  606.     NCBI_THROW(CException, eUnknown,
  607.         msg);
  608. }
  609. void CSeq_loc_CI::x_ProcessLocation(const CSeq_loc& loc)
  610. {
  611.     switch ( loc.Which() ) {
  612.     case CSeq_loc::e_not_set:
  613.     case CSeq_loc::e_Null:
  614.     case CSeq_loc::e_Empty:
  615.         {
  616.             if (m_EmptyFlag == eEmpty_Allow) {
  617.                 SLoc_Info info;
  618.                 info.m_Id.Reset(new CSeq_id);
  619.                 info.m_Range = TRange::GetEmpty();
  620.                 info.m_Loc = &loc;
  621.                 m_LocList.push_back(info);
  622.             }
  623.             return;
  624.         }
  625.     case CSeq_loc::e_Whole:
  626.         {
  627.             SLoc_Info info;
  628.             info.m_Id = &loc.GetWhole();
  629.             info.m_Range = TRange::GetWhole();
  630.             info.m_Loc = &loc;
  631.             m_LocList.push_back(info);
  632.             return;
  633.         }
  634.     case CSeq_loc::e_Int:
  635.         {
  636.             SLoc_Info info;
  637.             info.m_Id = &loc.GetInt().GetId();
  638.             info.m_Range.Set(loc.GetInt().GetFrom(), loc.GetInt().GetTo());
  639.             if ( loc.GetInt().IsSetStrand() )
  640.                 info.m_Strand = loc.GetInt().GetStrand();
  641.             info.m_Loc = &loc;
  642.             if (loc.GetInt().IsSetFuzz_from()) {
  643.                 info.m_Fuzz[0] = &loc.GetInt().GetFuzz_from();
  644.             }
  645.             if (loc.GetInt().IsSetFuzz_to()) {
  646.                 info.m_Fuzz[1] = &loc.GetInt().GetFuzz_to();
  647.             }
  648.             m_LocList.push_back(info);
  649.             return;
  650.         }
  651.     case CSeq_loc::e_Pnt:
  652.         {
  653.             SLoc_Info info;
  654.             info.m_Id = &loc.GetPnt().GetId();
  655.             info.m_Range.Set(loc.GetPnt().GetPoint(), loc.GetPnt().GetPoint());
  656.             if ( loc.GetPnt().IsSetStrand() )
  657.                 info.m_Strand = loc.GetPnt().GetStrand();
  658.             info.m_Loc = &loc;
  659.             if (loc.GetPnt().IsSetFuzz()) {
  660.                 info.m_Fuzz[0] = info.m_Fuzz[1] = &loc.GetPnt().GetFuzz();
  661.             }
  662.             m_LocList.push_back(info);
  663.             return;
  664.         }
  665.     case CSeq_loc::e_Packed_int:
  666.         {
  667.             ITERATE ( CPacked_seqint::Tdata, ii, loc.GetPacked_int().Get() ) {
  668.                 SLoc_Info info;
  669.                 info.m_Id = &(*ii)->GetId();
  670.                 info.m_Range.Set((*ii)->GetFrom(), (*ii)->GetTo());
  671.                 if ( (*ii)->IsSetStrand() )
  672.                     info.m_Strand = (*ii)->GetStrand();
  673.                 info.m_Loc = &loc;
  674.                 if ((*ii)->IsSetFuzz_from()) {
  675.                     info.m_Fuzz[0] = &(*ii)->GetFuzz_from();
  676.                 }
  677.                 if ((*ii)->IsSetFuzz_to()) {
  678.                     info.m_Fuzz[1] = &(*ii)->GetFuzz_to();
  679.                 }
  680.                 m_LocList.push_back(info);
  681.             }
  682.             return;
  683.         }
  684.     case CSeq_loc::e_Packed_pnt:
  685.         {
  686.             ITERATE ( CPacked_seqpnt::TPoints, pi, loc.GetPacked_pnt().GetPoints() ) {
  687.                 SLoc_Info info;
  688.                 info.m_Id = &loc.GetPacked_pnt().GetId();
  689.                 info.m_Range.Set(*pi, *pi);
  690.                 if ( loc.GetPacked_pnt().IsSetStrand() )
  691.                     info.m_Strand = loc.GetPacked_pnt().GetStrand();
  692.                 info.m_Loc = &loc;
  693.                 if (loc.GetPacked_pnt().IsSetFuzz()) {
  694.                     info.m_Fuzz[0] = info.m_Fuzz[1]
  695.                         = &loc.GetPacked_pnt().GetFuzz();
  696.                 }
  697.                 m_LocList.push_back(info);
  698.             }
  699.             return;
  700.         }
  701.     case CSeq_loc::e_Mix:
  702.         {
  703.             ITERATE(CSeq_loc_mix::Tdata, li, loc.GetMix().Get()) {
  704.                 x_ProcessLocation(**li);
  705.             }
  706.             return;
  707.         }
  708.     case CSeq_loc::e_Equiv:
  709.         {
  710.             ITERATE(CSeq_loc_equiv::Tdata, li, loc.GetEquiv().Get()) {
  711.                 x_ProcessLocation(**li);
  712.             }
  713.             return;
  714.         }
  715.     case CSeq_loc::e_Bond:
  716.         {
  717.             SLoc_Info infoA;
  718.             infoA.m_Id = &loc.GetBond().GetA().GetId();
  719.             infoA.m_Range.Set(loc.GetBond().GetA().GetPoint(),
  720.                               loc.GetBond().GetA().GetPoint());
  721.             if ( loc.GetBond().GetA().IsSetStrand() )
  722.                 infoA.m_Strand = loc.GetBond().GetA().GetStrand();
  723.             infoA.m_Loc = &loc;
  724.             if (loc.GetBond().GetA().IsSetFuzz()) {
  725.                 infoA.m_Fuzz[0] = infoA.m_Fuzz[1]
  726.                     = &loc.GetBond().GetA().GetFuzz();
  727.             }
  728.             m_LocList.push_back(infoA);
  729.             if ( loc.GetBond().IsSetB() ) {
  730.                 SLoc_Info infoB;
  731.                 infoB.m_Id = &loc.GetBond().GetB().GetId();
  732.                 infoB.m_Range.Set(loc.GetBond().GetB().GetPoint(),
  733.                                   loc.GetBond().GetB().GetPoint());
  734.                 if ( loc.GetBond().GetB().IsSetStrand() )
  735.                     infoB.m_Strand = loc.GetBond().GetB().GetStrand();
  736.                 infoB.m_Loc = &loc;
  737.                 if (loc.GetBond().GetB().IsSetFuzz()) {
  738.                     infoB.m_Fuzz[0] = infoB.m_Fuzz[1]
  739.                         = &loc.GetBond().GetB().GetFuzz();
  740.                 }
  741.                 m_LocList.push_back(infoB);
  742.             }
  743.             return;
  744.         }
  745.     case CSeq_loc::e_Feat:
  746.     default:
  747.         {
  748.             NCBI_THROW(CException, eUnknown,
  749.                        "CSeq_loc_CI -- unsupported location type");
  750.         }
  751.     }
  752. }
  753. // Append a string representation of a CSeq_id to label
  754. inline
  755. void s_GetLabel(const CSeq_id& id, string* label)
  756. {
  757.     CNcbiOstrstream os;
  758.     id.WriteAsFasta(os);
  759.     *label += CNcbiOstrstreamToString(os);
  760. }
  761. // Append to label info for a CSeq_point
  762. inline
  763. const CSeq_id* s_GetLabel
  764. (const CSeq_point& pnt,
  765.  const CSeq_id*    last_id,
  766.  string*           label)
  767. {
  768.     // If CSeq_id does not match last_id, then append id to label
  769.     if ( !last_id  ||  !last_id->Match(pnt.GetId()) ) {
  770.         s_GetLabel(pnt.GetId(), label);
  771.         *label += ":";
  772.     }
  773.     // Add strand info to label
  774.     if (pnt.IsSetStrand()) {
  775.         *label += GetTypeInfo_enum_ENa_strand()
  776.             ->FindName(pnt.GetStrand(), true);
  777.     }
  778.     if (pnt.IsSetFuzz()) {
  779.         // Append Fuzz info to label
  780.         pnt.GetFuzz().GetLabel(label, pnt.GetPoint());
  781.     } else {
  782.         // Append 1 based point to label
  783.         *label += NStr::IntToString(pnt.GetPoint()+1);
  784.     }
  785.     // update last_id
  786.     last_id = &pnt.GetId();
  787.     return last_id;
  788. }
  789. // Append to label info for CSeq_interval
  790. inline
  791. const CSeq_id* s_GetLabel
  792. (const CSeq_interval& itval,
  793.  const CSeq_id*       last_id,
  794.  string*              label)
  795. {
  796.     if (!last_id || !last_id->Match(itval.GetId())) {
  797.         s_GetLabel(itval.GetId(), label);
  798.         *label += ":";
  799.     }
  800.     last_id = &itval.GetId();
  801.     if (itval.IsSetStrand()) {
  802.         *label += GetTypeInfo_enum_ENa_strand()
  803.             ->FindName(itval.GetStrand(), true);
  804.     }
  805.     if (itval.IsSetStrand() &&
  806.         (itval.GetStrand() == eNa_strand_minus ||
  807.          itval.GetStrand() == eNa_strand_both_rev)) {
  808.         if (itval.IsSetFuzz_to()) {
  809.             itval.GetFuzz_to().GetLabel(label, itval.GetTo(), false);
  810.         } else {
  811.             *label += NStr::IntToString(itval.GetTo()+1);
  812.         }
  813.         *label += "-";
  814.         if (itval.IsSetFuzz_from()) {
  815.             itval.GetFuzz_from().GetLabel(label, itval.GetFrom());
  816.         } else {
  817.             *label += NStr::IntToString(itval.GetFrom()+1);
  818.         }
  819.     } else {
  820.         if (itval.IsSetFuzz_from()) {
  821.             itval.GetFuzz_from().GetLabel
  822.                 (label, itval.GetFrom(), false);
  823.         } else {
  824.             *label += NStr::IntToString(itval.GetFrom()+1);
  825.         }
  826.         *label += "-";
  827.         if (itval.IsSetFuzz_to()) {
  828.             itval.GetFuzz_to().GetLabel(label, itval.GetTo());
  829.         } else {
  830.             *label += NStr::IntToString(itval.GetTo()+1);
  831.         }
  832.     }
  833.     return last_id;
  834. }
  835. // Forward declaration
  836. const CSeq_id* s_GetLabel
  837. (const CSeq_loc& loc,
  838.  const CSeq_id*  last_id,
  839.  string*         label,
  840.  bool            first = false);
  841. // Appends to label info for each CSeq_loc in a list of CSeq_locs
  842. inline
  843. const CSeq_id* s_GetLabel
  844. (const list<CRef<CSeq_loc> >&  loc_list,
  845.  const CSeq_id*                last_id,
  846.  string*                       label)
  847. {
  848.     bool first = true;
  849.     ITERATE (list<CRef<CSeq_loc> >, it, loc_list) {
  850.         // Append to label for each CSeq_loc in list
  851.         last_id = s_GetLabel(**it, last_id, label, first);
  852.         first = false;
  853.     }
  854.     return last_id;
  855. }
  856. // Builds a label based upon a CSeq_loc and all embedded CSeq_locs
  857. const CSeq_id* s_GetLabel
  858. (const CSeq_loc& loc,
  859.  const CSeq_id*  last_id,
  860.  string*         label,
  861.  bool            first)
  862. {
  863.     // Ensure label is not null
  864.     if (!label) {
  865.         return last_id;
  866.     }
  867.     // Put a comma separator if necessary
  868.     if (!first) {
  869.         *label += ", ";
  870.     }
  871.     // Loop through embedded CSeq_locs and create a label, depending on
  872.     // type of CSeq_loc
  873.     switch (loc.Which()) {
  874.     case CSeq_loc::e_Null:
  875.         *label += "~";
  876.         break;
  877.     case CSeq_loc::e_Empty:
  878.         *label += "{";
  879.         s_GetLabel(loc.GetEmpty(), label);
  880.         last_id = &loc.GetEmpty();
  881.         *label += "}";
  882.         break;
  883.     case CSeq_loc::e_Whole:
  884.         s_GetLabel(loc.GetWhole(), label);
  885.         last_id = &loc.GetWhole();
  886.         break;
  887.     case CSeq_loc::e_Int:
  888.         last_id = s_GetLabel(loc.GetInt(), last_id, label);
  889.         break;
  890.     case CSeq_loc::e_Packed_int:
  891.     {
  892.         *label += "(";
  893.         bool first = true;
  894.         ITERATE(CPacked_seqint::Tdata, it, loc.GetPacked_int().Get()) {
  895.             if (!first) {
  896.                 *label += ", ";
  897.             }
  898.             first = false;
  899.             last_id = s_GetLabel(**it, last_id, label);
  900.         }
  901.         *label += ")";
  902.         break;
  903.     }
  904.     case CSeq_loc::e_Pnt:
  905.         last_id = s_GetLabel(loc.GetPnt(), last_id, label);
  906.         break;
  907.     case CSeq_loc::e_Packed_pnt:
  908.         *label += "(" + loc.GetPacked_pnt().GetId().AsFastaString() + ":";
  909.         {{
  910.              string str;
  911.              ITERATE (CPacked_seqpnt::TPoints, iter,
  912.                       loc.GetPacked_pnt().GetPoints()) {
  913.                  if ( !str.empty() ) {
  914.                      str += ", ";
  915.                  }
  916.                  str += NStr::IntToString(*iter);
  917.              }
  918.              *label += str;
  919.          }}
  920.         *label += ")";
  921.         last_id = &loc.GetPacked_pnt().GetId();
  922.         break;
  923.     case CSeq_loc::e_Mix:
  924.         *label += "[";
  925.         last_id = s_GetLabel(loc.GetMix().Get(), last_id, label);
  926.         *label += "]";
  927.         break;
  928.     case CSeq_loc::e_Equiv:
  929.         *label += "[";
  930.         last_id = s_GetLabel(loc.GetEquiv().Get(), last_id, label);
  931.         *label += "]";
  932.         break;
  933.     case CSeq_loc::e_Bond:
  934.         last_id = s_GetLabel(loc.GetBond().GetA(), last_id, label);
  935.         *label += "=";
  936.         if (loc.GetBond().IsSetB()) {
  937.             last_id = s_GetLabel(loc.GetBond().GetB(), last_id, label);
  938.         } else {
  939.             *label += "?";
  940.         }
  941.         break;
  942.     case CSeq_loc::e_Feat:
  943.         *label += "(feat)";
  944.         break;
  945.     default:
  946.         *label += "(??)";
  947.         break;
  948.     }
  949.     return last_id;
  950. }
  951. bool CSeq_loc::IsPartialLeft (void) const
  952. {
  953.     switch (Which ()) {
  954.         case CSeq_loc::e_Null :
  955.             return true;
  956.         case CSeq_loc::e_Int :
  957.             return GetInt ().IsPartialLeft ();
  958.         case CSeq_loc::e_Pnt :
  959.             return GetPnt ().IsPartialLeft ();
  960.         case CSeq_loc::e_Mix :
  961.             return GetMix ().IsPartialLeft ();
  962.         default :
  963.             break;
  964.     }
  965.     return false;
  966. }
  967. bool CSeq_loc::IsPartialRight (void) const
  968. {
  969.     switch (Which ()) {
  970.         case CSeq_loc::e_Null :
  971.             return true;
  972.         case CSeq_loc::e_Int :
  973.             return GetInt ().IsPartialRight ();
  974.         case CSeq_loc::e_Pnt :
  975.             return GetPnt ().IsPartialRight ();
  976.         case CSeq_loc::e_Mix :
  977.             return GetMix ().IsPartialRight ();
  978.         default :
  979.             break;
  980.     }
  981.     return false;
  982. }
  983. void CSeq_loc::SetPartialLeft (bool val)
  984. {
  985.     if ( val == IsPartialLeft() ) {
  986.         return;
  987.     }
  988.     switch ( Which() ) {
  989.         case CSeq_loc::e_Int:
  990.             SetInt().SetPartialLeft(val);
  991.         case CSeq_loc::e_Pnt:
  992.             SetPnt().SetPartialLeft(val);
  993.         case CSeq_loc::e_Mix :
  994.             SetMix().SetPartialLeft(val);
  995.         default :
  996.             break;
  997.     }
  998. }
  999. void CSeq_loc::SetPartialRight(bool val)
  1000. {
  1001.     if ( val == IsPartialRight() ) {
  1002.         return;
  1003.     }
  1004.     switch ( Which() ) {
  1005.         case CSeq_loc::e_Int:
  1006.             SetInt().SetPartialRight(val);
  1007.         case CSeq_loc::e_Pnt:
  1008.             SetPnt().SetPartialRight(val);
  1009.         case CSeq_loc::e_Mix:
  1010.             SetMix().SetPartialRight(val);
  1011.         default :
  1012.             break;
  1013.     }
  1014. }
  1015. // Appends a label suitable for display (e.g., error messages)
  1016. // label must point to an existing string object
  1017. // Method just returns if label is null
  1018. void CSeq_loc::GetLabel(string* label) const
  1019. {
  1020.     s_GetLabel(*this, 0, label, true);
  1021. }
  1022. // assign the 'id' field of each sub-interval to the supplied id
  1023. void CSeq_loc::SetId(CSeq_id& id)
  1024. {
  1025.     x_InvalidateCache();
  1026.     switch (Which()) {
  1027.     case e_Int:
  1028.         SetInt().SetId(id);
  1029.         break;
  1030.     case e_Pnt:
  1031.         SetPnt().SetId(id);
  1032.         break;
  1033.     case e_Packed_int:
  1034.         NON_CONST_ITERATE (CPacked_seqint::Tdata, iter, SetPacked_int().Set()) {
  1035.             (*iter)->SetId(id);
  1036.         }
  1037.         break;
  1038.     case e_Packed_pnt:
  1039.         SetPacked_pnt().SetId(id);
  1040.         break;
  1041.     case e_Mix:
  1042.         NON_CONST_ITERATE (CSeq_loc_mix::Tdata, iter, SetMix().Set()) {
  1043.             (*iter)->SetId(id);
  1044.         }
  1045.         break;
  1046.     case e_Whole:
  1047.         SetWhole(id);
  1048.         break;
  1049.     case e_Empty:
  1050.         SetEmpty(id);
  1051.         break;
  1052.     case e_Equiv:
  1053.         NON_CONST_ITERATE (CSeq_loc_equiv::Tdata, iter, SetEquiv().Set()) {
  1054.             (*iter)->SetId(id);
  1055.         }
  1056.         break;
  1057.     case e_Bond:
  1058.         if (GetBond().IsSetA()) {
  1059.             SetBond().SetA().SetId(id);
  1060.         }
  1061.         if (GetBond().IsSetB()) {
  1062.             SetBond().SetB().SetId(id);
  1063.         }
  1064.         break;
  1065.     case e_Feat:
  1066.         LOG_POST(Error << "unhandled loc type in CSeq_loc::SetId(): e_Feat");
  1067.         break;
  1068.     default:
  1069.         LOG_POST(Error << "unhandled loc type in CSeq_loc::SetId(): "
  1070.                  << Which());
  1071.         break;
  1072.     }
  1073. }
  1074. bool CSeq_loc::Equals(const CSerialObject& object, ESerialRecursionMode how) const
  1075. {
  1076.     if ( typeid(object) != typeid(*this) ) {
  1077.         ERR_POST(Fatal <<
  1078.             "CSeq_loc::Assign() -- Assignment of incompatible types: " <<
  1079.             typeid(*this).name() << " = " << typeid(object).name());
  1080.     }
  1081.     return CSerialObject::Equals(object, how);
  1082. }
  1083. void CSeq_loc::x_CheckId(const CSeq_id*& id) const
  1084. {
  1085.     switch ( Which() ) {
  1086.     case CSeq_loc::e_not_set:
  1087.     case CSeq_loc::e_Null:
  1088.         {
  1089.             x_UpdateId(id, 0);
  1090.             break;
  1091.         }
  1092.     case CSeq_loc::e_Empty:
  1093.         {
  1094.             x_UpdateId(id, &GetEmpty());
  1095.             break;
  1096.         }
  1097.     case CSeq_loc::e_Whole:
  1098.         {
  1099.             x_UpdateId(id, &GetWhole());
  1100.             break;
  1101.         }
  1102.     case CSeq_loc::e_Int:
  1103.         {
  1104.             const CSeq_interval& loc = GetInt();
  1105.             x_UpdateId(id, &loc.GetId());
  1106.             break;
  1107.         }
  1108.     case CSeq_loc::e_Pnt:
  1109.         {
  1110.             const CSeq_point& pnt = GetPnt();
  1111.             x_UpdateId(id, &pnt.GetId());
  1112.             break;
  1113.         }
  1114.     case CSeq_loc::e_Packed_int:
  1115.         {
  1116.             // Check ID of each interval
  1117.             const CPacked_seqint& ints = GetPacked_int();
  1118.             ITERATE ( CPacked_seqint::Tdata, ii, ints.Get() ) {
  1119.                 const CSeq_interval& loc = **ii;
  1120.                 x_UpdateId(id, &loc.GetId());
  1121.             }
  1122.             break;
  1123.         }
  1124.     case CSeq_loc::e_Packed_pnt:
  1125.         {
  1126.             const CPacked_seqpnt& pnts = GetPacked_pnt();
  1127.             x_UpdateId(id, &pnts.GetId());
  1128.             break;
  1129.         }
  1130.     case CSeq_loc::e_Mix:
  1131.         {
  1132.             // Check ID of each sub-location.
  1133.             const CSeq_loc_mix& mix = GetMix();
  1134.             ITERATE( CSeq_loc_mix::Tdata, li, mix.Get() ) {
  1135.                 (*li)->CheckId(id);
  1136.             }
  1137.             break;
  1138.         }
  1139.     case CSeq_loc::e_Bond:
  1140.         {
  1141.             const CSeq_bond& bond = GetBond();
  1142.             if ( bond.CanGetA() ) {
  1143.                 x_UpdateId(id, &bond.GetA().GetId());
  1144.             }
  1145.             if ( bond.CanGetB() ) {
  1146.                 x_UpdateId(id, &bond.GetB().GetId());
  1147.             }
  1148.             break;
  1149.         }        
  1150.     case CSeq_loc::e_Equiv:
  1151.         {
  1152.             // Doesn't make much sense to test equiv, but ...
  1153.             ITERATE(CSeq_loc_equiv::Tdata, li, GetEquiv().Get()) {
  1154.                 (*li)->CheckId(id);
  1155.             }
  1156.             break;
  1157.         }
  1158.     case CSeq_loc::e_Feat:
  1159.     default:
  1160.         {
  1161.             NCBI_THROW(CException, eUnknown,
  1162.                        "CSeq_loc::CheckId -- "
  1163.                        "unsupported location type");
  1164.         }
  1165.     }
  1166. }
  1167. void CSeq_loc::x_ChangeToMix(const CSeq_loc& other)
  1168. {
  1169.     CRef<CSeq_loc> self(new CSeq_loc);
  1170.     self->Assign(*this);
  1171.     CSeq_loc_mix& mix = SetMix();
  1172.     mix.AddSeqLoc(*self);
  1173.     mix.AddSeqLoc(other);
  1174. }
  1175. void CSeq_loc::x_ChangeToPackedInt(const CSeq_loc& other)
  1176. {
  1177.     _ASSERT(IsInt());
  1178.     _ASSERT(other.IsInt()  ||  other.IsPacked_int());
  1179.     
  1180.     CConstRef<CSeq_interval> self(&GetInt());
  1181.     SetPacked_int().AddInterval(*self);
  1182.     if ( other.IsInt() ) {
  1183.         SetPacked_int().AddInterval(other.GetInt());
  1184.     } else {  // other is packed int
  1185.         SetPacked_int().AddIntervals(other.GetPacked_int());
  1186.     }
  1187. }
  1188. void CSeq_loc::x_ChangeToPackedPnt(const CSeq_loc& other)
  1189. {
  1190.     _ASSERT(IsPnt());
  1191.     _ASSERT(other.IsPnt()  ||  other.IsPacked_pnt());
  1192.     CRef<CSeq_point> pnt(&SetPnt());
  1193.     CPacked_seqpnt& ppnt = SetPacked_pnt();
  1194.     if ( pnt->IsSetStrand() ) {
  1195.         ppnt.SetStrand(pnt->GetStrand());
  1196.     }
  1197.     if ( pnt->IsSetId() ) {
  1198.         ppnt.SetId(pnt->SetId());
  1199.     }
  1200.     if ( pnt->IsSetFuzz() ) {
  1201.         ppnt.SetFuzz(pnt->SetFuzz());
  1202.     }
  1203.     ppnt.AddPoint(pnt->GetPoint());
  1204.     if ( other.IsPnt() ) {
  1205.         ppnt.AddPoint(other.GetPnt().GetPoint());
  1206.     } else { // other is packed point
  1207.         ppnt.AddPoints(other.GetPacked_pnt().GetPoints());
  1208.     }
  1209. }
  1210. template<typename T1, typename T2>
  1211. bool s_CanAdd(const T1& obj1, const T2& obj2)
  1212. {
  1213.     // test strands
  1214.     {{
  1215.         ENa_strand s1 = obj1.CanGetStrand() ? obj1.GetStrand() : eNa_strand_unknown;
  1216.         ENa_strand s2 = obj2.CanGetStrand() ? obj2.GetStrand() : eNa_strand_unknown;
  1217.         if ( s1 != s2 ) {
  1218.             return false;
  1219.         }
  1220.     }}
  1221.     // test ids
  1222.     {{
  1223.         const CSeq_id* id1 = obj1.CanGetId() ? &obj1.GetId() : 0;
  1224.         const CSeq_id* id2 = obj2.CanGetId() ? &obj2.GetId() : 0;
  1225.         if ( ((id1 != id2)  &&  (id1 == 0  ||  id2 == 0))  ||
  1226.              !id1->Match(*id2) ) {
  1227.             return false;
  1228.         }
  1229.     }}
  1230.     // test fuzz
  1231.     {{
  1232.         const CInt_fuzz* f1 = obj1.CanGetFuzz() ? &obj1.GetFuzz() : 0;
  1233.         const CInt_fuzz* f2 = obj2.CanGetFuzz() ? &obj2.GetFuzz() : 0;
  1234.         if ( ((f1 != f2)  &&  (f1 == 0  ||  f2 == 0))  ||
  1235.              !f1->Equals(*f2) ) {
  1236.             return false;
  1237.         }
  1238.     }}
  1239.     return true;
  1240. }
  1241. bool s_CanAdd(const CSeq_loc& loc1, const CSeq_loc& loc2)
  1242. {
  1243.     switch ( loc1.Which() ) {
  1244.     case CSeq_loc::e_Pnt:
  1245.         {
  1246.             switch ( loc2.Which() ) {
  1247.             case CSeq_loc::e_Pnt:
  1248.                 return s_CanAdd(loc1.GetPnt(), loc2.GetPnt());
  1249.             case CSeq_loc::e_Packed_pnt:
  1250.                 return s_CanAdd(loc1.GetPnt(), loc2.GetPacked_pnt());
  1251.             }
  1252.             break;
  1253.         }
  1254.     case CSeq_loc::e_Packed_pnt:
  1255.         {
  1256.             switch ( loc2.Which() ) {
  1257.             case CSeq_loc::e_Pnt:
  1258.                 return s_CanAdd(loc1.GetPacked_pnt(), loc2.GetPnt());
  1259.             case CSeq_loc::e_Packed_pnt:
  1260.                 return s_CanAdd(loc1.GetPacked_pnt(), loc2.GetPacked_pnt());
  1261.             }
  1262.             break;
  1263.         }
  1264.     default:
  1265.         {
  1266.             return false;
  1267.         }
  1268.     }
  1269.     return false;
  1270. }
  1271. void CSeq_loc::Add(const CSeq_loc& other)
  1272. {
  1273.     x_InvalidateCache();
  1274.     switch ( Which() ) {
  1275.     case CSeq_loc::e_not_set:
  1276.         {
  1277.             Assign(other);
  1278.             break;
  1279.         }
  1280.     case CSeq_loc::e_Null:
  1281.         {
  1282.             // ??? skip if other is null?
  1283.             x_ChangeToMix(other);
  1284.             break;
  1285.         }
  1286.     case CSeq_loc::e_Empty:
  1287.         {
  1288.             // ??? skip if other is empty and ids match?
  1289.             x_ChangeToMix(other);
  1290.             break;
  1291.         }
  1292.         break;
  1293.     case CSeq_loc::e_Whole:
  1294.         {
  1295.             x_ChangeToMix(other);
  1296.             break;
  1297.         }
  1298.     case CSeq_loc::e_Int:
  1299.         {
  1300.             if ( other.IsInt()  ||  other.IsPacked_int() ) {
  1301.                 x_ChangeToPackedInt(other);
  1302.             } else {
  1303.                 x_ChangeToMix(other);
  1304.             }
  1305.         }
  1306.         break;
  1307.     case CSeq_loc::e_Pnt:
  1308.         {
  1309.             if ( s_CanAdd(*this, other) ) {
  1310.                 x_ChangeToPackedPnt(other);
  1311.             } else {
  1312.                 x_ChangeToMix(other);
  1313.             }
  1314.             break;
  1315.         }
  1316.     case CSeq_loc::e_Packed_int:
  1317.         {
  1318.             if ( other.IsInt() ) {
  1319.                 SetPacked_int().AddInterval(other.GetInt());
  1320.             } else if ( other.IsPacked_int() ) {
  1321.                 SetPacked_int().AddIntervals(other.GetPacked_int());
  1322.             } else {
  1323.                 x_ChangeToMix(other);
  1324.             }
  1325.             break;
  1326.         }
  1327.     case CSeq_loc::e_Packed_pnt:
  1328.         {
  1329.             if ( s_CanAdd(*this, other) ) {
  1330.                 if ( other.IsPnt() ) {
  1331.                     SetPacked_pnt().AddPoint(other.GetPnt().GetPoint());
  1332.                 } else if ( other.IsPacked_pnt() ) {
  1333.                     SetPacked_pnt().AddPoints(other.GetPacked_pnt().GetPoints());
  1334.                 }
  1335.             } else {
  1336.                 x_ChangeToMix(other);
  1337.             }
  1338.             break;
  1339.         }
  1340.     case CSeq_loc::e_Mix:
  1341.         {
  1342.             SetMix().AddSeqLoc(other);
  1343.             break;
  1344.         }
  1345.     case CSeq_loc::e_Equiv:
  1346.         {
  1347.             SetEquiv().Add(other);
  1348.             break;
  1349.         }
  1350.     case CSeq_loc::e_Bond:
  1351.         {
  1352.             x_ChangeToMix(other);
  1353.             break;
  1354.         }
  1355.     case CSeq_loc::e_Feat:
  1356.     default:
  1357.         {
  1358.             NCBI_THROW(CException, eUnknown,
  1359.                        "CSeq_loc::Add -- "
  1360.                        "unsupported location type");
  1361.         }
  1362.     }
  1363. }
  1364. END_objects_SCOPE // namespace ncbi::objects::
  1365. END_NCBI_SCOPE
  1366. /*
  1367.  * =============================================================================
  1368.  * $Log: Seq_loc.cpp,v $
  1369.  * Revision 1000.3  2004/06/01 19:34:35  gouriano
  1370.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R6.42
  1371.  *
  1372.  * Revision 6.42  2004/05/19 17:26:25  gorelenk
  1373.  * Added include of PCH - ncbi_pch.hpp
  1374.  *
  1375.  * Revision 6.41  2004/05/07 12:51:13  shomrat
  1376.  * Removed return from function returning void
  1377.  *
  1378.  * Revision 6.40  2004/05/06 16:55:00  shomrat
  1379.  * Added methods to set partial left and right
  1380.  *
  1381.  * Revision 6.39  2004/03/25 15:59:06  gouriano
  1382.  * Added possibility to copy and compare serial object non-recursively
  1383.  *
  1384.  * Revision 6.38  2004/01/29 19:58:52  shomrat
  1385.  * Adding missing cache invalidation
  1386.  *
  1387.  * Revision 6.37  2004/01/28 17:18:11  shomrat
  1388.  * Added methods to ease the construction of objects
  1389.  *
  1390.  * Revision 6.36  2003/11/21 14:45:05  grichenk
  1391.  * Replaced runtime_error with CException
  1392.  *
  1393.  * Revision 6.35  2003/10/15 15:50:36  ucko
  1394.  * CSeq_loc_CI: expose fuzz (if present).
  1395.  *
  1396.  * Revision 6.34  2003/10/14 16:48:53  dicuccio
  1397.  * Added SetId() function.  Added correct printing of packed seq-points in
  1398.  * Getlabel()
  1399.  *
  1400.  * Revision 6.33  2003/09/22 18:38:14  grichenk
  1401.  * Fixed circular seq-locs processing by TestForOverlap()
  1402.  *
  1403.  * Revision 6.32  2003/09/17 18:39:01  grichenk
  1404.  * + GetStart(), GetEnd(), GetCircularLength()
  1405.  *
  1406.  * Revision 6.31  2003/07/21 15:32:11  vasilche
  1407.  * Fixed access to uninitialized member.
  1408.  *
  1409.  * Revision 6.30  2003/06/18 16:00:07  vasilche
  1410.  * Fixed GetTotalRange() in multithreaded app.
  1411.  *
  1412.  * Revision 6.29  2003/06/13 17:21:20  grichenk
  1413.  * Added seq-id caching for single-id seq-locs
  1414.  *
  1415.  * Revision 6.28  2003/04/02 15:17:47  grichenk
  1416.  * Added flag for CSeq_loc_CI to skip/include empty locations.
  1417.  *
  1418.  * Revision 6.27  2003/03/11 15:55:44  kuznets
  1419.  * iterate -> ITERATE
  1420.  *
  1421.  * Revision 6.26  2003/02/24 18:52:13  vasilche
  1422.  * Added clearing of old data in assign.
  1423.  *
  1424.  * Revision 6.25  2003/02/06 22:23:29  vasilche
  1425.  * Added CSeq_id::Assign(), CSeq_loc::Assign().
  1426.  * Added int CSeq_id::Compare() (not safe).
  1427.  * Added caching of CSeq_loc::GetTotalRange().
  1428.  *
  1429.  * Revision 6.24  2003/02/04 15:15:15  grichenk
  1430.  * Overrided Assign() for CSeq_loc and CSeq_id
  1431.  *
  1432.  * Revision 6.23  2003/01/24 20:11:33  vasilche
  1433.  * Fixed trigraph warning on GCC.
  1434.  *
  1435.  * Revision 6.22  2003/01/22 20:17:33  vasilche
  1436.  * Optimized CSeq_loc::GetTotalRange().
  1437.  *
  1438.  * Revision 6.21  2002/12/30 19:37:02  vasilche
  1439.  * Rewrote CSeq_loc::GetTotalRange() to avoid using CSeq_loc_CI -
  1440.  * it's too expensive.
  1441.  *
  1442.  * Revision 6.20  2002/12/23 17:19:27  grichenk
  1443.  * Added GetSeq_loc() to CSeq_loc_CI
  1444.  *
  1445.  * Revision 6.19  2002/12/19 20:24:54  grichenk
  1446.  * Updated usage of CRange<>
  1447.  *
  1448.  * Revision 6.18  2002/12/06 15:36:04  grichenk
  1449.  * Added overlap type for annot-iterators
  1450.  *
  1451.  * Revision 6.17  2002/10/03 20:22:50  ucko
  1452.  * Drop duplicate default arg. spec. for s_GetLabel.
  1453.  *
  1454.  * Revision 6.16  2002/10/03 18:53:03  clausen
  1455.  * Removed extra whitespace
  1456.  *
  1457.  * Revision 6.15  2002/10/03 16:36:09  clausen
  1458.  * Added GetLabel()
  1459.  *
  1460.  * Revision 6.14  2002/09/12 21:19:02  kans
  1461.  * added IsPartialLeft and IsPartialRight
  1462.  *
  1463.  * Revision 6.13  2002/06/06 20:35:28  clausen
  1464.  * Moved methods using object manager to objects/util
  1465.  *
  1466.  * Revision 6.12  2002/05/31 13:33:02  grichenk
  1467.  * GetLength() -- return 0 for e_Null locations
  1468.  *
  1469.  * Revision 6.11  2002/05/06 03:39:12  vakatov
  1470.  * OM/OM1 renaming
  1471.  *
  1472.  * Revision 6.10  2002/05/03 21:28:18  ucko
  1473.  * Introduce T(Signed)SeqPos.
  1474.  *
  1475.  * Revision 6.9  2002/04/22 20:08:31  grichenk
  1476.  * Redesigned GetTotalRange() using CSeq_loc_CI
  1477.  *
  1478.  * Revision 6.8  2002/04/17 15:39:08  grichenk
  1479.  * Moved CSeq_loc_CI to the seq-loc library
  1480.  *
  1481.  * Revision 6.7  2002/01/16 18:56:32  grichenk
  1482.  * Removed CRef<> argument from choice variant setter, updated sources to
  1483.  * use references instead of CRef<>s
  1484.  *
  1485.  * Revision 6.6  2002/01/10 18:21:26  clausen
  1486.  * Added IsOneBioseq, GetStart, and GetId
  1487.  *
  1488.  * Revision 6.5  2001/10/22 11:40:32  clausen
  1489.  * Added Compare() implementation
  1490.  *
  1491.  * Revision 6.4  2001/01/03 18:59:09  vasilche
  1492.  * Added missing include.
  1493.  *
  1494.  * Revision 6.3  2001/01/03 16:39:05  vasilche
  1495.  * Added CAbstractObjectManager - stub for object manager.
  1496.  * CRange extracted to separate file.
  1497.  *
  1498.  * Revision 6.2  2000/12/26 17:28:55  vasilche
  1499.  * Simplified and formatted code.
  1500.  *
  1501.  * Revision 6.1  2000/11/17 21:35:10  vasilche
  1502.  * Added GetLength() method to CSeq_loc class.
  1503.  *
  1504.  *
  1505.  * ===========================================================================
  1506. */