diff --git a/model/lyrics.go b/model/lyrics.go index bf3c87aa4..46612d1e9 100644 --- a/model/lyrics.go +++ b/model/lyrics.go @@ -10,6 +10,7 @@ import ( "unicode" "github.com/navidrome/navidrome/log" + "github.com/navidrome/navidrome/utils/gg" "github.com/navidrome/navidrome/utils/str" ) @@ -542,7 +543,7 @@ func NormalizeCueEnds(cues []Cue, fallbackEnd *int64) []Cue { if end != nil && out[i].Start != nil && *end < *out[i].Start { end = out[i].Start } - out[i].End = ptrOrNil(end) + out[i].End = gg.Clone(end) } for i := range out { @@ -555,13 +556,3 @@ func NormalizeCueEnds(cues []Cue, fallbackEnd *int64) []Cue { } return out } - -// ptrOrNil returns a fresh copy of *v so callers never alias another cue's -// Start/End pointer into the result. -func ptrOrNil(v *int64) *int64 { - if v == nil { - return nil - } - c := *v - return &c -} diff --git a/model/lyrics_ttml.go b/model/lyrics_ttml.go index 8b90f93b1..fe3a547d5 100644 --- a/model/lyrics_ttml.go +++ b/model/lyrics_ttml.go @@ -13,6 +13,7 @@ import ( "unicode" "github.com/navidrome/navidrome/log" + "github.com/navidrome/navidrome/utils/gg" "github.com/navidrome/navidrome/utils/str" ) @@ -487,7 +488,7 @@ func splitTTMLPiecesByNewline(pieces []ttmlPiece) [][]ttmlPiece { if start < i { lines[len(lines)-1] = append(lines[len(lines)-1], ttmlPiece{ raw: raw[start:i], - cue: cloneTTMLCue(piece.cue), + cue: gg.Clone(piece.cue), }) } lines = append(lines, []ttmlPiece{}) @@ -496,7 +497,7 @@ func splitTTMLPiecesByNewline(pieces []ttmlPiece) [][]ttmlPiece { if start < len(raw) { lines[len(lines)-1] = append(lines[len(lines)-1], ttmlPiece{ raw: raw[start:], - cue: cloneTTMLCue(piece.cue), + cue: gg.Clone(piece.cue), }) } } @@ -562,15 +563,6 @@ func ttmlPiecesContainCue(pieces []ttmlPiece) bool { return false } -func cloneTTMLCue(cue *Cue) *Cue { - if cue == nil { - return nil - } - - cloned := *cue - return &cloned -} - func (p *ttmlParser) toLyricList() LyricList { res := make(LyricList, 0, len(p.mainLangOrder)+len(p.translationLangOrder)+len(p.pronunciationLangOrder)) for _, lang := range p.mainLangOrder { @@ -979,9 +971,9 @@ func (p *ttmlParser) updateTimingParams(attrs []xml.Attr) { } } - p.params.frameRate = positiveOrDefault(frameRate, defaultTTMLFrameRate) - p.params.subFrameRate = positiveOrDefault(subFrameRate, defaultTTMLSubFrameRate) - p.params.tickRate = positiveOrDefault(tickRate, defaultTTMLTickRate) + p.params.frameRate = gg.If(frameRate > 0, frameRate, defaultTTMLFrameRate) + p.params.subFrameRate = gg.If(subFrameRate > 0, subFrameRate, defaultTTMLSubFrameRate) + p.params.tickRate = gg.If(tickRate > 0, tickRate, defaultTTMLTickRate) } func parseTTMLDurationExpression(expr string, params ttmlTimingParams) (int64, bool) { @@ -1262,10 +1254,3 @@ func linesAreSynced(lines []Line) bool { } return false } - -func positiveOrDefault(v float64, fallback float64) float64 { - if v <= 0 { - return fallback - } - return v -} diff --git a/utils/gg/gg.go b/utils/gg/gg.go index 674cacf20..837f56339 100644 --- a/utils/gg/gg.go +++ b/utils/gg/gg.go @@ -16,3 +16,13 @@ func If[T any](cond bool, v1, v2 T) T { } return v2 } + +// Clone returns a pointer to a fresh copy of *p, or nil if p is nil. Use it to +// avoid aliasing the pointed-to value when a separate *T is needed. +func Clone[T any](p *T) *T { + if p == nil { + return nil + } + v := *p + return &v +} diff --git a/utils/gg/gg_test.go b/utils/gg/gg_test.go index a2dd8154f..bb6fae867 100644 --- a/utils/gg/gg_test.go +++ b/utils/gg/gg_test.go @@ -46,4 +46,25 @@ var _ = Describe("GG", func() { Expect(gg.If(false, 1.1, 2.2)).To(Equal(2.2)) }) }) + + Describe("Clone", func() { + It("returns a pointer to a copy of the value", func() { + original := 123 + cloned := gg.Clone(&original) + Expect(cloned).To(HaveValue(Equal(123))) + Expect(cloned).NotTo(BeIdenticalTo(&original)) + }) + + It("does not alias the original value", func() { + original := 123 + cloned := gg.Clone(&original) + original = 456 + Expect(*cloned).To(Equal(123)) + }) + + It("returns nil when the input is nil", func() { + var v *int + Expect(gg.Clone(v)).To(BeNil()) + }) + }) })