2
2
* text-delta.c -- Internal text delta representation
4
4
* ====================================================================
5
* Copyright (c) 2000-2006 CollabNet. All rights reserved.
7
* This software is licensed as described in the file COPYING, which
8
* you should have received as part of this distribution. The terms
9
* are also available at http://subversion.tigris.org/license-1.html.
10
* If newer versions of this license are posted there, you may use a
11
* newer version instead, at your option.
13
* This software consists of voluntary contributions made by many
14
* individuals. For exact contribution history, see the revision
15
* history and logs, available at http://subversion.tigris.org/.
5
* Licensed to the Apache Software Foundation (ASF) under one
6
* or more contributor license agreements. See the NOTICE file
7
* distributed with this work for additional information
8
* regarding copyright ownership. The ASF licenses this file
9
* to you under the Apache License, Version 2.0 (the
10
* "License"); you may not use this file except in compliance
11
* with the License. You may obtain a copy of the License at
13
* http://www.apache.org/licenses/LICENSE-2.0
15
* Unless required by applicable law or agreed to in writing,
16
* software distributed under the License is distributed on an
17
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18
* KIND, either express or implied. See the License for the
19
* specific language governing permissions and limitations
16
21
* ====================================================================
559
564
return SVN_NO_ERROR;
567
/* Copy LEN bytes from SOURCE to TARGET, optimizing for the case where LEN
568
* is often very small. Return a pointer to the first byte after the copied
569
* target range, unlike standard memcpy(), as a potential further
570
* optimization for the caller.
572
* memcpy() is hard to tune for a wide range of buffer lengths. Therefore,
573
* it is often tuned for high throughput on large buffers and relatively
574
* low latency for mid-sized buffers (tens of bytes). However, the overhead
575
* for very small buffers (<10 bytes) is still high. Even passing the
576
* parameters, for instance, may take as long as copying 3 bytes.
578
* Because short copy sequences seem to be a common case, at least in
579
* "format 2" FSFS repositories, we copy them directly. Larger buffer sizes
580
* aren't hurt measurably by the exta 'if' clause. */
581
static APR_INLINE char *
582
fast_memcpy(char *target, const char *source, apr_size_t len)
586
memcpy(target, source, len);
591
/* memcpy is not exactly fast for small block sizes.
592
* Since they are common, let's run optimized code for them. */
593
const char *end = source + len;
594
for (; source != end; source++)
595
*(target++) = *source;
601
/* Copy LEN bytes from SOURCE to TARGET. Unlike memmove() or memcpy(),
602
* create repeating patterns if the source and target ranges overlap.
603
* Return a pointer to the first byte after the copied target range. */
604
static APR_INLINE char *
605
patterning_copy(char *target, const char *source, apr_size_t len)
607
const char *end = source + len;
609
/* On many machines, we can do "chunky" copies. */
611
#if SVN_UNALIGNED_ACCESS_IS_OK
613
if (end + sizeof(apr_uint32_t) <= target)
615
/* Source and target are at least 4 bytes apart, so we can copy in
617
for (; source + sizeof(apr_uint32_t) <= end;
618
source += sizeof(apr_uint32_t),
619
target += sizeof(apr_uint32_t))
620
*(apr_uint32_t *)(target) = *(apr_uint32_t *)(source);
625
/* fall through to byte-wise copy (either for the below-chunk-size tail
626
* or the whole copy) */
627
for (; source != end; source++)
628
*(target++) = *source;
564
634
svn_txdelta_apply_instructions(svn_txdelta_window_t *window,
581
651
case svn_txdelta_source:
582
652
/* Copy from source area. */
583
653
assert(op->offset + op->length <= window->sview_len);
584
memcpy(tbuf + tpos, sbuf + op->offset, buf_len);
654
fast_memcpy(tbuf + tpos, sbuf + op->offset, buf_len);
587
657
case svn_txdelta_target:
588
/* Copy from target area. Don't use memcpy() since its
589
semantics aren't guaranteed for overlapping memory areas,
590
and target copies are allowed to overlap to generate
658
/* Copy from target area. We can't use memcpy() or the like
659
* since we need a specific semantics for overlapping copies:
660
* they must result in repeating patterns.
661
* Note that most copies won't have overlapping source and
662
* target ranges (they are just a result of self-compressed
663
* data) but a small percentage will. */
592
664
assert(op->offset < tpos);
593
for (i = op->offset, j = tpos; i < op->offset + buf_len; i++)
665
patterning_copy(tbuf + tpos, tbuf + op->offset, buf_len);
597
668
case svn_txdelta_new:
598
669
/* Copy from window new area. */
599
670
assert(op->offset + op->length <= window->new_data->len);
601
window->new_data->data + op->offset,
671
fast_memcpy(tbuf + tpos,
672
window->new_data->data + op->offset,