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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: sequtil_convert_imp.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 19:42:17  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.2
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: sequtil_convert_imp.cpp,v 1000.1 2004/06/01 19:42:17 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:  Mati Shomrat
  35.  *
  36.  * File Description:
  37.  *   
  38.  */   
  39. #include <ncbi_pch.hpp>
  40. #include <corelib/ncbistd.hpp>
  41. #include <util/sequtil/sequtil_expt.hpp>
  42. #include "sequtil_convert_imp.hpp"
  43. #include "sequtil_shared.hpp"
  44. #include "sequtil_tables.hpp"
  45. BEGIN_NCBI_SCOPE
  46. /////////////////////////////////////////////////////////////////////////////
  47. //
  48. // Conversions
  49. // NB: We try to use conversion tables wherever possible, minimizing bit 
  50. // shifting or any other operation within the main conversion loop.
  51. // All conversion functions takes the following parameters:
  52. // src - input sequence
  53. // pos - starting position in sequence coordinates
  54. // length - number of residues to convert
  55. // dst - an output container
  56. SIZE_TYPE CSeqConvert_imp::Convert
  57. (const char* src,
  58.  TCoding src_coding,
  59.  TSeqPos pos,
  60.  TSeqPos length,
  61.  char* dst,
  62.  TCoding dst_coding)
  63. {
  64.     _ASSERT((dst != 0)  &&  (src != 0));
  65.     _ASSERT(CSeqUtil::GetCodingType(src_coding) == 
  66.             CSeqUtil::GetCodingType(dst_coding));
  67.     if ( length == 0 ) {
  68.         return 0;
  69.     }
  70.     // conversion from a coding to itself.
  71.     if ( src_coding == dst_coding ) {
  72.         return Subseq(src, src_coding, pos, length, dst);
  73.     }
  74.     
  75.     // all other conversions
  76.     switch ( src_coding ) {
  77.         
  78.     // --- NA conversions 
  79.         
  80.     // iupacna -> ...
  81.     case CSeqUtil::e_Iupacna:
  82.         switch ( dst_coding ) {
  83.         case CSeqUtil::e_Ncbi2na:
  84.             return x_ConvertIupacnaTo2na(src, pos, length, dst);
  85.         case CSeqUtil::e_Ncbi2na_expand:
  86.             return x_ConvertIupacnaTo2naExpand(src, pos, length, dst);
  87.         case CSeqUtil::e_Ncbi4na:
  88.             return x_ConvertIupacnaTo4na(src, pos, length, dst);
  89.         case CSeqUtil::e_Ncbi4na_expand:
  90.         case CSeqUtil::e_Ncbi8na:
  91.             return x_ConvertIupacnaTo8na(src, pos, length, dst);
  92.         }
  93.         break;
  94.     
  95.     // ncbi2na -> ...
  96.     case CSeqUtil::e_Ncbi2na:
  97.         switch ( dst_coding ) {
  98.         case CSeqUtil::e_Iupacna:
  99.             return x_Convert2naToIupacna(src, pos, length, dst);
  100.         case CSeqUtil::e_Ncbi2na_expand:
  101.             return x_Convert2naTo2naExpand(src, pos, length, dst);
  102.         case CSeqUtil::e_Ncbi4na:
  103.             return x_Convert2naTo4na(src, pos, length, dst);
  104.         case CSeqUtil::e_Ncbi4na_expand:
  105.         case CSeqUtil::e_Ncbi8na:
  106.             return x_Convert2naTo8na(src, pos, length, dst);
  107.         }
  108.         break;
  109.     // ncbi2na_expand -> ...
  110.     case CSeqUtil::e_Ncbi2na_expand:
  111.         switch ( dst_coding ) {
  112.         case CSeqUtil::e_Iupacna:
  113.             return x_Convert2naExpandToIupacna(src, pos, length, dst);
  114.         case CSeqUtil::e_Ncbi2na:
  115.             return x_Convert2naExpandTo2na(src, pos, length, dst);
  116.         case CSeqUtil::e_Ncbi4na:
  117.             return x_Convert2naExpandTo4na(src, pos, length, dst);
  118.         case CSeqUtil::e_Ncbi4na_expand:
  119.         case CSeqUtil::e_Ncbi8na:
  120.             return x_Convert2naExpandTo8na(src, pos, length, dst);
  121.         }
  122.         break;
  123.         
  124.     // ncbi4na -> ...
  125.     case CSeqUtil::e_Ncbi4na:
  126.         switch ( dst_coding ) {
  127.         case CSeqUtil::e_Iupacna:
  128.             return x_Convert4naToIupacna(src, pos, length, dst);
  129.         case CSeqUtil::e_Ncbi2na:
  130.             return x_Convert4naTo2na(src, pos, length, dst);
  131.         case CSeqUtil::e_Ncbi2na_expand:
  132.             return x_Convert4naTo2naExpand(src, pos, length, dst);
  133.         case CSeqUtil::e_Ncbi4na_expand:
  134.         case CSeqUtil::e_Ncbi8na:
  135.             return x_Convert4naTo8na(src, pos, length, dst);
  136.         }
  137.         break;
  138.         
  139.     // ncbi8na / ncbi4na_expand -> ...
  140.     case CSeqUtil::e_Ncbi8na:
  141.     case CSeqUtil::e_Ncbi4na_expand:
  142.         switch ( dst_coding ) {
  143.         case CSeqUtil::e_Iupacna:
  144.             return x_Convert8naToIupacna(src, pos, length, dst);
  145.         case CSeqUtil::e_Ncbi2na:
  146.             return x_Convert8naTo2na(src, pos, length, dst);
  147.         case CSeqUtil::e_Ncbi2na_expand:
  148.             return x_Convert8naTo2naExpand(src, pos, length, dst);
  149.         case CSeqUtil::e_Ncbi4na:
  150.             return x_Convert8naTo4na(src, pos, length, dst);
  151.         case CSeqUtil::e_Ncbi8na:
  152.         case CSeqUtil::e_Ncbi4na_expand:
  153.             return Subseq(src, src_coding, pos, length, dst);
  154.         }
  155.         break;
  156.         
  157.     // --- AA conversions 
  158.                         
  159.     // NB: currently ncbi8aa is the same as ncbistdaa.
  160.               
  161.     // iupacaa -> ...
  162.     case CSeqUtil::e_Iupacaa:
  163.         switch ( dst_coding ) {
  164.         case CSeqUtil::e_Ncbieaa:
  165.             return x_ConvertIupacaaToEaa(src, pos, length, dst);
  166.         case CSeqUtil::e_Ncbistdaa:
  167.         case CSeqUtil::e_Ncbi8aa:
  168.             return x_ConvertIupacaaToStdaa(src, pos, length, dst);
  169.         }
  170.         break;
  171.         
  172.     // ncbieaa -> ...
  173.     case CSeqUtil::e_Ncbieaa:
  174.         switch ( dst_coding ) {
  175.         case CSeqUtil::e_Iupacaa:
  176.             return x_ConvertEaaToIupacaa(src, pos, length, dst);
  177.         case CSeqUtil::e_Ncbistdaa:
  178.         case CSeqUtil::e_Ncbi8aa:
  179.             return x_ConvertEaaToStdaa(src, pos, length, dst);            
  180.         }
  181.         break;
  182.         
  183.     // ncbistdaa / ncbi8aa -> ...
  184.     case CSeqUtil::e_Ncbi8aa:
  185.     case CSeqUtil::e_Ncbistdaa:
  186.         switch ( dst_coding ) {
  187.         case CSeqUtil::e_Ncbieaa:
  188.             return x_ConvertStdaaToEaa(src, pos, length, dst);
  189.         case CSeqUtil::e_Iupacaa:
  190.             return x_ConvertStdaaToIupacaa(src, pos, length, dst);
  191.         case CSeqUtil::e_Ncbi8aa:
  192.         case CSeqUtil::e_Ncbistdaa:
  193.             return Subseq(src, src_coding, pos, length, dst);
  194.         }
  195.         break;
  196.     }
  197.     // We should never reach here
  198.     NCBI_THROW(CSeqUtilException, eInvalidCoding, "Unknown conversion.");
  199. }
  200. // --- NA conversions:
  201. // from IUPACna to ...
  202. //===========================================================================
  203. // IUPACna -> IUPACna
  204. // This is not a simple copy since we handle conversion of lower to upper 
  205. // case and conversion of 'U'('u') to 'T'
  206. SIZE_TYPE CSeqConvert_imp::x_ConvertIupacnaToIupacna
  207. (const char* src,
  208.  TSeqPos pos,
  209.  TSeqPos length,
  210.  char* dst)
  211. {
  212.     // call the shared implementation for converting 1 byte to another byte
  213.     // given a specific conversion table.
  214.     // the iupacna to iupacna table converts upper and lower case to upper case
  215.     // and U (u) to T
  216.     return convert_1_to_1(src, pos, length, dst, 
  217.                           CIupacnaToIupacna::GetTable());
  218. }
  219. // IUPACna -> NCBI2na
  220. // convert 4 IUPACna characters into a single NCBI2na byte
  221. SIZE_TYPE CSeqConvert_imp::x_ConvertIupacnaTo2na
  222. (const char* src,
  223.  TSeqPos pos,
  224.  TSeqPos length,
  225.  char* dst)
  226. {
  227.     // The iupacna to ncbi2na table is constructed such that each row
  228.     // correspond to an iupacna letter and each column corresponds to
  229.     // that letter being in one of the 4 possible offsets within the 
  230.     // ncbi2na byte
  231.     const Uint1* table = CIupacnaTo2na::GetTable();
  232.     
  233.     const char* src_i = src + pos;
  234.     for ( size_t count = length / 4; count; --count ) {
  235.         *dst = 
  236.             table[*src_i * 4          ] | 
  237.             table[*(src_i + 1) * 4 + 1] |
  238.             table[*(src_i + 2) * 4 + 2] |
  239.             table[*(src_i + 3) * 4 + 3];
  240.         src_i += 4;
  241.         ++dst;
  242.     }
  243.     
  244.     // Handle overhang
  245.     if ( length % 4 != 0 ) {
  246.         *dst = 0x0;
  247.         for( size_t i = 0; i < (length % 4); ++i, ++src_i ) {
  248.             *dst |= table[static_cast<Uint1>(*src_i) * 4 + i];
  249.         }
  250.     }
  251.     
  252.     return length;
  253. }
  254. // IUPACna -> NCBI2na_expand
  255. // convert a single IUPACna character into a single NCBI2na_expand byte.
  256. SIZE_TYPE CSeqConvert_imp::x_ConvertIupacnaTo2naExpand
  257. (const char* src,
  258.  TSeqPos pos,
  259.  TSeqPos length,
  260.  char* dst)
  261. {
  262.     // call the shared implementation for converting 1 byte to another byte
  263.     // given a specific conversion table.
  264.     // the iupacna to ncbi2na_expand table converts upper and lower case IUPACna
  265.     // into a single ncbi2na_expand byte.
  266.     return convert_1_to_1(src, pos, length, dst, 
  267.                           CIupacnaTo2naExpand::GetTable());
  268. }
  269. // IUPACna -> NCBI4na
  270. // convert 2 IUPACna characters into a single NCBI4na byte
  271. SIZE_TYPE CSeqConvert_imp::x_ConvertIupacnaTo4na
  272. (const char* src,
  273.  TSeqPos pos,
  274.  TSeqPos length,
  275.  char* dst)
  276. {
  277.     // The iupacna to ncbi4na table is constructed such that each row
  278.     // correspond to an iupacna letter and each column corresponds to
  279.     // that letter being in one of the 2 possible offsets within the 
  280.     // ncbi4na byte
  281.     const Uint1* table = CIupacnaTo4na::GetTable();
  282.     
  283.     const char* src_i = src + pos;
  284.     
  285.     for ( size_t count = length / 2; count; --count ) {
  286.         *dst = table[*src_i * 2] | table[*(src_i + 1) * 2 + 1];
  287.         src_i += 2;
  288.         ++dst;
  289.     }
  290.     
  291.     // handle overhang
  292.     if ( length % 2 != 0 ) {
  293.         *dst = table[static_cast<Uint1>(*src_i) * 2];
  294.     }
  295.     
  296.     return length;
  297. }
  298. // IUPACna -> NCBI8na (NCBI4na_expand)
  299. // convert a single IUPACna character into a single NCBI8na byte.
  300. SIZE_TYPE CSeqConvert_imp::x_ConvertIupacnaTo8na
  301. (const char* src,
  302.  TSeqPos pos,
  303.  TSeqPos length,
  304.  char* dst)
  305. {
  306.     // call the shared implementation for converting 1 byte to another byte
  307.     // given a specific conversion table.
  308.     // the iupacna to ncbi8na table converts upper and lower case IUPACna
  309.     // into a single ncbi8na byte (which is the same as ncbi4na_expand)
  310.     return convert_1_to_1(src, pos, length, dst, 
  311.                           CIupacnaTo8na::GetTable());
  312. }
  313. // from NCBI2na to ...
  314. //===========================================================================
  315. // NCBI2na -> IUPACna
  316. // convert a NCBI2na byte into 4 IUPACna characters.
  317. SIZE_TYPE CSeqConvert_imp::x_Convert2naToIupacna
  318. (const char* src,
  319.  TSeqPos pos,
  320.  TSeqPos length,
  321.  char* dst)
  322. {
  323.     return convert_1_to_4(src, pos, length, dst, C2naToIupacna::GetTable());
  324. }
  325. // NCBI2na -> NCBI2na_expand
  326. // convert a NCBI2na byte into 4 NCBI2na_expand characters.
  327. SIZE_TYPE CSeqConvert_imp::x_Convert2naTo2naExpand
  328. (const char* src,
  329.  TSeqPos pos,
  330.  TSeqPos length,
  331.  char* dst)
  332. {
  333.     return convert_1_to_4(src, pos, length, dst, C2naTo2naExpand::GetTable());
  334. }
  335. // NCBI2na -> NCBI4na
  336. // convert a NCBI2na byte into 2 NCBI4na bytes.
  337. SIZE_TYPE CSeqConvert_imp::x_Convert2naTo4na
  338. (const char* src,
  339.  TSeqPos pos,
  340.  TSeqPos length,
  341.  char* dst)
  342. {
  343.     const Uint1* table = C2naTo4na::GetTable(pos % 2 == 0);
  344.     const Uint2* table2 = reinterpret_cast<const Uint2*>(table);
  345.     const char* iter = src + (pos / 4);
  346.     
  347.     size_t size = length;
  348.     // NB: branch within the inner loop as devastating consequences
  349.     // on performance.
  350.     
  351.     // we handle two different cases, the first being offsets 0 and 2.
  352.     // the second are offsets 1 and 3.
  353.     // for offsets 0,2 we use a 2 column table, where the first column
  354.     // corresponds to the lower 4 bits of the ncbi2na coding (entry 0)
  355.     // and the second column corresponds to the upper 4 bits (entry 1).
  356.     // in this case once we set the initial entry progress is the same.
  357.     // the overhang for this case is either 0 or 1.
  358.     // the 13 offset is a more complex one. for it we use a 3 column table.
  359.     // the first column corresponds to the lower 2 bits of the ncbi2na 
  360.     // coding, the second corresponds to the middle 4 bits and the third
  361.     // correspond to the upper 2 bits.
  362.     // we handle all cases as offset 3. for offset one we simply handle 
  363.     // the first 4 bits, which will being us to offset 3.
  364.     // as handling the middle 4 bits or the combination of the 2 lower
  365.     // ones and 2 upper ones are done differently, we handle 4 letters (8 bits)
  366.     // at a time, in oredr to prevent branching withing the inner loop.
  367.     // overhang for this case is 1, 2 or 3.
  368.     
  369.     switch ( pos % 4 ) {
  370.         // --- table entry size for offsets 0,2 is 2
  371.     case 2:
  372.         {{
  373.             *dst = table[static_cast<Uint1>(*iter) * 2 + 1];
  374.             if ( length == 1 ) {
  375.                 *dst &= 0xf0;
  376.                 return length;
  377.             }
  378.             size -= 2;
  379.             ++iter;
  380.             ++dst;
  381.         }}
  382.         // intentional fall through
  383.     case 0:
  384.         {{
  385.             // "trick" the compiler so that each assignment will
  386.             // be of 2 bytes.
  387.             Uint2* dst2 = reinterpret_cast<Uint2*>(dst);
  388.             for ( size_t i = size / 4; i; --i , ++dst2, ++iter ) {
  389.                 *dst2 = table2[static_cast<Uint1>(*iter)];
  390.             }
  391.             dst = reinterpret_cast<char*>(dst2);
  392.         }}
  393.         // handle overhang
  394.         if ( (size % 4) != 0 ) {
  395.             switch ( size % 4 ) {
  396.             case 1:
  397.                 *dst = table[static_cast<Uint1>(*iter) * 2] & 0xf0;
  398.                 break;
  399.             case 2:
  400.                 *dst = table[static_cast<Uint1>(*iter) * 2];
  401.                 break;
  402.             case 3:
  403.                 *dst = table[static_cast<Uint1>(*iter) * 2];
  404.                 ++dst;
  405.                 *dst = table[static_cast<Uint1>(*iter) * 2 + 1] & 0xf0;
  406.                 break;
  407.             }
  408.         }
  409.         break;
  410.         
  411.         // --- table entry size for offsets 1,3 is 3
  412.     case 3:
  413.         {{
  414.             if ( length == 1 ) {
  415.                 *dst = table[static_cast<Uint1>(*iter) * 3 + 2];
  416.                 return length;
  417.             } else {
  418.                 *dst = table[static_cast<Uint1>(*iter) * 3 + 2] |
  419.                        table[static_cast<Uint1>(*(iter + 1)) * 3];
  420.                 ++dst;
  421.                 ++iter;
  422.                 size -= 2;
  423.             }
  424.         }}
  425.         // intentional fall through
  426.     case 1:
  427.         {{
  428.             for ( size_t i = size / 4; i; --i, ++iter ) {
  429.                 *dst = table[static_cast<Uint1>(*iter) * 3 + 1];
  430.                 ++dst;
  431.                 *dst = table[static_cast<Uint1>(*iter) * 3 + 2] |
  432.                        table[static_cast<Uint1>(*(iter + 1)) * 3];
  433.                 ++dst;
  434.             }
  435.         }}
  436.         // handle overhang
  437.         if ( size % 4 != 0 ) {
  438.             switch ( size % 4 ) {
  439.             case 1:
  440.                 *dst = table[static_cast<Uint1>(*iter) * 3 + 1] & 0xF0;
  441.                 break;
  442.             case 2:
  443.                 *dst = table[static_cast<Uint1>(*iter) * 3 + 1];
  444.                 break;
  445.             case 3:
  446.                 *dst = table[static_cast<Uint1>(*iter) * 3 + 1];
  447.                 ++dst;
  448.                 *dst = table[static_cast<Uint1>(*iter) * 3 + 2];
  449.                 break;
  450.             }
  451.         }
  452.         break;
  453.     } // end of switch ( offset )
  454.     
  455.     return length;
  456. }
  457.     
  458. // NCBI2na -> NCBI8na (NCBI4na_expand)
  459. // convert a ncbi2na byte into 4 ncbi4na bytes.
  460. SIZE_TYPE CSeqConvert_imp::x_Convert2naTo8na
  461. (const char* src,
  462.  TSeqPos pos,
  463.  TSeqPos length,
  464.  char* dst)
  465. {
  466.     return convert_1_to_4(src, pos, length, dst, C2naTo8na::GetTable());
  467. }
  468. // from NCBI2na_expand to ...
  469. //===========================================================================
  470. // NCBI2na_expand -> IUPACna
  471. // convert a single NCBI2na_expand byte into a single IUPACna byte.
  472. SIZE_TYPE CSeqConvert_imp::x_Convert2naExpandToIupacna
  473. (const char* src,
  474.  TSeqPos pos,
  475.  TSeqPos length,
  476.  char* dst)
  477. {
  478.     return convert_1_to_1(src, pos, length, dst, 
  479.                           C2naExpandToIupacna::GetTable());
  480. }
  481. // NCBI2na_expand -> NCBI2na
  482. // convert 4 NCBI2na_expand bytes to a single NCBI2na one.
  483. SIZE_TYPE CSeqConvert_imp::x_Convert2naExpandTo2na
  484. (const char* src,
  485.  TSeqPos pos,
  486.  TSeqPos length,
  487.  char* dst)
  488. {
  489.     const char* iter = src + pos;
  490.     
  491.     // main loop. pack 4 ncbi2na_expand bytes into a single bye and add it
  492.     // to the output container
  493.     for ( size_t i = length / 4; i; --i, ++dst ) {
  494.         *dst = (*iter << 6) | (*(iter + 1) << 4) | 
  495.                (*(iter + 2) << 2) | (*(iter + 3));
  496.         iter += 4;
  497.     }
  498.     switch ( length % 4 ) {
  499.     case 1:
  500.         *dst = (*iter << 6);
  501.         break;
  502.     case 2:
  503.         *dst = (*iter << 6) | (*(iter + 1) << 4);
  504.         break;
  505.     case 3:
  506.         *dst = (*iter << 6) | (*(iter + 1) << 4) | (*(iter + 2) << 2);
  507.         break;
  508.     }
  509.     
  510.     return length;
  511. }
  512. // NCBI2na_expand -> NCBI4na
  513. // convert 2 NCBI2na_expand bytes into a single NCBI4na byte.
  514. SIZE_TYPE CSeqConvert_imp::x_Convert2naExpandTo4na
  515. (const char* src,
  516.  TSeqPos pos,
  517.  TSeqPos length,
  518.  char* dst)
  519. {
  520.     // A simple conversion table that converts a ncbi2na_expand byte
  521.     // into a "half" ncbi4na byte, based on the position of the 
  522.     // ncbi2na_expand byte within the ncbi4na byte
  523.     // positions 0 and 1 corresponds to the lower and upper 4 bits in 
  524.     // a ncbi4na byte respectively.
  525.     static Uint1 table[8] = {
  526.       //  0     1
  527.         0x10, 0x01,  // A 
  528.         0x20, 0x02,  // C
  529.         0x40, 0x04,  // G
  530.         0x80, 0x08   // T
  531.     };
  532.     const char* iter = src + pos;
  533.     for ( size_t i = length / 2; i; --i, ++dst ) {
  534.         *dst = table[*iter * 2] | table[*(iter + 1) * 2 + 1];
  535.         iter += 2;
  536.     }
  537.     
  538.     if ( length % 2 != 0 ) { // == 1
  539.         *dst = table[*iter * 2];
  540.     }
  541.     return length;
  542. }
  543. // NCBI2na_expand -> NCBI8na (NCBI4na_expand)
  544. // convert a single NCBI2na_expand byte into a single NCBI8na one.
  545. SIZE_TYPE CSeqConvert_imp::x_Convert2naExpandTo8na
  546. (const char* src,
  547.  TSeqPos pos,
  548.  TSeqPos length,
  549.  char* dst)
  550. {
  551.     // simple
  552.     static Uint1 table[4] = {
  553.         0x01,  // A  0 -> 1
  554.         0x02,  // C  1 -> 2
  555.         0x04,  // G  2 -> 4
  556.         0x08   // T  3 -> 8
  557.     };
  558.     
  559.     return convert_1_to_1(src, pos, length, dst, table);
  560. }
  561. // from NCBI4na to ...
  562. //===========================================================================
  563. // NCBI4na -> IUPACna
  564. // convert a NCBI4na byte into 2 IUPACna characters.
  565. SIZE_TYPE CSeqConvert_imp::x_Convert4naToIupacna
  566. (const char* src,
  567.  TSeqPos pos,
  568.  TSeqPos length,
  569.  char* dst)
  570. {
  571.     return convert_1_to_2(src, pos, length, dst, C4naToIupacna::GetTable());
  572. }
  573. // NCBI4na -> NCBI2na
  574. // convert 2 NCBI4na bytes into a NCBI2na byte.
  575. SIZE_TYPE CSeqConvert_imp::x_Convert4naTo2na
  576. (const char* src,
  577.  TSeqPos pos,
  578.  TSeqPos length,
  579.  char* dst)
  580. {
  581.     Uint1 offset = pos % 2;
  582.     const Uint1* table = C4naTo2na::GetTable(offset);
  583.     
  584.     size_t overhang = length % 4;
  585.     
  586.     const char* iter = src + (pos / 2);
  587.     
  588.     switch ( offset ) {
  589.     case 0:
  590.         // aligned copy
  591.         {{
  592.             for ( size_t i = length / 4; i; --i, ++dst ) {
  593.                 *dst = 
  594.                     table[static_cast<Uint1>(*iter) * 2] |
  595.                     table[static_cast<Uint1>(*(iter + 1)) * 2 + 1];
  596.                 iter += 2;
  597.             }
  598.             
  599.             // handle overhang
  600.             if ( overhang != 0 ) {
  601.                 switch ( overhang ) {
  602.                 case 1:
  603.                     // leave just the 2 lower bits
  604.                     *dst = (table[static_cast<Uint1>(*iter) * 2]) & 0xC0;
  605.                     break;
  606.                 case 2:
  607.                     // leave just the 4 lower bits
  608.                     *dst = (table[static_cast<Uint1>(*iter) * 2]) & 0xF0;
  609.                     break;
  610.                 case 3:
  611.                     *dst = 
  612.                         table[static_cast<Uint1>(*iter) * 2]           |
  613.                         table[static_cast<Uint1>(*(iter + 1)) * 2 + 1] &
  614.                         0xFC;
  615.                     break;
  616.                 }
  617.             }
  618.         }}
  619.         break;
  620.         
  621.     case 1:
  622.         // unaligned copy
  623.         {{
  624.             for ( size_t i = length / 4; i; --i, ++dst ) {
  625.                 *dst  = 
  626.                     table[static_cast<Uint1>(*iter) * 3]             |
  627.                     table[static_cast<Uint1>(*(iter + 1)) * 3 + 1]   |
  628.                     table[static_cast<Uint1>(*(iter + 2)) * 3 + 2];
  629.                 iter += 2;
  630.             }
  631.             
  632.             // handle overhang
  633.             if ( overhang != 0 ) {
  634.                 switch ( overhang ) {
  635.                 case 1:
  636.                     *dst = table[static_cast<Uint1>(*iter) * 3] & 0xC0;
  637.                     break;
  638.                 case 2:
  639.                     *dst = 
  640.                         table[static_cast<Uint1>(*iter) * 3]           |
  641.                         table[static_cast<Uint1>(*(iter + 1)) * 3 + 1] &
  642.                         0xF0;
  643.                     break;
  644.                 case 3:
  645.                     *dst = 
  646.                         table[static_cast<Uint1>(*iter) * 3]           |
  647.                         table[static_cast<Uint1>(*(iter + 1)) * 3 + 1] &
  648.                         0xFC;
  649.                     break;
  650.                 }
  651.             }
  652.         }}
  653.         break;
  654.     }
  655.     
  656.     return length;
  657. }
  658. // NCBI4na -> NCBI2na_expand
  659. // convert a NCBI4na byte into 2 NCBI2na_expand bytes.
  660. SIZE_TYPE CSeqConvert_imp::x_Convert4naTo2naExpand
  661. (const char* src,
  662.  TSeqPos pos,
  663.  TSeqPos length,
  664.  char* dst)
  665. {
  666.     return convert_1_to_2(src, pos, length, dst, 
  667.                           C4naTo2naExpand::GetTable());
  668. }
  669. // NCBI4na -> NCBI8na (NCBI4na_expand)
  670. // convert a NCBI2na byte into 4 IUPACna characters.
  671. SIZE_TYPE CSeqConvert_imp::x_Convert4naTo8na
  672. (const char* src,
  673.  TSeqPos pos,
  674.  TSeqPos length,
  675.  char* dst)
  676. {
  677.     return convert_1_to_2(src, pos, length, dst, C4naTo8na::GetTable());
  678. }
  679. // from NCBI8na (NCBI4na_expand) to ...
  680. //===========================================================================
  681. // NCBI8na -> IUPACna
  682. // convert a single NCBI8na byte into a single IUPACna byte.
  683. SIZE_TYPE CSeqConvert_imp::x_Convert8naToIupacna
  684. (const char* src,
  685.  TSeqPos pos,
  686.  TSeqPos length,
  687.  char *dst)
  688. {
  689.     return convert_1_to_1(src, pos, length, dst, C8naToIupacna::GetTable());
  690. }
  691. // NCBI8na -> NCBI2na
  692. // convert 4 NCBI8na bytes into a single NCBI2na byte.
  693. SIZE_TYPE CSeqConvert_imp::x_Convert8naTo2na
  694. (const char* src,
  695.  TSeqPos pos,
  696.  TSeqPos length,
  697.  char *dst)
  698. {
  699.     const Uint1* table = C8naTo2na::GetTable();
  700.     
  701.     const char* iter = src + pos;
  702.     
  703.     for ( size_t i = length / 4; i; --i, ++dst ) {
  704.         *dst = table[static_cast<Uint1>(*iter) * 4] |
  705.             table[static_cast<Uint1>(*(iter + 1)) * 4 + 1] |
  706.             table[static_cast<Uint1>(*(iter + 2)) * 4 + 2] |
  707.             table[static_cast<Uint1>(*(iter + 3)) * 4 + 3];
  708.         iter += 4;
  709.     }
  710.     
  711.     // Handle overhang
  712.     if ( (length % 4) != 0 ) {
  713.         *dst = 0;
  714.         for( size_t i = 0; i < (length % 4); ++i, ++iter ) {
  715.             *dst |= table[static_cast<Uint1>(*iter) * 4 + i];
  716.         }
  717.     }
  718.     
  719.     return length;
  720. }
  721. // NCBI8na -> NCBI2na_expand
  722. // convert a single NCBI8na byte into a single NCBI2na_expand byte.
  723. SIZE_TYPE CSeqConvert_imp::x_Convert8naTo2naExpand
  724. (const char* src,
  725.  TSeqPos pos,
  726.  TSeqPos length,
  727.  char *dst)
  728. {
  729.     // simple conversion table
  730.     static const Uint1 table[16] = {
  731.         0x03,    // gap -> T
  732.         0x00,    // A -> A
  733.         0x01,    // C -> C
  734.         0x01,    // M -> C
  735.         0x02,    // G -> G
  736.         0x02,    // R -> G
  737.         0x01,    // S -> C
  738.         0x00,    // V -> A
  739.         0x03,    // T -> T
  740.         0x03,    // W -> T
  741.         0x03,    // Y -> T
  742.         0x00,    // H -> A
  743.         0x02,    // K -> G
  744.         0x02,    // D -> G
  745.         0x01,    // B -> C
  746.         0x00     // N -> A
  747.     };
  748.     
  749.     return convert_1_to_1(src, pos, length, dst, table);
  750. }
  751. // NCBI8na -> NCBI4na
  752. // convert 2 NCBI8na bytes into  a single NCBI4na byte.
  753. SIZE_TYPE CSeqConvert_imp::x_Convert8naTo4na
  754. (const char* src,
  755.  TSeqPos pos,
  756.  TSeqPos length,
  757.  char *dst)
  758. {
  759.     const char* iter = src + pos;
  760.     for ( size_t i = length / 2; i; --i, ++dst ) {
  761.         *dst = (*iter << 4) | (*(iter + 1));
  762.         iter += 2;
  763.     }
  764.     if ( (length % 2) != 0 ) {
  765.         *dst = (*iter << 4) & 0xf0;
  766.     }
  767.     
  768.     return length;
  769. }
  770. // AA conversions:
  771. // All AA conversions ara a 1 to 1 conversion
  772. // from IUPACaa to ...
  773. //===========================================================================
  774. // IUPACaa -> NCBIeaa
  775. SIZE_TYPE CSeqConvert_imp::x_ConvertIupacaaToEaa
  776. (const char* src,
  777.  TSeqPos pos,
  778.  TSeqPos length,
  779.  char *dst)
  780. {
  781.     // they map directly
  782.     return Subseq(src, CSeqUtil::e_Iupacaa, pos, length, dst);
  783. }
  784. // IUPACaa -> NCBIstdaa (NCBI8aa)
  785. SIZE_TYPE CSeqConvert_imp::x_ConvertIupacaaToStdaa
  786. (const char* src,
  787.  TSeqPos pos,
  788.  TSeqPos length,
  789.  char *dst)
  790. {
  791.     return convert_1_to_1(src, pos, length, dst, CIupacaaToStdaa::GetTable());
  792. }
  793. // from NCBIeaa to ...
  794. //===========================================================================
  795. // NCBIeaa -> IUPACaa
  796. SIZE_TYPE CSeqConvert_imp::x_ConvertEaaToIupacaa
  797. (const char* src,
  798.  TSeqPos pos,
  799.  TSeqPos length,
  800.  char *dst)
  801. {
  802.     return convert_1_to_1(src, pos, length, dst, CEaaToIupacaa::GetTable());
  803. }
  804. // NCBIeaa -> NCBIstdaa (NCBI8aa)
  805. SIZE_TYPE CSeqConvert_imp::x_ConvertEaaToStdaa
  806. (const char* src,
  807.  TSeqPos pos,
  808.  TSeqPos length,
  809.  char *dst)
  810. {
  811.     return convert_1_to_1(src, pos, length, dst, CEaaToStdaa::GetTable());
  812. }
  813. // from NCBIstdaa (NCBI8aa) to ...
  814. //===========================================================================
  815. // NCBIstdaa (NCBI8aa) -> IUPACaa
  816. SIZE_TYPE CSeqConvert_imp::x_ConvertStdaaToIupacaa
  817. (const char* src,
  818.  TSeqPos pos,
  819.  TSeqPos length,
  820.  char *dst)
  821. {
  822.     return convert_1_to_1(src, pos, length, dst, CStdaaToIupacaa::GetTable());
  823. }
  824. // NCBIstdaa (NCBI8aa) -> NCBIeaa
  825. SIZE_TYPE CSeqConvert_imp::x_ConvertStdaaToEaa
  826. (const char* src,
  827.  TSeqPos pos,
  828.  TSeqPos length,
  829.  char *dst)
  830. {
  831.     return convert_1_to_1(src, pos, length, dst, CStdaaToEaa::GetTable());
  832. }
  833. /////////////////////////////////////////////////////////////////////////////
  834. //
  835. // Subseq - partial sequence
  836. SIZE_TYPE CSeqConvert_imp::Subseq
  837. (const char* src,
  838.  TCoding coding,
  839.  TSeqPos pos,
  840.  TSeqPos length,
  841.  char* dst)
  842. {
  843.     SIZE_TYPE converted = 0;
  844.     char *buf = 0;
  845.     try {
  846.         switch ( coding ) {
  847.             
  848.         // for packed coding (2na and 4na) first expand, then re-pack
  849.         case CSeqUtil::e_Ncbi2na:
  850.             {{
  851.                 buf = new char[length];
  852.                 x_Convert2naTo2naExpand(src, pos, length, buf);
  853.                 converted = x_Convert2naExpandTo2na(buf, 0, length, dst);
  854.                 delete[] buf;
  855.                 buf = 0;
  856.             }}
  857.             break;
  858.             
  859.         case CSeqUtil::e_Ncbi4na:
  860.             {{
  861.                 buf = new char[length];
  862.                 x_Convert4naTo8na(src, pos, length, buf);
  863.                 converted = x_Convert8naTo4na(buf, 0, length, dst);
  864.                 delete[] buf;
  865.                 buf = 0;
  866.             }}
  867.             break;
  868.             
  869.         // iupacna may contain 'U' that needs to be converted to 'T'
  870.         case CSeqUtil::e_Iupacna:
  871.             {{
  872.                 converted = convert_1_to_1(src, pos, length, dst, 
  873.                     CIupacnaToIupacna::GetTable());
  874.             }}
  875.             break;
  876.             
  877.         // for other ascii codings make sure the output is upper case
  878.         case CSeqUtil::e_Iupacaa:
  879.         case CSeqUtil::e_Ncbieaa:
  880.             {{
  881.                 const char* iter = src + pos;
  882.                 const char* end  = iter + length;
  883.                 
  884.                 for ( ; iter != end; ++iter, ++dst ) {
  885.                     *dst++ = toupper(*iter);
  886.                 }
  887.                 converted = length;
  888.             }}
  889.             break;
  890.             
  891.         // for the rest of the codings (e.g. 8na, stdaa) copy
  892.         // the desired range.
  893.         default:
  894.             {{
  895.                 copy(src + pos, src + pos + length, dst);
  896.                 converted = length;
  897.             }}
  898.             break;
  899.         } // end of switch statement
  900.     } catch ( ... ) {
  901.         if ( buf != 0 ) {
  902.             delete[] buf;
  903.         }
  904.         throw;
  905.     }
  906.     return converted;
  907. }
  908. /////////////////////////////////////////////////////////////////////////////
  909. //
  910. // Packing
  911. SIZE_TYPE CSeqConvert_imp::Pack
  912. (const char* src,
  913.  TSeqPos length,
  914.  TCoding src_coding,
  915.  char* dst,
  916.  TCoding& dst_coding)
  917. {
  918.     dst_coding = x_HasAmbig(src, src_coding, length) ?
  919.         CSeqUtil::e_Ncbi4na : CSeqUtil::e_Ncbi2na;
  920.     
  921.     return Convert(src, src_coding, 0, length, dst, dst_coding);
  922. }
  923. bool CSeqConvert_imp::x_HasAmbig
  924. (const char* src,
  925.  TCoding src_coding,
  926.  size_t length)
  927. {
  928.     if ( length == 0 ) {
  929.         return false;
  930.     }
  931.     
  932.     switch ( src_coding ) {
  933.     case CSeqUtil::e_Iupacna:
  934.         return x_HasAmbigIupacna(src, length);
  935.         
  936.     case CSeqUtil::e_Ncbi4na:
  937.         return x_HasAmbigNcbi4na(src, length);
  938.         
  939.     case CSeqUtil::e_Ncbi4na_expand:
  940.     case CSeqUtil::e_Ncbi8na:
  941.         return x_HasAmbigNcbi8na(src, length);
  942.         
  943.     case CSeqUtil::e_Ncbi2na:
  944.     case CSeqUtil::e_Ncbi2na_expand:
  945.         return false;
  946.     }
  947.     
  948.     return false;
  949. }
  950. bool CSeqConvert_imp::x_HasAmbigIupacna(const char* src, size_t length)
  951. {
  952.     const bool *not_ambig = CIupacnaAmbig::GetTable();
  953.     
  954.     const char* end = src + length;
  955.     
  956.     const char* iter = src;
  957.     while ( (iter != end)  &&  (not_ambig[static_cast<Uint1>(*iter)]) ) { 
  958.           ++iter;
  959.     }
  960.     return iter != end;
  961. }
  962. bool CSeqConvert_imp::x_HasAmbigNcbi4na(const char* src, size_t length)
  963. {
  964.     const bool* not_ambig = CNcbi4naAmbig::GetTable();
  965.     
  966.     const char* end = src + (length / 2);
  967.     
  968.     const char* iter = src;
  969.     while ( (iter != end)  &&  (not_ambig[static_cast<Uint1>(*iter)]) ) {
  970.           ++iter;
  971.     }
  972.     
  973.     if ( (iter == end)  &&  (length % 2) != 0 ) {
  974.         return not_ambig[static_cast<Uint1>(*iter) & 0xF1];
  975.     }
  976.     return iter != end;
  977. }
  978. bool CSeqConvert_imp::x_HasAmbigNcbi8na(const char* src, size_t length)
  979. {
  980.     const bool *not_ambig = CNcbi8naAmbig::GetTable();
  981.     
  982.     const char* end = src + length;
  983.     
  984.     const char* iter = src;
  985.     while ( (iter != end)  &&  (not_ambig[static_cast<Uint1>(*iter)]) ) {
  986.           ++iter;
  987.     }
  988.     
  989.     return iter != end;
  990. }
  991. END_NCBI_SCOPE
  992. /*
  993. * ===========================================================================
  994. *
  995. * $Log: sequtil_convert_imp.cpp,v $
  996. * Revision 1000.1  2004/06/01 19:42:17  gouriano
  997. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.2
  998. *
  999. * Revision 1.2  2004/05/17 21:08:53  gorelenk
  1000. * Added include of PCH ncbi_pch.hpp
  1001. *
  1002. * Revision 1.1  2003/10/08 13:34:59  shomrat
  1003. * Initial version
  1004. *
  1005. *
  1006. * ===========================================================================
  1007. */