本站源代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

181 lines
4.3KB

  1. // Package binary implements sintax-sugar functions on top of the standard
  2. // library binary package
  3. package binary
  4. import (
  5. "bufio"
  6. "encoding/binary"
  7. "io"
  8. "gopkg.in/src-d/go-git.v4/plumbing"
  9. )
  10. // Read reads structured binary data from r into data. Bytes are read and
  11. // decoded in BigEndian order
  12. // https://golang.org/pkg/encoding/binary/#Read
  13. func Read(r io.Reader, data ...interface{}) error {
  14. for _, v := range data {
  15. if err := binary.Read(r, binary.BigEndian, v); err != nil {
  16. return err
  17. }
  18. }
  19. return nil
  20. }
  21. // ReadUntil reads from r untin delim is found
  22. func ReadUntil(r io.Reader, delim byte) ([]byte, error) {
  23. if bufr, ok := r.(*bufio.Reader); ok {
  24. return ReadUntilFromBufioReader(bufr, delim)
  25. }
  26. var buf [1]byte
  27. value := make([]byte, 0, 16)
  28. for {
  29. if _, err := io.ReadFull(r, buf[:]); err != nil {
  30. if err == io.EOF {
  31. return nil, err
  32. }
  33. return nil, err
  34. }
  35. if buf[0] == delim {
  36. return value, nil
  37. }
  38. value = append(value, buf[0])
  39. }
  40. }
  41. // ReadUntilFromBufioReader is like bufio.ReadBytes but drops the delimiter
  42. // from the result.
  43. func ReadUntilFromBufioReader(r *bufio.Reader, delim byte) ([]byte, error) {
  44. value, err := r.ReadBytes(delim)
  45. if err != nil || len(value) == 0 {
  46. return nil, err
  47. }
  48. return value[:len(value)-1], nil
  49. }
  50. // ReadVariableWidthInt reads and returns an int in Git VLQ special format:
  51. //
  52. // Ordinary VLQ has some redundancies, example: the number 358 can be
  53. // encoded as the 2-octet VLQ 0x8166 or the 3-octet VLQ 0x808166 or the
  54. // 4-octet VLQ 0x80808166 and so forth.
  55. //
  56. // To avoid these redundancies, the VLQ format used in Git removes this
  57. // prepending redundancy and extends the representable range of shorter
  58. // VLQs by adding an offset to VLQs of 2 or more octets in such a way
  59. // that the lowest possible value for such an (N+1)-octet VLQ becomes
  60. // exactly one more than the maximum possible value for an N-octet VLQ.
  61. // In particular, since a 1-octet VLQ can store a maximum value of 127,
  62. // the minimum 2-octet VLQ (0x8000) is assigned the value 128 instead of
  63. // 0. Conversely, the maximum value of such a 2-octet VLQ (0xff7f) is
  64. // 16511 instead of just 16383. Similarly, the minimum 3-octet VLQ
  65. // (0x808000) has a value of 16512 instead of zero, which means
  66. // that the maximum 3-octet VLQ (0xffff7f) is 2113663 instead of
  67. // just 2097151. And so forth.
  68. //
  69. // This is how the offset is saved in C:
  70. //
  71. // dheader[pos] = ofs & 127;
  72. // while (ofs >>= 7)
  73. // dheader[--pos] = 128 | (--ofs & 127);
  74. //
  75. func ReadVariableWidthInt(r io.Reader) (int64, error) {
  76. var c byte
  77. if err := Read(r, &c); err != nil {
  78. return 0, err
  79. }
  80. var v = int64(c & maskLength)
  81. for c&maskContinue > 0 {
  82. v++
  83. if err := Read(r, &c); err != nil {
  84. return 0, err
  85. }
  86. v = (v << lengthBits) + int64(c&maskLength)
  87. }
  88. return v, nil
  89. }
  90. const (
  91. maskContinue = uint8(128) // 1000 000
  92. maskLength = uint8(127) // 0111 1111
  93. lengthBits = uint8(7) // subsequent bytes has 7 bits to store the length
  94. )
  95. // ReadUint64 reads 8 bytes and returns them as a BigEndian uint32
  96. func ReadUint64(r io.Reader) (uint64, error) {
  97. var v uint64
  98. if err := binary.Read(r, binary.BigEndian, &v); err != nil {
  99. return 0, err
  100. }
  101. return v, nil
  102. }
  103. // ReadUint32 reads 4 bytes and returns them as a BigEndian uint32
  104. func ReadUint32(r io.Reader) (uint32, error) {
  105. var v uint32
  106. if err := binary.Read(r, binary.BigEndian, &v); err != nil {
  107. return 0, err
  108. }
  109. return v, nil
  110. }
  111. // ReadUint16 reads 2 bytes and returns them as a BigEndian uint16
  112. func ReadUint16(r io.Reader) (uint16, error) {
  113. var v uint16
  114. if err := binary.Read(r, binary.BigEndian, &v); err != nil {
  115. return 0, err
  116. }
  117. return v, nil
  118. }
  119. // ReadHash reads a plumbing.Hash from r
  120. func ReadHash(r io.Reader) (plumbing.Hash, error) {
  121. var h plumbing.Hash
  122. if err := binary.Read(r, binary.BigEndian, h[:]); err != nil {
  123. return plumbing.ZeroHash, err
  124. }
  125. return h, nil
  126. }
  127. const sniffLen = 8000
  128. // IsBinary detects if data is a binary value based on:
  129. // http://git.kernel.org/cgit/git/git.git/tree/xdiff-interface.c?id=HEAD#n198
  130. func IsBinary(r io.Reader) (bool, error) {
  131. reader := bufio.NewReader(r)
  132. c := 0
  133. for {
  134. if c == sniffLen {
  135. break
  136. }
  137. b, err := reader.ReadByte()
  138. if err == io.EOF {
  139. break
  140. }
  141. if err != nil {
  142. return false, err
  143. }
  144. if b == byte(0) {
  145. return true, nil
  146. }
  147. c++
  148. }
  149. return false, nil
  150. }
上海开阖软件有限公司 沪ICP备12045867号-1