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 }