github.com/GeniusesGroup/libgo@v0.0.0-20220929090155-5ff932cb408e/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  }