LEFT | RIGHT |
(no file at all) | |
1 // Copyright 2010 The Go Authors. All rights reserved. | 1 // Copyright 2010 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package textproto | 5 package textproto |
6 | 6 |
7 import ( | 7 import ( |
8 "bufio" | 8 "bufio" |
9 "bytes" | 9 "bytes" |
10 "io" | 10 "io" |
(...skipping 544 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
555 } | 555 } |
556 return s | 556 return s |
557 } | 557 } |
558 | 558 |
559 const toLower = 'a' - 'A' | 559 const toLower = 'a' - 'A' |
560 | 560 |
561 // canonicalMIMEHeaderKey is like CanonicalMIMEHeaderKey but is | 561 // canonicalMIMEHeaderKey is like CanonicalMIMEHeaderKey but is |
562 // allowed to mutate the provided byte slice before returning the | 562 // allowed to mutate the provided byte slice before returning the |
563 // string. | 563 // string. |
564 func canonicalMIMEHeaderKey(a []byte) string { | 564 func canonicalMIMEHeaderKey(a []byte) string { |
565 // Look for it in commonHeaders , so that we can avoid an | |
566 // allocation by sharing the strings among all users | |
567 // of textproto. If we don't find it, a has been canonicalized | |
568 // so just return string(a). | |
569 upper := true | 565 upper := true |
570 » lo := 0 | 566 » for i, c := range a { |
571 » hi := len(commonHeaders) | |
572 » for i := 0; i < len(a); i++ { | |
573 // Canonicalize: first letter upper case | 567 // Canonicalize: first letter upper case |
574 // and upper case after each dash. | 568 // and upper case after each dash. |
575 // (Host, User-Agent, If-Modified-Since). | 569 // (Host, User-Agent, If-Modified-Since). |
576 // MIME headers are ASCII only, so no Unicode issues. | 570 // MIME headers are ASCII only, so no Unicode issues. |
577 c := a[i] | |
578 if c == ' ' { | 571 if c == ' ' { |
579 c = '-' | 572 c = '-' |
580 } else if upper && 'a' <= c && c <= 'z' { | 573 } else if upper && 'a' <= c && c <= 'z' { |
581 c -= toLower | 574 c -= toLower |
582 } else if !upper && 'A' <= c && c <= 'Z' { | 575 } else if !upper && 'A' <= c && c <= 'Z' { |
583 c += toLower | 576 c += toLower |
584 } | 577 } |
585 a[i] = c | 578 a[i] = c |
586 upper = c == '-' // for next time | 579 upper = c == '-' // for next time |
587 | 580 » } |
588 » » if lo < hi { | 581 » // The compiler recognizes m[string(byteSlice)] as a special |
589 » » » for lo < hi && (len(commonHeaders[lo]) <= i || commonHea
ders[lo][i] < c) { | 582 » // case, so a copy of a's bytes into a new string does not |
590 » » » » lo++ | 583 » // happen in this map lookup: |
591 » » » } | 584 » if v := commonHeader[string(a)]; v != "" { |
592 » » » for hi > lo && commonHeaders[hi-1][i] > c { | 585 » » return v |
593 » » » » hi-- | |
594 » » » } | |
595 » » } | |
596 » } | |
597 » if lo < hi && len(commonHeaders[lo]) == len(a) { | |
598 » » return commonHeaders[lo] | |
599 } | 586 } |
600 return string(a) | 587 return string(a) |
601 } | 588 } |
602 | 589 |
603 var commonHeaders = []string{ | 590 // commonHeader interns common header strings. |
604 » "Accept", | 591 var commonHeader = make(map[string]string) |
605 » "Accept-Charset", | 592 |
606 » "Accept-Encoding", | 593 func init() { |
607 » "Accept-Language", | 594 » for _, v := range []string{ |
608 » "Accept-Ranges", | 595 » » "Accept", |
609 » "Cache-Control", | 596 » » "Accept-Charset", |
610 » "Cc", | 597 » » "Accept-Encoding", |
611 » "Connection", | 598 » » "Accept-Language", |
612 » "Content-Id", | 599 » » "Accept-Ranges", |
613 » "Content-Language", | 600 » » "Cache-Control", |
614 » "Content-Length", | 601 » » "Cc", |
615 » "Content-Transfer-Encoding", | 602 » » "Connection", |
616 » "Content-Type", | 603 » » "Content-Id", |
617 » "Cookie", | 604 » » "Content-Language", |
618 » "Date", | 605 » » "Content-Length", |
619 » "Dkim-Signature", | 606 » » "Content-Transfer-Encoding", |
620 » "Etag", | 607 » » "Content-Type", |
621 » "Expires", | 608 » » "Cookie", |
622 » "From", | 609 » » "Date", |
623 » "Host", | 610 » » "Dkim-Signature", |
624 » "If-Modified-Since", | 611 » » "Etag", |
625 » "If-None-Match", | 612 » » "Expires", |
626 » "In-Reply-To", | 613 » » "From", |
627 » "Last-Modified", | 614 » » "Host", |
628 » "Location", | 615 » » "If-Modified-Since", |
629 » "Message-Id", | 616 » » "If-None-Match", |
630 » "Mime-Version", | 617 » » "In-Reply-To", |
631 » "Pragma", | 618 » » "Last-Modified", |
632 » "Received", | 619 » » "Location", |
633 » "Return-Path", | 620 » » "Message-Id", |
634 » "Server", | 621 » » "Mime-Version", |
635 » "Set-Cookie", | 622 » » "Pragma", |
636 » "Subject", | 623 » » "Received", |
637 » "To", | 624 » » "Return-Path", |
638 » "User-Agent", | 625 » » "Server", |
639 » "Via", | 626 » » "Set-Cookie", |
640 » "X-Forwarded-For", | 627 » » "Subject", |
641 » "X-Imforwards", | 628 » » "To", |
642 » "X-Powered-By", | 629 » » "User-Agent", |
643 } | 630 » » "Via", |
| 631 » » "X-Forwarded-For", |
| 632 » » "X-Imforwards", |
| 633 » » "X-Powered-By", |
| 634 » } { |
| 635 » » commonHeader[v] = v |
| 636 » } |
| 637 } |
LEFT | RIGHT |