LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/gtm - gtm.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 370 281 75.9 %
Date: 2010-01-09 Functions: 53 48 90.6 %

       1                 : /******************************************************************************
       2                 :  * $Id: gtm.cpp 17612 2009-09-03 19:18:45Z 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              22 : void appendFloat(void* pBuffer, float val)
      42                 : {
      43                 :     CPL_LSBPTR32(&val)
      44              22 :     memcpy(pBuffer, &val, 4);
      45              22 : }
      46                 : 
      47              76 : void appendInt(void* pBuffer, int val)
      48                 : {
      49                 :     CPL_LSBPTR32(&val)
      50              76 :     memcpy(pBuffer, &val, 4);
      51              76 : }
      52                 : 
      53              52 : void appendUChar(void* pBuffer, unsigned char val)
      54                 : {
      55              52 :     memcpy(pBuffer, &val, 1);
      56              52 : }
      57                 : 
      58              44 : void appendUShort(void* pBuffer, unsigned short val)
      59                 : {
      60                 :     CPL_LSBPTR16(&val)
      61              44 :     memcpy(pBuffer, &val, 2);
      62              44 : }
      63                 : 
      64               0 : void writeUChar(FILE* fp, unsigned char val)
      65                 : {
      66               0 :     VSIFWriteL(&val, 1, 1, fp);
      67               0 : }
      68                 : 
      69               6 : void writeDouble(FILE* fp, double val)
      70                 : {
      71                 :     CPL_LSBPTR64(&val)
      72               6 :     VSIFWriteL(&val, 1, 8, fp);
      73               6 : }
      74                 : 
      75              82 : static double readDouble(FILE* fp)
      76                 : {
      77                 :     double val;
      78              82 :     VSIFReadL( &val, 1, 8, fp );
      79                 :     CPL_LSBPTR64(&val)
      80              82 :     return val;
      81                 : }
      82                 : 
      83              41 : static float readFloat(FILE* fp)
      84                 : {
      85                 :     float val;
      86              41 :     VSIFReadL( &val, 1, 4, fp );
      87                 :     CPL_LSBPTR32(&val)
      88              41 :     return val;
      89                 : }
      90                 : 
      91              66 : static int readInt(FILE* fp)
      92                 : {
      93                 :     int val;
      94              66 :     VSIFReadL( &val, 1, 4, fp );
      95                 :     CPL_LSBPTR32(&val)
      96              66 :     return val;
      97                 : }
      98                 : 
      99              13 : static unsigned char readUChar(FILE* fp)
     100                 : {
     101                 :     unsigned char val;
     102              13 :     VSIFReadL( &val, 1, 1, fp );
     103              13 :     return val;
     104                 : }
     105                 : 
     106              60 : static unsigned short readUShort(FILE* fp, int *pbSuccess = NULL)
     107                 : {
     108                 :     unsigned short val;
     109              60 :     if (VSIFReadL( &val, 1, 2, fp ) != 2)
     110                 :     {
     111               0 :         if (pbSuccess) *pbSuccess = FALSE;
     112               0 :         return 0;
     113                 :     }
     114              60 :     if (pbSuccess) *pbSuccess = TRUE;
     115                 :     CPL_LSBPTR16(&val)
     116              60 :     return val;
     117                 : }
     118                 : 
     119               8 : void writeFloat(FILE* fp, float val)
     120                 : {
     121                 :     CPL_LSBPTR32(&val)
     122               8 :     VSIFWriteL(&val, 1, 4, fp);
     123               8 : }
     124                 : 
     125               6 : void writeInt(FILE* fp, int val)
     126                 : {
     127                 :     CPL_LSBPTR32(&val)
     128               6 :     VSIFWriteL(&val, 1, 4, fp);
     129               6 : }
     130                 : 
     131               0 : void writeUShort(FILE* 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               6 : 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               6 :     this->latitude = latitude;
     150               6 :     this->longitude = longitude;
     151               6 :     this->altitude = altitude;
     152               6 :     this->name = CPLStrdup(name);
     153               6 :     this->comment = CPLStrdup(comment);
     154               6 :     this->icon = icon;
     155               6 :     this->wptdate = wptdate;
     156               6 : }
     157                 : 
     158               6 : Waypoint::~Waypoint()
     159                 : {
     160               6 :     CPLFree(name);
     161               6 :     CPLFree(comment);
     162               6 : }
     163                 : 
     164               6 : double Waypoint::getLatitude() 
     165                 : {
     166               6 :     return latitude;
     167                 : }
     168                 : 
     169               6 : double Waypoint::getLongitude()
     170                 : {
     171               6 :     return longitude;
     172                 : }
     173                 : 
     174               6 : double Waypoint::getAltitude()
     175                 : {
     176               6 :     return altitude;
     177                 : }
     178                 : 
     179               6 : const char* Waypoint::getName()
     180                 : {
     181               6 :     return name;
     182                 : }
     183                 : 
     184               6 : const char* Waypoint::getComment()
     185                 : {
     186               6 :     return comment;
     187                 : }
     188                 : 
     189               6 : int Waypoint::getIcon()
     190                 : {
     191               6 :     return icon;
     192                 : }
     193                 : 
     194               6 : GIntBig Waypoint::getDate()
     195                 : {
     196               6 :     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               6 : GTM::GTM()
     264                 : {
     265               6 :     pGTMFile = NULL;
     266               6 :     pszFilename = NULL;
     267                 : 
     268               6 :     nwptstyles = 0;
     269               6 :     nwpts = 0;
     270               6 :     ntcks = 0;
     271               6 :     n_tk = 0;
     272               6 :     n_maps = 0;
     273               6 :     headerSize = 0;
     274                 : 
     275               6 :     firstWaypointOffset = 0;
     276               6 :     actualWaypointOffset = 0;
     277               6 :     waypointFetched = 0;
     278                 :   
     279               6 :     firstTrackpointOffset = 0;
     280               6 :     actualTrackpointOffset = 0;
     281               6 :     trackpointFetched = 0;
     282                 : 
     283               6 :     firstTrackOffset = 0;
     284               6 :     actualTrackOffset = 0;
     285               6 :     trackFetched = 0;
     286               6 : }
     287                 : 
     288               6 : GTM::~GTM()
     289                 : {
     290               6 :     CPLFree(pszFilename);
     291               6 :     if (pGTMFile != NULL)
     292                 :     {
     293               4 :         VSIFCloseL(pGTMFile);
     294               4 :         pGTMFile = NULL;
     295                 :     }
     296               6 : }
     297                 : 
     298               6 : bool GTM::Open(const char* pszFilename)
     299                 : {
     300                 : 
     301               6 :     if (pGTMFile != NULL)
     302               0 :         VSIFCloseL(pGTMFile);
     303                 :         
     304               6 :     CPLFree(this->pszFilename);
     305               6 :     this->pszFilename = CPLStrdup(pszFilename);
     306                 : 
     307               6 :     pGTMFile = VSIFOpenL( pszFilename, "r" );
     308               6 :     if (pGTMFile == NULL)
     309                 :     {
     310               2 :         return FALSE;
     311                 :     }
     312               4 :     return TRUE;
     313                 : }
     314                 : 
     315                 : 
     316               4 : 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               4 :     size_t nRead = VSIFReadL( buffer, 1, sizeof(buffer)-1, pGTMFile );
     330               4 :     if (nRead <= 0)
     331                 :     {
     332               0 :         VSIFCloseL( pGTMFile );
     333               0 :         pGTMFile = NULL;
     334               0 :         return FALSE;
     335                 :     }
     336               4 :     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               4 :     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 :         FILE* fp = VSIFOpenL(pszGZIPFileName, "rb");
     349               0 :         if (fp)
     350                 :         {
     351               0 :             FILE* pGTMFileOri = pGTMFile;
     352               0 :             pGTMFile = fp;
     353               0 :             if (isValid())
     354                 :             {
     355               0 :                 VSIFCloseL(pGTMFileOri);
     356               0 :                 return TRUE;
     357                 :             }
     358                 :             else
     359                 :             {
     360               0 :                 if (pGTMFile)
     361               0 :                     VSIFCloseL(pGTMFile);
     362               0 :                 pGTMFile = pGTMFileOri;
     363                 :             }
     364                 :         }
     365               0 :         CPLFree(pszGZIPFileName);
     366                 :     }
     367                 :     
     368               4 :     version = CPL_LSBINT16PTR(buffer);
     369                 :     /*Skip string length */
     370               4 :     szHeader = buffer + 2;
     371               4 :     if (version == 211 && strcmp(szHeader, "TrackMaker") == 0 )
     372                 :     {
     373               3 :         return TRUE;
     374                 :     }
     375               1 :     return FALSE;
     376                 : }
     377                 : 
     378               3 : bool GTM::readHeaderNumbers()
     379                 : {
     380               3 :     if (pGTMFile == NULL)
     381               0 :         return FALSE;
     382                 : 
     383                 :    
     384                 :     /* I'm supposing that the user has already checked if the file is
     385                 :        valid.  */
     386                 :     /* Also, I'm ignoring some header parameters that are unnecessary
     387                 :        for my purpose. If you want more features, implement it. :-P */
     388                 : 
     389                 :     /* Read Number of Waypoint Styles*/
     390                 :     /* Seek file */
     391               3 :     if (VSIFSeekL(pGTMFile, NWPTSTYLES_OFFSET, SEEK_SET) != 0)
     392               0 :         return FALSE;
     393                 :     /* Read nwptstyles */
     394               3 :     nwptstyles = readInt(pGTMFile);
     395               3 :     if (nwptstyles < 0)
     396               0 :         return FALSE;
     397                 : 
     398                 :     /* Read Number of Waypoints */
     399                 :     /* Seek file */
     400               3 :     if ( VSIFSeekL(pGTMFile, NWPTS_OFFSET, SEEK_SET) != 0)
     401               0 :         return FALSE;
     402                 :     /* Read nwpts */
     403               3 :     nwpts = readInt(pGTMFile);
     404               3 :     if (nwpts < 0)
     405               0 :         return FALSE;
     406                 : 
     407                 :     /* Read Number of Trackpoints */
     408               3 :     ntcks = readInt(pGTMFile);
     409               3 :     if (ntcks < 0)
     410               0 :         return FALSE;
     411                 : 
     412                 :     /* Read Number of images */
     413                 :     /* Seek file */
     414               3 :     if ( VSIFSeekL(pGTMFile, NMAPS_OFFSET, SEEK_SET) != 0)
     415               0 :         return FALSE;
     416                 :     /* read n_maps */
     417               3 :     n_maps = readInt(pGTMFile);
     418               3 :     if (n_maps < 0)
     419               0 :         return FALSE;
     420                 : 
     421                 :     /* Read Number of Tracks */
     422               3 :     n_tk = readInt(pGTMFile);
     423               3 :     if (n_tk < 0)
     424               0 :         return FALSE;
     425                 : 
     426                 :     /* Figure out the header size */
     427               3 :     headerSize = 99; // Constant size plus size of strings
     428                 :     unsigned short stringSize;
     429                 : 
     430                 :     /* Read gradfont string size */
     431               3 :     if ( VSIFSeekL(pGTMFile, 99, SEEK_SET) != 0)
     432               0 :         return FALSE;
     433               3 :     stringSize = readUShort(pGTMFile);
     434               3 :     headerSize += stringSize + 2; // String + size field
     435                 : 
     436                 :     /* Read labelfont string size */
     437               3 :     if ( VSIFSeekL(pGTMFile, stringSize, SEEK_CUR) != 0)
     438               0 :         return FALSE;
     439               3 :     stringSize = readUShort(pGTMFile);
     440               3 :     headerSize += stringSize + 2; // String + size field
     441                 : 
     442                 : 
     443                 :     /* Read userfont string size */
     444               3 :     if ( VSIFSeekL(pGTMFile, stringSize, SEEK_CUR) != 0)
     445               0 :         return FALSE;
     446               3 :     stringSize = readUShort(pGTMFile);
     447               3 :     headerSize += stringSize + 2; // String + size field
     448                 : 
     449                 :     /* Read newdatum string size */
     450               3 :     if ( VSIFSeekL(pGTMFile, stringSize, SEEK_CUR) != 0)
     451               0 :         return FALSE;
     452               3 :     stringSize = readUShort(pGTMFile);
     453               3 :     headerSize += stringSize + 2; // String + size field
     454                 : 
     455                 : 
     456                 : 
     457                 : /* -------------------------------------------------------------------- */
     458                 : /*                 Checks if it is using WGS84 datum                    */
     459                 : /* -------------------------------------------------------------------- */
     460                 :     /* Read newdatum string size */
     461               3 :     if ( VSIFSeekL(pGTMFile, headerSize + 34, SEEK_SET) != 0)
     462               0 :         return FALSE;
     463               3 :     if (readInt(pGTMFile) != 217)
     464                 :     {
     465                 :         CPLError( CE_Warning, CPLE_AppDefined,
     466                 :                   "You are attempting to open a file that is not using WGS84 datum.\n"
     467               0 :                   "Coordinates will be returned as if they were WGS84, but no reprojection will be done.");
     468                 :     }
     469                 : 
     470                 :     /* Look for the offsets */
     471                 :     /* Waypoints */
     472               3 :     firstWaypointOffset = findFirstWaypointOffset();
     473               3 :     if (firstWaypointOffset == 0)
     474               0 :         return FALSE;
     475               3 :     actualWaypointOffset = firstWaypointOffset;
     476                 :     /* Trackpoints */
     477               3 :     firstTrackpointOffset = findFirstTrackpointOffset();
     478               3 :     if (firstTrackpointOffset == 0)
     479               0 :         return FALSE;
     480               3 :     actualTrackpointOffset = firstTrackpointOffset;
     481                 : 
     482                 :     /* Tracks */
     483               3 :     firstTrackOffset = findFirstTrackOffset();
     484               3 :     if (firstTrackOffset == 0)
     485               0 :         return FALSE;
     486               3 :     actualTrackOffset = firstTrackOffset;
     487                 : 
     488               3 :     return TRUE;
     489                 : }
     490                 : 
     491                 : /************************************************************************/
     492                 : /*                        Waypoint control functions                    */
     493                 : /************************************************************************/
     494               5 : int GTM::getNWpts()
     495                 : {
     496               5 :     return nwpts;
     497                 : }
     498                 : 
     499               6 : bool GTM::hasNextWaypoint()
     500                 : {
     501               6 :     return waypointFetched < nwpts;
     502                 : }
     503                 : 
     504               0 : void GTM::rewindWaypoint() 
     505                 : {
     506               0 :     actualWaypointOffset = firstWaypointOffset;
     507               0 :     waypointFetched = 0;
     508               0 : }
     509                 : 
     510               6 : Waypoint* GTM::fetchNextWaypoint()
     511                 : {
     512                 :     unsigned short stringSize;
     513                 : 
     514                 :     double latitude, longitude;
     515                 :     char name[11];
     516                 :     char* comment;
     517                 :     unsigned short icon;
     518                 :     int i;
     519                 :     float altitude;
     520                 :     GIntBig wptdate;
     521                 : 
     522                 :     /* Point to the actual waypoint offset */
     523               6 :     if ( VSIFSeekL(pGTMFile, actualWaypointOffset, SEEK_SET) != 0)
     524               0 :         return NULL;
     525                 : 
     526               6 :     latitude = readDouble(pGTMFile);
     527               6 :     longitude = readDouble(pGTMFile);
     528                 : 
     529               6 :     if ( !readFile( name, 1, 10 ) )
     530               0 :         return NULL;
     531                 :     /* Trim string name */
     532              26 :     for (i = 9; i >= 0; --i)
     533                 :     {
     534              26 :         if (name[i] != ' ')
     535                 :         {
     536               6 :             name[i+1] = '\0';
     537               6 :             break;
     538                 :         }
     539                 :     }
     540               6 :     if (i < 0)
     541               0 :         name[0] = '\0';
     542                 : 
     543                 :     /* Read String Length */
     544               6 :     stringSize = readUShort(pGTMFile);
     545                 :     /* Read Comment String */
     546               6 :     comment = (char*) VSIMalloc2(sizeof(char), stringSize+1);
     547               6 :     if ( stringSize != 0 && !readFile( comment, 1, sizeof(char)*stringSize ) )
     548                 :     {
     549               0 :         CPLFree(comment);
     550               0 :         return NULL;
     551                 :     }
     552               6 :     comment[stringSize] = '\0';
     553                 : 
     554                 :     /* Read Icon */
     555               6 :     icon = readUShort(pGTMFile);
     556                 :     
     557                 :     /* Display number */
     558               6 :     readUChar(pGTMFile);
     559                 :     
     560                 :     /* Waypoint date */
     561                 :     
     562               6 :     wptdate = readInt(pGTMFile);
     563               6 :     if (wptdate != 0)
     564               3 :         wptdate += GTM_EPOCH;
     565                 :     
     566                 :     /* Rotation text angle */
     567               6 :     readUShort(pGTMFile);
     568                 :     
     569                 :     /* Altitude */
     570               6 :     altitude = readFloat(pGTMFile);
     571                 :   
     572                 :     Waypoint* poWaypoint = new Waypoint(latitude, longitude, altitude,
     573               6 :                                         name, comment, (int) icon, wptdate);
     574                 : 
     575                 : 
     576                 :     /* Set actual waypoint offset to the next it there is one */
     577               6 :     ++waypointFetched;
     578               6 :     if (waypointFetched < nwpts)
     579                 :     {
     580               3 :         actualWaypointOffset += 8 + 8 + 10 + 2 + stringSize + 2 + 1 + 4 + 2 + 4 + 2;
     581                 :     }
     582                 : 
     583               6 :     CPLFree(comment);
     584               6 :     return poWaypoint;
     585                 : }
     586                 : 
     587                 : 
     588                 : /************************************************************************/
     589                 : /*                        Track control functions                    */
     590                 : /************************************************************************/
     591               5 : int GTM::getNTracks()
     592                 : {
     593               5 :     return n_tk;
     594                 : }
     595                 : 
     596               7 : bool GTM::hasNextTrack()
     597                 : {
     598               7 :     return trackFetched < n_tk;
     599                 : }
     600                 : 
     601               0 : void GTM::rewindTrack() 
     602                 : {
     603               0 :     actualTrackpointOffset = firstTrackpointOffset;
     604               0 :     actualTrackOffset = firstTrackOffset;
     605               0 :     trackFetched = 0;
     606               0 :     trackpointFetched = 0;
     607               0 : }
     608                 : 
     609               7 : Track* GTM::fetchNextTrack()
     610                 : {
     611                 :     unsigned short stringSize;
     612                 : 
     613                 :     char* pszName;
     614                 :     unsigned char type;
     615                 :     int color;
     616                 :   
     617                 : 
     618                 :     /* Point to the actual track offset */
     619               7 :     if ( VSIFSeekL(pGTMFile, actualTrackOffset, SEEK_SET) != 0)
     620               0 :         return NULL;
     621                 : 
     622                 : 
     623                 :     /* Read string length */
     624               7 :     stringSize = readUShort(pGTMFile);
     625                 :     /* Read name string */
     626               7 :     pszName = (char*) VSIMalloc2(sizeof(char), stringSize+1);
     627               7 :     if ( stringSize != 0 && !readFile( pszName, 1, sizeof(char) * stringSize ) )
     628                 :     {
     629               0 :         CPLFree(pszName);
     630               0 :         return NULL;
     631                 :     }
     632               7 :     pszName[stringSize] = '\0';
     633                 : 
     634                 :     /* Read type */
     635               7 :     type = readUChar(pGTMFile);
     636                 :   
     637                 :     /* Read color */
     638               7 :     color = readInt(pGTMFile);
     639                 :     
     640               7 :     Track* poTrack = new Track(pszName, type, color);
     641                 : 
     642               7 :     CPLFree(pszName);
     643                 :     /* Adjust actual Track offset */
     644               7 :     actualTrackOffset = VSIFTellL(pGTMFile) + 7;
     645               7 :     ++trackFetched;
     646                 : 
     647                 :     /* Now, We read all trackpoints for this track */
     648                 :     double latitude, longitude;
     649                 :     GIntBig datetime;
     650                 :     unsigned char start;
     651                 :     float altitude;
     652                 :     /* NOTE: Parameters are passed by reference */
     653               7 :     if ( !readTrackPoints(latitude, longitude, datetime, start, altitude) )
     654                 :     {
     655               0 :         delete poTrack;
     656               0 :         return NULL;
     657                 :     }
     658                 : 
     659                 :     /* Check if it is the start, if not we have done something wrong */
     660               7 :     if (start != 1)
     661                 :     {
     662               0 :         delete poTrack;
     663               0 :         return NULL;
     664                 :     }
     665               7 :     poTrack->addPoint(longitude, latitude, datetime, altitude);
     666                 :   
     667              28 :     do
     668                 :     {
     669                 :         /* NOTE: Parameters are passed by reference */
     670              28 :         if ( !readTrackPoints(latitude, longitude, datetime, start, altitude) )
     671                 :         {
     672               0 :             delete poTrack;
     673               0 :             return NULL;
     674                 :         }
     675              28 :         if (start == 0)
     676              23 :             poTrack->addPoint(longitude, latitude, datetime, altitude);
     677                 :     } while(start == 0 && trackpointFetched < ntcks);
     678                 : 
     679                 :     /* We have read one more than necessary, so we adjust the offset */
     680               7 :     if (trackpointFetched < ntcks)
     681                 :     {
     682               5 :         actualTrackpointOffset -= 25;
     683               5 :         --trackpointFetched;
     684                 :     }
     685                 : 
     686               7 :     return poTrack;
     687                 : }
     688                 : 
     689                 : 
     690                 : 
     691                 : /************************************************************************/
     692                 : /*                        Private Methods Implementation                */
     693                 : /************************************************************************/
     694               3 : vsi_l_offset GTM::findFirstWaypointOffset()
     695                 : {
     696                 :     /* Skip header and datum */
     697               3 :     if ( VSIFSeekL(pGTMFile, headerSize + DATUM_SIZE, SEEK_SET) != 0)
     698               0 :         return 0;
     699                 :   
     700                 :     /* Skip images */
     701                 :     unsigned short stringSize;
     702               5 :     for (int i = 0; i < n_maps; ++i)
     703                 :     {
     704                 :         /* Read image name string size */
     705               2 :         stringSize = readUShort(pGTMFile);
     706                 : 
     707                 :         /* skip image name string */
     708               2 :         if ( VSIFSeekL(pGTMFile, stringSize, SEEK_CUR) != 0)
     709               0 :             return 0;
     710                 : 
     711                 :         /* read image comment string size */
     712               2 :         stringSize = readUShort(pGTMFile);
     713                 : 
     714                 :         /* skip image comment string */
     715               2 :         if ( VSIFSeekL(pGTMFile, stringSize, SEEK_CUR) != 0)
     716               0 :             return 0;
     717                 :     
     718                 :         /* skip the others image parameters */
     719               2 :         if ( VSIFSeekL(pGTMFile, 30, SEEK_CUR) != 0)
     720               0 :             return 0;
     721                 :     }
     722               3 :     return VSIFTellL(pGTMFile);
     723                 : }
     724                 : 
     725                 : 
     726               3 : vsi_l_offset GTM::findFirstTrackpointOffset()
     727                 : {
     728               3 :     if (firstWaypointOffset == 0)
     729                 :     {
     730               0 :         firstWaypointOffset = findFirstWaypointOffset();
     731               0 :         if (firstWaypointOffset == 0)
     732               0 :             return 0;
     733                 :     }
     734                 : 
     735                 :     /*---------------------------------------------*/
     736                 :     /*       We are going to skip the waypoints    */
     737                 :     /*---------------------------------------------*/
     738                 :     /* Seek file to the first Waypoint */
     739               3 :     if (VSIFSeekL(pGTMFile, firstWaypointOffset, SEEK_SET) != 0)
     740               0 :         return 0;
     741                 :   
     742                 :     unsigned short stringSize;
     743                 :     int bSuccess;
     744                 :     /* Skip waypoints */
     745               9 :     for (int i = 0; i < nwpts; ++i)
     746                 :     {
     747                 :         /* Seek file to the string size comment field */
     748               6 :         if (VSIFSeekL(pGTMFile, 26, SEEK_CUR) != 0)
     749               0 :             return 0;
     750                 :         /* Read string comment size */
     751               6 :         stringSize = readUShort(pGTMFile, &bSuccess);
     752                 :     
     753                 :         /* Skip to the next Waypoint */
     754               6 :         if (bSuccess == FALSE || VSIFSeekL(pGTMFile, stringSize + 15, SEEK_CUR) != 0)
     755               0 :             return 0;
     756                 :     }
     757                 :   
     758                 :     /* Skip waypoint styles */
     759                 :     /* If we don't have waypoints, we don't have waypoint styles, even
     760                 :        though the nwptstyles is telling the contrary. */
     761               3 :     if (nwpts != 0)
     762                 :     {
     763              16 :         for (int i = 0; i < nwptstyles; ++i)
     764                 :         {
     765                 :             /* Seek file to the string size facename field */
     766              13 :             if (VSIFSeekL(pGTMFile, 4, SEEK_CUR) != 0)
     767               0 :                 return 0;
     768                 : 
     769                 :             /* Read string facename size */
     770              13 :             stringSize = readUShort(pGTMFile, &bSuccess);
     771                 : 
     772                 :             /* Skip to the next Waypoint Style*/
     773              13 :             if (bSuccess == FALSE || VSIFSeekL(pGTMFile, stringSize + 24, SEEK_CUR) != 0)
     774               0 :                 return 0;
     775                 :         }
     776                 :     }
     777                 :     /* We've found the first track. Return the offset*/
     778               3 :     return VSIFTellL(pGTMFile);
     779                 : }
     780                 : 
     781               3 : vsi_l_offset GTM::findFirstTrackOffset()
     782                 : {
     783               3 :     if (firstTrackpointOffset == 0)
     784                 :     {
     785               0 :         firstTrackpointOffset = findFirstTrackpointOffset();
     786               0 :         if (firstTrackpointOffset == 0)
     787               0 :             return 0;
     788                 :     }
     789                 :     /* First track offset is the first trackpoint offset plus number of
     790                 :        trackpoints time size of a trackpoint*/
     791               3 :     return (vsi_l_offset) (firstTrackpointOffset + ntcks * 25);
     792                 : }
     793                 : 
     794              35 : bool GTM::readTrackPoints(double& latitude, double& longitude, GIntBig& datetime,
     795                 :                           unsigned char& start, float& altitude) {
     796                 :     /* Point to the actual trackpoint offset */
     797              35 :     if ( VSIFSeekL(pGTMFile, actualTrackpointOffset, SEEK_SET) != 0)
     798               0 :         return FALSE;
     799                 : 
     800                 :     /* Read latitude */
     801              35 :     latitude = readDouble(pGTMFile);
     802                 :   
     803                 :     /* Read longitude */
     804              35 :     longitude = readDouble(pGTMFile);
     805                 : 
     806                 :     /* Read trackpoint date */
     807              35 :     datetime = readInt(pGTMFile);
     808              35 :     if (datetime != 0)
     809               0 :         datetime += GTM_EPOCH;
     810                 :     
     811                 :     /* Read start flag */
     812              35 :     if ( !readFile( &start, 1, 1 ) )
     813               0 :         return FALSE;
     814                 :         
     815                 :     /* Read altitude */
     816              35 :     altitude = readFloat(pGTMFile);
     817                 : 
     818              35 :     ++trackpointFetched;
     819              35 :     if (trackpointFetched < ntcks)
     820                 :     {
     821              33 :         actualTrackpointOffset += 8 + 8 + 4 + 1 + 4;
     822                 :     }
     823              35 :     return TRUE;
     824                 : }
     825                 : 
     826              54 : bool GTM::readFile(void* pBuffer, size_t nSize, size_t nCount)
     827                 : {
     828                 :     size_t nRead;
     829              54 :     nRead = VSIFReadL( pBuffer, nSize, nCount, pGTMFile );
     830              54 :     if (nRead <= 0)
     831                 :     {
     832               0 :         VSIFCloseL( pGTMFile );
     833               0 :         pGTMFile = NULL;
     834               0 :         return FALSE;
     835                 :     }
     836              54 :     return TRUE;
     837            1140 : }
     838                 : 
     839                 : 
     840                 : 

Generated by: LCOV version 1.7