LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/cad/libopencad/dwg - io.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 377 496 76.0 %
Date: 2024-05-14 13:00:50 Functions: 28 31 90.3 %

          Line data    Source code
       1             : /*******************************************************************************
       2             :  *  Project: libopencad
       3             :  *  Purpose: OpenSource CAD formats support library
       4             :  *  Author: Alexandr Borzykh, mush3d at gmail.com
       5             :  *  Author: Dmitry Baryshnikov, bishop.dev@gmail.com
       6             :  *  Language: C++
       7             :  *******************************************************************************
       8             :  *  The MIT License (MIT)
       9             :  *
      10             :  *  Copyright (c) 2016 Alexandr Borzykh
      11             :  *  Copyright (c) 2016 NextGIS, <info@nextgis.com>
      12             :  *
      13             :  *  Permission is hereby granted, free of charge, to any person obtaining a copy
      14             :  *  of this software and associated documentation files (the "Software"), to deal
      15             :  *  in the Software without restriction, including without limitation the rights
      16             :  *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      17             :  *  copies of the Software, and to permit persons to whom the Software is
      18             :  *  furnished to do so, subject to the following conditions:
      19             :  *
      20             :  *  The above copyright notice and this permission notice shall be included in all
      21             :  *  copies or substantial portions of the Software.
      22             :  *
      23             :  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      24             :  *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      25             :  *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      26             :  *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      27             :  *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      28             :  *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      29             :  *  SOFTWARE.
      30             :  *******************************************************************************/
      31             : #include "io.h"
      32             : 
      33             : #include <iostream>
      34             : #include <cstdint>
      35             : #include <cstring>
      36             : 
      37             : const size_t DWGConstants::SentinelLength = 16;
      38             : const char * DWGConstants::HeaderVariablesStart
      39             :             = "\xCF\x7B\x1F\x23\xFD\xDE\x38\xA9\x5F\x7C\x68\xB8\x4E\x6D\x33\x5F";
      40             : const char * DWGConstants::HeaderVariablesEnd
      41             :             = "\x30\x84\xE0\xDC\x02\x21\xC7\x56\xA0\x83\x97\x47\xB1\x92\xCC\xA0";
      42             : 
      43             : const char * DWGConstants::DSClassesStart
      44             :                         = "\x8D\xA1\xC4\xB8\xC4\xA9\xF8\xC5\xC0\xDC\xF4\x5F\xE7\xCF\xB6\x8A";
      45             : const char * DWGConstants::DSClassesEnd
      46             :                         = "\x72\x5E\x3B\x47\x3B\x56\x07\x3A\x3F\x23\x0B\xA0\x18\x30\x49\x75";
      47             : 
      48             : const int DWGCRC8Table[256] = {
      49             :     0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1,
      50             :     0xC481, 0x0440, 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, 0x0A00, 0xCAC1, 0xCB81, 0x0B40,
      51             :     0xC901, 0x09C0, 0x0880, 0xC841, 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, 0x1E00, 0xDEC1,
      52             :     0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
      53             :     0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1,
      54             :     0xF281, 0x3240, 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, 0x3C00, 0xFCC1, 0xFD81, 0x3D40,
      55             :     0xFF01, 0x3FC0, 0x3E80, 0xFE41, 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, 0x2800, 0xE8C1,
      56             :     0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
      57             :     0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0,
      58             :     0x2080, 0xE041, 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, 0x6600, 0xA6C1, 0xA781, 0x6740,
      59             :     0xA501, 0x65C0, 0x6480, 0xA441, 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, 0xAA01, 0x6AC0,
      60             :     0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
      61             :     0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1,
      62             :     0xB681, 0x7640, 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, 0x5000, 0x90C1, 0x9181, 0x5140,
      63             :     0x9301, 0x53C0, 0x5280, 0x9241, 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, 0x9C01, 0x5CC0,
      64             :     0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
      65             :     0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0,
      66             :     0x4C80, 0x8C41, 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, 0x8201, 0x42C0, 0x4380, 0x8341,
      67             :     0x4100, 0x81C1, 0x8081, 0x4040
      68             : };
      69             : 
      70       36206 : unsigned short CalculateCRC8( unsigned short initialVal, const char *ptr, int num )
      71             : {
      72             :     unsigned char al;
      73       36206 :     while( num-- > 0 )
      74             :     {
      75       35977 :         al = static_cast<unsigned char>( ( *ptr ) ^
      76             :                                          ( static_cast<char>( initialVal & 0xFF ) ) );
      77       35977 :         initialVal = ( initialVal >> 8 ) & 0xFF;
      78       35977 :         initialVal = static_cast<unsigned short>( initialVal ^ DWGCRC8Table[al & 0xFF] );
      79       35977 :         ptr++;
      80             :     }
      81             : 
      82         229 :     return initialVal;
      83             : }
      84             : 
      85             : //------------------------------------------------------------------------------
      86             : // CADBuffer
      87             : //------------------------------------------------------------------------------
      88             : 
      89         450 : CADBuffer::CADBuffer(size_t size) : m_nBitOffsetFromStart(0)
      90             : {
      91         450 :     m_pBuffer = new char[size];
      92             :     // zero memory
      93         450 :     memset(m_pBuffer, 0, size);
      94         450 :     m_nSize = size;
      95         450 : }
      96             : 
      97         900 : CADBuffer::~CADBuffer()
      98             : {
      99         450 :     delete [] m_pBuffer;
     100         450 : }
     101             : 
     102          24 : void CADBuffer::WriteRAW(const void *data, size_t size)
     103             : {
     104          24 :     memcpy(m_pBuffer, data, size);
     105          24 :     m_nBitOffsetFromStart += size * 8;
     106          24 : }
     107             : 
     108        4470 : unsigned char CADBuffer::Read2B()
     109             : {
     110        4470 :     unsigned char result           = 0;
     111        4470 :     size_t        nByteOffset      = m_nBitOffsetFromStart / 8;
     112        4470 :     size_t        nBitOffsetInByte = m_nBitOffsetFromStart % 8;
     113             : 
     114        4470 :     if(nByteOffset + 2 > m_nSize)
     115             :     {
     116           0 :         m_bEOB = true;
     117           0 :         return 0;
     118             :     }
     119             : 
     120             :     unsigned char a2BBytes[2];
     121        4470 :     memcpy( a2BBytes, m_pBuffer + nByteOffset, 2 );
     122             : 
     123        4470 :     switch( nBitOffsetInByte )
     124             :     {
     125         163 :         case 7:
     126         163 :             result  = ( a2BBytes[0] & binary( 00000001 ) ) << 1;
     127         163 :             result |= ( a2BBytes[1] & binary( 10000000 ) ) >> 7;
     128         163 :             break;
     129        4307 :         default:
     130        4307 :             result = ( a2BBytes[0] >> ( 6 - nBitOffsetInByte ) );
     131        4307 :             break;
     132             :     }
     133             : 
     134        4470 :     result &= binary( 00000011 );
     135        4470 :     m_nBitOffsetFromStart += 2;
     136             : 
     137        4470 :     return result;
     138             : }
     139             : 
     140           0 : unsigned char CADBuffer::Read3B()
     141             : {
     142           0 :     unsigned char result           = 0;
     143           0 :     size_t        nByteOffset      = m_nBitOffsetFromStart / 8;
     144           0 :     size_t        nBitOffsetInByte = m_nBitOffsetFromStart % 8;
     145             : 
     146           0 :     if(nByteOffset + 2 > m_nSize)
     147             :     {
     148           0 :         m_bEOB = true;
     149           0 :         return 0;
     150             :     }
     151             : 
     152             :     unsigned char a3BBytes[2];
     153           0 :     memcpy( a3BBytes, m_pBuffer + nByteOffset, 2 );
     154             : 
     155           0 :     switch( nBitOffsetInByte )
     156             :     {
     157           0 :         case 6:
     158           0 :             result  = ( a3BBytes[0] & binary( 00000011 ) ) << 1;
     159           0 :             result |= ( a3BBytes[1] & binary( 10000000 ) ) >> 7;
     160           0 :             break;
     161             : 
     162           0 :         case 7:
     163           0 :             result  = ( a3BBytes[0] & binary( 00000001 ) ) << 2;
     164           0 :             result |= ( a3BBytes[1] & binary( 11000000 ) ) >> 6;
     165           0 :             break;
     166             : 
     167           0 :         default:
     168           0 :             result = ( a3BBytes[0] >> ( 5 - nBitOffsetInByte ) );
     169           0 :             break;
     170             :     }
     171             : 
     172           0 :     result &= binary( 00000111 );
     173           0 :     m_nBitOffsetFromStart += 3;
     174             : 
     175           0 :     return result;
     176             : }
     177             : 
     178        4016 : unsigned char CADBuffer::Read4B()
     179             : {
     180        4016 :     unsigned char result           = 0;
     181        4016 :     size_t        nByteOffset      = m_nBitOffsetFromStart / 8;
     182        4016 :     size_t        nBitOffsetInByte = m_nBitOffsetFromStart % 8;
     183             : 
     184        4016 :     if(nByteOffset + 2 > m_nSize)
     185             :     {
     186           0 :         m_bEOB = true;
     187           0 :         return 0;
     188             :     }
     189             : 
     190             :     unsigned char a4BBytes[2];
     191        4016 :     memcpy( a4BBytes, m_pBuffer + nByteOffset, 2 );
     192             : 
     193        4016 :     switch( nBitOffsetInByte )
     194             :     {
     195          64 :         case 5:
     196          64 :             result  = ( a4BBytes[0] & binary( 00000111 ) ) << 1;
     197          64 :             result |= ( a4BBytes[1] & binary( 10000000 ) ) >> 7;
     198          64 :             break;
     199        1040 :         case 6:
     200        1040 :             result  = ( a4BBytes[0] & binary( 00000011 ) ) << 2;
     201        1040 :             result |= ( a4BBytes[1] & binary( 11000000 ) ) >> 6;
     202        1040 :             break;
     203             : 
     204          20 :         case 7:
     205          20 :             result  = ( a4BBytes[0] & binary( 00000001 ) ) << 3;
     206          20 :             result |= ( a4BBytes[1] & binary( 11100000 ) ) >> 5;
     207          20 :             break;
     208             : 
     209        2892 :         default:
     210        2892 :             result = ( a4BBytes[0] >> ( 4 - nBitOffsetInByte ) );
     211        2892 :             break;
     212             :     }
     213             : 
     214        4016 :     result &= binary( 00001111 );
     215        4016 :     m_nBitOffsetFromStart += 4;
     216             : 
     217        4016 :     return result;
     218             : }
     219             : 
     220             : 
     221         790 : double CADBuffer::ReadBITDOUBLE()
     222             : {
     223         790 :     unsigned char BITCODE = Read2B();
     224             : 
     225         790 :     size_t nByteOffset      = m_nBitOffsetFromStart / 8;
     226         790 :     size_t nBitOffsetInByte = m_nBitOffsetFromStart % 8;
     227             : 
     228         790 :     if(nByteOffset + 9 > m_nSize)
     229             :     {
     230           0 :         m_bEOB = true;
     231           0 :         return 0.0;
     232             :     }
     233             : 
     234             :     unsigned char aDoubleBytes[9]; // maximum bytes a single double can take.
     235         790 :     memcpy( aDoubleBytes, m_pBuffer + nByteOffset, 9 );
     236             : 
     237         790 :     switch( BITCODE )
     238             :     {
     239         100 :         case BITDOUBLE_NORMAL:
     240             :         {
     241         100 :             aDoubleBytes[0] <<= nBitOffsetInByte;
     242         100 :             aDoubleBytes[0] |= ( aDoubleBytes[1] >> ( 8 - nBitOffsetInByte ) );
     243         100 :             aDoubleBytes[1] <<= nBitOffsetInByte;
     244         100 :             aDoubleBytes[1] |= ( aDoubleBytes[2] >> ( 8 - nBitOffsetInByte ) );
     245         100 :             aDoubleBytes[2] <<= nBitOffsetInByte;
     246         100 :             aDoubleBytes[2] |= ( aDoubleBytes[3] >> ( 8 - nBitOffsetInByte ) );
     247         100 :             aDoubleBytes[3] <<= nBitOffsetInByte;
     248         100 :             aDoubleBytes[3] |= ( aDoubleBytes[4] >> ( 8 - nBitOffsetInByte ) );
     249         100 :             aDoubleBytes[4] <<= nBitOffsetInByte;
     250         100 :             aDoubleBytes[4] |= ( aDoubleBytes[5] >> ( 8 - nBitOffsetInByte ) );
     251         100 :             aDoubleBytes[5] <<= nBitOffsetInByte;
     252         100 :             aDoubleBytes[5] |= ( aDoubleBytes[6] >> ( 8 - nBitOffsetInByte ) );
     253         100 :             aDoubleBytes[6] <<= nBitOffsetInByte;
     254         100 :             aDoubleBytes[6] |= ( aDoubleBytes[7] >> ( 8 - nBitOffsetInByte ) );
     255         100 :             aDoubleBytes[7] <<= nBitOffsetInByte;
     256         100 :             aDoubleBytes[7] |= ( aDoubleBytes[8] >> ( 8 - nBitOffsetInByte ) );
     257             : 
     258         100 :             m_nBitOffsetFromStart += 64;
     259             : 
     260             :             double result;
     261         100 :             memcpy(&result, aDoubleBytes, sizeof(result));
     262         100 :             FromLSB(result);
     263         100 :             return result;
     264             :         }
     265             : 
     266          87 :         case BITDOUBLE_ONE_VALUE:
     267             :         {
     268          87 :             m_nBitOffsetFromStart += 0;
     269             : 
     270          87 :             return 1.0f;
     271             :         }
     272             : 
     273         603 :         case BITDOUBLE_ZERO_VALUE:
     274             :         {
     275         603 :             m_nBitOffsetFromStart += 0;
     276             : 
     277         603 :             return 0.0f;
     278             :         }
     279             : 
     280           0 :         case BITDOUBLE_NOT_USED:
     281             :         {
     282           0 :             m_nBitOffsetFromStart += 0;
     283             : 
     284           0 :             return 0.0f;
     285             :         }
     286             :     }
     287             : 
     288           0 :     return 0.0f;
     289             : }
     290             : 
     291         272 : void CADBuffer::SkipBITDOUBLE()
     292             : {
     293         272 :     unsigned char BITCODE = Read2B();
     294         272 :     size_t nByteOffset      = m_nBitOffsetFromStart / 8;
     295         272 :     if(nByteOffset + 9 > m_nSize)
     296             :     {
     297           0 :         m_bEOB = true;
     298           0 :         return;
     299             :     }
     300             : 
     301         272 :     switch( BITCODE )
     302             :     {
     303          83 :         case BITDOUBLE_NORMAL:
     304          83 :             m_nBitOffsetFromStart += 64;
     305          83 :             break;
     306          61 :         case BITDOUBLE_ONE_VALUE:
     307          61 :             m_nBitOffsetFromStart += 0;
     308          61 :             break;
     309         128 :         case BITDOUBLE_ZERO_VALUE:
     310             :         case BITDOUBLE_NOT_USED:
     311         128 :             break;
     312             :     }
     313             : }
     314             : 
     315         253 : short CADBuffer::ReadRAWSHORT()
     316             : {
     317         253 :     size_t nByteOffset      = m_nBitOffsetFromStart / 8;
     318         253 :     size_t nBitOffsetInByte = m_nBitOffsetFromStart % 8;
     319             : 
     320         253 :     if(nByteOffset + 3 > m_nSize)
     321             :     {
     322           0 :         m_bEOB = true;
     323           0 :         return 0;
     324             :     }
     325             :     unsigned char aShortBytes[3];
     326         253 :     memcpy( aShortBytes, m_pBuffer + nByteOffset, 3 );
     327             : 
     328         253 :     switch( nBitOffsetInByte )
     329             :     {
     330         229 :         case 0:
     331         229 :             break;
     332             : 
     333          24 :         default:
     334          24 :             aShortBytes[0] <<= nBitOffsetInByte;
     335          24 :             aShortBytes[0] |= ( aShortBytes[1] >> ( 8 - nBitOffsetInByte ) );
     336          24 :             aShortBytes[1] <<= nBitOffsetInByte;
     337          24 :             aShortBytes[1] |= ( aShortBytes[2] >> ( 8 - nBitOffsetInByte ) );
     338          24 :             break;
     339             :     }
     340             : 
     341             :     int16_t result;
     342         253 :     memcpy(&result, aShortBytes, sizeof(result));
     343         253 :     FromLSB(result);
     344             : 
     345         253 :     m_nBitOffsetFromStart += 16;
     346             : 
     347         253 :     return result;
     348             : }
     349             : 
     350          93 : double CADBuffer::ReadRAWDOUBLE()
     351             : {
     352          93 :     size_t nByteOffset      = m_nBitOffsetFromStart / 8;
     353          93 :     size_t nBitOffsetInByte = m_nBitOffsetFromStart % 8;
     354             : 
     355          93 :     if(nByteOffset + 9 > m_nSize)
     356             :     {
     357           0 :         m_bEOB = true;
     358           0 :         return 0.0;
     359             :     }
     360             : 
     361             :     unsigned char aDoubleBytes[9];
     362          93 :     memcpy( aDoubleBytes, m_pBuffer + nByteOffset, 9 );
     363             : 
     364          93 :     switch( nBitOffsetInByte )
     365             :     {
     366          37 :         case 0:
     367          37 :             break;
     368             : 
     369          56 :         default:
     370          56 :             aDoubleBytes[0] <<= nBitOffsetInByte;
     371          56 :             aDoubleBytes[0] |= ( aDoubleBytes[1] >> ( 8 - nBitOffsetInByte ) );
     372          56 :             aDoubleBytes[1] <<= nBitOffsetInByte;
     373          56 :             aDoubleBytes[1] |= ( aDoubleBytes[2] >> ( 8 - nBitOffsetInByte ) );
     374          56 :             aDoubleBytes[2] <<= nBitOffsetInByte;
     375          56 :             aDoubleBytes[2] |= ( aDoubleBytes[3] >> ( 8 - nBitOffsetInByte ) );
     376          56 :             aDoubleBytes[3] <<= nBitOffsetInByte;
     377          56 :             aDoubleBytes[3] |= ( aDoubleBytes[4] >> ( 8 - nBitOffsetInByte ) );
     378          56 :             aDoubleBytes[4] <<= nBitOffsetInByte;
     379          56 :             aDoubleBytes[4] |= ( aDoubleBytes[5] >> ( 8 - nBitOffsetInByte ) );
     380          56 :             aDoubleBytes[5] <<= nBitOffsetInByte;
     381          56 :             aDoubleBytes[5] |= ( aDoubleBytes[6] >> ( 8 - nBitOffsetInByte ) );
     382          56 :             aDoubleBytes[6] <<= nBitOffsetInByte;
     383          56 :             aDoubleBytes[6] |= ( aDoubleBytes[7] >> ( 8 - nBitOffsetInByte ) );
     384          56 :             aDoubleBytes[7] <<= nBitOffsetInByte;
     385          56 :             aDoubleBytes[7] |= ( aDoubleBytes[8] >> ( 8 - nBitOffsetInByte ) );
     386          56 :             break;
     387             :     }
     388             : 
     389             :     double result;
     390          93 :     memcpy(&result, aDoubleBytes, sizeof(result));
     391          93 :     FromLSB(result);
     392             : 
     393          93 :     m_nBitOffsetFromStart += 64;
     394             : 
     395          93 :     return result;
     396             : }
     397             : 
     398         205 : int CADBuffer::ReadRAWLONG()
     399             : {
     400         205 :     size_t nByteOffset      = m_nBitOffsetFromStart / 8;
     401         205 :     size_t nBitOffsetInByte = m_nBitOffsetFromStart % 8;
     402             : 
     403         205 :     if(nByteOffset + 5 > m_nSize)
     404             :     {
     405           0 :         m_bEOB = true;
     406           0 :         return 0;
     407             :     }
     408             : 
     409             :     unsigned char aLongBytes[5];
     410         205 :     memcpy( aLongBytes, m_pBuffer + nByteOffset, 5 );
     411             : 
     412         205 :     switch( nBitOffsetInByte )
     413             :     {
     414           0 :         case 0:
     415           0 :             break;
     416             : 
     417         205 :         default:
     418         205 :             aLongBytes[0] <<= nBitOffsetInByte;
     419         205 :             aLongBytes[0] |= ( aLongBytes[1] >> ( 8 - nBitOffsetInByte ) );
     420         205 :             aLongBytes[1] <<= nBitOffsetInByte;
     421         205 :             aLongBytes[1] |= ( aLongBytes[2] >> ( 8 - nBitOffsetInByte ) );
     422         205 :             aLongBytes[2] <<= nBitOffsetInByte;
     423         205 :             aLongBytes[2] |= ( aLongBytes[3] >> ( 8 - nBitOffsetInByte ) );
     424         205 :             aLongBytes[3] <<= nBitOffsetInByte;
     425         205 :             aLongBytes[3] |= ( aLongBytes[4] >> ( 8 - nBitOffsetInByte ) );
     426         205 :             break;
     427             :     }
     428             : 
     429             :     int32_t result;
     430         205 :     memcpy(&result, aLongBytes, sizeof(result));
     431         205 :     FromLSB(result);
     432             : 
     433         205 :     m_nBitOffsetFromStart += 32;
     434             : 
     435         205 :     return result;
     436             : }
     437             : 
     438         298 : bool CADBuffer::ReadBIT()
     439             : {
     440         298 :     size_t nByteOffset      = m_nBitOffsetFromStart / 8;
     441         298 :     size_t nBitOffsetInByte = m_nBitOffsetFromStart % 8;
     442             : 
     443         298 :     if(nByteOffset >= m_nSize)
     444             :     {
     445           0 :         m_bEOB = true;
     446           0 :         return false;
     447             :     }
     448             : 
     449         298 :     unsigned char resultVal = ( m_pBuffer[nByteOffset] >> ( 7 - nBitOffsetInByte ) ) & binary( 00000001 );
     450         298 :     ++m_nBitOffsetFromStart;
     451             : 
     452         298 :     return resultVal == 0 ? false : true;
     453             : }
     454             : 
     455        2400 : short CADBuffer::ReadBITSHORT()
     456             : {
     457        2400 :     unsigned char BITCODE = Read2B();
     458             : 
     459        2400 :     size_t nByteOffset      = m_nBitOffsetFromStart / 8;
     460        2400 :     size_t nBitOffsetInByte = m_nBitOffsetFromStart % 8;
     461             : 
     462        2400 :     if(nByteOffset + 4 > m_nSize)
     463             :     {
     464           0 :         m_bEOB = true;
     465           0 :         return 0;
     466             :     }
     467             : 
     468             :     unsigned char aShortBytes[4]; // maximum bytes a single short can take.
     469        2400 :     memcpy( aShortBytes, m_pBuffer + nByteOffset, 4 );
     470             : 
     471        2400 :     switch( BITCODE )
     472             :     {
     473         349 :         case BITSHORT_NORMAL:
     474             :         {
     475         349 :             aShortBytes[0] = ( aShortBytes[0] << nBitOffsetInByte );
     476         349 :             aShortBytes[0] |= ( aShortBytes[1] >> ( 8 - nBitOffsetInByte ) );
     477         349 :             aShortBytes[1] = ( aShortBytes[1] << nBitOffsetInByte );
     478         349 :             aShortBytes[1] |= ( aShortBytes[2] >> ( 8 - nBitOffsetInByte ) );
     479             : 
     480         349 :             m_nBitOffsetFromStart += 16;
     481             : 
     482             :             int16_t result;
     483         349 :             memcpy(&result, aShortBytes, sizeof(result));
     484         349 :             FromLSB(result);
     485             : 
     486         349 :             return result;
     487             :         }
     488             : 
     489        1609 :         case BITSHORT_UNSIGNED_CHAR:
     490             :         {
     491        1609 :             aShortBytes[0] = ( aShortBytes[0] << nBitOffsetInByte );
     492        1609 :             aShortBytes[0] |= ( aShortBytes[1] >> ( 8 - nBitOffsetInByte ) );
     493             : 
     494        1609 :             m_nBitOffsetFromStart += 8;
     495             : 
     496        1609 :             return static_cast<unsigned char>(aShortBytes[0]);
     497             :         }
     498             : 
     499         399 :         case BITSHORT_ZERO_VALUE:
     500             :         {
     501         399 :             m_nBitOffsetFromStart += 0;
     502         399 :             return 0;
     503             :         }
     504             : 
     505          43 :         case BITSHORT_256:
     506             :         {
     507          43 :             m_nBitOffsetFromStart += 0;
     508          43 :             return 256;
     509             :         }
     510             :     }
     511             : 
     512           0 :     return -1;
     513             : }
     514             : 
     515       26233 : unsigned char CADBuffer::ReadCHAR()
     516             : {
     517       26233 :     unsigned char result           = 0;
     518       26233 :     size_t        nByteOffset      = m_nBitOffsetFromStart / 8;
     519       26233 :     size_t        nBitOffsetInByte = m_nBitOffsetFromStart % 8;
     520             : 
     521       26233 :     if(nByteOffset + 2 > m_nSize)
     522             :     {
     523           0 :         m_bEOB = true;
     524           0 :         return result;
     525             :     }
     526             : 
     527             :     unsigned char aCharBytes[2]; // maximum bytes a single char can take.
     528       26233 :     memcpy( aCharBytes, m_pBuffer + nByteOffset, 2 );
     529             : 
     530       26233 :     result = ( aCharBytes[0] << nBitOffsetInByte );
     531       26233 :     result |= ( aCharBytes[1] >> ( 8 - nBitOffsetInByte ) );
     532             : 
     533       26233 :     m_nBitOffsetFromStart += 8;
     534             : 
     535       26233 :     return result;
     536             : }
     537             : 
     538        1220 : std::string CADBuffer::ReadTV()
     539             : {
     540        1220 :     short stringLength = ReadBITSHORT();
     541             : 
     542        1220 :     std::string result;
     543             : 
     544       15532 :     for( short i = 0; i < stringLength; ++i )
     545             :     {
     546       14312 :         result += static_cast<char>(ReadCHAR());
     547             :     }
     548             : 
     549        1220 :     return result;
     550             : }
     551             : 
     552        1793 : long CADBuffer::ReadUMCHAR()
     553             : {
     554        1793 :     long result = 0;
     555        1793 :     size_t nByteOffset = m_nBitOffsetFromStart / 8;
     556             :     // TODO: bit offset is calculated, but function has nothing to do with it.
     557             :     /*size_t nBitOffsetInByte = m_nBitOffsetFromStart % 8;*/
     558             : 
     559        1793 :     if(nByteOffset + 8 > m_nSize)
     560             :     {
     561           0 :         m_bEOB = true;
     562           0 :         return 0;
     563             :     }
     564             :     unsigned char aMCharBytes[8]; // 8 bytes is maximum.
     565             :     //memcpy( aMCharBytes, m_pBuffer + nByteOffset, 8 );
     566             : 
     567        1793 :     unsigned char nMCharBytesCount = 0;
     568        1799 :     for( unsigned char i = 0; i < 8; ++i )
     569             :     {
     570        1799 :         aMCharBytes[i] = ReadCHAR();
     571        1799 :         ++nMCharBytesCount;
     572        1799 :         if ( !( aMCharBytes[i] & binary( 10000000 ) ) )
     573             :         {
     574        1793 :             break;
     575             :         }
     576           6 :         aMCharBytes[i] &= binary( 01111111 );
     577             :     }
     578             : 
     579        1793 :     int nOffset = 0;
     580        3592 :     for(unsigned char i = 0; i < nMCharBytesCount; ++i)
     581             :     {
     582        1799 :         unsigned long nVal = aMCharBytes[i];
     583        1799 :         result += nVal << nOffset;
     584        1799 :         nOffset += 7;
     585             :     }
     586        1793 :     return result;
     587             : }
     588             : 
     589        1793 : long CADBuffer::ReadMCHAR()
     590             : {
     591        1793 :     long   result      = 0;
     592        1793 :     bool   negative    = false;
     593        1793 :     size_t nByteOffset = m_nBitOffsetFromStart / 8;
     594             : 
     595             :     // TODO: bit offset is calculated, but function has nothing to do with it.
     596             :     /*size_t nBitOffsetInByte = nBitOffsetFromStart % 8;*/
     597             : 
     598        1793 :     if(nByteOffset + 8 > m_nSize)
     599             :     {
     600           0 :         m_bEOB = true;
     601           0 :         return 0;
     602             :     }
     603             :     unsigned char aMCharBytes[8]; // 8 bytes is maximum.
     604             : 
     605        1793 :     unsigned char nMCharBytesCount = 0;
     606        3841 :     for( unsigned char i = 0; i < 8; ++i )
     607             :     {
     608        3841 :         aMCharBytes[i] = ReadCHAR();
     609        3841 :         ++nMCharBytesCount;
     610        3841 :         if ( !( aMCharBytes[i] & binary( 10000000 ) ) )
     611             :         {
     612        1793 :             break;
     613             :         }
     614        2048 :         aMCharBytes[i] &= binary( 01111111 );
     615             :     }
     616             : 
     617        1793 :     if ( ( aMCharBytes[nMCharBytesCount - 1] & binary( 01000000 ) ) == binary( 01000000 ) )
     618             :     {
     619         723 :         aMCharBytes[nMCharBytesCount - 1] &= binary( 10111111 );
     620         723 :         negative = true;
     621             :     }
     622             : 
     623        1793 :     int nOffset = 0;
     624        5634 :     for(unsigned char i = 0; i < nMCharBytesCount; ++i)
     625             :     {
     626        3841 :         unsigned long nVal = aMCharBytes[i];
     627        3841 :         result += nVal << nOffset;
     628        3841 :         nOffset += 7;
     629             :     }
     630             : 
     631        1793 :     if( negative )
     632             :     {
     633         723 :         result *= -1;
     634             :     }
     635             : 
     636        1793 :     return result;
     637             : }
     638             : 
     639         426 : unsigned int CADBuffer::ReadMSHORT()
     640             : {
     641             :     unsigned char aMShortBytes[8]; // 8 bytes is maximum.
     642             : 
     643             :     // TODO: this function does not support MSHORTS longer than 4 bytes. ODA says
     644             :     //       it's impossible, but not sure.
     645         426 :     size_t MShortBytesCount = 2;
     646         426 :     aMShortBytes[0] = ReadCHAR();
     647         426 :     aMShortBytes[1] = ReadCHAR();
     648         426 :     if ( aMShortBytes[1] & binary( 10000000 ) )
     649             :     {
     650           0 :         aMShortBytes[2] = ReadCHAR();
     651           0 :         aMShortBytes[3] = ReadCHAR();
     652           0 :         MShortBytesCount = 4;
     653             :     }
     654             : 
     655         426 :     SwapEndianness( aMShortBytes, MShortBytesCount );
     656             : 
     657         426 :     if( MShortBytesCount == 2 )
     658             :     {
     659         426 :         aMShortBytes[0] &= binary( 01111111 ); // drop high order flag bit.
     660             :     }
     661             :     else
     662             :     {
     663           0 :         aMShortBytes[0] &= binary( 01111111 );
     664           0 :         aMShortBytes[2] &= binary( 01111111 );
     665             : 
     666           0 :         aMShortBytes[2] |= ( aMShortBytes[1] << 7 );
     667           0 :         aMShortBytes[1] = ( aMShortBytes[1] >> 1 );
     668           0 :         aMShortBytes[1] |= ( aMShortBytes[0] << 7 );
     669           0 :         aMShortBytes[0] = ( aMShortBytes[0] >> 1 );
     670             :     }
     671             : 
     672             :     unsigned int result;
     673         426 :     if( MShortBytesCount == 2 )
     674             :     {
     675         426 :         result = (aMShortBytes[0] << 8) | aMShortBytes[1];
     676             :     }
     677             :     else
     678             :     {
     679           0 :         result = (static_cast<unsigned>(aMShortBytes[0]) << 24) |
     680           0 :                  (aMShortBytes[1] << 16) | (aMShortBytes[2] << 8) | aMShortBytes[3];
     681             :     }
     682             : 
     683         426 :     return result;
     684             : }
     685             : 
     686             : 
     687             : 
     688           2 : double CADBuffer::ReadBITDOUBLEWD(double defaultvalue )
     689             : {
     690             :     unsigned char aDefaultValueBytes[8];
     691           2 :     memcpy( aDefaultValueBytes, & defaultvalue, 8 );
     692             : 
     693           2 :     unsigned char BITCODE = Read2B();
     694             : 
     695           2 :     switch( BITCODE )
     696             :     {
     697           0 :         case BITDOUBLEWD_DEFAULT_VALUE:
     698             :         {
     699           0 :             return defaultvalue;
     700             :         }
     701             : 
     702           0 :         case BITDOUBLEWD_4BYTES_PATCHED:
     703             :         {
     704           0 :             aDefaultValueBytes[0] = ReadCHAR();
     705           0 :             aDefaultValueBytes[1] = ReadCHAR();
     706           0 :             aDefaultValueBytes[2] = ReadCHAR();
     707           0 :             aDefaultValueBytes[3] = ReadCHAR();
     708             : 
     709             :             double result;
     710           0 :             memcpy(&result, aDefaultValueBytes, sizeof(result));
     711           0 :             FromLSB(result);
     712           0 :             return result;
     713             :         }
     714             : 
     715           0 :         case BITDOUBLEWD_6BYTES_PATCHED:
     716             :         {
     717           0 :             aDefaultValueBytes[4] = ReadCHAR();
     718           0 :             aDefaultValueBytes[5] = ReadCHAR();
     719           0 :             aDefaultValueBytes[0] = ReadCHAR();
     720           0 :             aDefaultValueBytes[1] = ReadCHAR();
     721           0 :             aDefaultValueBytes[2] = ReadCHAR();
     722           0 :             aDefaultValueBytes[3] = ReadCHAR();
     723             : 
     724             :             double result;
     725           0 :             memcpy(&result, aDefaultValueBytes, sizeof(result));
     726           0 :             FromLSB(result);
     727           0 :             return result;
     728             :         }
     729             : 
     730           2 :         case BITDOUBLEWD_FULL_RD:
     731             :         {
     732           2 :             aDefaultValueBytes[0] = ReadCHAR();
     733           2 :             aDefaultValueBytes[1] = ReadCHAR();
     734           2 :             aDefaultValueBytes[2] = ReadCHAR();
     735           2 :             aDefaultValueBytes[3] = ReadCHAR();
     736           2 :             aDefaultValueBytes[4] = ReadCHAR();
     737           2 :             aDefaultValueBytes[5] = ReadCHAR();
     738           2 :             aDefaultValueBytes[6] = ReadCHAR();
     739           2 :             aDefaultValueBytes[7] = ReadCHAR();
     740             : 
     741             :             double result;
     742           2 :             memcpy(&result, aDefaultValueBytes, sizeof(result));
     743           2 :             FromLSB(result);
     744           2 :             return result;
     745             :         }
     746             :     }
     747             : 
     748           0 :     return 0.0f;
     749             : }
     750             : 
     751        1936 : CADHandle CADBuffer::ReadHANDLE()
     752             : {
     753        1936 :     CADHandle result( Read4B() );
     754        1936 :     unsigned char counter = Read4B();
     755        4286 :     for( unsigned char i = 0; i < counter; ++i )
     756             :     {
     757        2350 :         result.addOffset( ReadCHAR() );
     758             :     }
     759             : 
     760        1936 :     return result;
     761             : }
     762             : 
     763          72 : void CADBuffer::SkipHANDLE()
     764             : {
     765          72 :     Read4B();
     766          72 :     unsigned char counter = Read4B();
     767          72 :     m_nBitOffsetFromStart += counter * 8;
     768          72 : }
     769             : 
     770           0 : CADHandle CADBuffer::ReadHANDLE8BLENGTH()
     771             : {
     772           0 :     CADHandle result;
     773             : 
     774           0 :     unsigned char counter = ReadCHAR();
     775             : 
     776           0 :     for( unsigned char i = 0; i < counter; ++i )
     777             :     {
     778           0 :         result.addOffset( ReadCHAR() );
     779             :     }
     780             : 
     781           0 :     return result;
     782             : }
     783             : 
     784         429 : int CADBuffer::ReadBITLONG()
     785             : {
     786         429 :     unsigned char BITCODE = Read2B();
     787             : 
     788         429 :     size_t nByteOffset      = m_nBitOffsetFromStart / 8;
     789         429 :     size_t nBitOffsetInByte = m_nBitOffsetFromStart % 8;
     790             : 
     791         429 :     if(nByteOffset + 5 > m_nSize)
     792             :     {
     793           0 :         m_bEOB = true;
     794           0 :         return 0;
     795             :     }
     796             :     unsigned char aLongBytes[5]; // maximum bytes a single short can take.
     797         429 :     memcpy( aLongBytes, m_pBuffer + nByteOffset, 5 );
     798             : 
     799         429 :     switch( BITCODE )
     800             :     {
     801          48 :         case BITLONG_NORMAL:
     802             :         {
     803          48 :             aLongBytes[0] <<= nBitOffsetInByte;
     804          48 :             aLongBytes[0] |= ( aLongBytes[1] >> ( 8 - nBitOffsetInByte ) );
     805          48 :             aLongBytes[1] <<= nBitOffsetInByte;
     806          48 :             aLongBytes[1] |= ( aLongBytes[2] >> ( 8 - nBitOffsetInByte ) );
     807          48 :             aLongBytes[2] <<= nBitOffsetInByte;
     808          48 :             aLongBytes[2] |= ( aLongBytes[3] >> ( 8 - nBitOffsetInByte ) );
     809          48 :             aLongBytes[3] <<= nBitOffsetInByte;
     810          48 :             aLongBytes[3] |= ( aLongBytes[4] >> ( 8 - nBitOffsetInByte ) );
     811             : 
     812          48 :             m_nBitOffsetFromStart += 32;
     813             : 
     814             :             int32_t result;
     815          48 :             memcpy(&result, aLongBytes, sizeof(result));
     816          48 :             FromLSB(result);
     817          48 :             return result;
     818             :         }
     819             : 
     820         264 :         case BITLONG_UNSIGNED_CHAR:
     821             :         {
     822         264 :             aLongBytes[0] <<= nBitOffsetInByte;
     823         264 :             aLongBytes[0] |= ( aLongBytes[1] >> ( 8 - nBitOffsetInByte ) );
     824             : 
     825         264 :             m_nBitOffsetFromStart += 8;
     826             : 
     827         264 :             return aLongBytes[0];
     828             :         }
     829             : 
     830         117 :         case BITLONG_ZERO_VALUE:
     831             :         {
     832         117 :             m_nBitOffsetFromStart += 0;
     833         117 :             return 0;
     834             :         }
     835             : 
     836           0 :         case BITLONG_NOT_USED:
     837             :         {
     838             : #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
     839             :             std::cerr <<
     840           0 :             "THAT SHOULD NEVER HAPPENED! BUG. (in file, or reader, or both.) ReadBITLONG(), case BITLONG_NOT_USED\n";
     841             : #endif
     842           0 :             m_nBitOffsetFromStart += 0;
     843           0 :             return 0;
     844             :         }
     845             :     }
     846             : 
     847           0 :     return -1;
     848             : }
     849             : 
     850          56 : void CADBuffer::SkipTV()
     851             : {
     852          56 :     short stringLength = ReadBITSHORT();
     853          56 :     if( stringLength < 0 )
     854             :     {
     855             : #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
     856           0 :         std::cerr << "Negative string length" << std::endl;
     857             : #endif
     858           0 :         return;
     859             :     }
     860          56 :     m_nBitOffsetFromStart += size_t( stringLength * 8 );
     861             : }
     862             : 
     863          24 : void CADBuffer::SkipBITLONG()
     864             : {
     865          24 :     unsigned char BITCODE = Read2B();
     866          24 :     size_t nByteOffset      = m_nBitOffsetFromStart / 8;
     867          24 :     if(nByteOffset + 5 > m_nSize)
     868             :     {
     869           0 :         m_bEOB = true;
     870           0 :         return;
     871             :     }
     872          24 :     switch( BITCODE )
     873             :     {
     874           8 :         case BITLONG_NORMAL:
     875           8 :             m_nBitOffsetFromStart += 32;
     876           8 :             break;
     877             : 
     878           0 :         case BITLONG_UNSIGNED_CHAR:
     879           0 :             m_nBitOffsetFromStart += 8;
     880           0 :             break;
     881             : 
     882          16 :         case BITLONG_ZERO_VALUE:
     883             :         case BITLONG_NOT_USED:
     884          16 :             break;
     885             :     }
     886             : }
     887             : 
     888         448 : void CADBuffer::SkipBITSHORT()
     889             : {
     890         448 :     unsigned char BITCODE = Read2B();
     891         448 :     size_t nByteOffset      = m_nBitOffsetFromStart / 8;
     892         448 :     if(nByteOffset + 4 > m_nSize)
     893             :     {
     894           0 :         m_bEOB = true;
     895           0 :         return;
     896             :     }
     897         448 :     switch( BITCODE )
     898             :     {
     899          56 :         case BITSHORT_NORMAL:
     900          56 :             m_nBitOffsetFromStart += 16;
     901          56 :             break;
     902             : 
     903         214 :         case BITSHORT_UNSIGNED_CHAR:
     904         214 :             m_nBitOffsetFromStart += 8;
     905         214 :             break;
     906             : 
     907         178 :         case BITSHORT_ZERO_VALUE:
     908             :         case BITSHORT_256:
     909         178 :             break;
     910             :     }
     911             : }
     912             : 
     913           0 : void CADBuffer::SkipBIT()
     914             : {
     915           0 :     size_t nByteOffset      = m_nBitOffsetFromStart / 8;
     916           0 :     if(nByteOffset >= m_nSize)
     917             :     {
     918           0 :         m_bEOB = true;
     919           0 :         return;
     920             :     }
     921           0 :     ++m_nBitOffsetFromStart;
     922             : }
     923             : 
     924          21 : CADVector CADBuffer::ReadVector()
     925             : {
     926             :     double x, y, z;
     927          21 :     x = ReadBITDOUBLE();
     928          21 :     y = ReadBITDOUBLE();
     929          21 :     z = ReadBITDOUBLE();
     930             : 
     931          21 :     return CADVector( x, y, z );
     932             : }
     933             : 
     934           9 : CADVector CADBuffer::ReadRAWVector()
     935             : {
     936             :     double x, y;
     937           9 :     x = ReadRAWDOUBLE();
     938           9 :     y = ReadRAWDOUBLE();
     939             : 
     940           9 :     return CADVector( x, y );
     941             : }
     942             : 
     943         508 : void CADBuffer::Seek(size_t offset, CADBuffer::SeekPosition position)
     944             : {
     945         508 :     switch (position) {
     946         460 :     case BEG:
     947         460 :         m_nBitOffsetFromStart = offset;
     948         460 :         break;
     949          48 :     case CURRENT:
     950          48 :         m_nBitOffsetFromStart += offset;
     951          48 :         break;
     952           0 :     case END:
     953           0 :         m_nBitOffsetFromStart = m_nSize - offset;
     954           0 :         break;
     955           0 :     default:
     956           0 :         break;
     957             :     }
     958         508 : }

Generated by: LCOV version 1.14