ObjFW  Check-in [d8a6ca3fbd]

Overview
Comment:There is no need to hash 32 bit per character if Unicode has only 24.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: d8a6ca3fbd04dd19e576378f34ec4c81c8d4b4df2a9a47dcbf9500c965e6cba8
User & Date: js on 2011-11-21 16:47:00
Other Links: manifest | tags
Context
2011-11-21
16:47
Implement -[OFString_UTF8 hash] for better performance. check-in: 855de7c3a7 user: js tags: trunk
16:47
There is no need to hash 32 bit per character if Unicode has only 24. check-in: d8a6ca3fbd user: js tags: trunk
15:32
Add new files to Xcode project. check-in: 6e83be4679 user: js tags: trunk
Changes

Modified src/OFString.m from [c57b8a6b12] to [598d9c6c56].

1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
	uint32_t hash;

	OF_HASH_INIT(hash);

	for (i = 0; i < length; i++) {
		const of_unichar_t c = unicodeString[i];

		OF_HASH_ADD(hash, (c & 0xFF000000) >> 24);
		OF_HASH_ADD(hash, (c & 0x00FF0000) >> 16);
		OF_HASH_ADD(hash, (c & 0x00FF0000) >>  8);
		OF_HASH_ADD(hash, c & 0xFF);
	}

	OF_HASH_FINALIZE(hash);

	return hash;
}








|
|
<
|







1097
1098
1099
1100
1101
1102
1103
1104
1105

1106
1107
1108
1109
1110
1111
1112
1113
	uint32_t hash;

	OF_HASH_INIT(hash);

	for (i = 0; i < length; i++) {
		const of_unichar_t c = unicodeString[i];

		OF_HASH_ADD(hash, (c & 0xFF0000) >> 16);
		OF_HASH_ADD(hash, (c & 0x00FF00) >>  8);

		OF_HASH_ADD(hash,  c & 0x0000FF);
	}

	OF_HASH_FINALIZE(hash);

	return hash;
}

Modified tests/OFDictionaryTests.m from [04d0bf130a] to [3c41c1f125].

94
95
96
97
98
99
100
101
102



103
104
105
106
107
108
109
		 forKey: keys[0]];

#ifdef OF_HAVE_FAST_ENUMERATION
	size_t i = 0;
	BOOL ok = YES;

	for (OFString *key in dict) {
		if (![key isEqual: keys[i]])
			ok = NO;



		[dict setObject: [dict objectForKey: key]
			 forKey: key];
		i++;
	}

	TEST(@"Fast Enumeration", ok)








|

>
>
>







94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
		 forKey: keys[0]];

#ifdef OF_HAVE_FAST_ENUMERATION
	size_t i = 0;
	BOOL ok = YES;

	for (OFString *key in dict) {
		if (i > 1 || ![key isEqual: keys[1 - i]]) {
			ok = NO;
			break;
		}

		[dict setObject: [dict objectForKey: key]
			 forKey: key];
		i++;
	}

	TEST(@"Fast Enumeration", ok)

124
125
126
127
128
129
130
131
132




133
134
135
136
137
138
139
#ifdef OF_HAVE_BLOCKS
	{
		__block size_t i = 0;
		__block BOOL ok = YES;

		[dict enumerateKeysAndObjectsUsingBlock:
		    ^ (id key, id obj, BOOL *stop) {
			if (![key isEqual: keys[i]])
				ok = NO;




			[dict setObject: [dict objectForKey: key]
				 forKey: key];
			i++;
		}];

		TEST(@"Enumeration using blocks", ok)








|

>
>
>
>







127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#ifdef OF_HAVE_BLOCKS
	{
		__block size_t i = 0;
		__block BOOL ok = YES;

		[dict enumerateKeysAndObjectsUsingBlock:
		    ^ (id key, id obj, BOOL *stop) {
			if (i > 1 || ![key isEqual: keys[1 - i]]) {
				ok = NO;
				*stop = YES;
				return;
			}

			[dict setObject: [dict objectForKey: key]
				 forKey: key];
			i++;
		}];

		TEST(@"Enumeration using blocks", ok)

170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
	    [[[dict mappedDictionaryUsingBlock: ^ id (id key, id obj) {
		if ([key isEqual: keys[0]])
			return @"val1";
		if ([key isEqual: keys[1]])
			return @"val2";

		return nil;
	    }] description] isEqual: @"{\n\tkey1 = val1;\n\tkey2 = val2;\n}"])

	TEST(@"-[filteredDictionaryUsingBlock:]",
	    [[[dict filteredDictionaryUsingBlock: ^ BOOL (id key, id obj) {
		return ([key isEqual: keys[0]] ?  YES : NO);
	    }] description] isEqual: @"{\n\tkey1 = value_1;\n}"])
#endif








|







177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
	    [[[dict mappedDictionaryUsingBlock: ^ id (id key, id obj) {
		if ([key isEqual: keys[0]])
			return @"val1";
		if ([key isEqual: keys[1]])
			return @"val2";

		return nil;
	    }] description] isEqual: @"{\n\tkey2 = val2;\n\tkey1 = val1;\n}"])

	TEST(@"-[filteredDictionaryUsingBlock:]",
	    [[[dict filteredDictionaryUsingBlock: ^ BOOL (id key, id obj) {
		return ([key isEqual: keys[0]] ?  YES : NO);
	    }] description] isEqual: @"{\n\tkey1 = value_1;\n}"])
#endif

Modified tests/OFSet.m from [809b5f5056] to [1652ab5388].

47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

	TEST(@"-[isEqual:]", [set1 isEqual: set2])

	TEST(@"-[hash]", [set1 hash] == [set2 hash])

	TEST(@"-[description]",
	    [[set1 description]
	    isEqual: @"{(\n\tbaz,\n\tbar,\n\tx,\n\tfoo\n)}"] &&
	    [[set1 description] isEqual: [set2 description]])

	TEST(@"-[copy]", [set1 isEqual: [[set1 copy] autorelease]])

	TEST(@"-[mutableCopy]",
	    (mutableSet = [[set1 mutableCopy] autorelease]));








|







47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

	TEST(@"-[isEqual:]", [set1 isEqual: set2])

	TEST(@"-[hash]", [set1 hash] == [set2 hash])

	TEST(@"-[description]",
	    [[set1 description]
	    isEqual: @"{(\n\tfoo,\n\tbaz,\n\tx,\n\tbar\n)}"] &&
	    [[set1 description] isEqual: [set2 description]])

	TEST(@"-[copy]", [set1 isEqual: [[set1 copy] autorelease]])

	TEST(@"-[mutableCopy]",
	    (mutableSet = [[set1 mutableCopy] autorelease]));

94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#ifdef OF_HAVE_FAST_ENUMERATION
	ok = YES;
	i = 0;

	for (OFString *s in set1) {
		switch (i) {
		case 0:
			if (![s isEqual: @"baz"])
				ok = NO;
			break;
		case 1:
			if (![s isEqual: @"bar"])
				ok = NO;
			break;
		case 2:
			if (![s isEqual: @"x"])
				ok = NO;
			break;
		case 3:
			if (![s isEqual: @"foo"])
				ok = NO;
			break;
		}

		i++;
	}








|



|







|







94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#ifdef OF_HAVE_FAST_ENUMERATION
	ok = YES;
	i = 0;

	for (OFString *s in set1) {
		switch (i) {
		case 0:
			if (![s isEqual: @"foo"])
				ok = NO;
			break;
		case 1:
			if (![s isEqual: @"baz"])
				ok = NO;
			break;
		case 2:
			if (![s isEqual: @"x"])
				ok = NO;
			break;
		case 3:
			if (![s isEqual: @"bar"])
				ok = NO;
			break;
		}

		i++;
	}

Modified tests/OFStringTests.m from [6206f4255c] to [7ac7e75e9c].

113
114
115
116
117
118
119
120
121
122
123
124
125
126
127

	TEST(@"-[appendString:] and -[appendUTF8String:]",
	    R([s[1] appendUTF8String: "1๐„ž"]) && R([s[1] appendString: @"3"]) &&
	    R([s[0] appendString: s[1]]) && [s[0] isEqual: @"tรคsโ‚ฌ1๐„ž3"])

	TEST(@"-[length]", [s[0] length] == 7)
	TEST(@"-[UTF8StringLength]", [s[0] UTF8StringLength] == 13)
	TEST(@"-[hash]", [s[0] hash] == 0x324B6743)

	TEST(@"-[characterAtIndex:]", [s[0] characterAtIndex: 0] == 't' &&
	    [s[0] characterAtIndex: 1] == 0xE4 &&
	    [s[0] characterAtIndex: 3] == 0x20AC &&
	    [s[0] characterAtIndex: 5] == 0x1D11E)

	EXPECT_EXCEPTION(@"Detect out of range in -[characterAtIndex:]",







|







113
114
115
116
117
118
119
120
121
122
123
124
125
126
127

	TEST(@"-[appendString:] and -[appendUTF8String:]",
	    R([s[1] appendUTF8String: "1๐„ž"]) && R([s[1] appendString: @"3"]) &&
	    R([s[0] appendString: s[1]]) && [s[0] isEqual: @"tรคsโ‚ฌ1๐„ž3"])

	TEST(@"-[length]", [s[0] length] == 7)
	TEST(@"-[UTF8StringLength]", [s[0] UTF8StringLength] == 13)
	TEST(@"-[hash]", [s[0] hash] == 0x2E623BD1)

	TEST(@"-[characterAtIndex:]", [s[0] characterAtIndex: 0] == 't' &&
	    [s[0] characterAtIndex: 1] == 0xE4 &&
	    [s[0] characterAtIndex: 3] == 0x20AC &&
	    [s[0] characterAtIndex: 5] == 0x1D11E)

	EXPECT_EXCEPTION(@"Detect out of range in -[characterAtIndex:]",

Modified tests/serialization.xml from [7633105928] to [12b8649327].

1
2
3

























4
5
6
7
8
9
10
<?xml version='1.0' encoding='UTF-8'?>
<serialization xmlns='https://webkeks.org/objfw/serialization' version='0'>
  <OFMutableDictionary>

























    <key>
      <OFList>
        <OFString>Hello</OFString>
        <OFString>Wo&#xD;ld!
How are you?</OFString>
        <OFURL>https://webkeks.org/</OFURL>
        <OFXMLElement name='x'>



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?xml version='1.0' encoding='UTF-8'?>
<serialization xmlns='https://webkeks.org/objfw/serialization' version='0'>
  <OFMutableDictionary>
    <key>
      <OFArray>
        <OFString>Qu&quot;xbar
test</OFString>
        <OFNumber type='signed'>1234</OFNumber>
        <OFNumber type='double'>0x1.34a456d5cfaadp+10</OFNumber>
        <OFMutableString>asd</OFMutableString>
        <OFDate>0x1.34a456d5cfaadp+10</OFDate>
      </OFArray>
    </key>
    <object>
      <OFString>Hello</OFString>
    </object>
    <key>
      <OFString>Blub</OFString>
    </key>
    <object>
      <OFString>B&quot;la</OFString>
    </object>
    <key>
      <OFDataArray>MDEyMzQ1Njc4OTo7PEFCQ0RFRkdISklLTE1OT1BRUlNUVVZXWFla</OFDataArray>
    </key>
    <object>
      <OFString>data</OFString>
    </object>
    <key>
      <OFList>
        <OFString>Hello</OFString>
        <OFString>Wo&#xD;ld!
How are you?</OFString>
        <OFURL>https://webkeks.org/</OFURL>
        <OFXMLElement name='x'>
45
46
47
48
49
50
51
52
53

54
55



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
                </namespaces>
              </OFXMLElement>
              <OFXMLCDATA><![CDATA[<]]></OFXMLCDATA>
            </OFMutableArray>
          </children>
        </OFXMLElement>
        <OFSet>
          <OFString>bar</OFString>
          <OFString>foo</OFString>

        </OFSet>
        <OFCountedSet>



          <object count='1'>
            <OFString>bar</OFString>
          </object>
          <object count='2'>
            <OFString>foo</OFString>
          </object>
        </OFCountedSet>
      </OFList>
    </key>
    <object>
      <OFString>list</OFString>
    </object>
    <key>
      <OFArray>
        <OFString>Qu&quot;xbar
test</OFString>
        <OFNumber type='signed'>1234</OFNumber>
        <OFNumber type='double'>0x1.34a456d5cfaadp+10</OFNumber>
        <OFMutableString>asd</OFMutableString>
        <OFDate>0x1.34a456d5cfaadp+10</OFDate>
      </OFArray>
    </key>
    <object>
      <OFString>Hello</OFString>
    </object>
    <key>
      <OFDataArray>MDEyMzQ1Njc4OTo7PEFCQ0RFRkdISklLTE1OT1BRUlNUVVZXWFla</OFDataArray>
    </key>
    <object>
      <OFString>data</OFString>
    </object>
    <key>
      <OFString>Blub</OFString>
    </key>
    <object>
      <OFString>B&quot;la</OFString>
    </object>
  </OFMutableDictionary>
</serialization>







<

>


>
>
>



<
<
<






<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


70
71
72
73
74
75
76

77
78
79
80
81
82
83
84
85
86



87
88
89
90
91
92

























93
94
                </namespaces>
              </OFXMLElement>
              <OFXMLCDATA><![CDATA[<]]></OFXMLCDATA>
            </OFMutableArray>
          </children>
        </OFXMLElement>
        <OFSet>

          <OFString>foo</OFString>
          <OFString>bar</OFString>
        </OFSet>
        <OFCountedSet>
          <object count='2'>
            <OFString>foo</OFString>
          </object>
          <object count='1'>
            <OFString>bar</OFString>
          </object>



        </OFCountedSet>
      </OFList>
    </key>
    <object>
      <OFString>list</OFString>
    </object>

























  </OFMutableDictionary>
</serialization>