LCOV - code coverage report
Current view: top level - frmts/pcidsk/sdk/core - pcidsk_utils.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 125 226 55.3 %
Date: 2024-05-04 12:52:34 Functions: 11 18 61.1 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Purpose:  Various private (undocumented) utility functions.
       4             :  *
       5             :  ******************************************************************************
       6             :  * Copyright (c) 2009
       7             :  * PCI Geomatics, 90 Allstate Parkway, Markham, Ontario, Canada.
       8             :  *
       9             :  * Permission is hereby granted, free of charge, to any person obtaining a
      10             :  * copy of this software and associated documentation files (the "Software"),
      11             :  * to deal in the Software without restriction, including without limitation
      12             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      13             :  * and/or sell copies of the Software, and to permit persons to whom the
      14             :  * Software is furnished to do so, subject to the following conditions:
      15             :  *
      16             :  * The above copyright notice and this permission notice shall be included
      17             :  * in all copies or substantial portions of the Software.
      18             :  *
      19             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      20             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      21             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      22             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      23             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      24             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      25             :  * DEALINGS IN THE SOFTWARE.
      26             :  ****************************************************************************/
      27             : 
      28             : #include "pcidsk_config.h"
      29             : #include "pcidsk_types.h"
      30             : #include "pcidsk_buffer.h"
      31             : #include "pcidsk_exception.h"
      32             : #include "pcidsk_georef.h"
      33             : #include "pcidsk_io.h"
      34             : #include "core/pcidsk_utils.h"
      35             : #include <cstdlib>
      36             : #include <cstring>
      37             : #include <cctype>
      38             : #include <cstdio>
      39             : #include <cmath>
      40             : #include <cstdarg>
      41             : #include <iostream>
      42             : 
      43             : extern "C"
      44             : {
      45             : int CPL_DLL CPLToupper(int c);
      46             : int CPL_DLL CPLTolower(int c);
      47             : }
      48             : 
      49             : #if !defined(va_copy) && defined(__va_copy)
      50             : #define va_copy __va_copy
      51             : #endif
      52             : 
      53             : using namespace PCIDSK;
      54             : 
      55             : /************************************************************************/
      56             : /*                         GetCurrentDateTime()                         */
      57             : /************************************************************************/
      58             : 
      59             : // format we want: "HH:MM DDMMMYYYY \0"
      60             : 
      61             : #include <time.h>
      62             : #include <sys/types.h>
      63             : 
      64        1365 : void    PCIDSK::GetCurrentDateTime( char *out_time )
      65             : 
      66             : {
      67             :     time_t          clock;
      68        1365 :     char            ctime_out[26] = {0};
      69             : 
      70        1365 :     time( &clock );
      71             : #ifdef HAVE_CTIME_R
      72        1365 :     ctime_r(&clock, ctime_out);
      73             : #elif defined(_WIN32)
      74             :     ctime_s(ctime_out, sizeof(ctime_out), &clock);
      75             : #else
      76             :     strncpy( ctime_out, ctime(&clock), 25 );
      77             : #endif
      78             : 
      79             :     // ctime() products: "Wed Jun 30 21:49:08 1993\n"
      80             : 
      81        1365 :     ctime_out[24] = '\0';
      82             : 
      83        1365 :     out_time[0] = ctime_out[11];
      84        1365 :     out_time[1] = ctime_out[12];
      85        1365 :     out_time[2] = ':';
      86        1365 :     out_time[3] = ctime_out[14];
      87        1365 :     out_time[4] = ctime_out[15];
      88        1365 :     out_time[5] = ' ';
      89        1365 :     out_time[6] = ctime_out[8];
      90        1365 :     out_time[7] = ctime_out[9];
      91        1365 :     out_time[8] = ctime_out[4];
      92        1365 :     out_time[9] = ctime_out[5];
      93        1365 :     out_time[10] = ctime_out[6];
      94        1365 :     out_time[11] = ctime_out[20];
      95        1365 :     out_time[12] = ctime_out[21];
      96        1365 :     out_time[13] = ctime_out[22];
      97        1365 :     out_time[14] = ctime_out[23];
      98        1365 :     out_time[15] = ' ';
      99        1365 :     out_time[16] = '\0';
     100        1365 : }
     101             : 
     102             : /************************************************************************/
     103             : /*                              UCaseStr()                              */
     104             : /*                                                                      */
     105             : /*      Force a string into upper case "in place".                      */
     106             : /************************************************************************/
     107             : 
     108         130 : std::string &PCIDSK::UCaseStr( std::string &target )
     109             : 
     110             : {
     111         778 :     for( unsigned int i = 0; i < target.size(); i++ )
     112             :     {
     113         648 :         target[i] = (char) CPLToupper(static_cast<unsigned char>(target[i]));
     114             :     }
     115             : 
     116         130 :     return target;
     117             : }
     118             : 
     119             : /************************************************************************/
     120             : /*                             atouint64()                              */
     121             : /************************************************************************/
     122             : 
     123      541894 : uint64 PCIDSK::atouint64( const char *str_value )
     124             : 
     125             : {
     126             : #if defined(__MSVCRT__) || defined(_MSC_VER)
     127             :     return (uint64) _atoi64( str_value );
     128             : #else
     129      541894 :     return (uint64) atoll( str_value );
     130             : #endif
     131             : }
     132             : 
     133             : /************************************************************************/
     134             : /*                              atoint64()                              */
     135             : /************************************************************************/
     136             : 
     137           0 : int64 PCIDSK::atoint64( const char *str_value )
     138             : 
     139             : {
     140             : #if defined(__MSVCRT__) || defined(_MSC_VER)
     141             :     return (int64) _atoi64( str_value );
     142             : #else
     143           0 :     return (int64) atoll( str_value );
     144             : #endif
     145             : }
     146             : 
     147             : /************************************************************************/
     148             : /*                            SwapPixels()                              */
     149             : /************************************************************************/
     150             : /**
     151             :  * @brief Perform an endianness swap for a given buffer of pixels
     152             :  *
     153             :  * Baed on the provided data type, do an appropriate endianness swap for
     154             :  * a buffer of pixels. Deals with the Complex case specially, in
     155             :  * particular.
     156             :  *
     157             :  * @param data the pixels to be swapped
     158             :  * @param type the data type of the pixels
     159             :  * @param count the count of pixels (not bytes, words, etc.)
     160             :  */
     161         184 : void PCIDSK::SwapPixels(void* const data,
     162             :                         const eChanType type,
     163             :                         const std::size_t count)
     164             : {
     165         184 :     switch(type) {
     166         144 :     case CHN_8U:
     167             :     case CHN_16U:
     168             :     case CHN_16S:
     169             :     case CHN_32U:
     170             :     case CHN_32S:
     171             :     case CHN_32R:
     172             :     case CHN_64U:
     173             :     case CHN_64S:
     174             :     case CHN_64R:
     175         144 :         SwapData(data, DataTypeSize(type), static_cast<int>(count));
     176         144 :         break;
     177          40 :     case CHN_C16U:
     178             :     case CHN_C16S:
     179             :     case CHN_C32U:
     180             :     case CHN_C32S:
     181             :     case CHN_C32R:
     182          40 :         SwapData(data, DataTypeSize(type) / 2, static_cast<int>(count) * 2);
     183          40 :         break;
     184           0 :     default:
     185           0 :         return ThrowPCIDSKException("Unknown data type passed to SwapPixels."
     186           0 :             "This is a software bug. Please contact your vendor.");
     187             :     }
     188             : }
     189             : 
     190             : /************************************************************************/
     191             : /*                              SwapData()                              */
     192             : /************************************************************************/
     193             : #if defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ > 3
     194       16051 : void PCIDSK::SwapData( void* const data, const int size, const int wcount )
     195             : {
     196       16051 :     if(size == 2)
     197             :     {
     198        2749 :         uint16 * data16 = reinterpret_cast<uint16*>(data);
     199       25792 :         for(int i = 0; i < wcount; i++)
     200       23043 :             data16[i] = __builtin_bswap16(data16[i]);
     201             :     }
     202       13302 :     else if(size == 4)
     203             :     {
     204       11850 :         uint32 * data32 = reinterpret_cast<uint32*>(data);
     205       51377 :         for(int i = 0; i < wcount; i++)
     206       39527 :             data32[i] = __builtin_bswap32(data32[i]);
     207             :     }
     208        1452 :     else if(size == 8)
     209             :     {
     210        1446 :         uint64 * data64 = reinterpret_cast<uint64*>(data);
     211        6538 :         for(int i = 0; i < wcount; i++)
     212        5092 :             data64[i] = __builtin_bswap64(data64[i]);
     213             :     }
     214       16051 : }
     215             : #elif defined(_MSC_VER)
     216             : #pragma intrinsic(_byteswap_ushort, _byteswap_ulong, _byteswap_uint64)
     217             : 
     218             : void PCIDSK::SwapData( void* const data, const int size, const int wcount )
     219             : {
     220             :     if(size == 2)
     221             :     {
     222             :         uint16 * data16 = reinterpret_cast<uint16*>(data);
     223             :         for(int i = 0; i < wcount; i++)
     224             :             data16[i] = _byteswap_ushort(data16[i]);
     225             :     }
     226             :     else if(size == 4)
     227             :     {
     228             :         uint32 * data32 = reinterpret_cast<uint32*>(data);
     229             :         for(int i = 0; i < wcount; i++)
     230             :             data32[i] = _byteswap_ulong(data32[i]);
     231             :     }
     232             :     else if(size == 8)
     233             :     {
     234             :         uint64 * data64 = reinterpret_cast<uint64*>(data);
     235             :         for(int i = 0; i < wcount; i++)
     236             :             data64[i] = _byteswap_uint64(data64[i]);
     237             :     }
     238             : }
     239             : 
     240             : #else
     241             : 
     242             : void PCIDSK::SwapData( void* const data, const int size, const int wcount )
     243             : 
     244             : {
     245             :     uint8* data8 = reinterpret_cast<uint8*>(data);
     246             :     std::size_t count = wcount;
     247             : 
     248             :     if( size == 2 )
     249             :     {
     250             :         uint8 t;
     251             : 
     252             :         for( ; count; count-- )
     253             :         {
     254             :             t = data8[0];
     255             :             data8[0] = data8[1];
     256             :             data8[1] = t;
     257             : 
     258             :             data8 += 2;
     259             :         }
     260             :     }
     261             :     else if( size == 1 )
     262             :         /* do nothing */;
     263             :     else if( size == 4 )
     264             :     {
     265             :         uint8 t;
     266             : 
     267             :         for( ; count; count-- )
     268             :         {
     269             :             t = data8[0];
     270             :             data8[0] = data8[3];
     271             :             data8[3] = t;
     272             : 
     273             :             t = data8[1];
     274             :             data8[1] = data8[2];
     275             :             data8[2] = t;
     276             : 
     277             :             data8 += 4;
     278             :         }
     279             :     }
     280             :     else if( size == 8 )
     281             :     {
     282             :         uint8 t;
     283             : 
     284             :         for( ; count; count-- )
     285             :         {
     286             :             t = data8[0];
     287             :             data8[0] = data8[7];
     288             :             data8[7] = t;
     289             : 
     290             :             t = data8[1];
     291             :             data8[1] = data8[6];
     292             :             data8[6] = t;
     293             : 
     294             :             t = data8[2];
     295             :             data8[2] = data8[5];
     296             :             data8[5] = t;
     297             : 
     298             :             t = data8[3];
     299             :             data8[3] = data8[4];
     300             :             data8[4] = t;
     301             : 
     302             :             data8 += 8;
     303             :         }
     304             :     }
     305             :     else
     306             :         return ThrowPCIDSKException( "Unsupported data size in SwapData()" );
     307             : }
     308             : 
     309             : #endif
     310             : 
     311             : /************************************************************************/
     312             : /*                          BigEndianSystem()                           */
     313             : /************************************************************************/
     314             : 
     315        6676 : bool PCIDSK::BigEndianSystem()
     316             : 
     317             : {
     318        6676 :     unsigned short test_value = 1;
     319             :     char test_char_value[2];
     320             : 
     321        6676 :     memcpy( test_char_value, &test_value, 2 );
     322             : 
     323        6676 :     return test_char_value[0] == 0;
     324             : }
     325             : 
     326             : 
     327             : /************************************************************************/
     328             : /*                          ParseTileFormat()                           */
     329             : /*                                                                      */
     330             : /*      Parse blocksize and compression out of a TILED interleaving     */
     331             : /*      string as passed to the Create() function or stored in          */
     332             : /*      _DBLayout metadata.                                             */
     333             : /************************************************************************/
     334             : 
     335           7 : void PCIDSK::ParseTileFormat(const std::string& oOptionsIn,
     336             :                              int & nTileSize, std::string & oCompress)
     337             : {
     338           7 :     nTileSize = PCIDSK_DEFAULT_TILE_SIZE;
     339           7 :     oCompress = "NONE";
     340             : 
     341          14 :     std::string oOptions(oOptionsIn);
     342           7 :     UCaseStr(oOptions);
     343             : 
     344           7 :     std::string::size_type nStart = oOptions.find_first_not_of(" ");
     345           7 :     std::string::size_type nEnd = oOptions.find_first_of(" ", nStart);
     346             : 
     347          22 :     while (nStart != std::string::npos || nEnd != std::string::npos)
     348             :     {
     349          30 :         const std::string oToken = oOptions.substr(nStart, nEnd - nStart);
     350             : 
     351          15 :         if (oToken.size() > 5 && STARTS_WITH(oToken.c_str(), "TILED"))
     352             :         {
     353             :             // the TILED entry can be TILED# or TILED=#
     354           6 :             int nPos = oToken[5] == '=' ? 6 : 5;
     355             : 
     356           6 :             nTileSize = atoi(oToken.substr(nPos).c_str());
     357             : 
     358           6 :             if (nTileSize <= 0)
     359           0 :                 ThrowPCIDSKException("Invalid tile option: %s", oToken.c_str());
     360             :         }
     361          18 :         else if (oToken == "NONE" || oToken == "RLE" ||
     362          23 :                  STARTS_WITH(oToken.c_str(), "JPEG") ||
     363           5 :                  STARTS_WITH(oToken.c_str(), "QUADTREE"))
     364             :         {
     365           4 :             oCompress = oToken;
     366             :         }
     367             : 
     368          15 :         nStart = oOptions.find_first_not_of(" ", nEnd);
     369          15 :         nEnd = oOptions.find_first_of(" ", nStart);
     370             :     }
     371           7 : }
     372             : 
     373             : /************************************************************************/
     374             : /*                         ParseLinkedFilename()                        */
     375             : /************************************************************************/
     376             : 
     377           0 : std::string PCIDSK::ParseLinkedFilename(std::string oOptions)
     378             : {
     379           0 :     std::string oToFind = "FILENOCREATE=";
     380           0 :     std::string oLinkedFileName;
     381             : 
     382           0 :     std::string::size_type nStart = oOptions.find_first_not_of(" ");
     383           0 :     std::string::size_type nEnd = oOptions.find_first_of(" ", nStart);
     384             : 
     385           0 :     while (nStart != std::string::npos || nEnd != std::string::npos)
     386             :     {
     387           0 :         std::string oToken = oOptions.substr(nStart, nEnd - nStart);
     388             : 
     389           0 :         if (oToken.size() > oToFind.size() &&
     390           0 :             strncmp(oToken.c_str(), oToFind.c_str(), oToFind.size()) == 0)
     391             :         {
     392           0 :             oLinkedFileName = oOptions.substr(nStart+oToFind.size());
     393           0 :             break;
     394             :         }
     395             : 
     396           0 :         nStart = oOptions.find_first_not_of(" ", nEnd);
     397           0 :         nEnd = oOptions.find_first_of(" ", nStart);
     398             :     }
     399             : 
     400           0 :     return oLinkedFileName;
     401             : }
     402             : 
     403             : /************************************************************************/
     404             : /*                           pci_strcasecmp()                           */
     405             : /************************************************************************/
     406             : 
     407           0 : int PCIDSK::pci_strcasecmp( const char *string1, const char *string2 )
     408             : 
     409             : {
     410             :     int i;
     411             : 
     412           0 :     for( i = 0; string1[i] != '\0' && string2[i] != '\0'; i++ )
     413             :     {
     414           0 :         char c1 = string1[i];
     415           0 :         char c2 = string2[i];
     416             : 
     417           0 :         c1 = (char) CPLToupper(static_cast<unsigned char>(c1));
     418           0 :         c2 = (char) CPLToupper(static_cast<unsigned char>(c2));
     419             : 
     420           0 :         if( c1 < c2 )
     421           0 :             return -1;
     422           0 :         else if( c1 > c2 )
     423           0 :             return 1;
     424             :     }
     425             : 
     426           0 :     if( string1[i] == '\0' && string2[i] == '\0' )
     427           0 :         return 0;
     428           0 :     else if( string1[i] == '\0' )
     429           0 :         return 1;
     430             :     else
     431           0 :         return -1;
     432             : }
     433             : 
     434             : /************************************************************************/
     435             : /*                          pci_strncasecmp()                           */
     436             : /************************************************************************/
     437             : 
     438           0 : int PCIDSK::pci_strncasecmp( const char *string1, const char *string2, size_t len )
     439             : 
     440             : {
     441           0 :     for( size_t i = 0; i < len; i++ )
     442             :     {
     443           0 :         if( string1[i] == '\0' && string2[i] == '\0' )
     444           0 :             return 0;
     445           0 :         else if( string1[i] == '\0' )
     446           0 :             return 1;
     447           0 :         else if( string2[i] == '\0' )
     448           0 :             return -1;
     449             : 
     450           0 :         char c1 = string1[i];
     451           0 :         char c2 = string2[i];
     452             : 
     453           0 :         c1 = (char) CPLToupper(static_cast<unsigned char>(c1));
     454           0 :         c2 = (char) CPLToupper(static_cast<unsigned char>(c2));
     455             : 
     456           0 :         if( c1 < c2 )
     457           0 :             return -1;
     458           0 :         else if( c1 > c2 )
     459           0 :             return 1;
     460             :     }
     461             : 
     462           0 :     return 0;
     463             : }
     464             : 
     465             : /************************************************************************/
     466             : /*                         ProjParamsFromText()                          */
     467             : /*                                                                      */
     468             : /*      function to turn a ProjParams string (17 floating point          */
     469             : /*      numbers) into an array, as well as attaching the units code     */
     470             : /*      derived from the geosys string.                                 */
     471             : /************************************************************************/
     472             : 
     473        1183 : std::vector<double> PCIDSK::ProjParamsFromText( std::string geosys,
     474             :                                                std::string sparms )
     475             : 
     476             : {
     477        1183 :     std::vector<double> dparms;
     478             : 
     479        1404 :     for( const char* next = sparms.c_str(); *next != '\0'; )
     480             :     {
     481         221 :         dparms.push_back( CPLAtof(next) );
     482             : 
     483             :         // move past this token
     484         442 :         while( *next != '\0' && *next != ' ' )
     485         221 :             next++;
     486             : 
     487             :         // move past white space.
     488         429 :         while( *next == ' ' )
     489         208 :             next++;
     490             :     }
     491             : 
     492        1183 :     dparms.resize(18);
     493             : 
     494             :     // This is rather iffy!
     495        1183 :     if( STARTS_WITH_CI(geosys.c_str(), "DEG" /* "DEGREE" */) )
     496           0 :         dparms[17] = (double) (int) UNIT_DEGREE;
     497        1183 :     else if( STARTS_WITH_CI(geosys.c_str(), "MET") )
     498        1171 :         dparms[17] = (double) (int) UNIT_METER;
     499          12 :     else if( STARTS_WITH_CI(geosys.c_str(), "FOOT") )
     500           0 :         dparms[17] = (double) (int) UNIT_US_FOOT;
     501          12 :     else if( STARTS_WITH_CI(geosys.c_str(), "FEET") )
     502           0 :         dparms[17] = (double) (int) UNIT_US_FOOT;
     503          12 :     else if( STARTS_WITH_CI(geosys.c_str(), "INTL " /* "INTL FOOT" */) )
     504           0 :         dparms[17] = (double) (int) UNIT_INTL_FOOT;
     505          12 :     else if( STARTS_WITH_CI(geosys.c_str(), "SPCS") )
     506           0 :         dparms[17] = (double) (int) UNIT_METER;
     507          12 :     else if( STARTS_WITH_CI(geosys.c_str(), "SPIF") )
     508           0 :         dparms[17] = (double) (int) UNIT_INTL_FOOT;
     509          12 :     else if( STARTS_WITH_CI(geosys.c_str(), "SPAF") )
     510           0 :         dparms[17] = (double) (int) UNIT_US_FOOT;
     511             :     else
     512          12 :         dparms[17] = -1.0; /* unknown */
     513             : 
     514        1183 :     return dparms;
     515             : }
     516             : 
     517             : /************************************************************************/
     518             : /*                          ProjParamsToText()                           */
     519             : /************************************************************************/
     520             : 
     521           6 : std::string PCIDSK::ProjParamsToText( std::vector<double> dparms )
     522             : 
     523             : {
     524           6 :     std::string sparms;
     525             : 
     526         108 :     for( unsigned int i = 0; i < 17; i++ )
     527             :     {
     528             :         char value[64];
     529             :         double dvalue;
     530             : 
     531         102 :         if( i < dparms.size() )
     532         102 :             dvalue = dparms[i];
     533             :         else
     534           0 :             dvalue = 0.0;
     535             : 
     536         102 :         if( dvalue == floor(dvalue) )
     537         102 :             CPLsnprintf( value, sizeof(value), "%d", (int) dvalue );
     538             :         else
     539           0 :             CPLsnprintf( value, sizeof(value), "%.15g", dvalue );
     540             : 
     541         102 :         if( i > 0 )
     542          96 :             sparms += " ";
     543             : 
     544         102 :         sparms += value;
     545             :     }
     546             : 
     547           6 :     return sparms;
     548             : }
     549             : 
     550             : /************************************************************************/
     551             : /*                            ExtractPath()                             */
     552             : /*                                                                      */
     553             : /*      Extract the directory path portion of the passed filename.      */
     554             : /*      It assumes the last component is a filename and should not      */
     555             : /*      be passed a bare path.  The trailing directory delimiter is     */
     556             : /*      removed from the result.  The return result is an empty         */
     557             : /*      string for a simple filename passed in with no directory        */
     558             : /*      component.                                                      */
     559             : /************************************************************************/
     560             : 
     561           6 : std::string PCIDSK::ExtractPath( std::string filename )
     562             : 
     563             : {
     564             :     int i;
     565             : 
     566          90 :     for( i = static_cast<int>(filename.size())-1; i >= 0; i-- )
     567             :     {
     568          90 :         if( filename[i] == '\\' || filename[i] == '/' )
     569           6 :             break;
     570             :     }
     571             : 
     572           6 :     if( i > 0 )
     573           6 :         return filename.substr(0,i);
     574             :     else
     575           0 :         return "";
     576             : }
     577             : 
     578             : /************************************************************************/
     579             : /*                         DefaultMergeRelativePath()                   */
     580             : /*                                                                      */
     581             : /*      This attempts to take src_filename and make it relative to      */
     582             : /*      the base of the file "base", if this evaluates to a new file    */
     583             : /*      in the filesystem.  It will not make any change if              */
     584             : /*      src_filename appears to be absolute or if the altered path      */
     585             : /*      does not resolve to a file in the filesystem.                   */
     586             : /************************************************************************/
     587             : 
     588           6 : std::string PCIDSK::DefaultMergeRelativePath(const PCIDSK::IOInterfaces *io_interfaces,
     589             :                                              const std::string& base,
     590             :                                              const std::string& src_filename)
     591             : 
     592             : {
     593             : /* -------------------------------------------------------------------- */
     594             : /*      Does src_filename appear to be absolute?                        */
     595             : /* -------------------------------------------------------------------- */
     596           6 :     if( src_filename.empty() )
     597           0 :         return src_filename; // we can't do anything with a blank.
     598           6 :     else if( src_filename.size() > 2 && src_filename[1] == ':' )
     599           0 :         return src_filename; // has a drive letter?
     600           6 :     else if( src_filename[0] == '/' || src_filename[0] == '\\' )
     601           0 :         return src_filename; // has a leading dir marker.
     602             : 
     603             : /* -------------------------------------------------------------------- */
     604             : /*      Figure out what path split char we want to use.                 */
     605             : /* -------------------------------------------------------------------- */
     606             : #if defined(__MSVCRT__) || defined(_MSC_VER)
     607             :     const static char  path_split = '\\';
     608             : #else
     609             :     const static char  path_split = '/';
     610             : #endif
     611             : 
     612             : /* -------------------------------------------------------------------- */
     613             : /*      Merge paths.                                                    */
     614             : /* -------------------------------------------------------------------- */
     615          12 :     std::string result = ExtractPath( base );
     616             : 
     617           6 :     if( result.empty() )
     618           0 :         return src_filename;
     619             : 
     620           6 :     result += path_split;
     621           6 :     result += src_filename;
     622             : 
     623             : /* -------------------------------------------------------------------- */
     624             : /*      Check if the target exists by this name.                        */
     625             : /* -------------------------------------------------------------------- */
     626             :     try
     627             :     {
     628           8 :         void *hFile = io_interfaces->Open( result, "r" );
     629             :         // should throw an exception on failure.
     630           5 :         io_interfaces->Close( hFile );
     631           5 :         return result;
     632             :     }
     633           2 :     catch( ... )
     634             :     {
     635           1 :         return src_filename;
     636             :     }
     637             : }
     638             : 
     639             : 
     640             : /************************************************************************/
     641             : /*                            DefaultDebug()                            */
     642             : /*                                                                      */
     643             : /*      Default implementation of the Debug() output interface.         */
     644             : /************************************************************************/
     645             : 
     646           0 : void PCIDSK::DefaultDebug( const char * message )
     647             : 
     648             : {
     649             :     static bool initialized = false;
     650             :     static bool enabled = false;
     651             : 
     652           0 :     if( !initialized )
     653             :     {
     654           0 :         if( getenv( "PCIDSK_DEBUG" ) != nullptr )
     655           0 :             enabled = true;
     656             : 
     657           0 :         initialized = true;
     658             :     }
     659             : 
     660           0 :     if( enabled )
     661           0 :         std::cerr << message;
     662           0 : }
     663             : 
     664             : /************************************************************************/
     665             : /*                               vDebug()                               */
     666             : /*                                                                      */
     667             : /*      Helper function for Debug().                                    */
     668             : /************************************************************************/
     669             : 
     670           0 : static void vDebug( void (*pfnDebug)(const char *),
     671             :                     const char *fmt, std::va_list args )
     672             : 
     673             : {
     674           0 :     std::string message;
     675             : 
     676             : /* -------------------------------------------------------------------- */
     677             : /*      This implementation for platforms without vsnprintf() will      */
     678             : /*      just plain fail if the formatted contents are too large.        */
     679             : /* -------------------------------------------------------------------- */
     680             : #if defined(MISSING_VSNPRINTF)
     681             :     char *pszBuffer = (char *) malloc(30000);
     682             :     if( vsprintf( pszBuffer, fmt, args) > 29998 )
     683             :     {
     684             :         message = "PCIDSK::Debug() ... buffer overrun.";
     685             :     }
     686             :     else
     687             :         message = pszBuffer;
     688             : 
     689             :     free( pszBuffer );
     690             : 
     691             : /* -------------------------------------------------------------------- */
     692             : /*      This should grow a big enough buffer to hold any formatted      */
     693             : /*      result.                                                         */
     694             : /* -------------------------------------------------------------------- */
     695             : #else
     696             :     char szModestBuffer[500];
     697             :     int nPR;
     698             :     va_list wrk_args;
     699             : 
     700             : #ifdef va_copy
     701           0 :     va_copy( wrk_args, args );
     702             : #else
     703             :     wrk_args = args;
     704             : #endif
     705             : 
     706           0 :     nPR = vsnprintf( szModestBuffer, sizeof(szModestBuffer), fmt,
     707             :                      wrk_args );
     708           0 :     if( nPR == -1 || nPR >= (int) sizeof(szModestBuffer)-1 )
     709             :     {
     710           0 :         int nWorkBufferSize = 2000;
     711           0 :         PCIDSKBuffer oWorkBuffer(nWorkBufferSize);
     712             : 
     713             : #ifdef va_copy
     714           0 :         va_end( wrk_args );
     715           0 :         va_copy( wrk_args, args );
     716             : #else
     717             :         wrk_args = args;
     718             : #endif
     719           0 :         while( (nPR=vsnprintf( oWorkBuffer.buffer, nWorkBufferSize, fmt, wrk_args))
     720           0 :                >= nWorkBufferSize-1
     721           0 :                || nPR == -1 )
     722             :         {
     723           0 :             nWorkBufferSize *= 4;
     724           0 :             oWorkBuffer.SetSize(nWorkBufferSize);
     725             : #ifdef va_copy
     726           0 :             va_end( wrk_args );
     727           0 :             va_copy( wrk_args, args );
     728             : #else
     729             :             wrk_args = args;
     730             : #endif
     731             :         }
     732           0 :         message = oWorkBuffer.buffer;
     733             :     }
     734             :     else
     735             :     {
     736           0 :         message = szModestBuffer;
     737             :     }
     738           0 :     va_end( wrk_args );
     739             : #endif
     740             : 
     741             : /* -------------------------------------------------------------------- */
     742             : /*      Forward the message.                                            */
     743             : /* -------------------------------------------------------------------- */
     744           0 :     pfnDebug( message.c_str() );
     745           0 : }
     746             : 
     747             : /************************************************************************/
     748             : /*                               Debug()                                */
     749             : /*                                                                      */
     750             : /*      Function to write output to a debug stream if one is            */
     751             : /*      enabled.  This is intended to be widely called in the           */
     752             : /*      library.                                                        */
     753             : /************************************************************************/
     754             : 
     755           0 : void PCIDSK::Debug( void (*pfnDebug)(const char *), const char *fmt, ... )
     756             : 
     757             : {
     758           0 :     if( pfnDebug == nullptr )
     759           0 :         return;
     760             : 
     761             :     std::va_list args;
     762             : 
     763           0 :     va_start( args, fmt );
     764           0 :     vDebug( pfnDebug, fmt, args );
     765           0 :     va_end( args );
     766             : }

Generated by: LCOV version 1.14