PostGIS  2.1.10dev-r@@SVN_REVISION@@
SHPHandle SHPAPI_CALL SHPOpenLL ( const char *  pszLayer,
const char *  pszAccess,
SAHooks psHooks 
)

Definition at line 483 of file shpopen.c.

References SHPInfo::adBoundsMax, SHPInfo::adBoundsMin, SHPInfo::bUpdated, SAHooks::Error, FALSE, SAHooks::FClose, SAHooks::FOpen, SHPInfo::fpSHP, SHPInfo::fpSHX, SAHooks::FRead, MAX, SHPInfo::nFileSize, SHPInfo::nMaxRecords, SHPInfo::nRecords, SHPInfo::nShapeType, SHPInfo::panRecOffset, SHPInfo::panRecSize, SHPInfo::sHooks, SwapWord(), and TRUE.

Referenced by SHPCreateLL(), and SHPOpen().

485 {
486  char *pszFullname, *pszBasename;
487  SHPHandle psSHP;
488 
489  uchar *pabyBuf;
490  int i;
491  double dValue;
492 
493 /* -------------------------------------------------------------------- */
494 /* Ensure the access string is one of the legal ones. We */
495 /* ensure the result string indicates binary to avoid common */
496 /* problems on Windows. */
497 /* -------------------------------------------------------------------- */
498  if( strcmp(pszAccess,"rb+") == 0 || strcmp(pszAccess,"r+b") == 0
499  || strcmp(pszAccess,"r+") == 0 )
500  pszAccess = "r+b";
501  else
502  pszAccess = "rb";
503 
504 /* -------------------------------------------------------------------- */
505 /* Establish the byte order on this machine. */
506 /* -------------------------------------------------------------------- */
507  i = 1;
508  if( *((uchar *) &i) == 1 )
509  bBigEndian = FALSE;
510  else
511  bBigEndian = TRUE;
512 
513 /* -------------------------------------------------------------------- */
514 /* Initialize the info structure. */
515 /* -------------------------------------------------------------------- */
516  psSHP = (SHPHandle) calloc(sizeof(SHPInfo),1);
517 
518  psSHP->bUpdated = FALSE;
519  memcpy( &(psSHP->sHooks), psHooks, sizeof(SAHooks) );
520 
521 /* -------------------------------------------------------------------- */
522 /* Compute the base (layer) name. If there is any extension */
523 /* on the passed in filename we will strip it off. */
524 /* -------------------------------------------------------------------- */
525  pszBasename = (char *) malloc(strlen(pszLayer)+5);
526  strcpy( pszBasename, pszLayer );
527  for( i = strlen(pszBasename)-1;
528  i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
529  && pszBasename[i] != '\\';
530  i-- ) {}
531 
532  if( pszBasename[i] == '.' )
533  pszBasename[i] = '\0';
534 
535 /* -------------------------------------------------------------------- */
536 /* Open the .shp and .shx files. Note that files pulled from */
537 /* a PC to Unix with upper case filenames won't work! */
538 /* -------------------------------------------------------------------- */
539  pszFullname = (char *) malloc(strlen(pszBasename) + 5);
540  sprintf( pszFullname, "%s.shp", pszBasename ) ;
541  psSHP->fpSHP = psSHP->sHooks.FOpen(pszFullname, pszAccess );
542  if( psSHP->fpSHP == NULL )
543  {
544  sprintf( pszFullname, "%s.SHP", pszBasename );
545  psSHP->fpSHP = psSHP->sHooks.FOpen(pszFullname, pszAccess );
546  }
547 
548  if( psSHP->fpSHP == NULL )
549  {
550  char *pszMessage = (char *) malloc(strlen(pszBasename)*2+256);
551  sprintf( pszMessage, "Unable to open %s.shp or %s.SHP.",
552  pszBasename, pszBasename );
553  psHooks->Error( pszMessage );
554  free( pszMessage );
555  free( psSHP );
556  free( pszBasename );
557  free( pszFullname );
558  return( NULL );
559  }
560 
561  sprintf( pszFullname, "%s.shx", pszBasename );
562  psSHP->fpSHX = psSHP->sHooks.FOpen(pszFullname, pszAccess );
563  if( psSHP->fpSHX == NULL )
564  {
565  sprintf( pszFullname, "%s.SHX", pszBasename );
566  psSHP->fpSHX = psSHP->sHooks.FOpen(pszFullname, pszAccess );
567  }
568 
569  if( psSHP->fpSHX == NULL )
570  {
571  char *pszMessage = (char *) malloc(strlen(pszBasename)*2+256);
572  sprintf( pszMessage, "Unable to open %s.shx or %s.SHX.",
573  pszBasename, pszBasename );
574  psHooks->Error( pszMessage );
575  free( pszMessage );
576 
577  psSHP->sHooks.FClose( psSHP->fpSHP );
578  free( psSHP );
579  free( pszBasename );
580  free( pszFullname );
581  return( NULL );
582  }
583 
584  free( pszFullname );
585  free( pszBasename );
586 
587 /* -------------------------------------------------------------------- */
588 /* Read the file size from the SHP file. */
589 /* -------------------------------------------------------------------- */
590  pabyBuf = (uchar *) malloc(100);
591  psSHP->sHooks.FRead( pabyBuf, 100, 1, psSHP->fpSHP );
592 
593  psSHP->nFileSize = ((unsigned int)pabyBuf[24] * 256 * 256 * 256
594  + (unsigned int)pabyBuf[25] * 256 * 256
595  + (unsigned int)pabyBuf[26] * 256
596  + (unsigned int)pabyBuf[27]) * 2;
597 
598 /* -------------------------------------------------------------------- */
599 /* Read SHX file Header info */
600 /* -------------------------------------------------------------------- */
601  if( psSHP->sHooks.FRead( pabyBuf, 100, 1, psSHP->fpSHX ) != 1
602  || pabyBuf[0] != 0
603  || pabyBuf[1] != 0
604  || pabyBuf[2] != 0x27
605  || (pabyBuf[3] != 0x0a && pabyBuf[3] != 0x0d) )
606  {
607  psSHP->sHooks.Error( ".shx file is unreadable, or corrupt." );
608  psSHP->sHooks.FClose( psSHP->fpSHP );
609  psSHP->sHooks.FClose( psSHP->fpSHX );
610  free( psSHP );
611 
612  return( NULL );
613  }
614 
615  psSHP->nRecords = pabyBuf[27] + pabyBuf[26] * 256
616  + pabyBuf[25] * 256 * 256 + pabyBuf[24] * 256 * 256 * 256;
617  psSHP->nRecords = (psSHP->nRecords*2 - 100) / 8;
618 
619  psSHP->nShapeType = pabyBuf[32];
620 
621  if( psSHP->nRecords < 0 || psSHP->nRecords > 256000000 )
622  {
623  char szError[200];
624 
625  sprintf( szError,
626  "Record count in .shp header is %d, which seems\n"
627  "unreasonable. Assuming header is corrupt.",
628  psSHP->nRecords );
629  psSHP->sHooks.Error( szError );
630  psSHP->sHooks.FClose( psSHP->fpSHP );
631  psSHP->sHooks.FClose( psSHP->fpSHX );
632  free( psSHP );
633  free(pabyBuf);
634 
635  return( NULL );
636  }
637 
638 /* -------------------------------------------------------------------- */
639 /* Read the bounds. */
640 /* -------------------------------------------------------------------- */
641  if( bBigEndian ) SwapWord( 8, pabyBuf+36 );
642  memcpy( &dValue, pabyBuf+36, 8 );
643  psSHP->adBoundsMin[0] = dValue;
644 
645  if( bBigEndian ) SwapWord( 8, pabyBuf+44 );
646  memcpy( &dValue, pabyBuf+44, 8 );
647  psSHP->adBoundsMin[1] = dValue;
648 
649  if( bBigEndian ) SwapWord( 8, pabyBuf+52 );
650  memcpy( &dValue, pabyBuf+52, 8 );
651  psSHP->adBoundsMax[0] = dValue;
652 
653  if( bBigEndian ) SwapWord( 8, pabyBuf+60 );
654  memcpy( &dValue, pabyBuf+60, 8 );
655  psSHP->adBoundsMax[1] = dValue;
656 
657  if( bBigEndian ) SwapWord( 8, pabyBuf+68 ); /* z */
658  memcpy( &dValue, pabyBuf+68, 8 );
659  psSHP->adBoundsMin[2] = dValue;
660 
661  if( bBigEndian ) SwapWord( 8, pabyBuf+76 );
662  memcpy( &dValue, pabyBuf+76, 8 );
663  psSHP->adBoundsMax[2] = dValue;
664 
665  if( bBigEndian ) SwapWord( 8, pabyBuf+84 ); /* z */
666  memcpy( &dValue, pabyBuf+84, 8 );
667  psSHP->adBoundsMin[3] = dValue;
668 
669  if( bBigEndian ) SwapWord( 8, pabyBuf+92 );
670  memcpy( &dValue, pabyBuf+92, 8 );
671  psSHP->adBoundsMax[3] = dValue;
672 
673  free( pabyBuf );
674 
675 /* -------------------------------------------------------------------- */
676 /* Read the .shx file to get the offsets to each record in */
677 /* the .shp file. */
678 /* -------------------------------------------------------------------- */
679  psSHP->nMaxRecords = psSHP->nRecords;
680 
681  psSHP->panRecOffset = (unsigned int *)
682  malloc(sizeof(unsigned int) * MAX(1,psSHP->nMaxRecords) );
683  psSHP->panRecSize = (unsigned int *)
684  malloc(sizeof(unsigned int) * MAX(1,psSHP->nMaxRecords) );
685  pabyBuf = (uchar *) malloc(8 * MAX(1,psSHP->nRecords) );
686 
687  if (psSHP->panRecOffset == NULL ||
688  psSHP->panRecSize == NULL ||
689  pabyBuf == NULL)
690  {
691  char szError[200];
692 
693  sprintf(szError,
694  "Not enough memory to allocate requested memory (nRecords=%d).\n"
695  "Probably broken SHP file",
696  psSHP->nRecords );
697  psSHP->sHooks.Error( szError );
698  psSHP->sHooks.FClose( psSHP->fpSHP );
699  psSHP->sHooks.FClose( psSHP->fpSHX );
700  if (psSHP->panRecOffset) free( psSHP->panRecOffset );
701  if (psSHP->panRecSize) free( psSHP->panRecSize );
702  if (pabyBuf) free( pabyBuf );
703  free( psSHP );
704  return( NULL );
705  }
706 
707  if( (int) psSHP->sHooks.FRead( pabyBuf, 8, psSHP->nRecords, psSHP->fpSHX )
708  != psSHP->nRecords )
709  {
710  char szError[200];
711 
712  sprintf( szError,
713  "Failed to read all values for %d records in .shx file.",
714  psSHP->nRecords );
715  psSHP->sHooks.Error( szError );
716 
717  /* SHX is short or unreadable for some reason. */
718  psSHP->sHooks.FClose( psSHP->fpSHP );
719  psSHP->sHooks.FClose( psSHP->fpSHX );
720  free( psSHP->panRecOffset );
721  free( psSHP->panRecSize );
722  free( pabyBuf );
723  free( psSHP );
724 
725  return( NULL );
726  }
727 
728  /* In read-only mode, we can close the SHX now */
729  if (strcmp(pszAccess, "rb") == 0)
730  {
731  psSHP->sHooks.FClose( psSHP->fpSHX );
732  psSHP->fpSHX = NULL;
733  }
734 
735  for( i = 0; i < psSHP->nRecords; i++ )
736  {
737  uint32 nOffset, nLength;
738 
739  memcpy( &nOffset, pabyBuf + i * 8, 4 );
740  if( !bBigEndian ) SwapWord( 4, &nOffset );
741 
742  memcpy( &nLength, pabyBuf + i * 8 + 4, 4 );
743  if( !bBigEndian ) SwapWord( 4, &nLength );
744 
745  psSHP->panRecOffset[i] = nOffset*2;
746  psSHP->panRecSize[i] = nLength*2;
747  }
748  free( pabyBuf );
749 
750  return( psSHP );
751 }
SHPInfo * SHPHandle
Definition: shapefil.h:302
double adBoundsMin[4]
Definition: shapefil.h:293
unsigned int nFileSize
Definition: shapefil.h:286
int(* FClose)(SAFile file)
Definition: shapefil.h:262
int nRecords
Definition: shapefil.h:288
#define FALSE
Definition: shpopen.c:278
unsigned int * panRecOffset
Definition: shapefil.h:290
static int bBigEndian
Definition: shpopen.c:294
unsigned int uint32
Definition: shpopen.c:274
SAHooks sHooks
Definition: shapefil.h:279
#define MAX(a, b)
Definition: shpopen.c:285
SAFile fpSHX
Definition: shapefil.h:282
int nMaxRecords
Definition: shapefil.h:289
double adBoundsMax[4]
Definition: shapefil.h:294
unsigned int * panRecSize
Definition: shapefil.h:291
int bUpdated
Definition: shapefil.h:296
SAFile(* FOpen)(const char *filename, const char *access)
Definition: shapefil.h:256
#define TRUE
Definition: shpopen.c:279
static void SwapWord(int length, void *wordP)
Definition: shpopen.c:303
unsigned char uchar
Definition: shpopen.c:269
void(* Error)(const char *message)
Definition: shapefil.h:265
SAOffset(* FRead)(void *p, SAOffset size, SAOffset nmemb, SAFile file)
Definition: shapefil.h:257
int nShapeType
Definition: shapefil.h:284
SAFile fpSHP
Definition: shapefil.h:281

Here is the call graph for this function:

Here is the caller graph for this function: