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

Generated by: LCOV version 1.14