diff options
Diffstat (limited to 'snap')
-rw-r--r-- | snap/parsing.go | 89 | ||||
-rw-r--r-- | snap/parsing_test.go | 31 | ||||
-rw-r--r-- | snap/snap.go | 6 |
3 files changed, 126 insertions, 0 deletions
diff --git a/snap/parsing.go b/snap/parsing.go new file mode 100644 index 0000000..a848c33 --- /dev/null +++ b/snap/parsing.go @@ -0,0 +1,89 @@ +package snap + +import ( + "strings" + "log" + "os" + "strconv" +) + +var die = log.New(os.Stderr, "", 0) + +func isEscaped(str string) bool { + n := len(str) + return n > 1 && str[0] == '"' && str[n - 1] == '"'; +} + +func parseEscaped(snapish string) *Relative { + if isEscaped(snapish) { + snapshot := strings.Trim(snapish, `"`); + + if(snapshot == "") { + die.Fatal("Snapshot cannot be empty \"\"") + + } + + return &Relative { + snapshot: snapshot, + } + } + + return nil +} + +func parseRelativeSyntax(snapish, directionToken string) *Relative { + parts := strings.Split(snapish, directionToken) + n_parts := len(parts) + + if n_parts == 1 { + return nil; + } + + // Test if the last the last token is a numeric offset + if offset, err := strconv.Atoi(parts[n_parts - 1]); + err == nil { + + // Two tokens (e.g. ++ or --) indicates increment syntax + if n_parts > 2 && parts[n_parts - 2] == "" { + die.Fatal("A snapshot reference cannot be a mix of increment syntax (e.g. my_snap++) and literal syntax (e.g. my_snap+4).") + } + + snapshot := strings.TrimRight(snapish, directionToken + "0123456789") + + return &Relative { + offset: offset, + snapshot: snapshot, + } + } + + // Parse the increment / decrement syntax + // E.g. snapshot+++ or snapshot--- + offset := 0; + for i := n_parts - 1; i >= 1 && parts[i] == ""; i-- { + offset += 1 + } + + return &Relative { + offset: offset, + snapshot: snapish[:len(snapish) - offset], + } +} + +func ToRelative(snapish string) * Relative { + if ref := parseEscaped(snapish); ref != nil { + return ref; + } + + if ref := parseRelativeSyntax(snapish, "+"); ref != nil { + return ref; + } + + if ref := parseRelativeSyntax(snapish, "-"); ref != nil { + ref.offset = -ref.offset; + return ref; + } + + return &Relative{ + snapshot: snapish, + }; +}
\ No newline at end of file diff --git a/snap/parsing_test.go b/snap/parsing_test.go new file mode 100644 index 0000000..1a87723 --- /dev/null +++ b/snap/parsing_test.go @@ -0,0 +1,31 @@ +package snap + +import "testing" + +func TestRelativeParsing(t * testing.T) { + cases := []struct { + snapish string + snapshot string + offset int + } { + {"snapshot", "snapshot", 0}, + {"testing--", "testing", -2}, + {"%SNAPSHOT%^+++", "%SNAPSHOT%^", 3}, + {"--prefixed", "--prefixed", 0}, + {"+++", "", 3}, + {"---", "", -3}, + {"+5", "", 5}, + {"-3", "", -3}, + {"+", "", 1}, + {"-", "", -1}, + {`"-"`, "-", 0}, + } + + for _, c := range cases { + got := ToRelative(c.snapish) + + if got.offset != c.offset || got.snapshot != c.snapshot { + t.Errorf("ToRelative(%s) == %+v, wanted %+v", c.snapish, got, c) + } + } +}
\ No newline at end of file diff --git a/snap/snap.go b/snap/snap.go new file mode 100644 index 0000000..fde60c4 --- /dev/null +++ b/snap/snap.go @@ -0,0 +1,6 @@ +package snap + +type Relative struct { + snapshot string + offset int +}
\ No newline at end of file |