LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/gtm - gtm.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 371 281 75.7 %
Date: 2012-04-28 Functions: 59 48 81.4 %

       1                 : /******************************************************************************
       2                 :  * $Id: gtm.cpp 20996 2010-10-28 18:38:15Z rouault $
       3                 :  *
       4                 :  * Project:  GTM Driver
       5                 :  * Purpose:  Class for reading, parsing and handling a gtmfile.
       6                 :  * Author:   Leonardo de Paula Rosa Piga; http://lampiao.lsc.ic.unicamp.br/~piga
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2009, Leonardo de Paula Rosa Piga
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : #include "gtm.h"
      30                 : 
      31                 : 
      32                 : /************************************************************************/
      33                 : /*        Methods for dealing with write on files and buffers           */
      34                 : /************************************************************************/
      35              60 : void appendDouble(void* pBuffer, double val)
      36                 : {
      37                 :     CPL_LSBPTR64(&val);
      38              60 :     memcpy(pBuffer, &val, 8);
      39              60 : }
      40                 : 
      41              46 : void appendFloat(void* pBuffer, float val)
      42                 : {
      43                 :     CPL_LSBPTR32(&val)
      44              46 :     memcpy(pBuffer, &val, 4);
      45              46 : }
      46                 : 
      47             208 : void appendInt(void* pBuffer, int val)
      48                 : {
      49                 :     CPL_LSBPTR32(&val)
      50             208 :     memcpy(pBuffer, &val, 4);
      51             208 : }
      52                 : 
      53             132 : void appendUChar(void* pBuffer, unsigned char val)
      54                 : {
      55             132 :     memcpy(pBuffer, &val, 1);
      56             132 : }
      57                 : 
      58             120 : void appendUShort(void* pBuffer, unsigned short val)
      59                 : {
      60                 :     CPL_LSBPTR16(&val)
      61             120 :     memcpy(pBuffer, &val, 2);
      62             120 : }
      63                 : 
      64               0 : void writeUChar(VSILFILE* fp, unsigned char val)
      65                 : {
      66               0 :     VSIFWriteL(&val, 1, 1, fp);
      67               0 : }
      68                 : 
      69              16 : void writeDouble(VSILFILE* fp, double val)
      70                 : {
      71                 :     CPL_LSBPTR64(&val)
      72              16 :     VSIFWriteL(&val, 1, 8, fp);
      73              16 : }
      74                 : 
      75             168 : static double readDouble(VSILFILE* fp)
      76                 : {
      77                 :     double val;
      78             168 :     VSIFReadL( &val, 1, 8, fp );
      79                 :     CPL_LSBPTR64(&val)
      80             168 :     return val;
      81                 : }
      82                 : 
      83              84 : static float readFloat(VSILFILE* fp)
      84                 : {
      85                 :     float val;
      86              84 :     VSIFReadL( &val, 1, 4, fp );
      87                 :     CPL_LSBPTR32(&val)
      88              84 :     return val;
      89                 : }
      90                 : 
      91             146 : static int readInt(VSILFILE* fp)
      92                 : {
      93                 :     int val;
      94             146 :     VSIFReadL( &val, 1, 4, fp );
      95                 :     CPL_LSBPTR32(&val)
      96             146 :     return val;
      97                 : }
      98                 : 
      99              28 : static unsigned char readUChar(VSILFILE* fp)
     100                 : {
     101                 :     unsigned char val;
     102              28 :     VSIFReadL( &val, 1, 1, fp );
     103              28 :     return val;
     104                 : }
     105                 : 
     106             144 : static unsigned short readUShort(VSILFILE* fp, int *pbSuccess = NULL)
     107                 : {
     108                 :     unsigned short val;
     109             144 :     if (VSIFReadL( &val, 1, 2, fp ) != 2)
     110                 :     {
     111               0 :         if (pbSuccess) *pbSuccess = FALSE;
     112               0 :         return 0;
     113                 :     }
     114             144 :     if (pbSuccess) *pbSuccess = TRUE;
     115                 :     CPL_LSBPTR16(&val)
     116             144 :     return val;
     117                 : }
     118                 : 
     119              24 : void writeFloat(VSILFILE* fp, float val)
     120                 : {
     121                 :     CPL_LSBPTR32(&val)
     122              24 :     VSIFWriteL(&val, 1, 4, fp);
     123              24 : }
     124                 : 
     125              18 : void writeInt(VSILFILE* fp, int val)
     126                 : {
     127                 :     CPL_LSBPTR32(&val)
     128              18 :     VSIFWriteL(&val, 1, 4, fp);
     129              18 : }
     130                 : 
     131               0 : void writeUShort(VSILFILE* fp, unsigned short val)
     132                 : {
     133                 :     CPL_LSBPTR16(&val)
     134               0 :     VSIFWriteL(&val, 1, 2, fp);
     135               0 : }
     136                 : 
     137                 : 
     138                 : /************************************************************************/
     139                 : /*             Implementation of Waypoint Function Members              */
     140                 : /************************************************************************/
     141              14 : Waypoint::Waypoint(double latitude,
     142                 :                    double longitude,
     143                 :                    double altitude,
     144                 :                    const char* name,
     145                 :                    const char* comment,
     146                 :                    int icon,
     147                 :                    GIntBig wptdate)
     148                 : {
     149              14 :     this->latitude = latitude;
     150              14 :     this->longitude = longitude;
     151              14 :     this->altitude = altitude;
     152              14 :     this->name = CPLStrdup(name);
     153              14 :     this->comment = CPLStrdup(comment);
     154              14 :     this->icon = icon;
     155              14 :     this->wptdate = wptdate;
     156              14 : }
     157                 : 
     158              14 : Waypoint::~Waypoint()
     159                 : {
     160              14 :     CPLFree(name);
     161              14 :     CPLFree(comment);
     162              14 : }
     163                 : 
     164              14 : double Waypoint::getLatitude() 
     165                 : {
     166              14 :     return latitude;
     167                 : }
     168                 : 
     169              14 : double Waypoint::getLongitude()
     170                 : {
     171              14 :     return longitude;
     172                 : }
     173                 : 
     174              14 : double Waypoint::getAltitude()
     175                 : {
     176              14 :     return altitude;
     177                 : }
     178                 : 
     179              14 : const char* Waypoint::getName()
     180                 : {
     181              14 :     return name;
     182                 : }
     183                 : 
     184              14 : const char* Waypoint::getComment()
     185                 : {
     186              14 :     return comment;
     187                 : }
     188                 : 
     189              14 : int Waypoint::getIcon()
     190                 : {
     191              14 :     return icon;
     192                 : }
     193                 : 
     194              14 : GIntBig Waypoint::getDate()
     195                 : {
     196              14 :     return wptdate;
     197                 : }
     198                 : 
     199                 : /************************************************************************/
     200                 : /*               Implementation of Track Function Members               */
     201                 : /************************************************************************/
     202              14 : Track::Track(const char* pszName,
     203                 :              unsigned char type,
     204                 :              int color)
     205                 : {
     206              14 :     this->pszName = CPLStrdup(pszName);
     207              14 :     this->type = type;
     208              14 :     this->color = color;
     209              14 :     nPoints = 0;
     210              14 :     pasTrackPoints = NULL;
     211              14 : }
     212                 : 
     213              14 : Track::~Track()
     214                 : {
     215              14 :     CPLFree(pszName);
     216              14 :     pszName = NULL;
     217              14 :     CPLFree(pasTrackPoints);
     218              14 : }
     219                 : 
     220              14 : const char* Track::getName() {
     221              14 :     return pszName;
     222                 : }
     223                 : 
     224              14 : unsigned char Track::getType()
     225                 : {
     226              14 :     return type;
     227                 : }
     228                 : 
     229                 : 
     230              14 : int Track::getColor()
     231                 : {
     232              14 :     return color;
     233                 : }
     234                 : 
     235              60 : void Track::addPoint(double x, double y, GIntBig datetime, double altitude)
     236                 : {
     237                 :     pasTrackPoints = (TrackPoint*)
     238              60 :         CPLRealloc(pasTrackPoints, (nPoints + 1) * sizeof(TrackPoint));
     239              60 :     pasTrackPoints[nPoints].x = x;
     240              60 :     pasTrackPoints[nPoints].y = y;
     241              60 :     pasTrackPoints[nPoints].datetime = datetime;
     242              60 :     pasTrackPoints[nPoints].altitude = altitude;
     243              60 :     nPoints ++;
     244              60 : }
     245                 : 
     246              74 : int Track::getNumPoints()
     247                 : {
     248              74 :     return nPoints;
     249                 : }
     250                 : 
     251              60 : const TrackPoint* Track::getPoint(int pointNum)
     252                 : {
     253              60 :     if (pointNum >=0 && pointNum < nPoints)
     254              60 :         return &pasTrackPoints[pointNum];
     255                 :     else
     256               0 :         return NULL;
     257                 : }
     258                 : 
     259                 : 
     260                 : /************************************************************************/
     261                 : /*                Implementation of GTM Function Members                */
     262                 : /************************************************************************/
     263             220 : GTM::GTM()
     264                 : {
     265             220 :     pGTMFile = NULL;
     266             220 :     pszFilename = NULL;
     267                 : 
     268             220 :     nwptstyles = 0;
     269             220 :     nwpts = 0;
     270             220 :     ntcks = 0;
     271             220 :     n_tk = 0;
     272             220 :     n_maps = 0;
     273             220 :     headerSize = 0;
     274                 : 
     275             220 :     firstWaypointOffset = 0;
     276             220 :     actualWaypointOffset = 0;
     277             220 :     waypointFetched = 0;
     278                 :   
     279             220 :     firstTrackpointOffset = 0;
     280             220 :     actualTrackpointOffset = 0;
     281             220 :     trackpointFetched = 0;
     282                 : 
     283             220 :     firstTrackOffset = 0;
     284             220 :     actualTrackOffset = 0;
     285             220 :     trackFetched = 0;
     286             220 : }
     287                 : 
     288             220 : GTM::~GTM()
     289                 : {
     290             220 :     CPLFree(pszFilename);
     291             220 :     if (pGTMFile != NULL)
     292                 :     {
     293             140 :         VSIFCloseL(pGTMFile);
     294             140 :         pGTMFile = NULL;
     295                 :     }
     296             220 : }
     297                 : 
     298             220 : bool GTM::Open(const char* pszFilename)
     299                 : {
     300                 : 
     301             220 :     if (pGTMFile != NULL)
     302               0 :         VSIFCloseL(pGTMFile);
     303                 :         
     304             220 :     CPLFree(this->pszFilename);
     305             220 :     this->pszFilename = CPLStrdup(pszFilename);
     306                 : 
     307             220 :     pGTMFile = VSIFOpenL( pszFilename, "r" );
     308             220 :     if (pGTMFile == NULL)
     309                 :     {
     310              80 :         return FALSE;
     311                 :     }
     312             140 :     return TRUE;
     313                 : }
     314                 : 
     315                 : 
     316             140 : bool GTM::isValid()
     317                 : {
     318                 :     //  2 bytes - version number
     319                 :     // 10 bytes - "TrackMaker" string
     320                 :     char buffer[13];
     321                 : 
     322                 :     char* szHeader;
     323                 :     short version;
     324                 : 
     325                 : /* -------------------------------------------------------------------- */
     326                 : /*      If we aren't sure it is GTM, load a header chunk and check      */
     327                 : /*      for signs it is GTM                                             */
     328                 : /* -------------------------------------------------------------------- */
     329             140 :     size_t nRead = VSIFReadL( buffer, 1, sizeof(buffer)-1, pGTMFile );
     330             140 :     if (nRead <= 0)
     331                 :     {
     332               0 :         VSIFCloseL( pGTMFile );
     333               0 :         pGTMFile = NULL;
     334               0 :         return FALSE;
     335                 :     }
     336             140 :     buffer[12] = '\0';
     337                 :     
     338                 : /* -------------------------------------------------------------------- */
     339                 : /*      If it looks like a GZip header, this may be a .gtz file, so     */
     340                 : /*      try opening with the /vsigzip/ prefix                           */
     341                 : /* -------------------------------------------------------------------- */
     342             140 :     if (buffer[0] == 0x1f && ((unsigned char*)buffer)[1] == 0x8b &&
     343                 :         strncmp(pszFilename, "/vsigzip/", strlen("/vsigzip/")) != 0)
     344                 :     {
     345                 :         char* pszGZIPFileName = (char*)CPLMalloc(
     346               0 :                            strlen("/vsigzip/") + strlen(pszFilename) + 1);
     347               0 :         sprintf(pszGZIPFileName, "/vsigzip/%s", pszFilename);
     348               0 :         VSILFILE* fp = VSIFOpenL(pszGZIPFileName, "rb");
     349               0 :         if (fp)
     350                 :         {
     351               0 :             VSILFILE* pGTMFileOri = pGTMFile;
     352               0 :             pGTMFile = fp;
     353               0 :             if (isValid())
     354                 :             {
     355               0 :                 VSIFCloseL(pGTMFileOri);
     356               0 :                 CPLFree(pszGZIPFileName);
     357               0 :                 return TRUE;
     358                 :             }
     359                 :             else
     360                 :             {
     361               0 :                 if (pGTMFile)
     362               0 :                     VSIFCloseL(pGTMFile);
     363               0 :                 pGTMFile = pGTMFileOri;
     364                 :             }
     365                 :         }
     366               0 :         CPLFree(pszGZIPFileName);
     367                 :     }
     368                 :     
     369             140 :     version = CPL_LSBINT16PTR(buffer);
     370                 :     /*Skip string length */
     371             140 :     szHeader = buffer + 2;
     372             140 :     if (version == 211 && strcmp(szHeader, "TrackMaker") == 0 )
     373                 :     {
     374               8 :         return TRUE;
     375                 :     }
     376             132 :     return FALSE;
     377                 : }
     378                 : 
     379               8 : bool GTM::readHeaderNumbers()
     380                 : {
     381               8 :     if (pGTMFile == NULL)
     382               0 :         return FALSE;
     383                 : 
     384                 :    
     385                 :     /* I'm supposing that the user has already checked if the file is
     386                 :        valid.  */
     387                 :     /* Also, I'm ignoring some header parameters that are unnecessary
     388                 :        for my purpose. If you want more features, implement it. :-P */
     389                 : 
     390                 :     /* Read Number of Waypoint Styles*/
     391                 :     /* Seek file */
     392               8 :     if (VSIFSeekL(pGTMFile, NWPTSTYLES_OFFSET, SEEK_SET) != 0)
     393               0 :         return FALSE;
     394                 :     /* Read nwptstyles */
     395               8 :     nwptstyles = readInt(pGTMFile);
     396               8 :     if (nwptstyles < 0)
     397               0 :         return FALSE;
     398                 : 
     399                 :     /* Read Number of Waypoints */
     400                 :     /* Seek file */
     401               8 :     if ( VSIFSeekL(pGTMFile, NWPTS_OFFSET, SEEK_SET) != 0)
     402               0 :         return FALSE;
     403                 :     /* Read nwpts */
     404               8 :     nwpts = readInt(pGTMFile);
     405               8 :     if (nwpts < 0)
     406               0 :         return FALSE;
     407                 : 
     408                 :     /* Read Number of Trackpoints */
     409               8 :     ntcks = readInt(pGTMFile);
     410               8 :     if (ntcks < 0)
     411               0 :         return FALSE;
     412                 : 
     413                 :     /* Read Number of images */
     414                 :     /* Seek file */
     415               8 :     if ( VSIFSeekL(pGTMFile, NMAPS_OFFSET, SEEK_SET) != 0)
     416               0 :         return FALSE;
     417                 :     /* read n_maps */
     418               8 :     n_maps = readInt(pGTMFile);
     419               8 :     if (n_maps < 0)
     420               0 :         return FALSE;
     421                 : 
     422                 :     /* Read Number of Tracks */
     423               8 :     n_tk = readInt(pGTMFile);
     424               8 :     if (n_tk < 0)
     425               0 :         return FALSE;
     426                 : 
     427                 :     /* Figure out the header size */
     428               8 :     headerSize = 99; // Constant size plus size of strings
     429                 :     unsigned short stringSize;
     430                 : 
     431                 :     /* Read gradfont string size */
     432               8 :     if ( VSIFSeekL(pGTMFile, 99, SEEK_SET) != 0)
     433               0 :         return FALSE;
     434               8 :     stringSize = readUShort(pGTMFile);
     435               8 :     headerSize += stringSize + 2; // String + size field
     436                 : 
     437                 :     /* Read labelfont string size */
     438               8 :     if ( VSIFSeekL(pGTMFile, stringSize, SEEK_CUR) != 0)
     439               0 :         return FALSE;
     440               8 :     stringSize = readUShort(pGTMFile);
     441               8 :     headerSize += stringSize + 2; // String + size field
     442                 : 
     443                 : 
     444                 :     /* Read userfont string size */
     445               8 :     if ( VSIFSeekL(pGTMFile, stringSize, SEEK_CUR) != 0)
     446               0 :         return FALSE;
     447               8 :     stringSize = readUShort(pGTMFile);
     448               8 :     headerSize += stringSize + 2; // String + size field
     449                 : 
     450                 :     /* Read newdatum string size */
     451               8 :     if ( VSIFSeekL(pGTMFile, stringSize, SEEK_CUR) != 0)
     452               0 :         return FALSE;
     453               8 :     stringSize = readUShort(pGTMFile);
     454               8 :     headerSize += stringSize + 2; // String + size field
     455                 : 
     456                 : 
     457                 : 
     458                 : /* -------------------------------------------------------------------- */
     459                 : /*                 Checks if it is using WGS84 datum                    */
     460                 : /* -------------------------------------------------------------------- */
     461                 :     /* Read newdatum string size */
     462               8 :     if ( VSIFSeekL(pGTMFile, headerSize + 34, SEEK_SET) != 0)
     463               0 :         return FALSE;
     464               8 :     if (readInt(pGTMFile) != 217)
     465                 :     {
     466                 :         CPLError( CE_Warning, CPLE_AppDefined,
     467                 :                   "You are attempting to open a file that is not using WGS84 datum.\n"
     468               0 :                   "Coordinates will be returned as if they were WGS84, but no reprojection will be done.");
     469                 :     }
     470                 : 
     471                 :     /* Look for the offsets */
     472                 :     /* Waypoints */
     473               8 :     firstWaypointOffset = findFirstWaypointOffset();
     474               8 :     if (firstWaypointOffset == 0)
     475               0 :         return FALSE;
     476               8 :     actualWaypointOffset = firstWaypointOffset;
     477                 :     /* Trackpoints */
     478               8 :     firstTrackpointOffset = findFirstTrackpointOffset();
     479               8 :     if (firstTrackpointOffset == 0)
     480               0 :         return FALSE;
     481               8 :     actualTrackpointOffset = firstTrackpointOffset;
     482                 : 
     483                 :     /* Tracks */
     484               8 :     firstTrackOffset = findFirstTrackOffset();
     485               8 :     if (firstTrackOffset == 0)
     486               0 :         return FALSE;
     487               8 :     actualTrackOffset = firstTrackOffset;
     488                 : 
     489               8 :     return TRUE;
     490                 : }
     491                 : 
     492                 : /************************************************************************/
     493                 : /*                        Waypoint control functions                    */
     494                 : /************************************************************************/
     495              12 : int GTM::getNWpts()
     496                 : {
     497              12 :     return nwpts;
     498                 : }
     499                 : 
     500              14 : bool GTM::hasNextWaypoint()
     501                 : {
     502              14 :     return waypointFetched < nwpts;
     503                 : }
     504                 : 
     505               0 : void GTM::rewindWaypoint() 
     506                 : {
     507               0 :     actualWaypointOffset = firstWaypointOffset;
     508               0 :     waypointFetched = 0;
     509               0 : }
     510                 : 
     511              14 : Waypoint* GTM::fetchNextWaypoint()
     512                 : {
     513                 :     unsigned short stringSize;
     514                 : 
     515                 :     double latitude, longitude;
     516                 :     char name[11];
     517                 :     char* comment;
     518                 :     unsigned short icon;
     519                 :     int i;
     520                 :     float altitude;
     521                 :     GIntBig wptdate;
     522                 : 
     523                 :     /* Point to the actual waypoint offset */
     524              14 :     if ( VSIFSeekL(pGTMFile, actualWaypointOffset, SEEK_SET) != 0)
     525               0 :         return NULL;
     526                 : 
     527              14 :     latitude = readDouble(pGTMFile);
     528              14 :     longitude = readDouble(pGTMFile);
     529                 : 
     530              14 :     if ( !readFile( name, 1, 10 ) )
     531               0 :         return NULL;
     532                 :     /* Trim string name */
     533              66 :     for (i = 9; i >= 0; --i)
     534                 :     {
     535              66 :         if (name[i] != ' ')
     536                 :         {
     537              14 :             name[i+1] = '\0';
     538              14 :             break;
     539                 :         }
     540                 :     }
     541              14 :     if (i < 0)
     542               0 :         name[0] = '\0';
     543                 : 
     544                 :     /* Read String Length */
     545              14 :     stringSize = readUShort(pGTMFile);
     546                 :     /* Read Comment String */
     547              14 :     comment = (char*) VSIMalloc2(sizeof(char), stringSize+1);
     548              14 :     if ( stringSize != 0 && !readFile( comment, 1, sizeof(char)*stringSize ) )
     549                 :     {
     550               0 :         CPLFree(comment);
     551               0 :         return NULL;
     552                 :     }
     553              14 :     comment[stringSize] = '\0';
     554                 : 
     555                 :     /* Read Icon */
     556              14 :     icon = readUShort(pGTMFile);
     557                 :     
     558                 :     /* Display number */
     559              14 :     readUChar(pGTMFile);
     560                 :     
     561                 :     /* Waypoint date */
     562                 :     
     563              14 :     wptdate = readInt(pGTMFile);
     564              14 :     if (wptdate != 0)
     565               6 :         wptdate += GTM_EPOCH;
     566                 :     
     567                 :     /* Rotation text angle */
     568              14 :     readUShort(pGTMFile);
     569                 :     
     570                 :     /* Altitude */
     571              14 :     altitude = readFloat(pGTMFile);
     572                 :   
     573                 :     Waypoint* poWaypoint = new Waypoint(latitude, longitude, altitude,
     574              14 :                                         name, comment, (int) icon, wptdate);
     575                 : 
     576                 : 
     577                 :     /* Set actual waypoint offset to the next it there is one */
     578              14 :     ++waypointFetched;
     579              14 :     if (waypointFetched < nwpts)
     580                 :     {
     581               6 :         actualWaypointOffset += 8 + 8 + 10 + 2 + stringSize + 2 + 1 + 4 + 2 + 4 + 2;
     582                 :     }
     583                 : 
     584              14 :     CPLFree(comment);
     585              14 :     return poWaypoint;
     586                 : }
     587                 : 
     588                 : 
     589                 : /************************************************************************/
     590                 : /*                        Track control functions                    */
     591                 : /************************************************************************/
     592              12 : int GTM::getNTracks()
     593                 : {
     594              12 :     return n_tk;
     595                 : }
     596                 : 
     597              14 : bool GTM::hasNextTrack()
     598                 : {
     599              14 :     return trackFetched < n_tk;
     600                 : }
     601                 : 
     602               0 : void GTM::rewindTrack() 
     603                 : {
     604               0 :     actualTrackpointOffset = firstTrackpointOffset;
     605               0 :     actualTrackOffset = firstTrackOffset;
     606               0 :     trackFetched = 0;
     607               0 :     trackpointFetched = 0;
     608               0 : }
     609                 : 
     610              14 : Track* GTM::fetchNextTrack()
     611                 : {
     612                 :     unsigned short stringSize;
     613                 : 
     614                 :     char* pszName;
     615                 :     unsigned char type;
     616                 :     int color;
     617                 :   
     618                 : 
     619                 :     /* Point to the actual track offset */
     620              14 :     if ( VSIFSeekL(pGTMFile, actualTrackOffset, SEEK_SET) != 0)
     621               0 :         return NULL;
     622                 : 
     623                 : 
     624                 :     /* Read string length */
     625              14 :     stringSize = readUShort(pGTMFile);
     626                 :     /* Read name string */
     627              14 :     pszName = (char*) VSIMalloc2(sizeof(char), stringSize+1);
     628              14 :     if ( stringSize != 0 && !readFile( pszName, 1, sizeof(char) * stringSize ) )
     629                 :     {
     630               0 :         CPLFree(pszName);
     631               0 :         return NULL;
     632                 :     }
     633              14 :     pszName[stringSize] = '\0';
     634                 : 
     635                 :     /* Read type */
     636              14 :     type = readUChar(pGTMFile);
     637                 :   
     638                 :     /* Read color */
     639              14 :     color = readInt(pGTMFile);
     640                 :     
     641              14 :     Track* poTrack = new Track(pszName, type, color);
     642                 : 
     643              14 :     CPLFree(pszName);
     644                 :     /* Adjust actual Track offset */
     645              14 :     actualTrackOffset = VSIFTellL(pGTMFile) + 7;
     646              14 :     ++trackFetched;
     647                 : 
     648                 :     /* Now, We read all trackpoints for this track */
     649                 :     double latitude, longitude;
     650                 :     GIntBig datetime;
     651                 :     unsigned char start;
     652                 :     float altitude;
     653                 :     /* NOTE: Parameters are passed by reference */
     654              14 :     if ( !readTrackPoints(latitude, longitude, datetime, start, altitude) )
     655                 :     {
     656               0 :         delete poTrack;
     657               0 :         return NULL;
     658                 :     }
     659                 : 
     660                 :     /* Check if it is the start, if not we have done something wrong */
     661              14 :     if (start != 1)
     662                 :     {
     663               0 :         delete poTrack;
     664               0 :         return NULL;
     665                 :     }
     666              14 :     poTrack->addPoint(longitude, latitude, datetime, altitude);
     667                 :   
     668              56 :     do
     669                 :     {
     670                 :         /* NOTE: Parameters are passed by reference */
     671              56 :         if ( !readTrackPoints(latitude, longitude, datetime, start, altitude) )
     672                 :         {
     673               0 :             delete poTrack;
     674               0 :             return NULL;
     675                 :         }
     676              56 :         if (start == 0)
     677              46 :             poTrack->addPoint(longitude, latitude, datetime, altitude);
     678                 :     } while(start == 0 && trackpointFetched < ntcks);
     679                 : 
     680                 :     /* We have read one more than necessary, so we adjust the offset */
     681              14 :     if (trackpointFetched < ntcks)
     682                 :     {
     683              10 :         actualTrackpointOffset -= 25;
     684              10 :         --trackpointFetched;
     685                 :     }
     686                 : 
     687              14 :     return poTrack;
     688                 : }
     689                 : 
     690                 : 
     691                 : 
     692                 : /************************************************************************/
     693                 : /*                        Private Methods Implementation                */
     694                 : /************************************************************************/
     695               8 : vsi_l_offset GTM::findFirstWaypointOffset()
     696                 : {
     697                 :     /* Skip header and datum */
     698               8 :     if ( VSIFSeekL(pGTMFile, headerSize + DATUM_SIZE, SEEK_SET) != 0)
     699               0 :         return 0;
     700                 :   
     701                 :     /* Skip images */
     702                 :     unsigned short stringSize;
     703              12 :     for (int i = 0; i < n_maps; ++i)
     704                 :     {
     705                 :         /* Read image name string size */
     706               4 :         stringSize = readUShort(pGTMFile);
     707                 : 
     708                 :         /* skip image name string */
     709               4 :         if ( VSIFSeekL(pGTMFile, stringSize, SEEK_CUR) != 0)
     710               0 :             return 0;
     711                 : 
     712                 :         /* read image comment string size */
     713               4 :         stringSize = readUShort(pGTMFile);
     714                 : 
     715                 :         /* skip image comment string */
     716               4 :         if ( VSIFSeekL(pGTMFile, stringSize, SEEK_CUR) != 0)
     717               0 :             return 0;
     718                 :     
     719                 :         /* skip the others image parameters */
     720               4 :         if ( VSIFSeekL(pGTMFile, 30, SEEK_CUR) != 0)
     721               0 :             return 0;
     722                 :     }
     723               8 :     return VSIFTellL(pGTMFile);
     724                 : }
     725                 : 
     726                 : 
     727               8 : vsi_l_offset GTM::findFirstTrackpointOffset()
     728                 : {
     729               8 :     if (firstWaypointOffset == 0)
     730                 :     {
     731               0 :         firstWaypointOffset = findFirstWaypointOffset();
     732               0 :         if (firstWaypointOffset == 0)
     733               0 :             return 0;
     734                 :     }
     735                 : 
     736                 :     /*---------------------------------------------*/
     737                 :     /*       We are going to skip the waypoints    */
     738                 :     /*---------------------------------------------*/
     739                 :     /* Seek file to the first Waypoint */
     740               8 :     if (VSIFSeekL(pGTMFile, firstWaypointOffset, SEEK_SET) != 0)
     741               0 :         return 0;
     742                 :   
     743                 :     unsigned short stringSize;
     744                 :     int bSuccess;
     745                 :     /* Skip waypoints */
     746              22 :     for (int i = 0; i < nwpts; ++i)
     747                 :     {
     748                 :         /* Seek file to the string size comment field */
     749              14 :         if (VSIFSeekL(pGTMFile, 26, SEEK_CUR) != 0)
     750               0 :             return 0;
     751                 :         /* Read string comment size */
     752              14 :         stringSize = readUShort(pGTMFile, &bSuccess);
     753                 :     
     754                 :         /* Skip to the next Waypoint */
     755              14 :         if (bSuccess == FALSE || VSIFSeekL(pGTMFile, stringSize + 15, SEEK_CUR) != 0)
     756               0 :             return 0;
     757                 :     }
     758                 :   
     759                 :     /* Skip waypoint styles */
     760                 :     /* If we don't have waypoints, we don't have waypoint styles, even
     761                 :        though the nwptstyles is telling the contrary. */
     762               8 :     if (nwpts != 0)
     763                 :     {
     764              42 :         for (int i = 0; i < nwptstyles; ++i)
     765                 :         {
     766                 :             /* Seek file to the string size facename field */
     767              34 :             if (VSIFSeekL(pGTMFile, 4, SEEK_CUR) != 0)
     768               0 :                 return 0;
     769                 : 
     770                 :             /* Read string facename size */
     771              34 :             stringSize = readUShort(pGTMFile, &bSuccess);
     772                 : 
     773                 :             /* Skip to the next Waypoint Style*/
     774              34 :             if (bSuccess == FALSE || VSIFSeekL(pGTMFile, stringSize + 24, SEEK_CUR) != 0)
     775               0 :                 return 0;
     776                 :         }
     777                 :     }
     778                 :     /* We've found the first track. Return the offset*/
     779               8 :     return VSIFTellL(pGTMFile);
     780                 : }
     781                 : 
     782               8 : vsi_l_offset GTM::findFirstTrackOffset()
     783                 : {
     784               8 :     if (firstTrackpointOffset == 0)
     785                 :     {
     786               0 :         firstTrackpointOffset = findFirstTrackpointOffset();
     787               0 :         if (firstTrackpointOffset == 0)
     788               0 :             return 0;
     789                 :     }
     790                 :     /* First track offset is the first trackpoint offset plus number of
     791                 :        trackpoints time size of a trackpoint*/
     792               8 :     return (vsi_l_offset) (firstTrackpointOffset + ntcks * 25);
     793                 : }
     794                 : 
     795              70 : bool GTM::readTrackPoints(double& latitude, double& longitude, GIntBig& datetime,
     796                 :                           unsigned char& start, float& altitude) {
     797                 :     /* Point to the actual trackpoint offset */
     798              70 :     if ( VSIFSeekL(pGTMFile, actualTrackpointOffset, SEEK_SET) != 0)
     799               0 :         return FALSE;
     800                 : 
     801                 :     /* Read latitude */
     802              70 :     latitude = readDouble(pGTMFile);
     803                 :   
     804                 :     /* Read longitude */
     805              70 :     longitude = readDouble(pGTMFile);
     806                 : 
     807                 :     /* Read trackpoint date */
     808              70 :     datetime = readInt(pGTMFile);
     809              70 :     if (datetime != 0)
     810               0 :         datetime += GTM_EPOCH;
     811                 :     
     812                 :     /* Read start flag */
     813              70 :     if ( !readFile( &start, 1, 1 ) )
     814               0 :         return FALSE;
     815                 :         
     816                 :     /* Read altitude */
     817              70 :     altitude = readFloat(pGTMFile);
     818                 : 
     819              70 :     ++trackpointFetched;
     820              70 :     if (trackpointFetched < ntcks)
     821                 :     {
     822              66 :         actualTrackpointOffset += 8 + 8 + 4 + 1 + 4;
     823                 :     }
     824              70 :     return TRUE;
     825                 : }
     826                 : 
     827             112 : bool GTM::readFile(void* pBuffer, size_t nSize, size_t nCount)
     828                 : {
     829                 :     size_t nRead;
     830             112 :     nRead = VSIFReadL( pBuffer, nSize, nCount, pGTMFile );
     831             112 :     if (nRead <= 0)
     832                 :     {
     833               0 :         VSIFCloseL( pGTMFile );
     834               0 :         pGTMFile = NULL;
     835               0 :         return FALSE;
     836                 :     }
     837             112 :     return TRUE;
     838            4029 : }
     839                 : 
     840                 : 
     841                 : 

Generated by: LCOV version 1.7