home *** CD-ROM | disk | FTP | other *** search
- #ifndef ONES
- #define ONES ((_BS_word)(~0L))
- #endif
-
- #ifndef DOIT_SOLID
- #ifdef DOIT
- #define DOIT_SOLID(dst, src) DOIT(dst, src, (_BS_word)(~0))
- #else
- #define DOIT_SOLID(dst, src) (dst) = (COMBINE(dst, src))
- #endif
- #endif
-
- #ifndef DOIT
- #define DOIT(dst, src, mask) \
- (dst) = ((COMBINE(dst, src)) & (mask)) | ((dst) & ~(mask))
- #endif
-
- _BS_word word0, mask;
- int shift0, shift1;
-
- if (length == 0)
- goto done;
-
- shift0 = srcbit - dstbit;
-
- /* First handle the case that only one destination word is touched. */
- if (length + dstbit <= _BS_BITS_PER_WORD)
- {
- _BS_word mask
- = (ONES _BS_LEFT (_BS_BITS_PER_WORD - length)) _BS_RIGHT dstbit;
- _BS_word word0 = *psrc++;
- if (shift0 <= 0) /* dstbit >= srcbit */
- {
- word0 = word0 _BS_RIGHT (-shift0);
- }
- else
- {
- word0 = word0 _BS_LEFT shift0;
- if (length + srcbit > _BS_BITS_PER_WORD)
- word0 = word0 | (*psrc _BS_RIGHT (_BS_BITS_PER_WORD - shift0));
- }
- DOIT(*pdst, word0, mask);
- goto done;
- }
-
- /* Next optimize the case that the source and destination are aligned. */
- if (shift0 == 0)
- {
- _BS_word mask;
- if (psrc > pdst)
- {
- if (srcbit)
- {
- mask = ONES _BS_RIGHT srcbit;
- DOIT(*pdst, *psrc, mask);
- pdst++; psrc++;
- length -= _BS_BITS_PER_WORD - srcbit;
- }
- for (; length >= _BS_BITS_PER_WORD; length -= _BS_BITS_PER_WORD)
- {
- DOIT_SOLID(*pdst, *psrc);
- pdst++; psrc++;
- }
- if (length)
- {
- mask = ONES _BS_LEFT (_BS_BITS_PER_WORD - length);
- DOIT(*pdst, *psrc, mask);
- }
- }
- else if (psrc < pdst)
- {
- _BS_size_t span = srcbit + length;
- pdst += span / (_BS_size_t)_BS_BITS_PER_WORD;
- psrc += span / (_BS_size_t)_BS_BITS_PER_WORD;
- span %= (_BS_size_t)_BS_BITS_PER_WORD;
- if (span)
- {
- mask = ONES _BS_LEFT (_BS_BITS_PER_WORD - span);
- DOIT(*pdst, *psrc, mask);
- length -= span;
- }
- pdst--; psrc--;
- for (; length >= _BS_BITS_PER_WORD; length -= _BS_BITS_PER_WORD)
- {
- DOIT_SOLID(*pdst, *psrc);
- pdst--; psrc--;
- }
- if (srcbit)
- {
- mask = ONES _BS_RIGHT srcbit;
- DOIT(*pdst, *psrc, mask);
- }
- }
- /* else if (psrc == pdst) --nothing to do--; */
- goto done;
- }
-
- /* Now we assume shift!=0, and more than on destination word is changed. */
- if (psrc >= pdst) /* Do the updates in forward direction. */
- {
- _BS_word word0 = *psrc++;
- _BS_word mask = ONES _BS_RIGHT dstbit;
- if (shift0 > 0)
- {
- _BS_word word1 = *psrc++;
- shift1 = _BS_BITS_PER_WORD - shift0;
- DOIT(*pdst, (word0 _BS_LEFT shift0) | (word1 _BS_RIGHT shift1), mask);
- word0 = word1;
- }
- else /* dstbit > srcbit */
- {
- shift1 = -shift0;
- shift0 += _BS_BITS_PER_WORD;
- DOIT(*pdst, word0 _BS_RIGHT shift1, mask);
- }
- pdst++;
- length -= _BS_BITS_PER_WORD - dstbit;
-
- for ( ; length >= _BS_BITS_PER_WORD; length -= _BS_BITS_PER_WORD)
- {
- register _BS_word word1 = *psrc++;
- DOIT_SOLID(*pdst,
- (word0 _BS_LEFT shift0) | (word1 _BS_RIGHT shift1));
- pdst++;
- word0 = word1;
- }
- if (length > 0)
- {
- _BS_size_t mask = ONES _BS_LEFT (_BS_BITS_PER_WORD - length);
- word0 = word0 _BS_LEFT shift0;
- if (length > shift1)
- word0 = word0 | (*psrc _BS_RIGHT shift1) ;
- DOIT (*pdst, word0, mask);
- }
- }
- else /* Do the updates in backward direction. */
- {
- _BS_word word0;
-
- /* Make (psrc, srcbit) and (pdst, dstbit) point to *last* bit. */
- psrc += (srcbit + length - 1) / _BS_BITS_PER_WORD;
- srcbit = (srcbit + length - 1) % _BS_BITS_PER_WORD;
- pdst += (dstbit + length - 1) / _BS_BITS_PER_WORD;
- dstbit = (dstbit + length - 1) % _BS_BITS_PER_WORD;
-
- shift0 = srcbit - dstbit;
-
- word0 = *psrc--;
- mask = ONES _BS_LEFT (_BS_BITS_PER_WORD - 1 - dstbit);
- if (shift0 < 0)
- {
- _BS_word word1 = *psrc--;
- shift1 = -shift0;
- shift0 += _BS_BITS_PER_WORD;
- DOIT (*pdst, (word0 _BS_RIGHT shift1) | (word1 _BS_LEFT shift0),
- mask);
- word0 = word1;
- }
- else
- {
- shift1 = _BS_BITS_PER_WORD - shift0;
- DOIT(*pdst, word0 _BS_LEFT shift0, mask);
- }
- pdst--;
- length -= dstbit + 1;
-
- for ( ; length >= _BS_BITS_PER_WORD; length -= _BS_BITS_PER_WORD)
- {
- register _BS_word word1 = *psrc--;
- DOIT_SOLID(*pdst,
- (word0 _BS_RIGHT shift1) | (word1 _BS_LEFT shift0));
- pdst--;
- word0 = word1;
- }
- if (length > 0)
- {
- _BS_size_t mask = ONES _BS_RIGHT (_BS_BITS_PER_WORD - length);
- word0 = word0 _BS_RIGHT shift1;
- if (length > shift0)
- word0 = word0 | (*psrc _BS_LEFT shift0) ;
- DOIT (*pdst, word0, mask);
- }
- }
- done: ;
-