mirror of
https://github.com/mainflux/mainflux.git
synced 2025-04-27 13:48:49 +08:00

* Switch CoAP lib Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com> * Revert removed adapter code Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com> * WIP CoAP refactor Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com> * Add auth key Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com> * Fix observers map Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com> * Fix reading message body Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com> * Fix subtopic parsing Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com> * Fix error handling Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com> * Fix multi-protocol communication Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com> * Separate client from observer Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com> * Remove unused config Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com> * Remove TCP option Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com> * Inline error check Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com> * Add logging client errors Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com> * Replace RWMutex since we're not using RLock Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com> * Inline error handling Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com> * Inline error handling Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>
149 lines
3.7 KiB
Go
149 lines
3.7 KiB
Go
// Copyright 2017, Joe Tsai. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE.md file.
|
|
|
|
// Package memfile implements an in-memory emulation of os.File.
|
|
package memfile
|
|
|
|
import (
|
|
"errors"
|
|
"io"
|
|
"sync"
|
|
)
|
|
|
|
var errInvalid = errors.New("invalid argument")
|
|
|
|
// File is an in-memory emulation of the I/O operations of os.File.
|
|
// The zero value for File is an empty file ready to use.
|
|
type File struct {
|
|
m sync.Mutex
|
|
b []byte
|
|
i int
|
|
}
|
|
|
|
// New creates and initializes a new File using b as its initial contents.
|
|
// The new File takes ownership of b.
|
|
func New(b []byte) *File {
|
|
return &File{b: b}
|
|
}
|
|
|
|
// Read reads up to len(b) bytes from the File.
|
|
// It returns the number of bytes read and any error encountered.
|
|
// At end of file, Read returns (0, io.EOF).
|
|
func (fb *File) Read(b []byte) (int, error) {
|
|
fb.m.Lock()
|
|
defer fb.m.Unlock()
|
|
|
|
n, err := fb.readAt(b, int64(fb.i))
|
|
fb.i += n
|
|
return n, err
|
|
}
|
|
|
|
// ReadAt reads len(b) bytes from the File starting at byte offset.
|
|
// It returns the number of bytes read and the error, if any.
|
|
// At end of file, that error is io.EOF.
|
|
func (fb *File) ReadAt(b []byte, offset int64) (int, error) {
|
|
fb.m.Lock()
|
|
defer fb.m.Unlock()
|
|
return fb.readAt(b, offset)
|
|
}
|
|
func (fb *File) readAt(b []byte, off int64) (int, error) {
|
|
if off < 0 || int64(int(off)) < off {
|
|
return 0, errInvalid
|
|
}
|
|
if off > int64(len(fb.b)) {
|
|
return 0, io.EOF
|
|
}
|
|
n := copy(b, fb.b[off:])
|
|
if n < len(b) {
|
|
return n, io.EOF
|
|
}
|
|
return n, nil
|
|
}
|
|
|
|
// Write writes len(b) bytes to the File.
|
|
// It returns the number of bytes written and an error, if any.
|
|
// If the current file offset is past the io.EOF, then the space in-between are
|
|
// implicitly filled with zero bytes.
|
|
func (fb *File) Write(b []byte) (int, error) {
|
|
fb.m.Lock()
|
|
defer fb.m.Unlock()
|
|
|
|
n, err := fb.writeAt(b, int64(fb.i))
|
|
fb.i += n
|
|
return n, err
|
|
}
|
|
|
|
// WriteAt writes len(b) bytes to the File starting at byte offset.
|
|
// It returns the number of bytes written and an error, if any.
|
|
// If offset lies past io.EOF, then the space in-between are implicitly filled
|
|
// with zero bytes.
|
|
func (fb *File) WriteAt(b []byte, offset int64) (int, error) {
|
|
fb.m.Lock()
|
|
defer fb.m.Unlock()
|
|
return fb.writeAt(b, offset)
|
|
}
|
|
func (fb *File) writeAt(b []byte, off int64) (int, error) {
|
|
if off < 0 || int64(int(off)) < off {
|
|
return 0, errInvalid
|
|
}
|
|
if off > int64(len(fb.b)) {
|
|
fb.truncate(off)
|
|
}
|
|
n := copy(fb.b[off:], b)
|
|
fb.b = append(fb.b, b[n:]...)
|
|
return len(b), nil
|
|
}
|
|
|
|
// Seek sets the offset for the next Read or Write on file with offset,
|
|
// interpreted according to whence: 0 means relative to the origin of the file,
|
|
// 1 means relative to the current offset, and 2 means relative to the end.
|
|
func (fb *File) Seek(offset int64, whence int) (int64, error) {
|
|
fb.m.Lock()
|
|
defer fb.m.Unlock()
|
|
|
|
var abs int64
|
|
switch whence {
|
|
case io.SeekStart:
|
|
abs = offset
|
|
case io.SeekCurrent:
|
|
abs = int64(fb.i) + offset
|
|
case io.SeekEnd:
|
|
abs = int64(len(fb.b)) + offset
|
|
default:
|
|
return 0, errInvalid
|
|
}
|
|
if abs < 0 {
|
|
return 0, errInvalid
|
|
}
|
|
fb.i = int(abs)
|
|
return abs, nil
|
|
}
|
|
|
|
// Truncate changes the size of the file. It does not change the I/O offset.
|
|
func (fb *File) Truncate(n int64) error {
|
|
fb.m.Lock()
|
|
defer fb.m.Unlock()
|
|
return fb.truncate(n)
|
|
}
|
|
func (fb *File) truncate(n int64) error {
|
|
switch {
|
|
case n < 0 || int64(int(n)) < n:
|
|
return errInvalid
|
|
case n <= int64(len(fb.b)):
|
|
fb.b = fb.b[:n]
|
|
return nil
|
|
default:
|
|
fb.b = append(fb.b, make([]byte, int(n)-len(fb.b))...)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// Bytes returns the full contents of the File.
|
|
// The result in only valid until the next Write, WriteAt, or Truncate call.
|
|
func (fb *File) Bytes() []byte {
|
|
fb.m.Lock()
|
|
defer fb.m.Unlock()
|
|
return fb.b
|
|
}
|