33 * (yes, C is bad ...) |
33 * (yes, C is bad ...) |
34 */ |
34 */ |
35 #define __fetchBytePointerAndSize__(o, pPtr, pSize) \ |
35 #define __fetchBytePointerAndSize__(o, pPtr, pSize) \ |
36 {\ |
36 {\ |
37 if (__isNonNilObject(o)) { \ |
37 if (__isNonNilObject(o)) { \ |
38 if (__isByteArrayLike(o)) { \ |
38 if (__isByteArrayLike(o)) { \ |
39 *(pPtr) = (unsigned char *)__ByteArrayInstPtr(o)->ba_element; \ |
39 *(pPtr) = (unsigned char *)__ByteArrayInstPtr(o)->ba_element; \ |
40 *(pSize) = __byteArraySize(o); \ |
40 *(pSize) = __byteArraySize(o); \ |
41 } else if (__qIsExternalBytesLike(o)) { \ |
41 } else if (__qIsExternalBytesLike(o)) { \ |
42 OBJ __sz__ = __externalBytesSize(o); \ |
42 OBJ __sz__ = __externalBytesSize(o); \ |
43 if (__isSmallInteger(__sz__)) { \ |
43 if (__isSmallInteger(__sz__)) { \ |
44 *(pSize) = __intVal(__sz__); \ |
44 *(pSize) = __intVal(__sz__); \ |
45 *(pPtr) = (unsigned char *)(__externalBytesAddress(o)); \ |
45 *(pPtr) = (unsigned char *)(__externalBytesAddress(o)); \ |
46 } else { \ |
46 } else { \ |
47 *(pSize) = 0; \ |
47 *(pSize) = 0; \ |
48 *(pPtr) = (unsigned char *)0; \ |
48 *(pPtr) = (unsigned char *)0; \ |
49 } \ |
49 } \ |
50 } else { \ |
50 } else { \ |
51 *(pSize) /* nInstBytes */ = OHDR_SIZE + __OBJS2BYTES__(__intVal(__ClassInstPtr(__qClass(o))->c_ninstvars)); \ |
51 *(pSize) /* nInstBytes */ = OHDR_SIZE + __OBJS2BYTES__(__intVal(__ClassInstPtr(__qClass(o))->c_ninstvars)); \ |
52 *(pPtr) = (char *)(__InstPtr(self)) + *(pSize) /* nInstBytes */; \ |
52 *(pPtr) = (char *)(__InstPtr(self)) + *(pSize) /* nInstBytes */; \ |
53 *(pSize) = __qSize(self) - *(pSize) /* nInstBytes */; \ |
53 *(pSize) = __qSize(self) - *(pSize) /* nInstBytes */; \ |
54 } \ |
54 } \ |
55 } else { \ |
55 } else { \ |
56 *(pSize) = 0; \ |
56 *(pSize) = 0; \ |
57 *(pPtr) = (unsigned char *)0; \ |
57 *(pPtr) = (unsigned char *)0; \ |
58 } \ |
58 } \ |
59 } |
59 } |
60 |
60 |
61 %} |
61 %} |
62 ! ! |
62 ! ! |
170 "read a bytearray from a printed string representation, where |
170 "read a bytearray from a printed string representation, where |
171 individual bytes are encoded as two hex digits, optionally separated by whiteSpace. |
171 individual bytes are encoded as two hex digits, optionally separated by whiteSpace. |
172 See also fromHexString:, which does something similar, but does not allow for spaces" |
172 See also fromHexString:, which does something similar, but does not allow for spaces" |
173 |
173 |
174 ^ self streamContents:[:outStream | |
174 ^ self streamContents:[:outStream | |
175 |inStream h| |
175 |inStream h| |
176 |
176 |
177 inStream := aString readStream. |
177 inStream := aString readStream. |
178 |
178 |
179 [ |
179 [ |
180 inStream skipSeparators. |
180 inStream skipSeparators. |
181 inStream atEnd |
181 inStream atEnd |
182 ] whileFalse:[ |
182 ] whileFalse:[ |
183 h := inStream next:2. |
183 h := inStream next:2. |
184 outStream nextPut:(Integer readFrom:h base:16). |
184 outStream nextPut:(Integer readFrom:h base:16). |
185 ]. |
185 ]. |
186 ]. |
186 ]. |
187 |
187 |
188 " |
188 " |
189 ByteArray fromHexString:'1234FEFF' |
189 ByteArray fromHexString:'1234FEFF' |
190 ByteArray fromHexStringWithSeparators:' 12 34 FE FF' |
190 ByteArray fromHexStringWithSeparators:' 12 34 FE FF' |
220 "the size modulo 3 is encoded in the last character, if it is in the |
220 "the size modulo 3 is encoded in the last character, if it is in the |
221 range 97 .. otherwise, its exact." |
221 range 97 .. otherwise, its exact." |
222 |
222 |
223 last := aString last codePoint. |
223 last := aString last codePoint. |
224 last > 96 ifTrue:[ |
224 last > 96 ifTrue:[ |
225 stop := stop - 3 + (last - 96) |
225 stop := stop - 3 + (last - 96) |
226 ]. |
226 ]. |
227 bytes := self new:stop. |
227 bytes := self new:stop. |
228 |
228 |
229 index := 1. dstIndex := 1. |
229 index := 1. dstIndex := 1. |
230 [dstIndex <= stop] whileTrue:[ |
230 [dstIndex <= stop] whileTrue:[ |
231 "/ take 4 characters ... |
231 "/ take 4 characters ... |
232 "/ allow a line break before each group of 4 |
232 "/ allow a line break before each group of 4 |
233 sixBits := (aString at:index) codePoint. |
233 sixBits := (aString at:index) codePoint. |
234 [sixBits < 32] whileTrue:[ |
234 [sixBits < 32] whileTrue:[ |
235 index := index + 1. |
235 index := index + 1. |
236 sixBits := (aString at:index) codePoint. |
236 sixBits := (aString at:index) codePoint. |
237 ]. |
237 ]. |
238 sixBits := sixBits bitAnd:16r3F. |
238 sixBits := sixBits bitAnd:16r3F. |
239 n := sixBits. |
239 n := sixBits. |
240 |
240 |
241 "/ self assert:(aString at:index+1) codePoint >= 32. |
241 "/ self assert:(aString at:index+1) codePoint >= 32. |
242 sixBits := (aString at:index+1) codePoint bitAnd:16r3F. |
242 sixBits := (aString at:index+1) codePoint bitAnd:16r3F. |
243 n := (n bitShift:6) + sixBits. |
243 n := (n bitShift:6) + sixBits. |
244 |
244 |
245 "/ self assert:(aString at:index+2) codePoint >= 32. |
245 "/ self assert:(aString at:index+2) codePoint >= 32. |
246 sixBits := (aString at:index+2) codePoint bitAnd:16r3F. |
246 sixBits := (aString at:index+2) codePoint bitAnd:16r3F. |
247 n := (n bitShift:6) + sixBits. |
247 n := (n bitShift:6) + sixBits. |
248 |
248 |
249 "/ self assert:(aString at:index+3) codePoint >= 32. |
249 "/ self assert:(aString at:index+3) codePoint >= 32. |
250 sixBits := (aString at:index+3) codePoint bitAnd:16r3F. |
250 sixBits := (aString at:index+3) codePoint bitAnd:16r3F. |
251 n := (n bitShift:6) + sixBits. |
251 n := (n bitShift:6) + sixBits. |
252 |
252 |
253 index := index + 4. |
253 index := index + 4. |
254 |
254 |
255 "/ now have 24 bits in n |
255 "/ now have 24 bits in n |
256 |
256 |
257 bytes at:dstIndex put:(n bitShift:-16). |
257 bytes at:dstIndex put:(n bitShift:-16). |
258 |
258 |
259 dstIndex < stop ifTrue:[ |
259 dstIndex < stop ifTrue:[ |
260 bytes at:dstIndex+1 put:((n bitShift:-8) bitAnd:16rFF). |
260 bytes at:dstIndex+1 put:((n bitShift:-8) bitAnd:16rFF). |
261 dstIndex+2 <= stop ifTrue:[ |
261 dstIndex+2 <= stop ifTrue:[ |
262 bytes at:dstIndex+2 put:(n bitAnd:16rFF). |
262 bytes at:dstIndex+2 put:(n bitAnd:16rFF). |
263 ] |
263 ] |
264 ]. |
264 ]. |
265 dstIndex := dstIndex + 3. |
265 dstIndex := dstIndex + 3. |
266 ]. |
266 ]. |
267 ^ bytes |
267 ^ bytes |
268 |
268 |
269 " |
269 " |
270 ByteArray fromPackedString:(#[1 1 1 1] asPackedString) |
270 ByteArray fromPackedString:(#[1 1 1 1] asPackedString) |
312 OBJ newobj; |
312 OBJ newobj; |
313 INT instsize, nInstVars, nindexedinstvars; |
313 INT instsize, nInstVars, nindexedinstvars; |
314 REGISTER OBJ *op; |
314 REGISTER OBJ *op; |
315 |
315 |
316 if (__isSmallInteger(anInteger)) { |
316 if (__isSmallInteger(anInteger)) { |
317 nindexedinstvars = __intVal(anInteger); |
317 nindexedinstvars = __intVal(anInteger); |
318 if (nindexedinstvars >= 0) { |
318 if (nindexedinstvars >= 0) { |
319 if (self == ByteArray) { |
319 if (self == ByteArray) { |
320 /* |
320 /* |
321 * the most common case |
321 * the most common case |
322 */ |
322 */ |
323 instsize = OHDR_SIZE + nindexedinstvars; |
323 instsize = OHDR_SIZE + nindexedinstvars; |
324 if (__CanDoQuickNew(instsize)) { /* OBJECT ALLOCATION */ |
324 if (__CanDoQuickNew(instsize)) { /* OBJECT ALLOCATION */ |
325 __qCheckedNew(newobj, instsize); |
325 __qCheckedNew(newobj, instsize); |
326 __InstPtr(newobj)->o_class = self; |
326 __InstPtr(newobj)->o_class = self; |
327 __qSTORE(newobj, self); |
327 __qSTORE(newobj, self); |
328 RETURN (newobj ); |
328 RETURN (newobj ); |
329 } |
329 } |
330 } else { |
330 } else { |
331 /* |
331 /* |
332 * Take care for subclasses like TwoByteString |
332 * Take care for subclasses like TwoByteString |
333 */ |
333 */ |
334 switch (__smallIntegerVal(__ClassInstPtr(self)->c_flags) & ARRAYMASK) { |
334 switch (__smallIntegerVal(__ClassInstPtr(self)->c_flags) & ARRAYMASK) { |
335 case BYTEARRAY: |
335 case BYTEARRAY: |
336 break; |
336 break; |
337 |
337 |
338 case WORDARRAY: |
338 case WORDARRAY: |
339 case SWORDARRAY: |
339 case SWORDARRAY: |
340 nindexedinstvars *= 2; |
340 nindexedinstvars *= 2; |
341 break; |
341 break; |
342 |
342 |
343 case LONGARRAY: |
343 case LONGARRAY: |
344 case SLONGARRAY: |
344 case SLONGARRAY: |
345 nindexedinstvars *= 4; |
345 nindexedinstvars *= 4; |
346 break; |
346 break; |
347 |
347 |
348 default: |
348 default: |
349 /* don't know about this array type, delegate to super */ |
349 /* don't know about this array type, delegate to super */ |
350 goto out; |
350 goto out; |
351 } |
351 } |
352 } |
352 } |
353 nInstVars = __intVal(__ClassInstPtr(self)->c_ninstvars); |
353 nInstVars = __intVal(__ClassInstPtr(self)->c_ninstvars); |
354 instsize = OHDR_SIZE + __OBJS2BYTES__(nInstVars) + nindexedinstvars; |
354 instsize = OHDR_SIZE + __OBJS2BYTES__(nInstVars) + nindexedinstvars; |
355 __PROTECT_CONTEXT__ |
355 __PROTECT_CONTEXT__ |
356 __qNew(newobj, instsize); /* OBJECT ALLOCATION */ |
356 __qNew(newobj, instsize); /* OBJECT ALLOCATION */ |
357 __UNPROTECT_CONTEXT__ |
357 __UNPROTECT_CONTEXT__ |
358 if (newobj != nil) { |
358 if (newobj != nil) { |
359 __InstPtr(newobj)->o_class = self; |
359 __InstPtr(newobj)->o_class = self; |
360 __qSTORE(newobj, self); |
360 __qSTORE(newobj, self); |
361 if (nInstVars) { |
361 if (nInstVars) { |
362 /* |
362 /* |
363 * still have to nil out named instvars ... |
363 * still have to nil out named instvars ... |
364 */ |
364 */ |
365 #if defined(memset4) && defined(FAST_OBJECT_MEMSET4) |
365 #if defined(memset4) && defined(FAST_OBJECT_MEMSET4) |
366 memset4(__InstPtr(newobj)->i_instvars, nil, nInstVars); |
366 memset4(__InstPtr(newobj)->i_instvars, nil, nInstVars); |
367 #else |
367 #else |
368 # if defined(FAST_MEMSET) && !defined(NEGATIVE_ADDRESSES) |
368 # if defined(FAST_MEMSET) && !defined(NEGATIVE_ADDRESSES) |
369 /* |
369 /* |
370 * knowing that nil is 0 |
370 * knowing that nil is 0 |
371 */ |
371 */ |
372 memset(__InstPtr(newobj)->i_instvars, 0, instsize - OHDR_SIZE); |
372 memset(__InstPtr(newobj)->i_instvars, 0, instsize - OHDR_SIZE); |
373 # else |
373 # else |
374 op = __InstPtr(newobj)->i_instvars; |
374 op = __InstPtr(newobj)->i_instvars; |
375 while (nInstVars--) |
375 while (nInstVars--) |
376 *op++ = nil; |
376 *op++ = nil; |
377 # endif |
377 # endif |
378 #endif |
378 #endif |
379 } |
379 } |
380 RETURN ( newobj ); |
380 RETURN ( newobj ); |
381 } |
381 } |
382 } |
382 } |
383 } |
383 } |
384 out:; |
384 out:; |
385 %}. |
385 %}. |
386 ^ self basicNew:anInteger |
386 ^ self basicNew:anInteger |
387 ! |
387 ! |
2477 The index is a smalltalk index (i.e. 1-based). |
2478 The index is a smalltalk index (i.e. 1-based). |
2478 Only aligned accesses are allowed." |
2479 Only aligned accesses are allowed." |
2479 |
2480 |
2480 %{ |
2481 %{ |
2481 if (__isSmallInteger(index)) { |
2482 if (__isSmallInteger(index)) { |
2482 unsigned char *cp; |
2483 unsigned char *cp; |
2483 INT sz; |
2484 INT sz; |
2484 |
2485 |
2485 __fetchBytePointerAndSize__(self, &cp, &sz); |
2486 __fetchBytePointerAndSize__(self, &cp, &sz); |
2486 if (cp) { |
2487 if (cp) { |
2487 unsigned INT idx = ((unsigned INT)__smallIntegerVal(index)) - 1; |
2488 unsigned INT idx = ((unsigned INT)__smallIntegerVal(index)) - 1; |
2488 char *pointer; |
2489 char *pointer; |
2489 |
2490 |
2490 if ((idx+(sizeof(pointer)-1)) < sz) { |
2491 if ((idx+(sizeof(pointer)-1)) < sz) { |
2491 cp += idx; |
2492 cp += idx; |
2492 /* |
2493 /* |
2493 * aligned |
2494 * aligned |
2494 */ |
2495 */ |
2495 if (((INT)cp & (sizeof(pointer)-1)) == 0) { |
2496 if (((INT)cp & (sizeof(pointer)-1)) == 0) { |
2496 pointer = ((char **)cp)[0]; |
2497 pointer = ((char **)cp)[0]; |
2497 RETURN (__MKEXTERNALADDRESS(pointer)); |
2498 RETURN (__MKEXTERNALADDRESS(pointer)); |
2498 } else { |
2499 } else { |
2499 #if 0 |
2500 #if 0 |
2500 printf("cp UNALIGNED (%"_lx_")\n", (INT)cp); |
2501 printf("cp UNALIGNED (%"_lx_")\n", (INT)cp); |
2501 #endif |
2502 #endif |
2502 } |
2503 } |
2503 } else { |
2504 } else { |
2504 #if 0 |
2505 #if 0 |
2505 printf("idx(%"_ld_")+(sizeof(pointer)-1) (%d) >= sz (%"_ld_")\n", |
2506 printf("idx(%"_ld_")+(sizeof(pointer)-1) (%d) >= sz (%"_ld_")\n", |
2506 idx, (int)(sizeof(pointer)-1), sz); |
2507 idx, (int)(sizeof(pointer)-1), sz); |
2507 #endif |
2508 #endif |
2508 } |
2509 } |
2509 } else { |
2510 } else { |
2510 #if 0 |
2511 #if 0 |
2511 printf("cp is NULL\n"); |
2512 printf("cp is NULL\n"); |
2512 #endif |
2513 #endif |
2513 } |
2514 } |
2514 } else { |
2515 } else { |
2515 #if 0 |
2516 #if 0 |
2516 printf("bad index\n"); |
2517 printf("bad index\n"); |
2517 #endif |
2518 #endif |
2518 } |
2519 } |
2519 bad:; |
2520 bad:; |
2520 %}. |
2521 %}. |
2521 |
2522 |
2538 |
2539 |
2539 %{ |
2540 %{ |
2540 OBJ *pointer; |
2541 OBJ *pointer; |
2541 |
2542 |
2542 if (__isExternalAddressLike(value)) { |
2543 if (__isExternalAddressLike(value)) { |
2543 pointer = __externalAddressVal(value); |
2544 pointer = __externalAddressVal(value); |
2544 } else if (__isExternalBytesLike(value)) { |
2545 } else if (__isExternalBytesLike(value)) { |
2545 pointer = __externalBytesVal(value); |
2546 pointer = __externalBytesVal(value); |
2546 if (pointer == (OBJ *)0) |
2547 if (pointer == (OBJ *)0) |
2547 pointer = 0; |
2548 pointer = 0; |
2548 } else if (value == nil) { |
2549 } else if (value == nil) { |
2549 pointer = 0; |
2550 pointer = 0; |
2550 } else if (__isSmallInteger(value)) { |
2551 } else if (__isSmallInteger(value)) { |
2551 pointer = (OBJ *)__intVal(value); |
2552 pointer = (OBJ *)__intVal(value); |
2552 } else { |
2553 } else { |
2553 if ((pointer = (OBJ *)__unsignedLongIntVal(value)) == 0) { |
2554 if ((pointer = (OBJ *)__unsignedLongIntVal(value)) == 0) { |
2554 goto bad; |
2555 goto bad; |
2555 } |
2556 } |
2556 } |
2557 } |
2557 |
2558 |
2558 if (__isSmallInteger(index)) { |
2559 if (__isSmallInteger(index)) { |
2559 unsigned char *cp; |
2560 unsigned char *cp; |
2560 INT sz; |
2561 INT sz; |
2561 |
2562 |
2562 __fetchBytePointerAndSize__(self, &cp, &sz); |
2563 __fetchBytePointerAndSize__(self, &cp, &sz); |
2563 if (cp) { |
2564 if (cp) { |
2564 unsigned INT idx = ((unsigned INT)__smallIntegerVal(index)) - 1; |
2565 unsigned INT idx = ((unsigned INT)__smallIntegerVal(index)) - 1; |
2565 |
2566 |
2566 if ((idx+(sizeof(pointer)-1)) < sz) { |
2567 if ((idx+(sizeof(pointer)-1)) < sz) { |
2567 cp += idx; |
2568 cp += idx; |
2568 /* |
2569 /* |
2569 * aligned |
2570 * aligned |
2570 */ |
2571 */ |
2571 if (((INT)cp & (sizeof(pointer)-1)) == 0) { |
2572 if (((INT)cp & (sizeof(pointer)-1)) == 0) { |
2572 ((char **)cp)[0] = (char *) pointer; |
2573 ((char **)cp)[0] = (char *) pointer; |
2573 RETURN (value); |
2574 RETURN (value); |
2574 } |
2575 } |
2575 } |
2576 } |
2576 } |
2577 } |
2577 } |
2578 } |
2578 bad:; |
2579 bad:; |
2579 %}. |
2580 %}. |
2580 |
2581 |
2581 self primitiveFailed. |
2582 self primitiveFailed. |
3154 ! |
3155 ! |
3155 |
3156 |
3156 signedInt16At:byteIndex MSB:msb |
3157 signedInt16At:byteIndex MSB:msb |
3157 "return the 2-bytes starting at index as a signed Integer. |
3158 "return the 2-bytes starting at index as a signed Integer. |
3158 The index is a smalltalk index (i.e. 1-based). |
3159 The index is a smalltalk index (i.e. 1-based). |
3159 The value is retrieved in the machines natural byte order. |
3160 The value is retrieved MSB (high 8 bits at lower index) if msb is true; |
3160 This may be worth a primitive." |
3161 LSB-first (i.e. low 8-bits at lower byte index) if it's false. |
3161 |
3162 Notice: |
3162 ^ (self unsignedInt16At:byteIndex MSB:msb) signExtendedShortValue |
3163 the index is a byte index; thus, this allows for unaligned access to |
3163 |
3164 words on any boundary." |
3164 " |
3165 |
3165 |b| |
3166 |b1 "{ Class: SmallInteger }" |
3166 b := ByteArray new:2. |
3167 b2 "{ Class: SmallInteger }"| |
3167 b wordAt:1 put:16rFFFF. |
3168 |
3168 b signedWordAt:1 |
3169 %{ |
3169 " |
3170 /* |
3170 |
3171 * handle the most common cases fast ... |
3171 "Modified: 1.7.1996 / 21:14:38 / cg" |
3172 */ |
|
3173 if (__isSmallInteger(byteIndex)) { |
|
3174 unsigned char *cp; |
|
3175 INT sz; |
|
3176 |
|
3177 __fetchBytePointerAndSize__(self, &cp, &sz); |
|
3178 if (cp) { |
|
3179 unsigned INT idx = ((unsigned INT)__intVal(byteIndex)) - 1; |
|
3180 |
|
3181 if ((idx+(2-1)) < sz) { |
|
3182 short sVal; |
|
3183 |
|
3184 cp += idx; |
|
3185 if (msb == false) { |
|
3186 #if defined(__i386__) || (defined(__LSBFIRST__) && defined(UNALIGNED_FETCH_OK)) |
|
3187 /* |
|
3188 * aligned or not, we dont care (i386 can do both) |
|
3189 */ |
|
3190 sVal = ((short *)cp)[0]; |
|
3191 #else |
|
3192 sVal = (cp[0] & 0xFF) | ((cp[1] & 0xFF) << 8); |
|
3193 #endif |
|
3194 } else { |
|
3195 sVal = ((cp[0] & 0xFF) << 8) | (cp[1] & 0xFF); |
|
3196 } |
|
3197 RETURN (__mkSmallInteger(sVal)); |
|
3198 } |
|
3199 } |
|
3200 } |
|
3201 %}. |
|
3202 |
|
3203 b1 := self byteAt:byteIndex. |
|
3204 b2 := self byteAt:(byteIndex + 1). |
|
3205 msb ifTrue:[ |
|
3206 ^ ((b1 bitShift:8) + b2) signExtendedShortValue |
|
3207 ]. |
|
3208 ^ ((b2 bitShift:8) + b1) signExtendedShortValue |
3172 ! |
3209 ! |
3173 |
3210 |
3174 signedInt16At:index put:anInteger |
3211 signedInt16At:index put:anInteger |
3175 "set the 2-bytes starting at index from the signed Integer value. |
3212 "set the 2-bytes starting at index from the signed Integer value. |
3176 The index is a smalltalk index (i.e. 1-based). |
3213 The index is a smalltalk index (i.e. 1-based). |
3188 " |
3225 " |
3189 |
3226 |
3190 "Modified: 1.7.1996 / 21:12:13 / cg" |
3227 "Modified: 1.7.1996 / 21:12:13 / cg" |
3191 ! |
3228 ! |
3192 |
3229 |
3193 signedInt16At:index put:anInteger MSB:msb |
3230 signedInt16At:byteIndex put:anInteger MSB:msb |
3194 "set the 2-bytes starting at index from the signed Integer value. |
3231 "set the 2-bytes starting at byteIndex from the signed integer value. |
3195 The index is a smalltalk index (i.e. 1-based). |
3232 The byteIndex is a smalltalk index (i.e. 1-based). |
3196 The stored value must be in the range -32768 .. +32676. |
3233 The stored value must be in the range -32768 .. +32676. |
3197 The value is stored MSB-first, if the msb-arg is true; |
3234 The value is stored MSB-first, if the msb-arg is true; |
3198 LSB-first otherwise. |
3235 LSB-first otherwise." |
3199 This may be worth a primitive." |
3236 |
3200 |
3237 %{ /* NOCONTEXT */ |
3201 |v| |
3238 /* |
3202 |
3239 * handle the most common case fast ... |
|
3240 */ |
|
3241 if (__isSmallInteger(byteIndex)) { |
|
3242 unsigned char *cp; |
|
3243 INT sz; |
|
3244 |
|
3245 __fetchBytePointerAndSize__(self, &cp, &sz); |
|
3246 if (cp) { |
|
3247 unsigned INT idx = ((unsigned INT)__intVal(byteIndex)) - 1; |
|
3248 |
|
3249 if ((idx+1) < sz) { |
|
3250 cp += idx; |
|
3251 |
|
3252 if (__isSmallInteger(anInteger)) { |
|
3253 INT __v = __intVal(anInteger); |
|
3254 |
|
3255 if ((__v < -0x8000L) || (__v > 0x7FFF)) { |
|
3256 goto badArg; |
|
3257 } |
|
3258 if (msb == false) { |
|
3259 #if defined(__i386__) || (defined(__LSBFIRST__) && defined(UNALIGNED_FETCH_OK)) |
|
3260 ((short *)cp)[0] = (short)__v; |
|
3261 #else |
|
3262 cp[0] = __v & 0xFF; |
|
3263 cp[1] = (__v >> 8) & 0xFF; |
|
3264 #endif |
|
3265 } else { |
|
3266 cp[0] = (__v >> 8) & 0xFF; |
|
3267 cp[1] = __v & 0xFF; |
|
3268 } |
|
3269 RETURN (anInteger); |
|
3270 } |
|
3271 } |
|
3272 } |
|
3273 } |
|
3274 badArg: ; |
|
3275 %}. |
3203 anInteger >= 0 ifTrue:[ |
3276 anInteger >= 0 ifTrue:[ |
3204 v := anInteger |
3277 self unsignedInt16At:byteIndex put:anInteger MSB:msb. |
3205 ] ifFalse:[ |
3278 ] ifFalse:[ |
3206 v := 16r10000 + anInteger |
3279 self unsignedInt16At:byteIndex put:(16r10000 + anInteger) MSB:msb. |
3207 ]. |
3280 ]. |
3208 self unsignedInt16At:index put:v MSB:msb. |
|
3209 ^ anInteger |
3281 ^ anInteger |
3210 |
3282 |
3211 " |
3283 " |
3212 |b| |
3284 |b| |
3213 b := ByteArray new:4. |
3285 b := ByteArray new:4. |
3214 b signedWordAt:1 put:-1. |
3286 b signedInt16At:1 put:-1. |
3215 b signedWordAt:3 put:-2. |
3287 b signedInt16At:3 put:-2. |
3216 b inspect |
3288 b inspect |
3217 " |
3289 " |
3218 |
3290 |
3219 "Modified: 1.7.1996 / 21:12:13 / cg" |
3291 "Modified: 1.7.1996 / 21:12:13 / cg" |
3220 ! |
3292 ! |
3226 Subclasses may redefine this for better performance." |
3298 Subclasses may redefine this for better performance." |
3227 |
3299 |
3228 ^ self unsignedInt16At:index MSB:IsBigEndian |
3300 ^ self unsignedInt16At:index MSB:IsBigEndian |
3229 ! |
3301 ! |
3230 |
3302 |
3231 unsignedInt16At:index MSB:msb |
3303 unsignedInt16At:byteIndex MSB:msb |
3232 "return the 2-bytes starting at index as an (unsigned) Integer. |
3304 "return the 2-bytes starting at index as an (unsigned) Integer. |
3233 The index is a smalltalk index (i.e. 1-based). |
3305 The index is a smalltalk index (i.e. 1-based). |
3234 The value is retrieved MSB (high 8 bits at lower index) if msb is true; |
3306 The value is retrieved MSB (high 8 bits at lower index) if msb is true; |
3235 LSB-first (i.e. low 8-bits at lower byte index) if its false. |
3307 LSB-first (i.e. low 8-bits at lower byte index) if it's false. |
3236 Notice: |
3308 Notice: |
3237 the index is a byte index; thus, this allows for unaligned access to |
3309 the index is a byte index; thus, this allows for unaligned access to |
3238 words on any boundary." |
3310 words on any boundary." |
3239 |
3311 |
3240 |b1 "{ Class: SmallInteger }" |
3312 |b1 "{ Class: SmallInteger }" |
3241 b2 "{ Class: SmallInteger }"| |
3313 b2 "{ Class: SmallInteger }"| |
3242 |
3314 |
3243 b1 := self byteAt:index. |
3315 %{ |
3244 b2 := self byteAt:(index + 1). |
3316 /* |
|
3317 * handle the most common cases fast ... |
|
3318 */ |
|
3319 if (__isSmallInteger(byteIndex)) { |
|
3320 unsigned char *cp; |
|
3321 INT sz; |
|
3322 |
|
3323 __fetchBytePointerAndSize__(self, &cp, &sz); |
|
3324 if (cp) { |
|
3325 unsigned INT idx = ((unsigned INT)__intVal(byteIndex)) - 1; |
|
3326 |
|
3327 if ((idx+(2-1)) < sz) { |
|
3328 int iVal; |
|
3329 |
|
3330 cp += idx; |
|
3331 if (msb == false) { |
|
3332 #if defined(__i386__) || (defined(__LSBFIRST__) && defined(UNALIGNED_FETCH_OK)) |
|
3333 /* |
|
3334 * aligned or not, we dont care (i386 can do both) |
|
3335 */ |
|
3336 iVal = ((unsigned short *)cp)[0]; |
|
3337 #else |
|
3338 iVal = (cp[0] & 0xFF) | ((cp[1] & 0xFF) << 8); |
|
3339 #endif |
|
3340 } else { |
|
3341 iVal = ((cp[0] & 0xFF) << 8) | (cp[1] & 0xFF); |
|
3342 } |
|
3343 RETURN (__mkSmallInteger(iVal)); |
|
3344 } |
|
3345 } |
|
3346 } |
|
3347 %}. |
|
3348 |
|
3349 b1 := self byteAt:byteIndex. |
|
3350 b2 := self byteAt:(byteIndex + 1). |
3245 msb ifTrue:[ |
3351 msb ifTrue:[ |
3246 ^ (b1 bitShift:8) + b2 |
3352 ^ (b1 bitShift:8) + b2 |
3247 ]. |
3353 ]. |
3248 ^ (b2 bitShift:8) + b1 |
3354 ^ (b2 bitShift:8) + b1 |
3249 ! |
3355 ! |
3266 |
3372 |
3267 "Created: / 5.3.1998 / 11:54:52 / stefan" |
3373 "Created: / 5.3.1998 / 11:54:52 / stefan" |
3268 "Modified: / 5.3.1998 / 14:59:38 / stefan" |
3374 "Modified: / 5.3.1998 / 14:59:38 / stefan" |
3269 ! |
3375 ! |
3270 |
3376 |
3271 unsignedInt16At:index put:anInteger MSB:msb |
3377 unsignedInt16At:byteIndex put:anInteger MSB:msb |
3272 "set the 2-bytes starting at index from the (unsigned) Integer value. |
3378 "set the 2-bytes starting at index from the (unsigned) Integer value. |
3273 The index is a smalltalk index (i.e. 1-based). |
3379 The index is a smalltalk index (i.e. 1-based). |
3274 The stored value must be in the range 0 .. 16rFFFF. |
3380 The stored value must be in the range 0 .. 16rFFFF. |
3275 The value is stored LSB-first (i.e. the low 8bits are stored at the |
3381 The value is stored LSB-first (i.e. the low 8bits are stored at the |
3276 lower index) if msb is false, MSB-first otherwise" |
3382 lower index) if msb is false, MSB-first otherwise" |
3277 |
3383 |
3278 |b1 b2 |
3384 |b1 b2 |
3279 iVal "{ Class: SmallInteger }"| |
3385 iVal "{ Class: SmallInteger }"| |
3280 |
3386 |
|
3387 %{ /* NOCONTEXT */ |
|
3388 /* |
|
3389 * handle the most common case fast ... |
|
3390 */ |
|
3391 if (__isSmallInteger(byteIndex)) { |
|
3392 unsigned char *cp; |
|
3393 INT sz; |
|
3394 |
|
3395 __fetchBytePointerAndSize__(self, &cp, &sz); |
|
3396 printf("cp=%"_lx_"\n", (INT)cp); |
|
3397 if (cp) { |
|
3398 unsigned INT idx = ((unsigned INT)__intVal(byteIndex)) - 1; |
|
3399 |
|
3400 if ((idx+1) < sz) { |
|
3401 cp += idx; |
|
3402 |
|
3403 if (__isSmallInteger(anInteger)) { |
|
3404 INT __v = __intVal(anInteger); |
|
3405 |
|
3406 if (((unsigned INT)__v) > 0xFFFF) { |
|
3407 goto badArg; |
|
3408 } |
|
3409 if (msb == false) { |
|
3410 #if defined(__i386__) || (defined(__LSBFIRST__) && defined(UNALIGNED_FETCH_OK)) |
|
3411 ((unsigned short *)cp)[0] = (unsigned short)__v; |
|
3412 #else |
|
3413 cp[0] = __v & 0xFF; |
|
3414 cp[1] = (__v >> 8) & 0xFF; |
|
3415 #endif |
|
3416 } else { |
|
3417 cp[0] = (__v >> 8) & 0xFF; |
|
3418 cp[1] = __v & 0xFF; |
|
3419 } |
|
3420 RETURN (anInteger); |
|
3421 } |
|
3422 } |
|
3423 } |
|
3424 } |
|
3425 badArg: ; |
|
3426 %}. |
3281 iVal := anInteger. |
3427 iVal := anInteger. |
3282 ((iVal < 0) or:[iVal > 16rFFFF]) ifTrue:[ |
3428 ((iVal < 0) or:[iVal > 16rFFFF]) ifTrue:[ |
3283 ^ self elementBoundsError:iVal |
3429 ^ self elementBoundsError:iVal |
3284 ]. |
3430 ]. |
3285 msb ifTrue:[ |
3431 msb ifTrue:[ |
3584 and replace them with replacementCharacter" |
3730 and replace them with replacementCharacter" |
3585 |
3731 |
3586 |in out c| |
3732 |in out c| |
3587 |
3733 |
3588 self containsNon7BitAscii ifFalse:[ |
3734 self containsNon7BitAscii ifFalse:[ |
3589 ^ self asSingleByteString |
3735 ^ self asSingleByteString |
3590 ]. |
3736 ]. |
3591 |
3737 |
3592 out := WriteStream on:(String uninitializedNew:self size * 3 // 2). |
3738 out := WriteStream on:(String uninitializedNew:self size * 3 // 2). |
3593 in := self readStream. |
3739 in := self readStream. |
3594 [in atEnd] whileFalse:[ |
3740 [in atEnd] whileFalse:[ |
3595 c := Character utf8DecodeFrom:in. |
3741 c := Character utf8DecodeFrom:in. |
3596 c codePoint > 16rFF ifTrue:[ |
3742 c codePoint > 16rFF ifTrue:[ |
3597 c := replacementCharacter |
3743 c := replacementCharacter |
3598 ]. |
3744 ]. |
3599 out nextPut:c. |
3745 out nextPut:c. |
3600 ]. |
3746 ]. |
3601 ^ out contents |
3747 ^ out contents |
3602 |
3748 |
3603 " |
3749 " |
3604 (Character value:16r220) utf8Encoded |
3750 (Character value:16r220) utf8Encoded |
3605 utf8DecodedWithTwoByteCharactersReplacedBy:(Character space) |
3751 utf8DecodedWithTwoByteCharactersReplacedBy:(Character space) |
3606 |
3752 |
3607 (Character value:16r220) utf8Encoded asExternalBytes copyButLast |
3753 (Character value:16r220) utf8Encoded asExternalBytes copyButLast |
3608 utf8DecodedWithTwoByteCharactersReplacedBy:(Character space) |
3754 utf8DecodedWithTwoByteCharactersReplacedBy:(Character space) |
3609 " |
3755 " |
3610 ! ! |
3756 ! ! |
3611 |
3757 |
3612 !UninterpretedBytes methodsFor:'filling & replacing'! |
3758 !UninterpretedBytes methodsFor:'filling & replacing'! |
3613 |
3759 |
3631 #ifndef NO_PRIM_BYTEARR |
3777 #ifndef NO_PRIM_BYTEARR |
3632 if ((__isBytes(aCollection) || __isExternalBytesLike(aCollection)) |
3778 if ((__isBytes(aCollection) || __isExternalBytesLike(aCollection)) |
3633 && (__isBytes(self) || __isWords(self)) |
3779 && (__isBytes(self) || __isWords(self)) |
3634 && __bothSmallInteger(start, stop) |
3780 && __bothSmallInteger(start, stop) |
3635 && __isSmallInteger(repStart)) { |
3781 && __isSmallInteger(repStart)) { |
3636 startIndex = __intVal(start) - 1; |
3782 startIndex = __intVal(start) - 1; |
3637 if (startIndex >= 0) { |
3783 if (startIndex >= 0) { |
3638 dst = (__ByteArrayInstPtr(self)->ba_element) + startIndex; |
3784 dst = (__ByteArrayInstPtr(self)->ba_element) + startIndex; |
3639 nIndex = __byteArraySize(self); |
3785 nIndex = __byteArraySize(self); |
3640 |
3786 |
3641 if ((cls = __qClass(self)) != @global(ByteArray)) { |
3787 if ((cls = __qClass(self)) != @global(ByteArray)) { |
3642 int nInst; |
3788 int nInst; |
3643 |
3789 |
3644 nInst = __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars)); |
3790 nInst = __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars)); |
3645 dst += nInst; |
3791 dst += nInst; |
3646 nIndex -= nInst; |
3792 nIndex -= nInst; |
3647 } |
3793 } |
3648 |
3794 |
3649 stopIndex = __intVal(stop) - 1; |
3795 stopIndex = __intVal(stop) - 1; |
3650 count = stopIndex - startIndex + 1; |
3796 count = stopIndex - startIndex + 1; |
3651 if (count == 0) { |
3797 if (count == 0) { |
3652 RETURN ( self ); |
3798 RETURN ( self ); |
3653 } |
3799 } |
3654 |
3800 |
3655 if ((count > 0) && (stopIndex < nIndex)) { |
3801 if ((count > 0) && (stopIndex < nIndex)) { |
3656 repStartIndex = __intVal(repStart) - 1; |
3802 repStartIndex = __intVal(repStart) - 1; |
3657 if (repStartIndex >= 0) { |
3803 if (repStartIndex >= 0) { |
3658 if (__isExternalBytesLike(aCollection)) { |
3804 if (__isExternalBytesLike(aCollection)) { |
3659 OBJ sz; |
3805 OBJ sz; |
3660 |
3806 |
3661 src = __externalAddressVal(aCollection); |
3807 src = __externalAddressVal(aCollection); |
3662 if (src == 0) goto fallBack; |
3808 if (src == 0) goto fallBack; |
3663 |
3809 |
3664 sz = __externalBytesSize(aCollection); |
3810 sz = __externalBytesSize(aCollection); |
3665 if (__isSmallInteger(sz)) { |
3811 if (__isSmallInteger(sz)) { |
3666 repNIndex = __smallIntegerVal(sz); |
3812 repNIndex = __smallIntegerVal(sz); |
3667 } else { |
3813 } else { |
3668 repNIndex = repStopIndex+1; /* always enough */ |
3814 repNIndex = repStopIndex+1; /* always enough */ |
3669 } |
3815 } |
3670 src = src + repStartIndex; |
3816 src = src + repStartIndex; |
3671 } else { |
3817 } else { |
3672 if (__isStringLike(aCollection)) { |
3818 if (__isStringLike(aCollection)) { |
3673 repNIndex = __stringSize(aCollection); |
3819 repNIndex = __stringSize(aCollection); |
3674 } else { |
3820 } else { |
3675 repNIndex = __qSize(aCollection) - OHDR_SIZE; |
3821 repNIndex = __qSize(aCollection) - OHDR_SIZE; |
3676 } |
3822 } |
3677 src = (__ByteArrayInstPtr(aCollection)->ba_element) + repStartIndex; |
3823 src = (__ByteArrayInstPtr(aCollection)->ba_element) + repStartIndex; |
3678 if ((cls = __qClass(aCollection)) != @global(ByteArray)) { |
3824 if ((cls = __qClass(aCollection)) != @global(ByteArray)) { |
3679 int nInst; |
3825 int nInst; |
3680 |
3826 |
3681 nInst = __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars)); |
3827 nInst = __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars)); |
3682 src += nInst; |
3828 src += nInst; |
3683 repNIndex -= nInst; |
3829 repNIndex -= nInst; |
3684 } |
3830 } |
3685 } |
3831 } |
3686 repStopIndex = repStartIndex + (stopIndex - startIndex); |
3832 repStopIndex = repStartIndex + (stopIndex - startIndex); |
3687 if (repStopIndex < repNIndex) { |
3833 if (repStopIndex < repNIndex) { |
3688 if (aCollection == self) { |
3834 if (aCollection == self) { |
3689 /* take care of overlapping copy */ |
3835 /* take care of overlapping copy */ |
3690 if (src < dst) { |
3836 if (src < dst) { |
3691 /* must do a reverse copy */ |
3837 /* must do a reverse copy */ |
3692 src += count; |
3838 src += count; |
3693 dst += count; |
3839 dst += count; |
3694 while (count-- > 0) { |
3840 while (count-- > 0) { |
3695 *--dst = *--src; |
3841 *--dst = *--src; |
3696 } |
3842 } |
3697 RETURN ( self ); |
3843 RETURN ( self ); |
3698 } |
3844 } |
3699 } |
3845 } |
3700 |
3846 |
3701 # ifdef bcopy4 |
3847 # ifdef bcopy4 |
3702 if (((unsigned INT)src & 3) == ((unsigned INT)dst & 3)) { |
3848 if (((unsigned INT)src & 3) == ((unsigned INT)dst & 3)) { |
3703 int nW; |
3849 int nW; |
3704 |
3850 |
3705 /* copy unaligned part */ |
3851 /* copy unaligned part */ |
3706 while (count && ((unsigned INT)src & 3)) { |
3852 while (count && ((unsigned INT)src & 3)) { |
3707 *dst++ = *src++; |
3853 *dst++ = *src++; |
3708 count--; |
3854 count--; |
3709 } |
3855 } |
3710 |
3856 |
3711 if (count > 0) { |
3857 if (count > 0) { |
3712 /* copy aligned part */ |
3858 /* copy aligned part */ |
3713 nW = count >> 2; |
3859 nW = count >> 2; |
3714 bcopy4(src, dst, nW); |
3860 bcopy4(src, dst, nW); |
3715 if ((count = count & 3) != 0) { |
3861 if ((count = count & 3) != 0) { |
3716 /* copy any remaining part */ |
3862 /* copy any remaining part */ |
3717 src += (nW<<2); |
3863 src += (nW<<2); |
3718 dst += (nW<<2); |
3864 dst += (nW<<2); |
3719 while (count--) { |
3865 while (count--) { |
3720 *dst++ = *src++; |
3866 *dst++ = *src++; |
3721 } |
3867 } |
3722 } |
3868 } |
3723 } |
3869 } |
3724 RETURN ( self ); |
3870 RETURN ( self ); |
3725 } |
3871 } |
3726 # else |
3872 # else |
3727 # if __POINTER_SIZE__ == 8 |
3873 # if __POINTER_SIZE__ == 8 |
3728 if (((unsigned INT)src & 7) == ((unsigned INT)dst & 7)) { |
3874 if (((unsigned INT)src & 7) == ((unsigned INT)dst & 7)) { |
3729 /* copy unaligned part */ |
3875 /* copy unaligned part */ |
3730 while (count && ((unsigned INT)src & 7)) { |
3876 while (count && ((unsigned INT)src & 7)) { |
3731 *dst++ = *src++; |
3877 *dst++ = *src++; |
3732 count--; |
3878 count--; |
3733 } |
3879 } |
3734 |
3880 |
3735 /* copy aligned part */ |
3881 /* copy aligned part */ |
3736 while (count >= 8) { |
3882 while (count >= 8) { |
3737 ((unsigned INT *)dst)[0] = ((unsigned INT *)src)[0]; |
3883 ((unsigned INT *)dst)[0] = ((unsigned INT *)src)[0]; |
3738 dst += 8; |
3884 dst += 8; |
3739 src += 8; |
3885 src += 8; |
3740 count -= 8; |
3886 count -= 8; |
3741 } |
3887 } |
3742 while (count--) { |
3888 while (count--) { |
3743 *dst++ = *src++; |
3889 *dst++ = *src++; |
3744 } |
3890 } |
3745 RETURN ( self ); |
3891 RETURN ( self ); |
3746 } |
3892 } |
3747 # endif /* 64bit */ |
3893 # endif /* 64bit */ |
3748 # endif /* bcopy4 */ |
3894 # endif /* bcopy4 */ |
3749 |
3895 |
3750 # ifdef FAST_MEMCPY |
3896 # ifdef FAST_MEMCPY |
3751 bcopy(src, dst, count); |
3897 bcopy(src, dst, count); |
3752 # else |
3898 # else |
3753 # ifdef __UNROLL_LOOPS__ |
3899 # ifdef __UNROLL_LOOPS__ |
3754 while (count >= 8) { |
3900 while (count >= 8) { |
3755 dst[0] = src[0]; dst[1] = src[1]; |
3901 dst[0] = src[0]; dst[1] = src[1]; |
3756 dst[2] = src[2]; dst[3] = src[3]; |
3902 dst[2] = src[2]; dst[3] = src[3]; |
3757 dst[4] = src[4]; dst[5] = src[5]; |
3903 dst[4] = src[4]; dst[5] = src[5]; |
3758 dst[6] = src[6]; dst[7] = src[7]; |
3904 dst[6] = src[6]; dst[7] = src[7]; |
3759 dst += 8; src += 8; |
3905 dst += 8; src += 8; |
3760 count -= 8; |
3906 count -= 8; |
3761 } |
3907 } |
3762 # endif /* __UNROLL_LOOPS__ */ |
3908 # endif /* __UNROLL_LOOPS__ */ |
3763 while (count-- > 0) { |
3909 while (count-- > 0) { |
3764 *dst++ = *src++; |
3910 *dst++ = *src++; |
3765 } |
3911 } |
3766 # endif |
3912 # endif |
3767 RETURN ( self ); |
3913 RETURN ( self ); |
3768 } |
3914 } |
3769 } |
3915 } |
3770 } |
3916 } |
3771 } |
3917 } |
3772 } |
3918 } |
3773 fallBack: ; |
3919 fallBack: ; |
3774 #endif |
3920 #endif |
3775 %}. |
3921 %}. |
3776 " |
3922 " |
3779 " |
3925 " |
3780 self slowReplaceBytesFrom:start to:stop with:aCollection startingAt:repStart |
3926 self slowReplaceBytesFrom:start to:stop with:aCollection startingAt:repStart |
3781 |
3927 |
3782 " |
3928 " |
3783 #[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16] |
3929 #[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16] |
3784 copy |
3930 copy |
3785 replaceFrom:1 to:8 |
3931 replaceFrom:1 to:8 |
3786 with:#[10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160] |
3932 with:#[10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160] |
3787 startingAt:1 |
3933 startingAt:1 |
3788 |
3934 |
3789 #[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16] |
3935 #[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16] |
3790 copy |
3936 copy |
3791 replaceFrom:3 to:10 |
3937 replaceFrom:3 to:10 |
3792 with:#[10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160] |
3938 with:#[10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160] |
3793 startingAt:1 |
3939 startingAt:1 |
3794 |
3940 |
3795 #[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16] |
3941 #[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16] |
3796 copy |
3942 copy |
3797 replaceFrom:3 to:4 |
3943 replaceFrom:3 to:4 |
3798 with:#[10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160] |
3944 with:#[10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160] |
3799 startingAt:1 |
3945 startingAt:1 |
3800 |
3946 |
3801 #[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16] |
3947 #[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16] |
3802 copy |
3948 copy |
3803 replaceFrom:0 to:9 |
3949 replaceFrom:0 to:9 |
3804 with:#[10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160] |
3950 with:#[10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160] |
3805 startingAt:1 |
3951 startingAt:1 |
3806 |
3952 |
3807 #[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16] |
3953 #[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16] |
3808 copy |
3954 copy |
3809 replaceFrom:1 to:10 |
3955 replaceFrom:1 to:10 |
3810 with:#[10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160] |
3956 with:#[10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160] |
3811 startingAt:0 |
3957 startingAt:0 |
3812 " |
3958 " |
3813 ! |
3959 ! |
3814 |
3960 |
3815 replaceBytesFrom:startIndex with:replacementCollection startingAt:repStartIndex |
3961 replaceBytesFrom:startIndex with:replacementCollection startingAt:repStartIndex |
3816 "replace elements from another collection, which must be |
3962 "replace elements from another collection, which must be |
3865 |
4011 |
3866 Notice: This operation modifies the receiver, NOT a copy; |
4012 Notice: This operation modifies the receiver, NOT a copy; |
3867 therefore the change may affect all others referencing the receiver." |
4013 therefore the change may affect all others referencing the receiver." |
3868 |
4014 |
3869 self class isBytes ifTrue:[ |
4015 self class isBytes ifTrue:[ |
3870 ((aCollection class == self class) |
4016 ((aCollection class == self class) |
3871 or:[aCollection isByteCollection]) ifTrue:[ |
4017 or:[aCollection isByteCollection]) ifTrue:[ |
3872 ^ self replaceBytesFrom:startIndex to:stopIndex with:aCollection startingAt:repStartIndex |
4018 ^ self replaceBytesFrom:startIndex to:stopIndex with:aCollection startingAt:repStartIndex |
3873 ]. |
4019 ]. |
3874 ]. |
4020 ]. |
3875 ^ super replaceFrom:startIndex to:stopIndex with:aCollection startingAt:repStartIndex |
4021 ^ super replaceFrom:startIndex to:stopIndex with:aCollection startingAt:repStartIndex |
3876 |
4022 |
3877 " |
4023 " |
3878 args: startIndex : <integer> |
4024 args: startIndex : <integer> |
3879 stopIndex : <integer> |
4025 stopIndex : <integer> |
3880 replacementCollection : <collection of <bytes> > |
4026 replacementCollection : <collection of <bytes> > |
3881 repStartIndex : <integer> |
4027 repStartIndex : <integer> |
3882 |
4028 |
3883 returns: self |
4029 returns: self |
3884 " |
4030 " |
3885 |
4031 |
3886 "Modified: / 08-05-2012 / 13:23:27 / cg" |
4032 "Modified: / 08-05-2012 / 13:23:27 / cg" |
3892 "compute and answer the SmallInteger-Hash of the bytes |
4038 "compute and answer the SmallInteger-Hash of the bytes |
3893 from startIndex to endIndex. |
4039 from startIndex to endIndex. |
3894 If endindex = 0 or endIndex > size, hash up the size. |
4040 If endindex = 0 or endIndex > size, hash up the size. |
3895 |
4041 |
3896 NOTE: startIndex and endIndex are only hints about what should be hashed. |
4042 NOTE: startIndex and endIndex are only hints about what should be hashed. |
3897 In fact, more bytes could be involved in hashing. |
4043 In fact, more bytes could be involved in hashing. |
3898 SO ARRAYS MUST BE EQUAL TO HASH TO THE SAME VALUE" |
4044 SO ARRAYS MUST BE EQUAL TO HASH TO THE SAME VALUE" |
3899 |
4045 |
3900 |w| |
4046 |w| |
3901 |
4047 |
3902 %{ |
4048 %{ |
3903 if (__bothSmallInteger(startIndex, endIndex)) { |
4049 if (__bothSmallInteger(startIndex, endIndex)) { |
3904 unsigned char *cp; |
4050 unsigned char *cp; |
3905 INT sz; |
4051 INT sz; |
3906 |
4052 |
3907 __fetchBytePointerAndSize__(self, &cp, &sz); |
4053 __fetchBytePointerAndSize__(self, &cp, &sz); |
3908 if (cp) { |
4054 if (cp) { |
3909 INT sidx = ((unsigned INT)__smallIntegerVal(startIndex)) - 1; |
4055 INT sidx = ((unsigned INT)__smallIntegerVal(startIndex)) - 1; |
3910 INT eidx = ((unsigned INT)__smallIntegerVal(endIndex)) - 1; |
4056 INT eidx = ((unsigned INT)__smallIntegerVal(endIndex)) - 1; |
3911 unsigned char *ep; |
4057 unsigned char *ep; |
3912 unsigned INT hash = 0, hash2 = 0, carry; |
4058 unsigned INT hash = 0, hash2 = 0, carry; |
3913 int i; |
4059 int i; |
3914 |
4060 |
3915 if (eidx < 0 || eidx >= sz) eidx = sz - 1; |
4061 if (eidx < 0 || eidx >= sz) eidx = sz - 1; |
3916 if (sidx > eidx) sidx = eidx; |
4062 if (sidx > eidx) sidx = eidx; |
3917 if (sidx < 0) { |
4063 if (sidx < 0) { |
3918 RETURN(__mkSmallInteger(0)); |
4064 RETURN(__mkSmallInteger(0)); |
3919 } |
4065 } |
3920 |
4066 |
3921 ep = cp + eidx; |
4067 ep = cp + eidx; |
3922 cp += sidx; |
4068 cp += sidx; |
3923 |
4069 |
3924 #if 0 |
4070 #if 0 |
3925 /* |
4071 /* |
3926 * On LSB-First (little endian) cpus, |
4072 * On LSB-First (little endian) cpus, |
3927 * this code does not produce the same result |
4073 * this code does not produce the same result |
3928 * if the same bytes are at different positions |
4074 * if the same bytes are at different positions |
3929 */ |
4075 */ |
3930 |
4076 |
3931 if ((INT)cp & (sizeof(INT)-1)) { |
4077 if ((INT)cp & (sizeof(INT)-1)) { |
3932 /* not aligned */ |
4078 /* not aligned */ |
3933 |
4079 |
3934 for (i=0; cp <= ep; cp++) { |
4080 for (i=0; cp <= ep; cp++) { |
3935 hash2 = (hash2 << 8) | *cp; |
4081 hash2 = (hash2 << 8) | *cp; |
3936 if (++i == sizeof(INT)) { |
4082 if (++i == sizeof(INT)) { |
3937 hash ^= hash2; |
4083 hash ^= hash2; |
3938 i = hash2 = 0; |
4084 i = hash2 = 0; |
3939 } |
4085 } |
3940 } |
4086 } |
3941 } else { |
4087 } else { |
3942 /* aligned */ |
4088 /* aligned */ |
3943 for (; cp+sizeof(INT) <= ep; cp += sizeof(INT)) { |
4089 for (; cp+sizeof(INT) <= ep; cp += sizeof(INT)) { |
3944 hash ^= *(unsigned INT *)cp; |
4090 hash ^= *(unsigned INT *)cp; |
3945 } |
4091 } |
3946 for (; cp <= ep; cp++) { |
4092 for (; cp <= ep; cp++) { |
3947 hash2 = (hash2 << 8) | *cp; |
4093 hash2 = (hash2 << 8) | *cp; |
3948 } |
4094 } |
3949 } |
4095 } |
3950 #else |
4096 #else |
3951 for (i=0; cp <= ep-sizeof(INT); cp += sizeof(INT)) { |
4097 for (i=0; cp <= ep-sizeof(INT); cp += sizeof(INT)) { |
3952 hash2 = cp[0]; |
4098 hash2 = cp[0]; |
3953 hash2 = (hash2 << 8) | cp[1]; |
4099 hash2 = (hash2 << 8) | cp[1]; |
3954 hash2 = (hash2 << 8) | cp[2]; |
4100 hash2 = (hash2 << 8) | cp[2]; |
3955 hash2 = (hash2 << 8) | cp[3]; |
4101 hash2 = (hash2 << 8) | cp[3]; |
3956 #if __POINTER_SIZE__ == 8 |
4102 #if __POINTER_SIZE__ == 8 |
3957 hash2 = (hash2 << 8) | cp[4]; |
4103 hash2 = (hash2 << 8) | cp[4]; |
3958 hash2 = (hash2 << 8) | cp[5]; |
4104 hash2 = (hash2 << 8) | cp[5]; |
3959 hash2 = (hash2 << 8) | cp[6]; |
4105 hash2 = (hash2 << 8) | cp[6]; |
3960 hash2 = (hash2 << 8) | cp[7]; |
4106 hash2 = (hash2 << 8) | cp[7]; |
3961 #endif |
4107 #endif |
3962 /* |
4108 /* |
3963 * multiply by large prime to scramble bits and |
4109 * multiply by large prime to scramble bits and |
3964 * to avoid a 0 result from |
4110 * to avoid a 0 result from |
3965 * #[1 2 3 4 1 2 3 4] computeXorHashFrom:1 to:8. |
4111 * #[1 2 3 4 1 2 3 4] computeXorHashFrom:1 to:8. |
3966 */ |
4112 */ |
3967 hash ^= (hash * 31415821) ^ hash2; |
4113 hash ^= (hash * 31415821) ^ hash2; |
3968 } |
4114 } |
3969 for (hash2 = 0; cp <= ep; cp++) { |
4115 for (hash2 = 0; cp <= ep; cp++) { |
3970 hash2 = (hash2 << 8) | *cp; |
4116 hash2 = (hash2 << 8) | *cp; |
3971 } |
4117 } |
3972 #endif |
4118 #endif |
3973 hash ^= (hash * 31415821) ^ hash2; |
4119 hash ^= (hash * 31415821) ^ hash2; |
3974 |
4120 |
3975 /* |
4121 /* |
3976 * fold the high bits not fitting into a SmallInteger |
4122 * fold the high bits not fitting into a SmallInteger |
3977 */ |
4123 */ |
3978 carry = hash & ~_MAX_INT; |
4124 carry = hash & ~_MAX_INT; |
3979 if (carry) { |
4125 if (carry) { |
3980 hash = (hash & _MAX_INT) ^ (carry >> 8); |
4126 hash = (hash & _MAX_INT) ^ (carry >> 8); |
3981 } |
4127 } |
3982 |
4128 |
3983 RETURN(__mkSmallInteger(hash)); |
4129 RETURN(__mkSmallInteger(hash)); |
3984 } |
4130 } |
3985 } |
4131 } |
3986 %}. |
4132 %}. |
3987 |
4133 |
3988 ^ self primitiveFailed |
4134 ^ self primitiveFailed |
3989 |
4135 |