Skip to content

Commit

Permalink
- initial code commit
Browse files Browse the repository at this point in the history
  • Loading branch information
tox committed Apr 8, 2024
1 parent cc034de commit 9090db2
Show file tree
Hide file tree
Showing 37 changed files with 2,317 additions and 2 deletions.
42 changes: 40 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,40 @@
# flo
FLO (File Layer Operations) is a Go library to simplify working with files and directories.
# FLO (File Layer Operations)
... is a Go library to simplify working with files and directories. Feel free to use or fork it, if it works for you.

It is intended to be fast to use with a certain degree of flexibility.

## Examples

### `examples/codecs/main.go`
A test application for reading and writing data using the different formats supported. Also tests checksum comparisons.

### `examples/exec/main.go`
A simple application that can execute another application.

### `examples/flat-tree/main.go`
A tool that can list all files and directories contained in a directory. Recursion depth can be limited.

### `examples/hello/main.go`
An example that shows how to create a script on the fly, make it executable and execute it.

### `examples/lha/main.go`
An example application that acts like `ls -lha` with a few extras.

### `examples/ls/main.go`
An example that acts like a call to `ls`.

### `examples/tree/main.go`
Similar to the `flat-tree` example, but displays a tree structure instead, just like good ol' `tree`.

## Logging
There are a few cases where the library logs, in those cases it will use the `Error` and `Panic` functions found in `log/main.go`. You can overwrite these functions to handle errors yourself, e.g. to ignore errors:
```golang
// silence all logging
log.SetFns(nil, nil)

// no errors, custom panic handler
log.SetFns(nil, func(fmtStr string, args ...any) { panic(fmt.Sprintf("lib died: "+fmtStr, args...)) })

// no panics, custom error handler
log.SetFns(func(err error, fmtStr string, args ...any) (shouldReturn bool) { fmt.Println("Error", err.Error()) ; return err != nil }, nil)
```
31 changes: 31 additions & 0 deletions bitmask/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package bitmask

import "fmt"

type Bitmask uint32

func (bm *Bitmask) Uint() uint32 { return uint32(*bm) }
func (bm *Bitmask) String() string { return fmt.Sprintf("%032b", bm.Uint()) }
func (bm *Bitmask) AND(v uint32) *Bitmask { return New(bm.Uint() & v) }
func (bm *Bitmask) AND_NOT(v uint32) *Bitmask { return New(bm.Uint() &^ v) }
func (bm *Bitmask) OR(v uint32) *Bitmask { return New(bm.Uint() | v) }
func (bm *Bitmask) XOR(v uint32) *Bitmask { return New(bm.Uint() ^ v) }
func (bm *Bitmask) NOT() *Bitmask { return New(^bm.Uint()) }
func (bm *Bitmask) ShiftRight(n int) *Bitmask { return New(bm.Uint() >> n) }
func (bm *Bitmask) ShiftLeft(n int) *Bitmask { return New(bm.Uint() << n) }
func (bm *Bitmask) SetBit(n uint) *Bitmask { return bm.OR(uint32(0b1 << n)) }
func (bm *Bitmask) ClearBit(n uint) *Bitmask { return bm.AND_NOT(uint32(0b1 << n)) }
func (bm *Bitmask) Set(v uint32) *Bitmask { return bm.OR(v) }
func (bm *Bitmask) Clear(v uint32) *Bitmask { return bm.AND_NOT(v) }
func (bm *Bitmask) Match(v uint32) bool { return (bm.Uint() & v) == v }
func (bm *Bitmask) MatchAny(v uint32) bool { return (bm.Uint() & v) != 0 }
func (bm *Bitmask) Mask(m uint32, shift int) *Bitmask { return bm.AND(m).ShiftRight(shift) }

func New(value uint32) *Bitmask {
b := Bitmask(value)
return &b
}

func NewWithMask(value uint32, mask uint32, shift int) *Bitmask {
return New(value).Mask(mask, shift)
}
32 changes: 32 additions & 0 deletions checksum.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package flo

import (
c "github.com/toxyl/flo/codec"
)

func (f *FileObj) checksum(codec *c.Codec) string {
s := ""
f.read(codec, &s)
return s
}

func (f *FileObj) SHA1() string { return f.checksum(c.SHA1) }
func (f *FileObj) SHA256() string { return f.checksum(c.SHA256) }
func (f *FileObj) SHA512() string { return f.checksum(c.SHA512) }
func (f *FileObj) MD5() string { return f.checksum(c.MD5) }
func (f *FileObj) CRC32() string { return f.checksum(c.CRC32) }
func (f *FileObj) CRC64() string { return f.checksum(c.CRC64) }

func (f *FileObj) ReadSHA1(target *string) error { return f.read(c.SHA1, target) }
func (f *FileObj) ReadSHA256(target *string) error { return f.read(c.SHA256, target) }
func (f *FileObj) ReadSHA512(target *string) error { return f.read(c.SHA512, target) }
func (f *FileObj) ReadMD5(target *string) error { return f.read(c.MD5, target) }
func (f *FileObj) ReadCRC32(target *string) error { return f.read(c.CRC32, target) }
func (f *FileObj) ReadCRC64(target *string) error { return f.read(c.CRC64, target) }

func (f *FileObj) MustReadSHA1(target *string) *FileObj { return f.mustRead(c.SHA1, target) }
func (f *FileObj) MustReadSHA256(target *string) *FileObj { return f.mustRead(c.SHA256, target) }
func (f *FileObj) MustReadSHA512(target *string) *FileObj { return f.mustRead(c.SHA512, target) }
func (f *FileObj) MustReadMD5(target *string) *FileObj { return f.mustRead(c.MD5, target) }
func (f *FileObj) MustReadCRC32(target *string) *FileObj { return f.mustRead(c.CRC32, target) }
func (f *FileObj) MustReadCRC64(target *string) *FileObj { return f.mustRead(c.CRC64, target) }
64 changes: 64 additions & 0 deletions checksum/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package checksum

import (
"os"

"github.com/toxyl/flo/codec"
)

type Checksum struct {
algo *codec.Codec
file string
val string
}

func (c *Checksum) sum() string {
s := ""
file, _ := os.Open(c.file)
_ = c.algo.Decode(file, &s)
return s
}

func (c *Checksum) Get() string {
return c.val
}

func (c *Checksum) Update() {
valid := false
switch c.algo {
case codec.SHA1, codec.SHA256, codec.SHA512, codec.MD5, codec.CRC32, codec.CRC64:
valid = true
}
if !valid {
panic("you must choose a valid checksum algorithm (SHA1, SHA256, SHA512, MD5, CRC32 or CRC64)")
}
c.val = c.sum()
}

// Changed returns whether the current file checksum differs with the last one stored.
// When `update` is set to `true`, the old checksum will be updated if it has changed.
func (c *Checksum) Changed(update bool) bool {
chksum := c.sum()
changed := chksum != c.val
if changed && update {
c.val = chksum
}
return changed
}

func (c *Checksum) Matches(other *Checksum) bool {
return c.sum() == other.sum()
}

func (c *Checksum) MatchesBytes(data []byte) bool {
return c.sum() == c.algo.EncodeString(data)
}

func New(algo *codec.Codec, path string) *Checksum {
c := &Checksum{
algo: algo,
file: path,
val: "",
}
return c
}
Loading

0 comments on commit 9090db2

Please sign in to comment.