ObjFW  Check-in [fcaa549324]

Overview
Comment:A few more API improvements.

This should make it more future-proof, as adding new options is easier
than adding new methods for each and every combination of options.

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: fcaa549324c318e8c78464c95154352f6ac6608d017fd15594f913ec529deaed
User & Date: js on 2012-10-16 14:47:55
Other Links: manifest | tags
Context
2012-10-16
14:49
Fix a few forgotten renames. check-in: c47538ce8e user: js tags: trunk
14:47
A few more API improvements. check-in: fcaa549324 user: js tags: trunk
13:03
Make OFMethods comparable and hashable. check-in: c64a6fd74d user: js tags: trunk
Changes

Modified src/OFConstantString.m from [f72b46effc] to [4bef6d21b7].

350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
{
	[self finishInitialization];

	return [self rangeOfString: string];
}

- (of_range_t)rangeOfString: (OFString*)string
		    options: (of_string_search_options_t)options
{
	[self finishInitialization];

	return [self rangeOfString: string
			   options: options];
}








|







350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
{
	[self finishInitialization];

	return [self rangeOfString: string];
}

- (of_range_t)rangeOfString: (OFString*)string
		    options: (int)options
{
	[self finishInitialization];

	return [self rangeOfString: string
			   options: options];
}

Modified src/OFMutableString.h from [86f17a9e49] to [2c3f1dcc50].

163
164
165
166
167
168
169


170
171
172
173

174
175
176
177
178
179
180
181

/**
 * \brief Replaces all occurrences of a string in the specified range with
 *	  another string.
 *
 * \param string The string to replace
 * \param replacement The string with which it should be replaced


 * \param range The range in which the string should be replaced
 */
- (void)replaceOccurrencesOfString: (OFString*)string
			withString: (OFString*)replacement

			   inRange: (of_range_t)range;

/**
 * \brief Deletes all whitespaces at the beginning of the string.
 */
- (void)deleteLeadingWhitespaces;

/**







>
>




>
|







163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184

/**
 * \brief Replaces all occurrences of a string in the specified range with
 *	  another string.
 *
 * \param string The string to replace
 * \param replacement The string with which it should be replaced
 * \param options Options modifying search behaviour
 *		  Possible values: None yet
 * \param range The range in which the string should be replaced
 */
- (void)replaceOccurrencesOfString: (OFString*)string
			withString: (OFString*)replacement
			   options: (int)options
			     range: (of_range_t)range;

/**
 * \brief Deletes all whitespaces at the beginning of the string.
 */
- (void)deleteLeadingWhitespaces;

/**

Modified src/OFMutableString.m from [fbeacc8bf8] to [c4f091786b].

454
455
456
457
458
459
460

461
462
463
464
465

466
467
468
469
470
471
472
473
}

- (void)replaceOccurrencesOfString: (OFString*)string
			withString: (OFString*)replacement
{
	[self replaceOccurrencesOfString: string
			      withString: replacement

				 inRange: of_range(0, [self length])];
}

- (void)replaceOccurrencesOfString: (OFString*)string
			withString: (OFString*)replacement

			   inRange: (of_range_t)range
{
	void *pool = objc_autoreleasePoolPush(), *pool2;
	const of_unichar_t *unicodeString;
	const of_unichar_t *searchString = [string unicodeString];
	size_t searchLength = [string length];
	size_t replacementLength = [replacement length];
	size_t i;







>
|




>
|







454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
}

- (void)replaceOccurrencesOfString: (OFString*)string
			withString: (OFString*)replacement
{
	[self replaceOccurrencesOfString: string
			      withString: replacement
				 options: 0
				   range: of_range(0, [self length])];
}

- (void)replaceOccurrencesOfString: (OFString*)string
			withString: (OFString*)replacement
			   options: (int)options
			     range: (of_range_t)range
{
	void *pool = objc_autoreleasePoolPush(), *pool2;
	const of_unichar_t *unicodeString;
	const of_unichar_t *searchString = [string unicodeString];
	size_t searchLength = [string length];
	size_t replacementLength = [replacement length];
	size_t i;

Modified src/OFMutableString_UTF8.m from [df7ab28870] to [3b96c919ea].

591
592
593
594
595
596
597

598
599
600
601
602
603
604
605

	s->cStringLength = newCStringLength;
	s->length = newLength;
}

- (void)replaceOccurrencesOfString: (OFString*)string
			withString: (OFString*)replacement

			   inRange: (of_range_t)range
{
	const char *searchString = [string UTF8String];
	const char *replacementString = [replacement UTF8String];
	size_t searchLength = [string UTF8StringLength];
	size_t replacementLength = [replacement UTF8StringLength];
	size_t i, last, newCStringLength, newLength;
	char *newCString;







>
|







591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606

	s->cStringLength = newCStringLength;
	s->length = newLength;
}

- (void)replaceOccurrencesOfString: (OFString*)string
			withString: (OFString*)replacement
			   options: (int)options
			     range: (of_range_t)range
{
	const char *searchString = [string UTF8String];
	const char *replacementString = [replacement UTF8String];
	size_t searchLength = [string UTF8StringLength];
	size_t replacementLength = [replacement UTF8StringLength];
	size_t i, last, newCStringLength, newLength;
	char *newCString;

Modified src/OFString.h from [9619983a96] to [1cf435b925].

40
41
42
43
44
45
46
47
48
49

50
51
52
53
54
55
56
57
	OF_STRING_ENCODING_ASCII,
	OF_STRING_ENCODING_ISO_8859_1,
	OF_STRING_ENCODING_ISO_8859_15,
	OF_STRING_ENCODING_WINDOWS_1252,
	OF_STRING_ENCODING_AUTODETECT = 0xFF
} of_string_encoding_t;


typedef enum of_string_search_options_t {
	OF_STRING_SEARCH_BACKWARDS = 1

} of_string_search_options_t;

/* FIXME */
#define OF_STRING_ENCODING_NATIVE OF_STRING_ENCODING_UTF_8

#ifdef OF_HAVE_BLOCKS
typedef void (^of_string_line_enumeration_block_t)(OFString *line, BOOL *stop);
#endif







|
<
|
>
|







40
41
42
43
44
45
46
47

48
49
50
51
52
53
54
55
56
57
	OF_STRING_ENCODING_ASCII,
	OF_STRING_ENCODING_ISO_8859_1,
	OF_STRING_ENCODING_ISO_8859_15,
	OF_STRING_ENCODING_WINDOWS_1252,
	OF_STRING_ENCODING_AUTODETECT = 0xFF
} of_string_encoding_t;

enum {

	OF_STRING_SEARCH_BACKWARDS = 1,
	OF_STRING_SKIP_EMPTY	   = 2
};

/* FIXME */
#define OF_STRING_ENCODING_NATIVE OF_STRING_ENCODING_UTF_8

#ifdef OF_HAVE_BLOCKS
typedef void (^of_string_line_enumeration_block_t)(OFString *line, BOOL *stop);
#endif
623
624
625
626
627
628
629
630

631
632
633
634
635
636
637
638
639
640
641

642
643
644
645
646
647
648
649
650
651
652
653
654
 */
- (of_range_t)rangeOfString: (OFString*)string;

/**
 * \brief Returns the range of the string.
 *
 * \param string The string to search
 * \param options Options modifying search behaviour

 * \return The range of the first occurrence of the string or a range with
 *	   OF_NOT_FOUND as start position if it was not found
 */
- (of_range_t)rangeOfString: (OFString*)string
		    options: (of_string_search_options_t)options;

/**
 * \brief Returns the range of the string in the specified range.
 *
 * \param string The string to search
 * \param options Options modifying search behaviour

 * \param range The range in which to search
 * \return The range of the first occurrence of the string or a range with
 *	   OF_NOT_FOUND as start position if it was not found
 */
- (of_range_t)rangeOfString: (OFString*)string
		    options: (of_string_search_options_t)options
		      range: (of_range_t)range;

/**
 * \brief Returns whether the string contains the specified string.
 *
 * \param string The string to search
 * \return Whether the string contains the specified string







|
>




|





|
>





|







623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
 */
- (of_range_t)rangeOfString: (OFString*)string;

/**
 * \brief Returns the range of the string.
 *
 * \param string The string to search
 * \param options Options modifying search behaviour.
 *		  Possible values: OF_STRING_SEARCH_BACKWARDS
 * \return The range of the first occurrence of the string or a range with
 *	   OF_NOT_FOUND as start position if it was not found
 */
- (of_range_t)rangeOfString: (OFString*)string
		    options: (int)options;

/**
 * \brief Returns the range of the string in the specified range.
 *
 * \param string The string to search
 * \param options Options modifying search behaviour.
 *		  Possible values: OF_STRING_SEARCH_BACKWARDS
 * \param range The range in which to search
 * \return The range of the first occurrence of the string or a range with
 *	   OF_NOT_FOUND as start position if it was not found
 */
- (of_range_t)rangeOfString: (OFString*)string
		    options: (int)options
		      range: (of_range_t)range;

/**
 * \brief Returns whether the string contains the specified string.
 *
 * \param string The string to search
 * \return Whether the string contains the specified string
700
701
702
703
704
705
706


707
708
709
710
711

712
713
714
715
716
717
718
719

/**
 * \brief Creates a new string by replacing the occurrences of the specified
 *	  string in the specified range with the specified replacement.
 *
 * \param string The string to replace
 * \param replacement The string with which it should be replaced


 * \param range The range in which to replace the string
 * \return A new string with the occurrences of the specified string replaced
 */
- (OFString*)stringByReplacingOccurrencesOfString: (OFString*)string
				       withString: (OFString*)replacement

					  inRange: (of_range_t)range;

/**
 * \brief Returns the string in uppercase.
 *
 * \return The string in uppercase
 */
- (OFString*)uppercaseString;







>
>





>
|







702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724

/**
 * \brief Creates a new string by replacing the occurrences of the specified
 *	  string in the specified range with the specified replacement.
 *
 * \param string The string to replace
 * \param replacement The string with which it should be replaced
 * \param options Options modifying search behaviour.
 *		  Possible values: None yet
 * \param range The range in which to replace the string
 * \return A new string with the occurrences of the specified string replaced
 */
- (OFString*)stringByReplacingOccurrencesOfString: (OFString*)string
				       withString: (OFString*)replacement
					  options: (int)options
					    range: (of_range_t)range;

/**
 * \brief Returns the string in uppercase.
 *
 * \return The string in uppercase
 */
- (OFString*)uppercaseString;
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789

790
791
792
793
794
795
796
797
798
799
800
 *
 * \param suffix The suffix to check for
 * \return A boolean whether the string has the specified suffix
 */
- (BOOL)hasSuffix: (OFString*)suffix;

/**
 * \brief Splits an OFString into an OFArray of OFStrings.
 *
 * \param delimiter The delimiter for splitting
 * \return An autoreleased OFArray with the split string
 */
- (OFArray*)componentsSeparatedByString: (OFString*)delimiter;

/**
 * \brief Splits an OFString into an OFArray of OFStrings.
 *
 * \param delimiter The delimiter for splitting
 * \param skipEmpty Whether empty components should be skipped

 * \return An autoreleased OFArray with the split string
 */
- (OFArray*)componentsSeparatedByString: (OFString*)delimiter
			      skipEmpty: (BOOL)skipEmpty;

/**
 * \brief Returns the components of the path.
 *
 * \return The components of the path
 */
- (OFArray*)pathComponents;







|

|
|




|

|
|
>
|


|







776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
 *
 * \param suffix The suffix to check for
 * \return A boolean whether the string has the specified suffix
 */
- (BOOL)hasSuffix: (OFString*)suffix;

/**
 * \brief Separates an OFString into an OFArray of OFStrings.
 *
 * \param delimiter The delimiter for separating
 * \return An autoreleased OFArray with the separated string
 */
- (OFArray*)componentsSeparatedByString: (OFString*)delimiter;

/**
 * \brief Separates an OFString into an OFArray of OFStrings.
 *
 * \param delimiter The delimiter for separating
 * \param options Options according to which the string should be separated
 * 		  Possible values: OF_STRING_SKIP_EMPTY
 * \return An autoreleased OFArray with the separated string
 */
- (OFArray*)componentsSeparatedByString: (OFString*)delimiter
				options: (int)options;

/**
 * \brief Returns the components of the path.
 *
 * \return The components of the path
 */
- (OFArray*)pathComponents;

Modified src/OFString.m from [3bdf38b289] to [5e5459873a].

1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
{
	return [self rangeOfString: string
			   options: 0
			     range: of_range(0, [self length])];
}

- (of_range_t)rangeOfString: (OFString*)string
		    options: (of_string_search_options_t)options
{
	return [self rangeOfString: string
			   options: options
			     range: of_range(0, [self length])];
}

- (of_range_t)rangeOfString: (OFString*)string
		    options: (of_string_search_options_t)options
		      range: (of_range_t)range
{
	void *pool;
	const of_unichar_t *searchString;
	of_unichar_t *unicodeString;
	size_t i, searchLength;








|







|







1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
{
	return [self rangeOfString: string
			   options: 0
			     range: of_range(0, [self length])];
}

- (of_range_t)rangeOfString: (OFString*)string
		    options: (int)options
{
	return [self rangeOfString: string
			   options: options
			     range: of_range(0, [self length])];
}

- (of_range_t)rangeOfString: (OFString*)string
		    options: (int)options
		      range: (of_range_t)range
{
	void *pool;
	const of_unichar_t *searchString;
	of_unichar_t *unicodeString;
	size_t i, searchLength;

1322
1323
1324
1325
1326
1327
1328

1329
1330
1331
1332
1333
1334

1335
1336
1337
1338
1339
1340
1341
1342
	[new makeImmutable];

	return new;
}

- (OFString*)stringByReplacingOccurrencesOfString: (OFString*)string
				       withString: (OFString*)replacement

					  inRange: (of_range_t)range
{
	OFMutableString *new = [[self mutableCopy] autorelease];

	[new replaceOccurrencesOfString: string
			     withString: replacement

				inRange: range];

	[new makeImmutable];

	return new;
}

- (OFString*)uppercaseString







>
|





>
|







1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
	[new makeImmutable];

	return new;
}

- (OFString*)stringByReplacingOccurrencesOfString: (OFString*)string
				       withString: (OFString*)replacement
					  options: (int)options
					    range: (of_range_t)range
{
	OFMutableString *new = [[self mutableCopy] autorelease];

	[new replaceOccurrencesOfString: string
			     withString: replacement
				options: options
				  range: range];

	[new makeImmutable];

	return new;
}

- (OFString*)uppercaseString
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482

1483
1484
1485
1486
1487
1488
1489

	return !compare;
}

- (OFArray*)componentsSeparatedByString: (OFString*)delimiter
{
	return [self componentsSeparatedByString: delimiter
				       skipEmpty: NO];
}

- (OFArray*)componentsSeparatedByString: (OFString*)delimiter
			      skipEmpty: (BOOL)skipEmpty
{
	void *pool;
	OFMutableArray *array = [OFMutableArray array];
	const of_unichar_t *string, *delimiterString;

	size_t length = [self length];
	size_t delimiterLength = [delimiter length];
	size_t i, last;
	OFString *component;

	pool = objc_autoreleasePoolPush();








|



|




>







1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492

	return !compare;
}

- (OFArray*)componentsSeparatedByString: (OFString*)delimiter
{
	return [self componentsSeparatedByString: delimiter
					 options: 0];
}

- (OFArray*)componentsSeparatedByString: (OFString*)delimiter
				options: (int)options
{
	void *pool;
	OFMutableArray *array = [OFMutableArray array];
	const of_unichar_t *string, *delimiterString;
	BOOL skipEmpty = (options & OF_STRING_SKIP_EMPTY);
	size_t length = [self length];
	size_t delimiterLength = [delimiter length];
	size_t i, last;
	OFString *component;

	pool = objc_autoreleasePoolPush();

Modified src/OFString_UTF8.m from [b09a7e72c1] to [7a3937da16].

1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
	memcpy(buffer, unicodeString + range.location,
	    range.length * sizeof(of_unichar_t));

	objc_autoreleasePoolPop(pool);
}

- (of_range_t)rangeOfString: (OFString*)string
		    options: (of_string_search_options_t)options
		      range: (of_range_t)range
{
	const char *cString = [string UTF8String];
	size_t i, cStringLength = [string UTF8StringLength];
	size_t rangeLocation, rangeLength;

	if (range.length > SIZE_MAX - range.location ||







|







1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
	memcpy(buffer, unicodeString + range.location,
	    range.length * sizeof(of_unichar_t));

	objc_autoreleasePoolPop(pool);
}

- (of_range_t)rangeOfString: (OFString*)string
		    options: (int)options
		      range: (of_range_t)range
{
	const char *cString = [string UTF8String];
	size_t i, cStringLength = [string UTF8StringLength];
	size_t rangeLocation, rangeLength;

	if (range.length > SIZE_MAX - range.location ||
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168

1169
1170
1171
1172
1173
1174
1175
		return NO;

	return !memcmp(s->cString + (s->cStringLength - cStringLength),
	    [suffix UTF8String], cStringLength);
}

- (OFArray*)componentsSeparatedByString: (OFString*)delimiter
			      skipEmpty: (BOOL)skipEmpty
{
	void *pool;
	OFMutableArray *array;
	const char *cString = [delimiter UTF8String];
	size_t cStringLength = [delimiter UTF8StringLength];

	size_t i, last;
	OFString *component;

	array = [OFMutableArray array];
	pool = objc_autoreleasePoolPush();

	if (cStringLength > s->cStringLength) {







|





>







1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
		return NO;

	return !memcmp(s->cString + (s->cStringLength - cStringLength),
	    [suffix UTF8String], cStringLength);
}

- (OFArray*)componentsSeparatedByString: (OFString*)delimiter
				options: (int)options
{
	void *pool;
	OFMutableArray *array;
	const char *cString = [delimiter UTF8String];
	size_t cStringLength = [delimiter UTF8StringLength];
	BOOL skipEmpty = (options & OF_STRING_SKIP_EMPTY);
	size_t i, last;
	OFString *component;

	array = [OFMutableArray array];
	pool = objc_autoreleasePoolPush();

	if (cStringLength > s->cStringLength) {

Modified tests/OFStringTests.m from [8d7d5918e5] to [7769c4140e].

265
266
267
268
269
270
271
272
273

274
275
276
277
278
279
280
281
	    [[a objectAtIndex: i++] isEqual: @"bar"] &&
	    [[a objectAtIndex: i++] isEqual: @""] &&
	    [[a objectAtIndex: i++] isEqual: @"baz"] &&
	    [[a objectAtIndex: i++] isEqual: @""] &&
	    [[a objectAtIndex: i++] isEqual: @""])

	i = 0;
	TEST(@"-[componentsSeparatedByString:skipEmpty:]",
	    (a = [@"fooXXbarXXXXbazXXXX" componentsSeparatedByString: @"XX"

							   skipEmpty: YES]) &&
	    [a count] == 3 &&
	    [[a objectAtIndex: i++] isEqual: @"foo"] &&
	    [[a objectAtIndex: i++] isEqual: @"bar"] &&
	    [[a objectAtIndex: i++] isEqual: @"baz"])

	TEST(@"+[stringWithPath:]",
	    (is = [OFString stringWithPath: @"foo", @"bar", @"baz", nil]) &&







|
|
>
|







265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
	    [[a objectAtIndex: i++] isEqual: @"bar"] &&
	    [[a objectAtIndex: i++] isEqual: @""] &&
	    [[a objectAtIndex: i++] isEqual: @"baz"] &&
	    [[a objectAtIndex: i++] isEqual: @""] &&
	    [[a objectAtIndex: i++] isEqual: @""])

	i = 0;
	TEST(@"-[componentsSeparatedByString:options:]",
	    (a = [@"fooXXbarXXXXbazXXXX"
	    componentsSeparatedByString: @"XX"
				options: OF_STRING_SKIP_EMPTY]) &&
	    [a count] == 3 &&
	    [[a objectAtIndex: i++] isEqual: @"foo"] &&
	    [[a objectAtIndex: i++] isEqual: @"bar"] &&
	    [[a objectAtIndex: i++] isEqual: @"baz"])

	TEST(@"+[stringWithPath:]",
	    (is = [OFString stringWithPath: @"foo", @"bar", @"baz", nil]) &&
497
498
499
500
501
502
503
504
505
506
507
508

509
510
511
512
513
514
515
516
				    withString: @"foo"]) &&
	    [s[0] isEqual: @"asd foo asd foofoo asd"] &&
	    (s[0] = [OFMutableString stringWithString: @"XX"]) &&
	    R([s[0] replaceOccurrencesOfString: @"X"
				    withString: @"XX"]) &&
	    [s[0] isEqual: @"XXXX"])

	TEST(@"-[replaceOccurrencesOfString:withString:inRange:]",
	    (s[0] = [OFMutableString stringWithString:
	    @"foofoobarfoobarfoo"]) &&
	    R([s[0] replaceOccurrencesOfString: @"oo"
				    withString: @"óò"

				       inRange: of_range(2, 15)]) &&
	    [s[0] isEqual: @"foofóòbarfóòbarfoo"])

	TEST(@"-[deleteLeadingWhitespaces]",
	    (s[0] = [OFMutableString stringWithString: whitespace[0]]) &&
	    R([s[0] deleteLeadingWhitespaces]) &&
	    [s[0] isEqual: @"asd  \t \t\t\r\n"] &&
	    (s[0] = [OFMutableString stringWithString: whitespace[1]]) &&







|




>
|







498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
				    withString: @"foo"]) &&
	    [s[0] isEqual: @"asd foo asd foofoo asd"] &&
	    (s[0] = [OFMutableString stringWithString: @"XX"]) &&
	    R([s[0] replaceOccurrencesOfString: @"X"
				    withString: @"XX"]) &&
	    [s[0] isEqual: @"XXXX"])

	TEST(@"-[replaceOccurrencesOfString:withString:options:range:]",
	    (s[0] = [OFMutableString stringWithString:
	    @"foofoobarfoobarfoo"]) &&
	    R([s[0] replaceOccurrencesOfString: @"oo"
				    withString: @"óò"
				       options: 0
					 range: of_range(2, 15)]) &&
	    [s[0] isEqual: @"foofóòbarfóòbarfoo"])

	TEST(@"-[deleteLeadingWhitespaces]",
	    (s[0] = [OFMutableString stringWithString: whitespace[0]]) &&
	    R([s[0] deleteLeadingWhitespaces]) &&
	    [s[0] isEqual: @"asd  \t \t\t\r\n"] &&
	    (s[0] = [OFMutableString stringWithString: whitespace[1]]) &&