1package psd 2 3import ( 4 "io" 5 "io/ioutil" 6 "math" 7 "unicode/utf16" 8) 9 10func itoa(x int) string { 11 var b [32]byte 12 var minus bool 13 if x < 0 { 14 minus = true 15 x = -x 16 } 17 i := len(b) - 1 18 for x > 9 { 19 b[i] = byte(x%10 + '0') 20 x /= 10 21 i-- 22 } 23 b[i] = byte(x + '0') 24 if minus { 25 i-- 26 b[i] = '-' 27 } 28 return string(b[i:]) 29} 30 31func readUint16(b []byte, offset int) uint16 { 32 return uint16(b[offset])<<8 | uint16(b[offset+1]) 33} 34 35func writeUint16(b []byte, v uint16, offset int) { 36 b[offset] = uint8(v >> 8) 37 b[offset+1] = uint8(v) 38} 39 40func readUint32(b []byte, offset int) uint32 { 41 return uint32(b[offset])<<24 | uint32(b[offset+1])<<16 | uint32(b[offset+2])<<8 | uint32(b[offset+3]) 42} 43 44func readUint64(b []byte, offset int) uint64 { 45 return uint64(b[offset])<<56 | uint64(b[offset+1])<<48 | uint64(b[offset+2])<<40 | uint64(b[offset+3])<<32 | 46 uint64(b[offset+4])<<24 | uint64(b[offset+5])<<16 | uint64(b[offset+6])<<8 | uint64(b[offset+7]) 47} 48 49func get4or8(is64 bool) int { 50 if is64 { 51 return 8 52 } 53 return 4 54} 55 56func readUint(b []byte, offset int, size int) uint64 { 57 switch size { 58 case 8: 59 return readUint64(b, offset) 60 case 4: 61 return uint64(readUint32(b, offset)) 62 case 2: 63 return uint64(readUint16(b, offset)) 64 case 1: 65 return uint64(b[offset]) 66 } 67 panic("psd: unexpected size") 68} 69 70func readFloat32(b []byte, offset int) float32 { 71 return math.Float32frombits(readUint32(b, offset)) 72} 73 74func readFloat64(b []byte, offset int) float64 { 75 return math.Float64frombits(readUint64(b, offset)) 76} 77 78func writeUint32(b []byte, v uint32, offset int) { 79 b[offset] = uint8(v >> 24) 80 b[offset+1] = uint8(v >> 16) 81 b[offset+2] = uint8(v >> 8) 82 b[offset+3] = uint8(v) 83} 84 85func readUnicodeString(b []byte) string { 86 ln := readUint32(b, 0) 87 if ln == 0 { 88 return "" 89 } 90 buf := make([]uint16, ln) 91 for i := range buf { 92 buf[i] = readUint16(b, 4+i<<1) 93 } 94 return string(utf16.Decode(buf)) 95} 96 97func adjustAlign2(r io.Reader, l int) (read int, err error) { 98 if l&1 != 0 { 99 var b [1]byte 100 return r.Read(b[:]) 101 } 102 return 0, nil 103} 104 105func adjustAlign4(r io.Reader, l int) (read int, err error) { 106 if gap := l & 3; gap > 0 { 107 var b [4]byte 108 return r.Read(b[:4-gap]) 109 } 110 return 0, nil 111} 112 113func discard(r io.Reader, skip int) (read int, err error) { 114 type discarder interface { 115 Discard(n int) (discarded int, err error) 116 } 117 switch rr := r.(type) { 118 case discarder: 119 return rr.Discard(skip) 120 case io.Seeker: 121 if _, err = rr.Seek(int64(skip), 1); err != nil { 122 return 0, err 123 } 124 return skip, nil 125 default: 126 rd, err := io.CopyN(ioutil.Discard, r, int64(skip)) 127 return int(rd), err 128 } 129} 130 131func readPascalString(r io.Reader) (str string, read int, err error) { 132 b := make([]byte, 1) 133 if _, err := io.ReadFull(r, b); err != nil { 134 return "", 0, err 135 } 136 if b[0] == 0 { 137 return "", 1, nil 138 } 139 buf := make([]byte, b[0]) 140 if _, err := io.ReadFull(r, buf); err != nil { 141 return "", 1, err 142 } 143 return string(buf), len(buf) + 1, nil 144} 145 146func reportReaderPosition(format string, r io.Reader) error { 147 sk, ok := r.(io.Seeker) 148 if !ok { 149 return nil 150 } 151 152 pos, err := sk.Seek(0, 1) 153 if err != nil { 154 return err 155 } 156 Debug.Printf(format, pos) 157 return nil 158} 159