-
Notifications
You must be signed in to change notification settings - Fork 2
/
BarbDB.go
132 lines (113 loc) · 3.36 KB
/
BarbDB.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package BarbDB
import (
"encoding/base64" // To encode and decode strings in the database
"errors" // To return custom errors
"os" // To perform CRUD operations on files
"strings" // To split and merge strings
)
// The struct that represents the database.
type barbDB struct {
file os.File
}
// Opens a database at the given path.
func OpenDB(path string) (*barbDB, error) {
// Open the file
file, fileError := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0600)
if fileError != nil {
return nil, fileError
}
// Return the database struct
return &barbDB{
file: *file,
}, nil
}
// Helper function to read the file.
func (db barbDB) readFile() ([]string, error) {
// Read the file
data, readError := os.ReadFile(db.file.Name())
if readError != nil {
return nil, readError
}
// Split the data into lines and return it
return strings.Split(string(data), "\n"), nil
}
// Returns the value of the given key.
func (db barbDB) Get(key string) (string, error) {
// Base64 encode the key
encodedKey := base64.RawStdEncoding.EncodeToString([]byte(key))
// Read the file
fileContent, fileReadError := db.readFile()
if fileReadError != nil {
return "", fileReadError
}
// Loop over the lines in the file
for i := 0; i < len(fileContent); i++ {
splitString := strings.Split(fileContent[i], "=")
if splitString[0] == encodedKey {
// Decode the value and return it
toReturn, base64DecodeError := base64.RawStdEncoding.DecodeString(splitString[1])
if base64DecodeError != nil {
return "", base64DecodeError
}
return string(toReturn), nil
}
}
// Return an error if the key doesn't exist
return "", errors.New("key not found")
}
// Sets the value of the given key.
func (db barbDB) Set(key string, value string) error {
// Base64 encode the key and value
encodedKey := base64.RawStdEncoding.EncodeToString([]byte(key))
encodedValue := base64.RawStdEncoding.EncodeToString([]byte(value))
// Read the file
fileContent, fileReadError := db.readFile()
if fileReadError != nil {
return fileReadError
}
// Check if the key already exists
for i := 0; i < len(fileContent); i++ {
splitString := strings.Split(fileContent[i], "=")
if splitString[0] == encodedKey {
// Delete the key if it does
deleteError := db.Delete(key)
if deleteError != nil {
return deleteError
}
}
}
// Write the key and value to the file
_, fileWriteError := db.file.WriteString(encodedKey + "=" + encodedValue + "\n")
if fileWriteError != nil {
return fileWriteError
}
return db.file.Sync()
}
// Deletes the given key from the database.
func (db barbDB) Delete(key string) error {
// Base64 encode the key
encodedKey := base64.RawStdEncoding.EncodeToString([]byte(key))
// Read the file
fileContent, fileReadError := db.readFile()
if fileReadError != nil {
return fileReadError
}
// Loop over the lines in the file
for i := 0; i < len(fileContent); i++ {
splitString := strings.Split(fileContent[i], "=")
if splitString[0] == encodedKey {
// Delete the key
fileContent = append(fileContent[:i], fileContent[i+1:]...)
}
}
// Remove the key and value from the file
fileWriteError := os.WriteFile(db.file.Name(), []byte(strings.Join(fileContent, "\n")), 0600)
if fileWriteError != nil {
return fileWriteError
}
return db.file.Sync()
}
// Closes the database.
func (db barbDB) Close() error {
return db.file.Close()
}