BUrl::BUrl(const BUrl& base, const BString& location) : fUrlString(), fProtocol(), fUser(), fPassword(), fHost(), fPort(0), fPath(), fRequest(), fAuthorityValid(false), fUserInfoValid(false), fHasUserName(false), fHasPassword(false), fHasHost(false), fHasPort(false), fHasFragment(false) { // This implements the algorithm in RFC3986, Section 5.2. BUrl relative(location); if (relative.HasProtocol()) { SetProtocol(relative.Protocol()); if (relative.HasAuthority()) SetAuthority(relative.Authority()); SetPath(relative.Path()); SetRequest(relative.Request()); } else { if (relative.HasAuthority()) { SetAuthority(relative.Authority()); SetPath(relative.Path()); SetRequest(relative.Request()); } else { if (relative.Path().IsEmpty()) { _SetPathUnsafe(base.Path()); if (relative.HasRequest()) SetRequest(relative.Request()); else SetRequest(base.Request()); } else { if (relative.Path()[0] == '/') SetPath(relative.Path()); else { BString path = base._MergePath(relative.Path()); SetPath(path); } SetRequest(relative.Request()); } if (base.HasAuthority()) SetAuthority(base.Authority()); } SetProtocol(base.Protocol()); } if (relative.HasFragment()) SetFragment(relative.Fragment()); }
BUrl::BUrl(const BUrl& base, const BString& location) : fUrlString(), fProtocol(), fUser(), fPassword(), fHost(), fPort(0), fPath(), fRequest(), fHasAuthority(false) { // This implements the algorithm in RFC3986, Section 5.2. BUrl relative(location); if (relative.HasProtocol()) { SetProtocol(relative.Protocol()); SetAuthority(relative.Authority()); SetPath(relative.Path()); // TODO _RemoveDotSegments() SetRequest(relative.Request()); } else { if (relative.HasAuthority()) { SetAuthority(relative.Authority()); SetPath(relative.Path()); // TODO _RemoveDotSegments() SetRequest(relative.Request()); } else { if (relative.Path().IsEmpty()) { SetPath(base.Path()); if (relative.HasRequest()) SetRequest(relative.Request()); else SetRequest(Request()); } else { if (relative.Path()[0] == '/') SetPath(relative.Path()); else { BString path = base.Path(); // Remove last part of path (the file, if any) so we get the // "current directory" path.Truncate(path.FindLast('/') + 1); path += relative.Path(); // TODO _RemoveDotSegments() SetPath(path); } SetRequest(relative.Request()); } SetAuthority(base.Authority()); } SetProtocol(base.Protocol()); } SetFragment(relative.Fragment()); }
void BUrl::_ExplodeUrlString(const BString& url) { // The regexp is provided in RFC3986 (URI generic syntax), Appendix B static RegExp urlMatcher( "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?"); _ResetFields(); RegExp::MatchResult match = urlMatcher.Match(url.String()); if (!match.HasMatched()) return; // TODO error reporting // Scheme/Protocol url.CopyInto(fProtocol, match.GroupStartOffsetAt(1), match.GroupEndOffsetAt(1) - match.GroupStartOffsetAt(1)); if (!_IsProtocolValid()) { fHasProtocol = false; fProtocol.Truncate(0); } else fHasProtocol = true; // Authority (including user credentials, host, and port url.CopyInto(fAuthority, match.GroupStartOffsetAt(3), match.GroupEndOffsetAt(3) - match.GroupStartOffsetAt(3)); SetAuthority(fAuthority); // Path url.CopyInto(fPath, match.GroupStartOffsetAt(4), match.GroupEndOffsetAt(4) - match.GroupStartOffsetAt(4)); if (!fPath.IsEmpty()) fHasPath = true; // Query url.CopyInto(fRequest, match.GroupStartOffsetAt(6), match.GroupEndOffsetAt(6) - match.GroupStartOffsetAt(6)); if (!fRequest.IsEmpty()) fHasRequest = true; // Fragment url.CopyInto(fFragment, match.GroupStartOffsetAt(8), match.GroupEndOffsetAt(8) - match.GroupStartOffsetAt(8)); if (!fFragment.IsEmpty()) fHasFragment = true; }
OGRErr OGRSpatialReference::importFromUSGS( long iProjSys, long iZone, double *padfPrjParams, long iDatum, int bAnglesInPackedDMSFormat ) { if( !padfPrjParams ) return OGRERR_CORRUPT_DATA; double (*pfnUnpackAnglesFn)(double); if (bAnglesInPackedDMSFormat) pfnUnpackAnglesFn = CPLPackedDMSToDec; else pfnUnpackAnglesFn = OGRSpatialReferenceUSGSUnpackNoOp; /* -------------------------------------------------------------------- */ /* Operate on the basis of the projection code. */ /* -------------------------------------------------------------------- */ switch ( iProjSys ) { case GEO: break; case UTM: { int bNorth = TRUE; if ( !iZone ) { if ( padfPrjParams[2] != 0.0 ) iZone = (long) padfPrjParams[2]; else if (padfPrjParams[0] != 0.0 && padfPrjParams[1] != 0.0) { iZone = (long)(((pfnUnpackAnglesFn(padfPrjParams[0]) + 180.0) / 6.0) + 1.0); if ( pfnUnpackAnglesFn(padfPrjParams[0]) < 0 ) bNorth = FALSE; } } if ( iZone < 0 ) { iZone = -iZone; bNorth = FALSE; } SetUTM( iZone, bNorth ); } break; case SPCS: { int bNAD83 = TRUE; if ( iDatum == 0 ) bNAD83 = FALSE; else if ( iDatum != 8 ) CPLError( CE_Warning, CPLE_AppDefined, "Wrong datum for State Plane projection %d. " "Should be 0 or 8.", (int) iDatum ); SetStatePlane( iZone, bNAD83 ); } break; case ALBERS: SetACEA( pfnUnpackAnglesFn(padfPrjParams[2]), pfnUnpackAnglesFn(padfPrjParams[3]), pfnUnpackAnglesFn(padfPrjParams[5]), pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6], padfPrjParams[7] ); break; case LAMCC: SetLCC( pfnUnpackAnglesFn(padfPrjParams[2]), pfnUnpackAnglesFn(padfPrjParams[3]), pfnUnpackAnglesFn(padfPrjParams[5]), pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6], padfPrjParams[7] ); break; case MERCAT: SetMercator( pfnUnpackAnglesFn(padfPrjParams[5]), pfnUnpackAnglesFn(padfPrjParams[4]), 1.0, padfPrjParams[6], padfPrjParams[7] ); break; case PS: SetPS( pfnUnpackAnglesFn(padfPrjParams[5]), pfnUnpackAnglesFn(padfPrjParams[4]), 1.0, padfPrjParams[6], padfPrjParams[7] ); break; case POLYC: SetPolyconic( pfnUnpackAnglesFn(padfPrjParams[5]), pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6], padfPrjParams[7] ); break; case EQUIDC: if ( padfPrjParams[8] ) { SetEC( pfnUnpackAnglesFn(padfPrjParams[2]), pfnUnpackAnglesFn(padfPrjParams[3]), pfnUnpackAnglesFn(padfPrjParams[5]), pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6], padfPrjParams[7] ); } else { SetEC( pfnUnpackAnglesFn(padfPrjParams[2]), pfnUnpackAnglesFn(padfPrjParams[2]), pfnUnpackAnglesFn(padfPrjParams[5]), pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6], padfPrjParams[7] ); } break; case TM: SetTM( pfnUnpackAnglesFn(padfPrjParams[5]), pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[2], padfPrjParams[6], padfPrjParams[7] ); break; case STEREO: SetStereographic( pfnUnpackAnglesFn(padfPrjParams[5]), pfnUnpackAnglesFn(padfPrjParams[4]), 1.0, padfPrjParams[6], padfPrjParams[7] ); break; case LAMAZ: SetLAEA( pfnUnpackAnglesFn(padfPrjParams[5]), pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6], padfPrjParams[7] ); break; case AZMEQD: SetAE( pfnUnpackAnglesFn(padfPrjParams[5]), pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6], padfPrjParams[7] ); break; case GNOMON: SetGnomonic( pfnUnpackAnglesFn(padfPrjParams[5]), pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6], padfPrjParams[7] ); break; case ORTHO: SetOrthographic( pfnUnpackAnglesFn(padfPrjParams[5]), pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6], padfPrjParams[7] ); break; // FIXME: GVNSP --- General Vertical Near-Side Perspective skipped case SNSOID: SetSinusoidal( pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6], padfPrjParams[7] ); break; case EQRECT: SetEquirectangular2( 0.0, pfnUnpackAnglesFn(padfPrjParams[4]), pfnUnpackAnglesFn(padfPrjParams[5]), padfPrjParams[6], padfPrjParams[7] ); break; case MILLER: SetMC( pfnUnpackAnglesFn(padfPrjParams[5]), pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6], padfPrjParams[7] ); break; case VGRINT: SetVDG( pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6], padfPrjParams[7] ); break; case HOM: if ( padfPrjParams[12] ) { SetHOM( pfnUnpackAnglesFn(padfPrjParams[5]), pfnUnpackAnglesFn(padfPrjParams[4]), pfnUnpackAnglesFn(padfPrjParams[3]), 0.0, padfPrjParams[2], padfPrjParams[6], padfPrjParams[7] ); } else { SetHOM2PNO( pfnUnpackAnglesFn(padfPrjParams[5]), pfnUnpackAnglesFn(padfPrjParams[9]), pfnUnpackAnglesFn(padfPrjParams[8]), pfnUnpackAnglesFn(padfPrjParams[11]), pfnUnpackAnglesFn(padfPrjParams[10]), padfPrjParams[2], padfPrjParams[6], padfPrjParams[7] ); } break; case ROBIN: SetRobinson( pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6], padfPrjParams[7] ); break; // FIXME: SOM --- Space Oblique Mercator skipped // FIXME: ALASKA --- Alaska Conformal skipped // FIXME: GOODE --- Interrupted Goode skipped case MOLL: SetMollweide( pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6], padfPrjParams[7] ); break; // FIXME: IMOLL --- Interrupted Mollweide skipped // FIXME: HAMMER --- Hammer skipped case WAGIV: SetWagner( 4, 0.0, padfPrjParams[6], padfPrjParams[7] ); break; case WAGVII: SetWagner( 7, 0.0, padfPrjParams[6], padfPrjParams[7] ); break; // FIXME: OBEQA --- Oblated Equal Area skipped // FIXME: ISINUS1 --- Integerized Sinusoidal Grid (the same as 99) skipped // FIXME: CEA --- Cylindrical Equal Area skipped (Grid corners set in meters for EASE grid) // FIXME: BCEA --- Cylindrical Equal Area skipped (Grid corners set in DMS degs for EASE grid) // FIXME: ISINUS --- Integrized Sinusoidal skipped default: CPLDebug( "OSR_USGS", "Unsupported projection: %ld", iProjSys ); SetLocalCS( CPLString().Printf("GCTP projection number %ld", iProjSys) ); break; } /* -------------------------------------------------------------------- */ /* Try to translate the datum/spheroid. */ /* -------------------------------------------------------------------- */ if ( !IsLocal() ) { char *pszName = NULL; double dfSemiMajor, dfInvFlattening; if ( iDatum < 0 ) // Use specified ellipsoid parameters { if ( padfPrjParams[0] > 0.0 ) { if ( padfPrjParams[1] > 1.0 ) { if( ABS(padfPrjParams[0] - padfPrjParams[1]) < 0.01 ) dfInvFlattening = 0.0; else { dfInvFlattening = padfPrjParams[0] / ( padfPrjParams[0] - padfPrjParams[1] ); } } else if ( padfPrjParams[1] > 0.0 ) { dfInvFlattening = 1.0 / ( 1.0 - sqrt(1.0 - padfPrjParams[1]) ); } else dfInvFlattening = 0.0; SetGeogCS( "Unknown datum based upon the custom spheroid", "Not specified (based on custom spheroid)", "Custom spheroid", padfPrjParams[0], dfInvFlattening, NULL, 0, NULL, 0 ); } else if ( padfPrjParams[1] > 0.0 ) // Clarke 1866 { if ( OSRGetEllipsoidInfo( 7008, &pszName, &dfSemiMajor, &dfInvFlattening ) == OGRERR_NONE ) { SetGeogCS( CPLString().Printf( "Unknown datum based upon the %s ellipsoid", pszName ), CPLString().Printf( "Not specified (based on %s spheroid)", pszName ), pszName, dfSemiMajor, dfInvFlattening, NULL, 0.0, NULL, 0.0 ); SetAuthority( "SPHEROID", "EPSG", 7008 ); } } else // Sphere, rad 6370997 m { if ( OSRGetEllipsoidInfo( 7047, &pszName, &dfSemiMajor, &dfInvFlattening ) == OGRERR_NONE ) { SetGeogCS( CPLString().Printf( "Unknown datum based upon the %s ellipsoid", pszName ), CPLString().Printf( "Not specified (based on %s spheroid)", pszName ), pszName, dfSemiMajor, dfInvFlattening, NULL, 0.0, NULL, 0.0 ); SetAuthority( "SPHEROID", "EPSG", 7047 ); } } } else if ( iDatum < NUMBER_OF_ELLIPSOIDS && aoEllips[iDatum] ) { if( OSRGetEllipsoidInfo( aoEllips[iDatum], &pszName, &dfSemiMajor, &dfInvFlattening ) == OGRERR_NONE ) { SetGeogCS( CPLString().Printf("Unknown datum based upon the %s ellipsoid", pszName ), CPLString().Printf( "Not specified (based on %s spheroid)", pszName ), pszName, dfSemiMajor, dfInvFlattening, NULL, 0.0, NULL, 0.0 ); SetAuthority( "SPHEROID", "EPSG", aoEllips[iDatum] ); } else { CPLError( CE_Warning, CPLE_AppDefined, "Failed to lookup datum code %d, likely due to missing GDAL gcs.csv\n" " file. Falling back to use WGS84.", (int) iDatum ); SetWellKnownGeogCS("WGS84" ); } } else { CPLError( CE_Warning, CPLE_AppDefined, "Wrong datum code %d. Supported datums 0--%d only.\n" "Setting WGS84 as a fallback.", (int) iDatum, NUMBER_OF_ELLIPSOIDS ); SetWellKnownGeogCS( "WGS84" ); } if ( pszName ) CPLFree( pszName ); } /* -------------------------------------------------------------------- */ /* Grid units translation */ /* -------------------------------------------------------------------- */ if( IsLocal() || IsProjected() ) SetLinearUnits( SRS_UL_METER, 1.0 ); FixupOrdering(); return OGRERR_NONE; }
OGRErr OGRSpatialReference::importFromPanorama( long iProjSys, long iDatum, long iEllips, double *padfPrjParams ) { Clear(); /* -------------------------------------------------------------------- */ /* Use safe defaults if projection parameters are not supplied. */ /* -------------------------------------------------------------------- */ int bProjAllocated = FALSE; if( padfPrjParams == NULL ) { int i; padfPrjParams = (double *)CPLMalloc( 7 * sizeof(double) ); if ( !padfPrjParams ) return OGRERR_NOT_ENOUGH_MEMORY; for ( i = 0; i < 7; i++ ) padfPrjParams[i] = 0.0; bProjAllocated = TRUE; } /* -------------------------------------------------------------------- */ /* Operate on the basis of the projection code. */ /* -------------------------------------------------------------------- */ switch ( iProjSys ) { case PAN_PROJ_NONE: break; case PAN_PROJ_UTM: { long nZone = (long)TO_ZONE(padfPrjParams[3]); // XXX: no way to determine south hemisphere. Always assume // nothern hemisphere. SetUTM( nZone, TRUE ); } break; case PAN_PROJ_WAG1: SetWagner( 1, 0.0, padfPrjParams[5], padfPrjParams[6] ); break; case PAN_PROJ_MERCAT: SetMercator( TO_DEGREES * padfPrjParams[0], TO_DEGREES * padfPrjParams[3], padfPrjParams[4], padfPrjParams[5], padfPrjParams[6] ); break; case PAN_PROJ_PS: SetPS( TO_DEGREES * padfPrjParams[2], TO_DEGREES * padfPrjParams[3], padfPrjParams[4], padfPrjParams[5], padfPrjParams[6] ); break; case PAN_PROJ_POLYC: SetPolyconic( TO_DEGREES * padfPrjParams[2], TO_DEGREES * padfPrjParams[3], padfPrjParams[5], padfPrjParams[6] ); break; case PAN_PROJ_EC: SetEC( TO_DEGREES * padfPrjParams[0], TO_DEGREES * padfPrjParams[1], TO_DEGREES * padfPrjParams[2], TO_DEGREES * padfPrjParams[3], padfPrjParams[5], padfPrjParams[6] ); break; case PAN_PROJ_LCC: SetLCC( TO_DEGREES * padfPrjParams[0], TO_DEGREES * padfPrjParams[1], TO_DEGREES * padfPrjParams[2], TO_DEGREES * padfPrjParams[3], padfPrjParams[5], padfPrjParams[6] ); break; case PAN_PROJ_TM: { // XXX: we need zone number to compute false easting // parameter, because usually it is not contained in the // "Panorama" projection definition. // FIXME: what to do with negative values? long nZone = (long)TO_ZONE(padfPrjParams[3]); padfPrjParams[5] = nZone * 1000000.0 + 500000.0; padfPrjParams[4] = 1.0; SetTM( TO_DEGREES * padfPrjParams[2], TO_DEGREES * padfPrjParams[3], padfPrjParams[4], padfPrjParams[5], padfPrjParams[6] ); } break; case PAN_PROJ_STEREO: SetStereographic( TO_DEGREES * padfPrjParams[2], TO_DEGREES * padfPrjParams[3], padfPrjParams[4], padfPrjParams[5], padfPrjParams[6] ); break; case PAN_PROJ_AE: SetAE( TO_DEGREES * padfPrjParams[0], TO_DEGREES * padfPrjParams[3], padfPrjParams[5], padfPrjParams[6] ); break; case PAN_PROJ_GNOMON: SetGnomonic( TO_DEGREES * padfPrjParams[2], TO_DEGREES * padfPrjParams[3], padfPrjParams[5], padfPrjParams[6] ); break; case PAN_PROJ_MOLL: SetMollweide( TO_DEGREES * padfPrjParams[3], padfPrjParams[5], padfPrjParams[6] ); break; case PAN_PROJ_LAEA: SetLAEA( TO_DEGREES * padfPrjParams[0], TO_DEGREES * padfPrjParams[3], padfPrjParams[5], padfPrjParams[6] ); break; case PAN_PROJ_EQC: SetEquirectangular( TO_DEGREES * padfPrjParams[0], TO_DEGREES * padfPrjParams[3], padfPrjParams[5], padfPrjParams[6] ); break; case PAN_PROJ_CEA: SetCEA( TO_DEGREES * padfPrjParams[0], TO_DEGREES * padfPrjParams[3], padfPrjParams[5], padfPrjParams[6] ); break; case PAN_PROJ_IMWP: SetIWMPolyconic( TO_DEGREES * padfPrjParams[0], TO_DEGREES * padfPrjParams[1], TO_DEGREES * padfPrjParams[3], padfPrjParams[5], padfPrjParams[6] ); break; default: CPLDebug( "OSR_Panorama", "Unsupported projection: %ld", iProjSys ); SetLocalCS( CPLString().Printf("\"Panorama\" projection number %ld", iProjSys) ); break; } /* -------------------------------------------------------------------- */ /* Try to translate the datum/spheroid. */ /* -------------------------------------------------------------------- */ if ( !IsLocal() ) { if ( iDatum > 0 && iDatum < NUMBER_OF_DATUMS && aoDatums[iDatum] ) { OGRSpatialReference oGCS; oGCS.importFromEPSG( aoDatums[iDatum] ); CopyGeogCSFrom( &oGCS ); } else if ( iEllips > 0 && iEllips < (long)NUMBER_OF_ELLIPSOIDS && aoEllips[iEllips] ) { char *pszName = NULL; double dfSemiMajor, dfInvFlattening; if ( OSRGetEllipsoidInfo( aoEllips[iEllips], &pszName, &dfSemiMajor, &dfInvFlattening ) == OGRERR_NONE ) { SetGeogCS( CPLString().Printf( "Unknown datum based upon the %s ellipsoid", pszName ), CPLString().Printf( "Not specified (based on %s spheroid)", pszName ), pszName, dfSemiMajor, dfInvFlattening, NULL, 0.0, NULL, 0.0 ); SetAuthority( "SPHEROID", "EPSG", aoEllips[iEllips] ); } else { CPLError( CE_Warning, CPLE_AppDefined, "Failed to lookup ellipsoid code %d, likely due to" " missing GDAL gcs.csv\n" " file. Falling back to use WGS84.", (int) iEllips ); SetWellKnownGeogCS( "WGS84" ); } if ( pszName ) CPLFree( pszName ); } else { CPLError( CE_Warning, CPLE_AppDefined, "Wrong datum code %d. Supported datums are 1--%ld only.\n" "Setting WGS84 as a fallback.", (int) iDatum, NUMBER_OF_DATUMS - 1 ); SetWellKnownGeogCS( "WGS84" ); } } /* -------------------------------------------------------------------- */ /* Grid units translation */ /* -------------------------------------------------------------------- */ if( IsLocal() || IsProjected() ) SetLinearUnits( SRS_UL_METER, 1.0 ); FixupOrdering(); if ( bProjAllocated && padfPrjParams ) CPLFree( padfPrjParams ); return OGRERR_NONE; }
/* * This function takes a URL in string-form and parses the components of the URL out. */ status_t BUrl::_ExplodeUrlString(const BString& url) { _ResetFields(); // RFC3986, Appendix C; the URL should not contain whitespace or delimiters // by this point. if (_ContainsDelimiter(url)) return B_BAD_VALUE; explode_url_parse_state state = EXPLODE_PROTOCOL; int32 offset = 0; int32 length = url.Length(); const char *url_c = url.String(); // The regexp is provided in RFC3986 (URI generic syntax), Appendix B // ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))? // The ensuing logic attempts to simulate the behaviour of extracting the groups // from the string without requiring a group-capable regex engine. while (offset < length) { switch (state) { case EXPLODE_PROTOCOL: { int32 end_protocol = char_offset_until_fn_false(url_c, length, offset, explode_is_protocol_char); if (end_protocol < length) { SetProtocol(BString(&url_c[offset], end_protocol - offset)); state = EXPLODE_PROTOCOLTERMINATOR; offset = end_protocol; } else { // No protocol was found, try parsing from the string // start, beginning with authority or path SetProtocol(""); offset = 0; state = EXPLODE_AUTHORITYORPATH; } break; } case EXPLODE_PROTOCOLTERMINATOR: { if (url[offset] == ':') { offset++; } else { // No protocol was found, try parsing from the string // start, beginning with authority or path SetProtocol(""); offset = 0; } state = EXPLODE_AUTHORITYORPATH; break; } case EXPLODE_AUTHORITYORPATH: { // The authority must start with //. If it isn't there, skip // to parsing the path. if (strncmp(&url_c[offset], "//", 2) == 0) { state = EXPLODE_AUTHORITY; offset += 2; } else { state = EXPLODE_PATH; } break; } case EXPLODE_AUTHORITY: { int end_authority = char_offset_until_fn_false(url_c, length, offset, explode_is_authority_char); SetAuthority(BString(&url_c[offset], end_authority - offset)); state = EXPLODE_PATH; offset = end_authority; break; } case EXPLODE_PATH: { int end_path = char_offset_until_fn_false(url_c, length, offset, explode_is_path_char); SetPath(BString(&url_c[offset], end_path - offset)); state = EXPLODE_REQUEST; offset = end_path; break; } case EXPLODE_REQUEST: // query { if (url_c[offset] == '?') { offset++; int end_request = char_offset_until_fn_false(url_c, length, offset, explode_is_request_char); SetRequest(BString(&url_c[offset], end_request - offset)); offset = end_request; } state = EXPLODE_FRAGMENT; break; } case EXPLODE_FRAGMENT: { if (url_c[offset] == '#') { offset++; SetFragment(BString(&url_c[offset], length - offset)); offset = length; } state = EXPLODE_COMPLETE; break; } case EXPLODE_COMPLETE: // should never be reached - keeps the compiler happy break; } } return B_OK; }