github.com/yusys-cloud/go-jsonstore-rest@v0.0.0-20230228115429-0a54aa4a27a6/jsonstore/jsonstore.go (about)

     1  // Author: yangzq80@gmail.com
     2  // Date: 2021-03-30
     3  package jsonstore
     4  
     5  import (
     6  	"compress/gzip"
     7  	"encoding/json"
     8  	"io"
     9  	"os"
    10  	"regexp"
    11  	"strings"
    12  	"sync"
    13  )
    14  
    15  // NoSuchKeyError is thrown when calling Get with invalid key
    16  type NoSuchKeyError struct {
    17  	key string
    18  }
    19  
    20  func (err NoSuchKeyError) Error() string {
    21  	return "jsonstore: no such key \"" + err.key + "\""
    22  }
    23  
    24  // JSONStore is the basic store object.
    25  type JSONStore struct {
    26  	Data map[string]json.RawMessage
    27  	sync.RWMutex
    28  }
    29  
    30  // Open will load a jsonstore from a file.
    31  func Open(filename string) (*JSONStore, error) {
    32  	var err error
    33  	f, err := os.Open(filename)
    34  	//defer f.Close()
    35  	if err != nil {
    36  		return nil, err
    37  	}
    38  
    39  	var w io.Reader
    40  	if strings.HasSuffix(filename, ".gz") {
    41  		w, err = gzip.NewReader(f)
    42  		if err != nil {
    43  			return nil, err
    44  		}
    45  	} else {
    46  		w = f
    47  	}
    48  
    49  	toOpen := make(map[string]string)
    50  	err = json.NewDecoder(w).Decode(&toOpen)
    51  	if err != nil {
    52  		return nil, err
    53  	}
    54  
    55  	ks := new(JSONStore)
    56  	ks.Data = make(map[string]json.RawMessage)
    57  	for key := range toOpen {
    58  		ks.Data[key] = json.RawMessage(toOpen[key])
    59  	}
    60  	return ks, nil
    61  }
    62  
    63  // Save writes the jsonstore to disk
    64  func Save(ks *JSONStore, filename string) (err error) {
    65  	ks.RLock()
    66  	defer ks.RUnlock()
    67  	toSave := make(map[string]string)
    68  	for key := range ks.Data {
    69  		toSave[key] = string(ks.Data[key])
    70  	}
    71  	f, err := os.Create(filename)
    72  	if err != nil {
    73  		return err
    74  	}
    75  	//defer f.Close()
    76  	if strings.HasSuffix(filename, ".gz") {
    77  		w := gzip.NewWriter(f)
    78  		defer w.Close()
    79  		enc := json.NewEncoder(w)
    80  		enc.SetIndent("", " ")
    81  		return enc.Encode(toSave)
    82  	}
    83  	enc := json.NewEncoder(f)
    84  	enc.SetIndent("", " ")
    85  	return enc.Encode(toSave)
    86  }
    87  
    88  // Set saves a value at the given key.
    89  func (s *JSONStore) Set(key string, value interface{}) error {
    90  	s.Lock()
    91  	defer s.Unlock()
    92  	if s.Data == nil {
    93  		s.Data = make(map[string]json.RawMessage)
    94  	}
    95  	b, err := json.Marshal(value)
    96  	if err != nil {
    97  		return err
    98  	}
    99  	s.Data[key] = json.RawMessage(b)
   100  	return nil
   101  }
   102  
   103  // Set saves a value at the given key.
   104  func (s *JSONStore) SetMarshalValue(key string, marshalValue []byte) error {
   105  	s.Lock()
   106  	defer s.Unlock()
   107  	if s.Data == nil {
   108  		s.Data = make(map[string]json.RawMessage)
   109  	}
   110  	s.Data[key] = json.RawMessage(marshalValue)
   111  	return nil
   112  }
   113  
   114  // Get will return the value with a key.
   115  func (s *JSONStore) GetRawMessage(key string) (error, json.RawMessage) {
   116  	s.RLock()
   117  	defer s.RUnlock()
   118  	b, ok := s.Data[key]
   119  	if !ok {
   120  		return NoSuchKeyError{key}, b
   121  	}
   122  	return nil, b
   123  }
   124  
   125  // Get will return the value associated with a key.
   126  func (s *JSONStore) Get(key string, v interface{}) error {
   127  	s.RLock()
   128  	defer s.RUnlock()
   129  	b, ok := s.Data[key]
   130  	if !ok {
   131  		return NoSuchKeyError{key}
   132  	}
   133  	return json.Unmarshal(b, &v)
   134  }
   135  
   136  // GetAll is like a filter with a regexp. If the regexp is nil, then it returns everything.
   137  func (s *JSONStore) GetAll(re *regexp.Regexp, limit ...int) map[string]json.RawMessage {
   138  	s.RLock()
   139  	defer s.RUnlock()
   140  	results := make(map[string]json.RawMessage)
   141  	for k, v := range s.Data {
   142  		if re == nil || re.MatchString(k) {
   143  			results[k] = v
   144  			if len(limit) > 0 {
   145  				if len(results) >= limit[0] {
   146  					return results
   147  				}
   148  			}
   149  		}
   150  	}
   151  	return results
   152  }
   153  
   154  // Keys returns all the keys currently in map
   155  func (s *JSONStore) Keys() []string {
   156  	s.RLock()
   157  	defer s.RUnlock()
   158  	keys := make([]string, len(s.Data))
   159  	i := 0
   160  	for k := range s.Data {
   161  		keys[i] = k
   162  		i++
   163  	}
   164  	return keys
   165  }
   166  
   167  // Delete removes a key from the store.
   168  func (s *JSONStore) Delete(key string) {
   169  	s.Lock()
   170  	defer s.Unlock()
   171  	delete(s.Data, key)
   172  }