PostGIS  2.5.7dev-r@@SVN_REVISION@@

◆ SHPOpenLL()

SHPHandle SHPAPI_CALL SHPOpenLL ( const char *  pszLayer,
const char *  pszAccess,
SAHooks psHooks 
)

Definition at line 482 of file shpopen.c.

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

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

Referenced by SHPCreateLL(), and SHPOpen().

Here is the call graph for this function:
Here is the caller graph for this function: