1 // Copyright 2013 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4 5 // Package transform provides reader and writer wrappers that transform the
6 // bytes passing through as well as various transformations. Example
7 // transformations provided by other packages include normalization and
8 // conversion between character sets.
9 package transform // import "golang.org/x/text/transform"
10 11 import (
12 "bytes"
13 "errors"
14 "io"
15 "unicode/utf8"
16 )
17 18 var (
19 // ErrShortDst means that the destination buffer was too short to
20 // receive all of the transformed bytes.
21 ErrShortDst = errors.New("transform: short destination buffer")
22 23 // ErrShortSrc means that the source buffer has insufficient data to
24 // complete the transformation.
25 ErrShortSrc = errors.New("transform: short source buffer")
26 27 // ErrEndOfSpan means that the input and output (the transformed input)
28 // are not identical.
29 ErrEndOfSpan = errors.New("transform: input and output are not identical")
30 31 // errInconsistentByteCount means that Transform returned success (nil
32 // error) but also returned nSrc inconsistent with the src argument.
33 errInconsistentByteCount = errors.New("transform: inconsistent byte count returned")
34 35 // errShortInternal means that an internal buffer is not large enough
36 // to make progress and the Transform operation must be aborted.
37 errShortInternal = errors.New("transform: short internal buffer")
38 )
39 40 // Transformer transforms bytes.
41 type Transformer interface {
42 // Transform writes to dst the transformed bytes read from src, and
43 // returns the number of dst bytes written and src bytes read. The
44 // atEOF argument tells whether src represents the last bytes of the
45 // input.
46 //
47 // Callers should always process the nDst bytes produced and account
48 // for the nSrc bytes consumed before considering the error err.
49 //
50 // A nil error means that all of the transformed bytes (whether freshly
51 // transformed from src or left over from previous Transform calls)
52 // were written to dst. A nil error can be returned regardless of
53 // whether atEOF is true. If err is nil then nSrc must equal len(src);
54 // the converse is not necessarily true.
55 //
56 // ErrShortDst means that dst was too short to receive all of the
57 // transformed bytes. ErrShortSrc means that src had insufficient data
58 // to complete the transformation. If both conditions apply, then
59 // either error may be returned. Other than the error conditions listed
60 // here, implementations are free to report other errors that arise.
61 Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error)
62 63 // Reset resets the state and allows a Transformer to be reused.
64 Reset()
65 }
66 67 // SpanningTransformer extends the Transformer interface with a Span method
68 // that determines how much of the input already conforms to the Transformer.
69 type SpanningTransformer interface {
70 Transformer
71 72 // Span returns a position in src such that transforming src[:n] results in
73 // identical output src[:n] for these bytes. It does not necessarily return
74 // the largest such n. The atEOF argument tells whether src represents the
75 // last bytes of the input.
76 //
77 // Callers should always account for the n bytes consumed before
78 // considering the error err.
79 //
80 // A nil error means that all input bytes are known to be identical to the
81 // output produced by the Transformer. A nil error can be returned
82 // regardless of whether atEOF is true. If err is nil, then n must
83 // equal len(src); the converse is not necessarily true.
84 //
85 // ErrEndOfSpan means that the Transformer output may differ from the
86 // input after n bytes. Note that n may be len(src), meaning that the output
87 // would contain additional bytes after otherwise identical output.
88 // ErrShortSrc means that src had insufficient data to determine whether the
89 // remaining bytes would change. Other than the error conditions listed
90 // here, implementations are free to report other errors that arise.
91 //
92 // Calling Span can modify the Transformer state as a side effect. In
93 // effect, it does the transformation just as calling Transform would, only
94 // without copying to a destination buffer and only up to a point it can
95 // determine the input and output bytes are the same. This is obviously more
96 // limited than calling Transform, but can be more efficient in terms of
97 // copying and allocating buffers. Calls to Span and Transform may be
98 // interleaved.
99 Span(src []byte, atEOF bool) (n int, err error)
100 }
101 102 // NopResetter can be embedded by implementations of Transformer to add a nop
103 // Reset method.
104 type NopResetter struct{}
105 106 // Reset implements the Reset method of the Transformer interface.
107 func (NopResetter) Reset() {}
108 109 // Reader wraps another io.Reader by transforming the bytes read.
110 type Reader struct {
111 r io.Reader
112 t Transformer
113 err error
114 115 // dst[dst0:dst1] contains bytes that have been transformed by t but
116 // not yet copied out via Read.
117 dst []byte
118 dst0, dst1 int
119 120 // src[src0:src1] contains bytes that have been read from r but not
121 // yet transformed through t.
122 src []byte
123 src0, src1 int
124 125 // transformComplete is whether the transformation is complete,
126 // regardless of whether or not it was successful.
127 transformComplete bool
128 }
129 130 const defaultBufSize = 4096
131 132 // NewReader returns a new Reader that wraps r by transforming the bytes read
133 // via t. It calls Reset on t.
134 func NewReader(r io.Reader, t Transformer) *Reader {
135 t.Reset()
136 return &Reader{
137 r: r,
138 t: t,
139 dst: []byte{:defaultBufSize},
140 src: []byte{:defaultBufSize},
141 }
142 }
143 144 // Read implements the io.Reader interface.
145 func (r *Reader) Read(p []byte) (int, error) {
146 n, err := 0, error(nil)
147 for {
148 // Copy out any transformed bytes and return the final error if we are done.
149 if r.dst0 != r.dst1 {
150 n = copy(p, r.dst[r.dst0:r.dst1])
151 r.dst0 += n
152 if r.dst0 == r.dst1 && r.transformComplete {
153 return n, r.err
154 }
155 return n, nil
156 } else if r.transformComplete {
157 return 0, r.err
158 }
159 160 // Try to transform some source bytes, or to flush the transformer if we
161 // are out of source bytes. We do this even if r.r.Read returned an error.
162 // As the io.Reader documentation says, "process the n > 0 bytes returned
163 // before considering the error".
164 if r.src0 != r.src1 || r.err != nil {
165 r.dst0 = 0
166 r.dst1, n, err = r.t.Transform(r.dst, r.src[r.src0:r.src1], r.err == io.EOF)
167 r.src0 += n
168 169 switch {
170 case err == nil:
171 if r.src0 != r.src1 {
172 r.err = errInconsistentByteCount
173 }
174 // The Transform call was successful; we are complete if we
175 // cannot read more bytes into src.
176 r.transformComplete = r.err != nil
177 continue
178 case err == ErrShortDst && (r.dst1 != 0 || n != 0):
179 // Make room in dst by copying out, and try again.
180 continue
181 case err == ErrShortSrc && r.src1-r.src0 != len(r.src) && r.err == nil:
182 // Read more bytes into src via the code below, and try again.
183 default:
184 r.transformComplete = true
185 // The reader error (r.err) takes precedence over the
186 // transformer error (err) unless r.err is nil or io.EOF.
187 if r.err == nil || r.err == io.EOF {
188 r.err = err
189 }
190 continue
191 }
192 }
193 194 // Move any untransformed source bytes to the start of the buffer
195 // and read more bytes.
196 if r.src0 != 0 {
197 r.src0, r.src1 = 0, copy(r.src, r.src[r.src0:r.src1])
198 }
199 n, r.err = r.r.Read(r.src[r.src1:])
200 r.src1 += n
201 }
202 }
203 204 // TODO: implement ReadByte (and ReadRune??).
205 206 // Writer wraps another io.Writer by transforming the bytes read.
207 // The user needs to call Close to flush unwritten bytes that may
208 // be buffered.
209 type Writer struct {
210 w io.Writer
211 t Transformer
212 dst []byte
213 214 // src[:n] contains bytes that have not yet passed through t.
215 src []byte
216 n int
217 }
218 219 // NewWriter returns a new Writer that wraps w by transforming the bytes written
220 // via t. It calls Reset on t.
221 func NewWriter(w io.Writer, t Transformer) *Writer {
222 t.Reset()
223 return &Writer{
224 w: w,
225 t: t,
226 dst: []byte{:defaultBufSize},
227 src: []byte{:defaultBufSize},
228 }
229 }
230 231 // Write implements the io.Writer interface. If there are not enough
232 // bytes available to complete a Transform, the bytes will be buffered
233 // for the next write. Call Close to convert the remaining bytes.
234 func (w *Writer) Write(data []byte) (n int, err error) {
235 src := data
236 if w.n > 0 {
237 // Append bytes from data to the last remainder.
238 // TODO: limit the amount copied on first try.
239 n = copy(w.src[w.n:], data)
240 w.n += n
241 src = w.src[:w.n]
242 }
243 for {
244 nDst, nSrc, err := w.t.Transform(w.dst, src, false)
245 if _, werr := w.w.Write(w.dst[:nDst]); werr != nil {
246 return n, werr
247 }
248 src = src[nSrc:]
249 if w.n == 0 {
250 n += nSrc
251 } else if len(src) <= n {
252 // Enough bytes from w.src have been consumed. We make src point
253 // to data instead to reduce the copying.
254 w.n = 0
255 n -= len(src)
256 src = data[n:]
257 if n < len(data) && (err == nil || err == ErrShortSrc) {
258 continue
259 }
260 }
261 switch err {
262 case ErrShortDst:
263 // This error is okay as long as we are making progress.
264 if nDst > 0 || nSrc > 0 {
265 continue
266 }
267 case ErrShortSrc:
268 if len(src) < len(w.src) {
269 m := copy(w.src, src)
270 // If w.n > 0, bytes from data were already copied to w.src and n
271 // was already set to the number of bytes consumed.
272 if w.n == 0 {
273 n += m
274 }
275 w.n = m
276 err = nil
277 } else if nDst > 0 || nSrc > 0 {
278 // Not enough buffer to store the remainder. Keep processing as
279 // long as there is progress. Without this case, transforms that
280 // require a lookahead larger than the buffer may result in an
281 // error. This is not something one may expect to be common in
282 // practice, but it may occur when buffers are set to small
283 // sizes during testing.
284 continue
285 }
286 case nil:
287 if w.n > 0 {
288 err = errInconsistentByteCount
289 }
290 }
291 return n, err
292 }
293 }
294 295 // Close implements the io.Closer interface.
296 func (w *Writer) Close() error {
297 src := w.src[:w.n]
298 for {
299 nDst, nSrc, err := w.t.Transform(w.dst, src, true)
300 if _, werr := w.w.Write(w.dst[:nDst]); werr != nil {
301 return werr
302 }
303 if err != ErrShortDst {
304 return err
305 }
306 src = src[nSrc:]
307 }
308 }
309 310 type nop struct{ NopResetter }
311 312 func (nop) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
313 n := copy(dst, src)
314 if n < len(src) {
315 err = ErrShortDst
316 }
317 return n, n, err
318 }
319 320 func (nop) Span(src []byte, atEOF bool) (n int, err error) {
321 return len(src), nil
322 }
323 324 type discard struct{ NopResetter }
325 326 func (discard) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
327 return 0, len(src), nil
328 }
329 330 var (
331 // Discard is a Transformer for which all Transform calls succeed
332 // by consuming all bytes and writing nothing.
333 Discard Transformer = discard{}
334 335 // Nop is a SpanningTransformer that copies src to dst.
336 Nop SpanningTransformer = nop{}
337 )
338 339 // chain is a sequence of links. A chain with N Transformers has N+1 links and
340 // N+1 buffers. Of those N+1 buffers, the first and last are the src and dst
341 // buffers given to chain.Transform and the middle N-1 buffers are intermediate
342 // buffers owned by the chain. The i'th link transforms bytes from the i'th
343 // buffer chain.link[i].b at read offset chain.link[i].p to the i+1'th buffer
344 // chain.link[i+1].b at write offset chain.link[i+1].n, for i in [0, N).
345 type chain struct {
346 link []link
347 err error
348 // errStart is the index at which the error occurred plus 1. Processing
349 // errStart at this level at the next call to Transform. As long as
350 // errStart > 0, chain will not consume any more source bytes.
351 errStart int
352 }
353 354 func (c *chain) fatalError(errIndex int, err error) {
355 if i := errIndex + 1; i > c.errStart {
356 c.errStart = i
357 c.err = err
358 }
359 }
360 361 type link struct {
362 t Transformer
363 // b[p:n] holds the bytes to be transformed by t.
364 b []byte
365 p int
366 n int
367 }
368 369 func (l *link) src() []byte {
370 return l.b[l.p:l.n]
371 }
372 373 func (l *link) dst() []byte {
374 return l.b[l.n:]
375 }
376 377 // Chain returns a Transformer that applies t in sequence.
378 func Chain(t ...Transformer) Transformer {
379 if len(t) == 0 {
380 return nop{}
381 }
382 c := &chain{link: []link{:len(t)+1}}
383 for i, tt := range t {
384 c.link[i].t = tt
385 }
386 // Allocate intermediate buffers.
387 b := [][defaultBufSize]byte{:len(t)-1}
388 for i := range b {
389 c.link[i+1].b = b[i][:]
390 }
391 return c
392 }
393 394 // Reset resets the state of Chain. It calls Reset on all the Transformers.
395 func (c *chain) Reset() {
396 for i, l := range c.link {
397 if l.t != nil {
398 l.t.Reset()
399 }
400 c.link[i].p, c.link[i].n = 0, 0
401 }
402 }
403 404 // TODO: make chain use Span (is going to be fun to implement!)
405 406 // Transform applies the transformers of c in sequence.
407 func (c *chain) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
408 // Set up src and dst in the chain.
409 srcL := &c.link[0]
410 dstL := &c.link[len(c.link)-1]
411 srcL.b, srcL.p, srcL.n = src, 0, len(src)
412 dstL.b, dstL.n = dst, 0
413 var lastFull, needProgress bool // for detecting progress
414 415 // i is the index of the next Transformer to apply, for i in [low, high].
416 // low is the lowest index for which c.link[low] may still produce bytes.
417 // high is the highest index for which c.link[high] has a Transformer.
418 // The error returned by Transform determines whether to increase or
419 // decrease i. We try to completely fill a buffer before converting it.
420 for low, i, high := c.errStart, c.errStart, len(c.link)-2; low <= i && i <= high; {
421 in, out := &c.link[i], &c.link[i+1]
422 nDst, nSrc, err0 := in.t.Transform(out.dst(), in.src(), atEOF && low == i)
423 out.n += nDst
424 in.p += nSrc
425 if i > 0 && in.p == in.n {
426 in.p, in.n = 0, 0
427 }
428 needProgress, lastFull = lastFull, false
429 switch err0 {
430 case ErrShortDst:
431 // Process the destination buffer next. Return if we are already
432 // at the high index.
433 if i == high {
434 return dstL.n, srcL.p, ErrShortDst
435 }
436 if out.n != 0 {
437 i++
438 // If the Transformer at the next index is not able to process any
439 // source bytes there is nothing that can be done to make progress
440 // and the bytes will remain unprocessed. lastFull is used to
441 // detect this and break out of the loop with a fatal error.
442 lastFull = true
443 continue
444 }
445 // The destination buffer was too small, but is completely empty.
446 // Return a fatal error as this transformation can never complete.
447 c.fatalError(i, errShortInternal)
448 case ErrShortSrc:
449 if i == 0 {
450 // Save ErrShortSrc in err. All other errors take precedence.
451 err = ErrShortSrc
452 break
453 }
454 // Source bytes were depleted before filling up the destination buffer.
455 // Verify we made some progress, move the remaining bytes to the errStart
456 // and try to get more source bytes.
457 if needProgress && nSrc == 0 || in.n-in.p == len(in.b) {
458 // There were not enough source bytes to proceed while the source
459 // buffer cannot hold any more bytes. Return a fatal error as this
460 // transformation can never complete.
461 c.fatalError(i, errShortInternal)
462 break
463 }
464 // in.b is an internal buffer and we can make progress.
465 in.p, in.n = 0, copy(in.b, in.src())
466 // Inlined from nil case (fallthrough not allowed in moxie).
467 if i > low {
468 i--
469 continue
470 }
471 case nil:
472 // if i == low, we have depleted the bytes at index i or any lower levels.
473 // In that case we increase low and i. In all other cases we decrease i to
474 // fetch more bytes before proceeding to the next index.
475 if i > low {
476 i--
477 continue
478 }
479 default:
480 c.fatalError(i, err0)
481 }
482 // Exhausted level low or fatal error: increase low and continue
483 // to process the bytes accepted so far.
484 i++
485 low = i
486 }
487 488 // If c.errStart > 0, this means we found a fatal error. We will clear
489 // all upstream buffers. At this point, no more progress can be made
490 // downstream, as Transform would have bailed while handling ErrShortDst.
491 if c.errStart > 0 {
492 for i := 1; i < c.errStart; i++ {
493 c.link[i].p, c.link[i].n = 0, 0
494 }
495 err, c.errStart, c.err = c.err, 0, nil
496 }
497 return dstL.n, srcL.p, err
498 }
499 500 // Deprecated: Use runes.Remove instead.
501 func RemoveFunc(f func(r rune) bool) Transformer {
502 return removeF(f)
503 }
504 505 type removeF func(r rune) bool
506 507 func (removeF) Reset() {}
508 509 // Transform implements the Transformer interface.
510 func (t removeF) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
511 for r, sz := rune(0), 0; len(src) > 0; src = src[sz:] {
512 513 if r = rune(src[0]); r < utf8.RuneSelf {
514 sz = 1
515 } else {
516 r, sz = utf8.DecodeRune(src)
517 518 if sz == 1 {
519 // Invalid rune.
520 if !atEOF && !utf8.FullRune(src) {
521 err = ErrShortSrc
522 break
523 }
524 // We replace illegal bytes with RuneError. Not doing so might
525 // otherwise turn a sequence of invalid UTF-8 into valid UTF-8.
526 // The resulting byte sequence may subsequently contain runes
527 // for which t(r) is true that were passed unnoticed.
528 if !t(r) {
529 if nDst+3 > len(dst) {
530 err = ErrShortDst
531 break
532 }
533 nDst += copy(dst[nDst:], "\uFFFD")
534 }
535 nSrc++
536 continue
537 }
538 }
539 540 if !t(r) {
541 if nDst+sz > len(dst) {
542 err = ErrShortDst
543 break
544 }
545 nDst += copy(dst[nDst:], src[:sz])
546 }
547 nSrc += sz
548 }
549 return
550 }
551 552 // grow returns a new []byte that is longer than b, and copies the first n bytes
553 // of b to the start of the new slice.
554 func grow(b []byte, n int) []byte {
555 m := len(b)
556 if m <= 32 {
557 m = 64
558 } else if m <= 256 {
559 m *= 2
560 } else {
561 m += m >> 1
562 }
563 buf := []byte{:m}
564 copy(buf, b[:n])
565 return buf
566 }
567 568 const initialBufSize = 128
569 570 // String returns a string with the result of converting s[:n] using t, where
571 // n <= len(s). If err == nil, n will be len(s). It calls Reset on t.
572 func String(t Transformer, s string) (result string, n int, err error) {
573 t.Reset()
574 if s == "" {
575 // Fast path for the common case for empty input. Results in about a
576 // 86% reduction of running time for BenchmarkStringLowerEmpty.
577 if _, _, err := t.Transform(nil, nil, true); err == nil {
578 return "", 0, nil
579 }
580 }
581 582 // Allocate only once. Note that both dst and src escape when passed to
583 // Transform.
584 buf := [2 * initialBufSize]byte{}
585 dst := buf[:initialBufSize:initialBufSize]
586 src := buf[initialBufSize : 2*initialBufSize]
587 588 // The input string s is transformed in multiple chunks (starting with a
589 // chunk size of initialBufSize). nDst and nSrc are per-chunk (or
590 // per-Transform-call) indexes, pDst and pSrc are overall indexes.
591 nDst, nSrc := 0, 0
592 pDst, pSrc := 0, 0
593 594 // pPrefix is the length of a common prefix: the first pPrefix bytes of the
595 // result will equal the first pPrefix bytes of s. It is not guaranteed to
596 // be the largest such value, but if pPrefix, len(result) and len(s) are
597 // all equal after the final transform (i.e. calling Transform with atEOF
598 // being true returned nil error) then we don't need to allocate a new
599 // result string.
600 pPrefix := 0
601 for {
602 // Invariant: pDst == pPrefix && pSrc == pPrefix.
603 604 n := copy(src, s[pSrc:])
605 nDst, nSrc, err = t.Transform(dst, src[:n], pSrc+n == len(s))
606 pDst += nDst
607 pSrc += nSrc
608 609 // TODO: let transformers implement an optional Spanner interface, akin
610 // to norm's QuickSpan. This would even allow us to avoid any allocation.
611 if !bytes.Equal(dst[:nDst], src[:nSrc]) {
612 break
613 }
614 pPrefix = pSrc
615 if err == ErrShortDst {
616 // A buffer can only be short if a transformer modifies its input.
617 break
618 } else if err == ErrShortSrc {
619 if nSrc == 0 {
620 // No progress was made.
621 break
622 }
623 // Equal so far and !atEOF, so continue checking.
624 } else if err != nil || pPrefix == len(s) {
625 return string(s[:pPrefix]), pPrefix, err
626 }
627 }
628 // Post-condition: pDst == pPrefix + nDst && pSrc == pPrefix + nSrc.
629 630 // We have transformed the first pSrc bytes of the input s to become pDst
631 // transformed bytes. Those transformed bytes are discontiguous: the first
632 // pPrefix of them equal s[:pPrefix] and the last nDst of them equal
633 // dst[:nDst]. We copy them around, into a new dst buffer if necessary, so
634 // that they become one contiguous slice: dst[:pDst].
635 if pPrefix != 0 {
636 newDst := dst
637 if pDst > len(newDst) {
638 newDst = []byte{:len(s)+nDst-nSrc}
639 }
640 copy(newDst[pPrefix:pDst], dst[:nDst])
641 copy(newDst[:pPrefix], s[:pPrefix])
642 dst = newDst
643 }
644 645 // Prevent duplicate Transform calls with atEOF being true at the end of
646 // the input. Also return if we have an unrecoverable error.
647 if (err == nil && pSrc == len(s)) ||
648 (err != nil && err != ErrShortDst && err != ErrShortSrc) {
649 return string(dst[:pDst]), pSrc, err
650 }
651 652 // Transform the remaining input, growing dst and src buffers as necessary.
653 for {
654 n := copy(src, s[pSrc:])
655 atEOF := pSrc+n == len(s)
656 nDst, nSrc, err := t.Transform(dst[pDst:], src[:n], atEOF)
657 pDst += nDst
658 pSrc += nSrc
659 660 // If we got ErrShortDst or ErrShortSrc, do not grow as long as we can
661 // make progress. This may avoid excessive allocations.
662 if err == ErrShortDst {
663 if nDst == 0 {
664 dst = grow(dst, pDst)
665 }
666 } else if err == ErrShortSrc {
667 if atEOF {
668 return string(dst[:pDst]), pSrc, err
669 }
670 if nSrc == 0 {
671 src = grow(src, 0)
672 }
673 } else if err != nil || pSrc == len(s) {
674 return string(dst[:pDst]), pSrc, err
675 }
676 }
677 }
678 679 // Bytes returns a new byte slice with the result of converting b[:n] using t,
680 // where n <= len(b). If err == nil, n will be len(b). It calls Reset on t.
681 func Bytes(t Transformer, b []byte) (result []byte, n int, err error) {
682 return doAppend(t, 0, []byte{:len(b)}, b)
683 }
684 685 // Append appends the result of converting src[:n] using t to dst, where
686 // n <= len(src), If err == nil, n will be len(src). It calls Reset on t.
687 func Append(t Transformer, dst, src []byte) (result []byte, n int, err error) {
688 if len(dst) == cap(dst) {
689 n := len(src) + len(dst) // It is okay for this to be 0.
690 b := []byte{:n}
691 dst = b[:copy(b, dst)]
692 }
693 return doAppend(t, len(dst), dst[:cap(dst)], src)
694 }
695 696 func doAppend(t Transformer, pDst int, dst, src []byte) (result []byte, n int, err error) {
697 t.Reset()
698 pSrc := 0
699 for {
700 nDst, nSrc, err := t.Transform(dst[pDst:], src[pSrc:], true)
701 pDst += nDst
702 pSrc += nSrc
703 if err != ErrShortDst {
704 return dst[:pDst], pSrc, err
705 }
706 707 // Grow the destination buffer, but do not grow as long as we can make
708 // progress. This may avoid excessive allocations.
709 if nDst == 0 {
710 dst = grow(dst, pDst)
711 }
712 }
713 }
714