#ifdef CFURL_INCLUDE_PARSE_COMPONENTS // defined when we want this block of code included
{
enum {
scheme_index = 0,
user_index = 1,
password_index = 2,
host_index = 3,
port_index = 4,
path_index = 5,
parameters_index = 6,
query_index = 7,
fragment_index = 8,
};
CFRange unpackedRanges[MAX_COMPONENTS];
CFIndex idx, base_idx = 0;
CFIndex string_length;
UInt32 flags = *theFlags;
Boolean isCompliant;
uint8_t numRanges = 0;
string_length = cfStringLength;
for (idx = base_idx; idx < string_length; idx++) {
if ('#' == characterArray[idx]) {
flags |= HAS_FRAGMENT;
unpackedRanges[fragment_index].location = idx + 1;
unpackedRanges[fragment_index].length = string_length - (idx + 1);
numRanges ++;
string_length = idx; break;
}
}
for (idx = base_idx; idx < string_length; idx++) {
UniChar ch = characterArray[idx];
if (':' == ch) {
flags |= HAS_SCHEME;
unpackedRanges[scheme_index].location = base_idx;
unpackedRanges[scheme_index].length = idx;
numRanges ++;
base_idx = idx + 1;
if (idx == 3 && characterArray[0] == 'f' && characterArray[1] == 't' && characterArray[2] == 'p') {
_setSchemeTypeInFlags(&flags, kHasFtpScheme);
}
else if (idx == 4) {
if (characterArray[0] == 'h' && characterArray[1] == 't' && characterArray[2] == 't' && characterArray[3] == 'p') {
_setSchemeTypeInFlags(&flags, kHasHttpScheme);
}
if (characterArray[0] == 'f' && characterArray[1] == 'i' && characterArray[2] == 'l' && characterArray[3] == 'e') {
_setSchemeTypeInFlags(&flags, kHasFileScheme);
}
if (characterArray[0] == 'd' && characterArray[1] == 'a' && characterArray[2] == 't' && characterArray[3] == 'a') {
_setSchemeTypeInFlags(&flags, kHasDataScheme);
}
}
else if (idx == 5 && characterArray[0] == 'h' && characterArray[1] == 't' && characterArray[2] == 't' && characterArray[3] == 'p' && characterArray[3] == 's') {
_setSchemeTypeInFlags(&flags, kHasHttpsScheme);
}
break;
} else if (!scheme_valid(ch)) {
break; }
}
if (!(flags & HAS_SCHEME)) {
isCompliant = true;
} else if (base_idx == string_length) {
isCompliant = false;
} else if (characterArray[base_idx] != '/') {
isCompliant = false;
} else {
isCompliant = true;
}
if (!isCompliant) {
if (flags & HAS_FRAGMENT) {
flags &= (~HAS_FRAGMENT);
string_length = cfStringLength;
}
(*theFlags) = flags;
packedRanges[scheme_index].location = unpackedRanges[scheme_index].location;
packedRanges[scheme_index].length = unpackedRanges[scheme_index].length;
*numberOfRanges = 1;
}
else {
flags |= IS_DECOMPOSABLE;
if (2 <= (string_length - base_idx) && '/' == characterArray[base_idx] && '/' == characterArray[base_idx+1]) {
CFIndex base = 2 + base_idx, extent;
for (idx = base; idx < string_length; idx++) {
if ('/' == characterArray[idx] || '?' == characterArray[idx]) {
break;
}
}
extent = idx;
if (extent != base) {
for (idx = base; idx < extent; idx++) {
if ('@' == characterArray[idx]) { CFIndex idx2;
flags |= HAS_USER;
numRanges ++;
unpackedRanges[user_index].location = base; for (idx2 = base; idx2 < idx; idx2++) {
if (':' == characterArray[idx2]) { flags |= HAS_PASSWORD;
numRanges ++;
unpackedRanges[password_index].location = idx2+1; unpackedRanges[password_index].length = idx-(idx2+1); unpackedRanges[user_index].length = idx2 - base; break;
}
}
if (!(flags & HAS_PASSWORD)) {
unpackedRanges[user_index].length = idx - base; }
base = idx + 1;
break;
}
}
flags |= HAS_HOST;
numRanges ++;
unpackedRanges[host_index].location = base;
for (idx = base; idx < extent; idx++) {
if ('[' == characterArray[idx]) { for ( ; idx < extent; ++ idx ) {
if ( ']' == characterArray[idx]) {
flags |= IS_IPV6_ENCODED;
break;
}
}
}
else if ( ':' == characterArray[idx]) {
flags |= HAS_PORT;
numRanges ++;
unpackedRanges[port_index].location = idx+1; unpackedRanges[port_index].length = extent - (idx+1); unpackedRanges[host_index].length = idx - base; break;
}
}
if (!(flags & HAS_PORT)) {
unpackedRanges[host_index].length = extent - base; }
}
base_idx = extent;
}
for (idx = base_idx; idx < string_length; idx++) {
if ('?' == characterArray[idx]) {
flags |= HAS_QUERY;
numRanges ++;
unpackedRanges[query_index].location = idx + 1;
unpackedRanges[query_index].length = string_length - (idx+1);
string_length = idx; break;
}
}
for (idx = base_idx; idx < string_length; idx++) {
if (';' == characterArray[idx]) {
flags |= HAS_PARAMETERS;
numRanges ++;
unpackedRanges[parameters_index].location = idx + 1;
unpackedRanges[parameters_index].length = string_length - (idx+1);
string_length = idx; break;
}
}
if (string_length - base_idx != 0 || (flags & NET_LOCATION_MASK))
{
UniChar ch;
Boolean isDir;
CFRange pathRg;
flags |= HAS_PATH;
numRanges ++;
pathRg.location = base_idx;
pathRg.length = string_length - base_idx;
unpackedRanges[path_index] = pathRg;
if (pathRg.length > 0) {
Boolean sawPercent = FALSE;
for (idx = pathRg.location; idx < string_length; idx++) {
if ('%' == characterArray[idx]) {
sawPercent = TRUE;
break;
}
}
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
if (pathRg.length > 6 && characterArray[pathRg.location] == '/' && characterArray[pathRg.location + 1] == '.' && characterArray[pathRg.location + 2] == 'f' && characterArray[pathRg.location + 3] == 'i' && characterArray[pathRg.location + 4] == 'l' && characterArray[pathRg.location + 5] == 'e' && characterArray[pathRg.location + 6] == '/') {
flags |= PATH_HAS_FILE_ID;
} else if (!sawPercent) {
flags |= POSIX_AND_URL_PATHS_MATCH;
}
#elif DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_WINDOWS
if (!sawPercent) {
flags |= POSIX_AND_URL_PATHS_MATCH;
}
#endif
ch = characterArray[pathRg.location + pathRg.length - 1];
if (ch == '/') {
isDir = true;
} else if (ch == '.') {
if (pathRg.length == 1) {
isDir = true;
} else {
ch = characterArray[pathRg.location + pathRg.length - 2];
if (ch == '/') {
isDir = true;
} else if (ch != '.') {
isDir = false;
} else if (pathRg.length == 2) {
isDir = true;
} else {
isDir = (characterArray[pathRg.location + pathRg.length - 3] == '/');
}
}
} else {
isDir = false;
}
} else {
isDir = (baseURL != NULL) ? CFURLHasDirectoryPath(baseURL) : false;
}
if (isDir) {
flags |= IS_DIRECTORY;
}
}
(*theFlags) = flags;
*numberOfRanges = numRanges;
numRanges = 0;
for (idx = 0, flags = 1; flags != (1<<9); flags = (flags<<1), idx ++) {
if ((*theFlags) & flags) {
packedRanges[numRanges] = unpackedRanges[idx];
numRanges ++;
}
}
}
}
#endif // CFURL_INCLUDE_PARSE_COMPONENTS
#ifdef CFURL_INCLUDE_SCAN_CHARACTERS // defined when we want this block of code included
{
CFIndex idx;
Boolean sawIllegalChar = false;
for (idx = base; idx < end; idx ++) {
Boolean shouldEscape;
UniChar ch = characterArray[idx];
if (isURLLegalCharacter(ch)) {
if ((componentFlag == HAS_USER || componentFlag == HAS_PASSWORD) && (ch == '/' || ch == '?' || ch == '@')) {
shouldEscape = true;
} else {
shouldEscape = false;
}
} else if (ch == '%' && idx + 2 < end && isHexDigit(characterArray[idx + 1]) && isHexDigit(characterArray[idx+2])) {
shouldEscape = false;
} else if (componentFlag == HAS_HOST && ((idx == base && ch == '[') || (idx == end-1 && ch == ']'))) {
shouldEscape = false;
} else {
shouldEscape = true;
}
if (shouldEscape) {
sawIllegalChar = true;
if (componentFlag && flags) {
*flags |= componentFlag;
}
if (!*escapedString) {
*escapedString = CFStringCreateMutable(alloc, 0);
}
if (useCString) {
CFStringRef tempString = CFStringCreateWithBytes(alloc, (uint8_t *)&(characterArray[*mark]), idx - *mark, kCFStringEncodingISOLatin1, false);
CFStringAppend(*escapedString, tempString);
CFRelease(tempString);
} else {
CFStringAppendCharacters(*escapedString, (const UniChar *)&(characterArray[*mark]), idx - *mark);
}
*mark = idx + 1;
_appendPercentEscapesForCharacter(ch, encoding, *escapedString); }
}
return sawIllegalChar;
}
#endif // CFURL_INCLUDE_SCAN_CHARACTERS