github.com/geniusesgroup/libgo@v0.0.0-20220713101832-828057a9d3d4/os/default/file.go (about) 1 /* For license and copyright information please see LEGAL file in repository */ 2 3 package dos 4 5 import ( 6 "bytes" 7 "compress/gzip" 8 "io" 9 "mime" 10 goos "os" 11 12 "../../codec" 13 "../../minify" 14 "../../protocol" 15 ) 16 17 // File store some data about a file! 18 type File struct { 19 metadata fileMetaData 20 parentDirectory *FileDirectory 21 mediaType string 22 compressType string 23 data []byte 24 } 25 26 func (f *File) MetaData() protocol.FileMetaData { return &f.metadata } 27 func (f *File) Data() protocol.FileData { return f } 28 func (f *File) ParentDirectory() protocol.FileDirectory { return f.parentDirectory } 29 30 func (f *File) init(path string) (err protocol.Error) { 31 f.metadata.uri.Init(path) 32 f.mediaType = mime.TypeByExtension("." + f.metadata.uri.Extension()) 33 return 34 } 35 36 // Save use to write file to the file system! 37 func (f *File) Save() (err protocol.Error) { 38 // Just write changed file 39 if f.data != nil { 40 var goErr = goos.WriteFile(f.metadata.uri.Path(), f.data, 0700) 41 if goErr != nil { 42 // err = 43 } 44 } 45 return 46 } 47 48 // Rename rename file name and full name 49 func (f *File) Rename(newName string) { 50 delete(f.parentDirectory.files, f.metadata.uri.Name()) 51 f.parentDirectory.files[newName] = f 52 f.metadata.uri.Rename(newName) 53 } 54 55 // Minify replace file data with minify of them if possible. 56 func (f *File) Minify() (err protocol.Error) { 57 err = minify.Minify(f) 58 return 59 } 60 61 // Compress use to compress file data to mostly to use in serving file by servers. 62 func (f *File) Compress(compressType string) { 63 // Check file type and compress just if it worth. 64 switch f.metadata.uri.Extension() { 65 case "png", "jpg", "gif", "jpeg", "mkv", "avi", "mp3", "mp4": 66 return 67 } 68 69 f.compressType = compressType 70 switch compressType { 71 case codec.CompressTypeGZIP: 72 var b bytes.Buffer 73 var gz = gzip.NewWriter(&b) 74 gz.Write(f.data) 75 gz.Close() 76 f.data = b.Bytes() 77 } 78 } 79 80 // Replace replace all old data in the file with new one 81 func (f *File) Replace(old, new []byte, n int) { 82 f.data = bytes.Replace(f.data, old, new, n) 83 } 84 85 // ReplaceReq is request structure of Replace method. 86 type ReplaceReq struct { 87 Data string 88 Start int 89 End int 90 } 91 92 // Replace replace given data in the file 93 func (f *File) ReplaceLocation(data []ReplaceReq) { 94 var totalAddedSize, addedSize int 95 for _, d := range data { 96 d.Start += totalAddedSize 97 d.End += totalAddedSize 98 99 var ln = len(d.Data) 100 addedSize = ln - (d.End - d.Start) 101 if addedSize > 0 { 102 if (cap(f.data) - len(f.data)) < addedSize { 103 f.data = append(f.data, make([]byte, addedSize)...) 104 } else { 105 // increase f.data len 106 f.data = f.data[:len(f.data)+addedSize] 107 } 108 } 109 totalAddedSize += addedSize 110 111 copy(f.data[d.End+addedSize:], f.data[d.End:]) 112 copy(f.data[d.Start:], d.Data) 113 114 if addedSize < 0 { 115 // decrease f.data len 116 f.data = f.data[:len(f.data)+addedSize] 117 } 118 } 119 } 120 121 /* 122 ********** protocol.FileData interface ********** 123 */ 124 125 // Prepend add given data to start of exiting data that add earlier 126 func (f *File) Prepend(data []byte) { 127 if f.data != nil { 128 f.data = append(data, f.data...) 129 } else { 130 // TODO::: 131 } 132 } 133 134 // Append append given data to end of exiting data that add earlier 135 func (f *File) Append(data []byte) { 136 if f.data != nil { 137 f.data = append(f.data, data...) 138 } else { 139 var goErr error 140 var file *goos.File 141 file, goErr = goos.OpenFile(f.metadata.URI().URI(), goos.O_APPEND|goos.O_WRONLY, 0700) 142 if goErr != nil { 143 // if goos.IsNotExist(goErr) { 144 // return ErrStorageNotExist 145 // } 146 // if goos.IsPermission(goErr) { 147 // return ErrStorageNotAuthorize 148 // } 149 // return ErrStorageDeviceProblem 150 return 151 } 152 153 _, goErr = file.Write(data) 154 var err1 = file.Close() 155 if goErr == nil { 156 goErr = err1 157 } 158 } 159 } 160 161 /* 162 ********** protocol.Codec interface ********** 163 */ 164 165 func (f *File) MediaType() string { return f.mediaType } 166 func (f *File) CompressType() string { return f.compressType } 167 168 func (f *File) Decode(reader io.Reader) (err protocol.Error) { 169 var buf bytes.Buffer 170 var _, goErr = io.Copy(&buf, reader) 171 if goErr != nil { 172 // err = 173 } 174 err = f.Unmarshal(buf.Bytes()) 175 return 176 } 177 178 // Encode write file to given writer 179 func (f *File) Encode(writer io.Writer) (err error) { _, err = f.WriteTo(writer); return } 180 181 // Marshal enecodes and return whole file data! 182 func (f *File) Marshal() (data []byte) { 183 if f.data != nil { 184 return f.data 185 } 186 data, _ = goos.ReadFile(f.metadata.uri.Path()) 187 return 188 } 189 190 // MarshalTo enecodes whole file data to given data and return it with new len! 191 func (f *File) MarshalTo(data []byte) []byte { 192 data = append(data, f.data...) 193 return data 194 } 195 196 // Unmarshal save given data to the file. It will overwritten exiting data. 197 func (f *File) Unmarshal(data []byte) (err protocol.Error) { 198 // TODO::: MediaType?? 199 f.data = data 200 return 201 } 202 203 // Len return length of file 204 func (f *File) Len() (ln int) { return len(f.data) } 205 206 /* 207 ********** io package interfaces ********** 208 */ 209 210 // ReadFrom decodes f *File data by read from given io.Reader! 211 func (f *File) ReadFrom(reader io.Reader) (n int64, err error) { 212 var buf bytes.Buffer 213 n, err = io.Copy(&buf, reader) 214 f.data = buf.Bytes() 215 return 216 } 217 218 // WriteTo enecodes f *File data and write it to given io.Writer! 219 // Declare to respect io.WriterTo interface! 220 func (f *File) WriteTo(w io.Writer) (totalWrite int64, err error) { 221 var writeLength int 222 writeLength, err = w.Write(f.data) 223 totalWrite = int64(writeLength) 224 return 225 }