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: 2011-12-18 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              30 : void appendDouble(void* pBuffer, double val)
      36                 : {
      37                 :     CPL_LSBPTR64(&val);
      38              30 :     memcpy(pBuffer, &val, 8);
      39              30 : }
      40                 : 
      41              23 : void appendFloat(void* pBuffer, float val)
      42                 : {
      43                 :     CPL_LSBPTR32(&val)
      44              23 :     memcpy(pBuffer, &val, 4);
      45              23 : }
      46                 : 
      47             104 : void appendInt(void* pBuffer, int val)
      48                 : {
      49                 :     CPL_LSBPTR32(&val)
      50             104 :     memcpy(pBuffer, &val, 4);
      51             104 : }
      52                 : 
      53              66 : void appendUChar(void* pBuffer, unsigned char val)
      54                 : {
      55              66 :     memcpy(pBuffer, &val, 1);
      56              66 : }
      57                 : 
      58              60 : void appendUShort(void* pBuffer, unsigned short val)
      59                 : {
      60                 :     CPL_LSBPTR16(&val)
      61              60 :     memcpy(pBuffer, &val, 2);
      62              60 : }
      63                 : 
      64               0 : void writeUChar(VSILFILE* fp, unsigned char val)
      65                 : {
      66               0 :     VSIFWriteL(&val, 1, 1, fp);
      67               0 : }
      68                 : 
      69               8 : void writeDouble(VSILFILE* fp, double val)
      70                 : {
      71                 :     CPL_LSBPTR64(&val)
      72               8 :     VSIFWriteL(&val, 1, 8, fp);
      73               8 : }
      74                 : 
      75              84 : static double readDouble(VSILFILE* fp)
      76                 : {
      77                 :     double val;
      78              84 :     VSIFReadL( &val, 1, 8, fp );
      79                 :     CPL_LSBPTR64(&val)
      80              84 :     return val;
      81                 : }
      82                 : 
      83              42 : static float readFloat(VSILFILE* fp)
      84                 : {
      85                 :     float val;
      86              42 :     VSIFReadL( &val, 1, 4, fp );
      87                 :     CPL_LSBPTR32(&val)
      88              42 :     return val;
      89                 : }
      90                 : 
      91              73 : static int readInt(VSILFILE* fp)
      92                 : {
      93                 :     int val;
      94              73 :     VSIFReadL( &val, 1, 4, fp );
      95                 :     CPL_LSBPTR32(&val)
      96              73 :     return val;
      97                 : }
      98                 : 
      99              14 : static unsigned char readUChar(VSILFILE* fp)
     100                 : {
     101                 :     unsigned char val;
     102              14 :     VSIFReadL( &val, 1, 1, fp );
     103              14 :     return val;
     104                 : }
     105                 : 
     106              72 : static unsigned short readUShort(VSILFILE* fp, int *pbSuccess = NULL)
     107                 : {
     108                 :     unsigned short val;
     109              72 :     if (VSIFReadL( &val, 1, 2, fp ) != 2)
     110                 :     {
     111               0 :         if (pbSuccess) *pbSuccess = FALSE;
     112               0 :         return 0;
     113                 :     }
     114              72 :     if (pbSuccess) *pbSuccess = TRUE;
     115                 :     CPL_LSBPTR16(&val)
     116              72 :     return val;
     117                 : }
     118                 : 
     119              12 : void writeFloat(VSILFILE* fp, float val)
     120                 : {
     121                 :     CPL_LSBPTR32(&val)
     122              12 :     VSIFWriteL(&val, 1, 4, fp);
     123              12 : }
     124                 : 
     125               9 : void writeInt(VSILFILE* fp, int val)
     126                 : {
     127                 :     CPL_LSBPTR32(&val)
     128               9 :     VSIFWriteL(&val, 1, 4, fp);
     129               9 : }
     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               7 : 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               7 :     this->latitude = latitude;
     150               7 :     this->longitude = longitude;
     151               7 :     this->altitude = altitude;
     152               7 :     this->name = CPLStrdup(name);
     153               7 :     this->comment = CPLStrdup(comment);
     154               7 :     this->icon = icon;
     155               7 :     this->wptdate = wptdate;
     156               7 : }
     157                 : 
     158               7 : Waypoint::~Waypoint()
     159                 : {
     160               7 :     CPLFree(name);
     161               7 :     CPLFree(comment);
     162               7 : }
     163                 : 
     164               7 : double Waypoint::getLatitude() 
     165                 : {
     166               7 :     return latitude;
     167                 : }
     168                 : 
     169               7 : double Waypoint::getLongitude()
     170                 : {
     171               7 :     return longitude;
     172                 : }
     173                 : 
     174               7 : double Waypoint::getAltitude()
     175                 : {
     176               7 :     return altitude;
     177                 : }
     178                 : 
     179               7 : const char* Waypoint::getName()
     180                 : {
     181               7 :     return name;
     182                 : }
     183                 : 
     184               7 : const char* Waypoint::getComment()
     185                 : {
     186               7 :     return comment;
     187                 : }
     188                 : 
     189               7 : int Waypoint::getIcon()
     190                 : {
     191               7 :     return icon;
     192                 : }
     193                 : 
     194               7 : GIntBig Waypoint::getDate()
     195                 : {
     196               7 :     return wptdate;
     197                 : }
     198                 : 
     199                 : /************************************************************************/
     200                 : /*               Implementation of Track Function Members               */
     201                 : /************************************************************************/
     202               7 : Track::Track(const char* pszName,
     203                 :              unsigned char type,
     204                 :              int color)
     205                 : {
     206               7 :     this->pszName = CPLStrdup(pszName);
     207               7 :     this->type = type;
     208               7 :     this->color = color;
     209               7 :     nPoints = 0;
     210               7 :     pasTrackPoints = NULL;
     211               7 : }
     212                 : 
     213               7 : Track::~Track()
     214                 : {
     215               7 :     CPLFree(pszName);
     216               7 :     pszName = NULL;
     217               7 :     CPLFree(pasTrackPoints);
     218               7 : }
     219                 : 
     220               7 : const char* Track::getName() {
     221               7 :     return pszName;
     222                 : }
     223                 : 
     224               7 : unsigned char Track::getType()
     225                 : {
     226               7 :     return type;
     227                 : }
     228                 : 
     229                 : 
     230               7 : int Track::getColor()
     231                 : {
     232               7 :     return color;
     233                 : }
     234                 : 
     235              30 : void Track::addPoint(double x, double y, GIntBig datetime, double altitude)
     236                 : {
     237                 :     pasTrackPoints = (TrackPoint*)
     238              30 :         CPLRealloc(pasTrackPoints, (nPoints + 1) * sizeof(TrackPoint));
     239              30 :     pasTrackPoints[nPoints].x = x;
     240              30 :     pasTrackPoints[nPoints].y = y;
     241              30 :     pasTrackPoints[nPoints].datetime = datetime;
     242              30 :     pasTrackPoints[nPoints].altitude = altitude;
     243              30 :     nPoints ++;
     244              30 : }
     245                 : 
     246              37 : int Track::getNumPoints()
     247                 : {
     248              37 :     return nPoints;
     249                 : }
     250                 : 
     251              30 : const TrackPoint* Track::getPoint(int pointNum)
     252                 : {
     253              30 :     if (pointNum >=0 && pointNum < nPoints)
     254              30 :         return &pasTrackPoints[pointNum];
     255                 :     else
     256               0 :         return NULL;
     257                 : }
     258                 : 
     259                 : 
     260                 : /************************************************************************/
     261                 : /*                Implementation of GTM Function Members                */
     262                 : /************************************************************************/
     263              81 : GTM::GTM()
     264                 : {
     265              81 :     pGTMFile = NULL;
     266              81 :     pszFilename = NULL;
     267                 : 
     268              81 :     nwptstyles = 0;
     269              81 :     nwpts = 0;
     270              81 :     ntcks = 0;
     271              81 :     n_tk = 0;
     272              81 :     n_maps = 0;
     273              81 :     headerSize = 0;
     274                 : 
     275              81 :     firstWaypointOffset = 0;
     276              81 :     actualWaypointOffset = 0;
     277              81 :     waypointFetched = 0;
     278                 :   
     279              81 :     firstTrackpointOffset = 0;
     280              81 :     actualTrackpointOffset = 0;
     281              81 :     trackpointFetched = 0;
     282                 : 
     283              81 :     firstTrackOffset = 0;
     284              81 :     actualTrackOffset = 0;
     285              81 :     trackFetched = 0;
     286              81 : }
     287                 : 
     288              81 : GTM::~GTM()
     289                 : {
     290              81 :     CPLFree(pszFilename);
     291              81 :     if (pGTMFile != NULL)
     292                 :     {
     293              44 :         VSIFCloseL(pGTMFile);
     294              44 :         pGTMFile = NULL;
     295                 :     }
     296              81 : }
     297                 : 
     298              81 : bool GTM::Open(const char* pszFilename)
     299                 : {
     300                 : 
     301              81 :     if (pGTMFile != NULL)
     302               0 :         VSIFCloseL(pGTMFile);
     303                 :         
     304              81 :     CPLFree(this->pszFilename);
     305              81 :     this->pszFilename = CPLStrdup(pszFilename);
     306                 : 
     307              81 :     pGTMFile = VSIFOpenL( pszFilename, "r" );
     308              81 :     if (pGTMFile == NULL)
     309                 :     {
     310              37 :         return FALSE;
     311                 :     }
     312              44 :     return TRUE;
     313                 : }
     314                 : 
     315                 : 
     316              44 : 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              44 :     size_t nRead = VSIFReadL( buffer, 1, sizeof(buffer)-1, pGTMFile );
     330              44 :     if (nRead <= 0)
     331                 :     {
     332               0 :         VSIFCloseL( pGTMFile );
     333               0 :         pGTMFile = NULL;
     334               0 :         return FALSE;
     335                 :     }
     336              44 :     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              44 :     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              44 :     version = CPL_LSBINT16PTR(buffer);
     370                 :     /*Skip string length */
     371              44 :     szHeader = buffer + 2;
     372              44 :     if (version == 211 && strcmp(szHeader, "TrackMaker") == 0 )
     373                 :     {
     374               4 :         return TRUE;
     375                 :     }
     376              40 :     return FALSE;
     377                 : }
     378                 : 
     379               4 : bool GTM::readHeaderNumbers()
     380                 : {
     381               4 :     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               4 :     if (VSIFSeekL(pGTMFile, NWPTSTYLES_OFFSET, SEEK_SET) != 0)
     393               0 :         return FALSE;
     394                 :     /* Read nwptstyles */
     395               4 :     nwptstyles = readInt(pGTMFile);
     396               4 :     if (nwptstyles < 0)
     397               0 :         return FALSE;
     398                 : 
     399                 :     /* Read Number of Waypoints */
     400                 :     /* Seek file */
     401               4 :     if ( VSIFSeekL(pGTMFile, NWPTS_OFFSET, SEEK_SET) != 0)
     402               0 :         return FALSE;
     403                 :     /* Read nwpts */
     404               4 :     nwpts = readInt(pGTMFile);
     405               4 :     if (nwpts < 0)
     406               0 :         return FALSE;
     407                 : 
     408                 :     /* Read Number of Trackpoints */
     409               4 :     ntcks = readInt(pGTMFile);
     410               4 :     if (ntcks < 0)
     411               0 :         return FALSE;
     412                 : 
     413                 :     /* Read Number of images */
     414                 :     /* Seek file */
     415               4 :     if ( VSIFSeekL(pGTMFile, NMAPS_OFFSET, SEEK_SET) != 0)
     416               0 :         return FALSE;
     417                 :     /* read n_maps */
     418               4 :     n_maps = readInt(pGTMFile);
     419               4 :     if (n_maps < 0)
     420               0 :         return FALSE;
     421                 : 
     422                 :     /* Read Number of Tracks */
     423               4 :     n_tk = readInt(pGTMFile);
     424               4 :     if (n_tk < 0)
     425               0 :         return FALSE;
     426                 : 
     427                 :     /* Figure out the header size */
     428               4 :     headerSize = 99; // Constant size plus size of strings
     429                 :     unsigned short stringSize;
     430                 : 
     431                 :     /* Read gradfont string size */
     432               4 :     if ( VSIFSeekL(pGTMFile, 99, SEEK_SET) != 0)
     433               0 :         return FALSE;
     434               4 :     stringSize = readUShort(pGTMFile);
     435               4 :     headerSize += stringSize + 2; // String + size field
     436                 : 
     437                 :     /* Read labelfont string size */
     438               4 :     if ( VSIFSeekL(pGTMFile, stringSize, SEEK_CUR) != 0)
     439               0 :         return FALSE;
     440               4 :     stringSize = readUShort(pGTMFile);
     441               4 :     headerSize += stringSize + 2; // String + size field
     442                 : 
     443                 : 
     444                 :     /* Read userfont string size */
     445               4 :     if ( VSIFSeekL(pGTMFile, stringSize, SEEK_CUR) != 0)
     446               0 :         return FALSE;
     447               4 :     stringSize = readUShort(pGTMFile);
     448               4 :     headerSize += stringSize + 2; // String + size field
     449                 : 
     450                 :     /* Read newdatum string size */
     451               4 :     if ( VSIFSeekL(pGTMFile, stringSize, SEEK_CUR) != 0)
     452               0 :         return FALSE;
     453               4 :     stringSize = readUShort(pGTMFile);
     454               4 :     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               4 :     if ( VSIFSeekL(pGTMFile, headerSize + 34, SEEK_SET) != 0)
     463               0 :         return FALSE;
     464               4 :     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               4 :     firstWaypointOffset = findFirstWaypointOffset();
     474               4 :     if (firstWaypointOffset == 0)
     475               0 :         return FALSE;
     476               4 :     actualWaypointOffset = firstWaypointOffset;
     477                 :     /* Trackpoints */
     478               4 :     firstTrackpointOffset = findFirstTrackpointOffset();
     479               4 :     if (firstTrackpointOffset == 0)
     480               0 :         return FALSE;
     481               4 :     actualTrackpointOffset = firstTrackpointOffset;
     482                 : 
     483                 :     /* Tracks */
     484               4 :     firstTrackOffset = findFirstTrackOffset();
     485               4 :     if (firstTrackOffset == 0)
     486               0 :         return FALSE;
     487               4 :     actualTrackOffset = firstTrackOffset;
     488                 : 
     489               4 :     return TRUE;
     490                 : }
     491                 : 
     492                 : /************************************************************************/
     493                 : /*                        Waypoint control functions                    */
     494                 : /************************************************************************/
     495               6 : int GTM::getNWpts()
     496                 : {
     497               6 :     return nwpts;
     498                 : }
     499                 : 
     500               7 : bool GTM::hasNextWaypoint()
     501                 : {
     502               7 :     return waypointFetched < nwpts;
     503                 : }
     504                 : 
     505               0 : void GTM::rewindWaypoint() 
     506                 : {
     507               0 :     actualWaypointOffset = firstWaypointOffset;
     508               0 :     waypointFetched = 0;
     509               0 : }
     510                 : 
     511               7 : 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               7 :     if ( VSIFSeekL(pGTMFile, actualWaypointOffset, SEEK_SET) != 0)
     525               0 :         return NULL;
     526                 : 
     527               7 :     latitude = readDouble(pGTMFile);
     528               7 :     longitude = readDouble(pGTMFile);
     529                 : 
     530               7 :     if ( !readFile( name, 1, 10 ) )
     531               0 :         return NULL;
     532                 :     /* Trim string name */
     533              33 :     for (i = 9; i >= 0; --i)
     534                 :     {
     535              33 :         if (name[i] != ' ')
     536                 :         {
     537               7 :             name[i+1] = '\0';
     538               7 :             break;
     539                 :         }
     540                 :     }
     541               7 :     if (i < 0)
     542               0 :         name[0] = '\0';
     543                 : 
     544                 :     /* Read String Length */
     545               7 :     stringSize = readUShort(pGTMFile);
     546                 :     /* Read Comment String */
     547               7 :     comment = (char*) VSIMalloc2(sizeof(char), stringSize+1);
     548               7 :     if ( stringSize != 0 && !readFile( comment, 1, sizeof(char)*stringSize ) )
     549                 :     {
     550               0 :         CPLFree(comment);
     551               0 :         return NULL;
     552                 :     }
     553               7 :     comment[stringSize] = '\0';
     554                 : 
     555                 :     /* Read Icon */
     556               7 :     icon = readUShort(pGTMFile);
     557                 :     
     558                 :     /* Display number */
     559               7 :     readUChar(pGTMFile);
     560                 :     
     561                 :     /* Waypoint date */
     562                 :     
     563               7 :     wptdate = readInt(pGTMFile);
     564               7 :     if (wptdate != 0)
     565               3 :         wptdate += GTM_EPOCH;
     566                 :     
     567                 :     /* Rotation text angle */
     568               7 :     readUShort(pGTMFile);
     569                 :     
     570                 :     /* Altitude */
     571               7 :     altitude = readFloat(pGTMFile);
     572                 :   
     573                 :     Waypoint* poWaypoint = new Waypoint(latitude, longitude, altitude,
     574               7 :                                         name, comment, (int) icon, wptdate);
     575                 : 
     576                 : 
     577                 :     /* Set actual waypoint offset to the next it there is one */
     578               7 :     ++waypointFetched;
     579               7 :     if (waypointFetched < nwpts)
     580                 :     {
     581               3 :         actualWaypointOffset += 8 + 8 + 10 + 2 + stringSize + 2 + 1 + 4 + 2 + 4 + 2;
     582                 :     }
     583                 : 
     584               7 :     CPLFree(comment);
     585               7 :     return poWaypoint;
     586                 : }
     587                 : 
     588                 : 
     589                 : /************************************************************************/
     590                 : /*                        Track control functions                    */
     591                 : /************************************************************************/
     592               6 : int GTM::getNTracks()
     593                 : {
     594               6 :     return n_tk;
     595                 : }
     596                 : 
     597               7 : bool GTM::hasNextTrack()
     598                 : {
     599               7 :     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               7 : 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               7 :     if ( VSIFSeekL(pGTMFile, actualTrackOffset, SEEK_SET) != 0)
     621               0 :         return NULL;
     622                 : 
     623                 : 
     624                 :     /* Read string length */
     625               7 :     stringSize = readUShort(pGTMFile);
     626                 :     /* Read name string */
     627               7 :     pszName = (char*) VSIMalloc2(sizeof(char), stringSize+1);
     628               7 :     if ( stringSize != 0 && !readFile( pszName, 1, sizeof(char) * stringSize ) )
     629                 :     {
     630               0 :         CPLFree(pszName);
     631               0 :         return NULL;
     632                 :     }
     633               7 :     pszName[stringSize] = '\0';
     634                 : 
     635                 :     /* Read type */
     636               7 :     type = readUChar(pGTMFile);
     637                 :   
     638                 :     /* Read color */
     639               7 :     color = readInt(pGTMFile);
     640                 :     
     641               7 :     Track* poTrack = new Track(pszName, type, color);
     642                 : 
     643               7 :     CPLFree(pszName);
     644                 :     /* Adjust actual Track offset */
     645               7 :     actualTrackOffset = VSIFTellL(pGTMFile) + 7;
     646               7 :     ++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               7 :     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               7 :     if (start != 1)
     662                 :     {
     663               0 :         delete poTrack;
     664               0 :         return NULL;
     665                 :     }
     666               7 :     poTrack->addPoint(longitude, latitude, datetime, altitude);
     667                 :   
     668              28 :     do
     669                 :     {
     670                 :         /* NOTE: Parameters are passed by reference */
     671              28 :         if ( !readTrackPoints(latitude, longitude, datetime, start, altitude) )
     672                 :         {
     673               0 :             delete poTrack;
     674               0 :             return NULL;
     675                 :         }
     676              28 :         if (start == 0)
     677              23 :             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               7 :     if (trackpointFetched < ntcks)
     682                 :     {
     683               5 :         actualTrackpointOffset -= 25;
     684               5 :         --trackpointFetched;
     685                 :     }
     686                 : 
     687               7 :     return poTrack;
     688                 : }
     689                 : 
     690                 : 
     691                 : 
     692                 : /************************************************************************/
     693                 : /*                        Private Methods Implementation                */
     694                 : /************************************************************************/
     695               4 : vsi_l_offset GTM::findFirstWaypointOffset()
     696                 : {
     697                 :     /* Skip header and datum */
     698               4 :     if ( VSIFSeekL(pGTMFile, headerSize + DATUM_SIZE, SEEK_SET) != 0)
     699               0 :         return 0;
     700                 :   
     701                 :     /* Skip images */
     702                 :     unsigned short stringSize;
     703               6 :     for (int i = 0; i < n_maps; ++i)
     704                 :     {
     705                 :         /* Read image name string size */
     706               2 :         stringSize = readUShort(pGTMFile);
     707                 : 
     708                 :         /* skip image name string */
     709               2 :         if ( VSIFSeekL(pGTMFile, stringSize, SEEK_CUR) != 0)
     710               0 :             return 0;
     711                 : 
     712                 :         /* read image comment string size */
     713               2 :         stringSize = readUShort(pGTMFile);
     714                 : 
     715                 :         /* skip image comment string */
     716               2 :         if ( VSIFSeekL(pGTMFile, stringSize, SEEK_CUR) != 0)
     717               0 :             return 0;
     718                 :     
     719                 :         /* skip the others image parameters */
     720               2 :         if ( VSIFSeekL(pGTMFile, 30, SEEK_CUR) != 0)
     721               0 :             return 0;
     722                 :     }
     723               4 :     return VSIFTellL(pGTMFile);
     724                 : }
     725                 : 
     726                 : 
     727               4 : vsi_l_offset GTM::findFirstTrackpointOffset()
     728                 : {
     729               4 :     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               4 :     if (VSIFSeekL(pGTMFile, firstWaypointOffset, SEEK_SET) != 0)
     741               0 :         return 0;
     742                 :   
     743                 :     unsigned short stringSize;
     744                 :     int bSuccess;
     745                 :     /* Skip waypoints */
     746              11 :     for (int i = 0; i < nwpts; ++i)
     747                 :     {
     748                 :         /* Seek file to the string size comment field */
     749               7 :         if (VSIFSeekL(pGTMFile, 26, SEEK_CUR) != 0)
     750               0 :             return 0;
     751                 :         /* Read string comment size */
     752               7 :         stringSize = readUShort(pGTMFile, &bSuccess);
     753                 :     
     754                 :         /* Skip to the next Waypoint */
     755               7 :         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               4 :     if (nwpts != 0)
     763                 :     {
     764              21 :         for (int i = 0; i < nwptstyles; ++i)
     765                 :         {
     766                 :             /* Seek file to the string size facename field */
     767              17 :             if (VSIFSeekL(pGTMFile, 4, SEEK_CUR) != 0)
     768               0 :                 return 0;
     769                 : 
     770                 :             /* Read string facename size */
     771              17 :             stringSize = readUShort(pGTMFile, &bSuccess);
     772                 : 
     773                 :             /* Skip to the next Waypoint Style*/
     774              17 :             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               4 :     return VSIFTellL(pGTMFile);
     780                 : }
     781                 : 
     782               4 : vsi_l_offset GTM::findFirstTrackOffset()
     783                 : {
     784               4 :     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               4 :     return (vsi_l_offset) (firstTrackpointOffset + ntcks * 25);
     793                 : }
     794                 : 
     795              35 : bool GTM::readTrackPoints(double& latitude, double& longitude, GIntBig& datetime,
     796                 :                           unsigned char& start, float& altitude) {
     797                 :     /* Point to the actual trackpoint offset */
     798              35 :     if ( VSIFSeekL(pGTMFile, actualTrackpointOffset, SEEK_SET) != 0)
     799               0 :         return FALSE;
     800                 : 
     801                 :     /* Read latitude */
     802              35 :     latitude = readDouble(pGTMFile);
     803                 :   
     804                 :     /* Read longitude */
     805              35 :     longitude = readDouble(pGTMFile);
     806                 : 
     807                 :     /* Read trackpoint date */
     808              35 :     datetime = readInt(pGTMFile);
     809              35 :     if (datetime != 0)
     810               0 :         datetime += GTM_EPOCH;
     811                 :     
     812                 :     /* Read start flag */
     813              35 :     if ( !readFile( &start, 1, 1 ) )
     814               0 :         return FALSE;
     815                 :         
     816                 :     /* Read altitude */
     817              35 :     altitude = readFloat(pGTMFile);
     818                 : 
     819              35 :     ++trackpointFetched;
     820              35 :     if (trackpointFetched < ntcks)
     821                 :     {
     822              33 :         actualTrackpointOffset += 8 + 8 + 4 + 1 + 4;
     823                 :     }
     824              35 :     return TRUE;
     825                 : }
     826                 : 
     827              56 : bool GTM::readFile(void* pBuffer, size_t nSize, size_t nCount)
     828                 : {
     829                 :     size_t nRead;
     830              56 :     nRead = VSIFReadL( pBuffer, nSize, nCount, pGTMFile );
     831              56 :     if (nRead <= 0)
     832                 :     {
     833               0 :         VSIFCloseL( pGTMFile );
     834               0 :         pGTMFile = NULL;
     835               0 :         return FALSE;
     836                 :     }
     837              56 :     return TRUE;
     838            1947 : }
     839                 : 
     840                 : 
     841                 : 

Generated by: LCOV version 1.7