2017-03-13 18:55:02 -04:00
// Copyright 2017 The Hugo Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package strings
import (
"regexp"
"sync"
"github.com/spf13/cast"
)
// FindRE returns a list of strings that match the regular expression. By default all matches
// will be included. The number of matches can be limited with an optional third parameter.
2022-03-17 17:03:27 -04:00
func ( ns * Namespace ) FindRE ( expr string , content any , limit ... any ) ( [ ] string , error ) {
2017-03-13 18:55:02 -04:00
re , err := reCache . Get ( expr )
if err != nil {
return nil , err
}
conv , err := cast . ToStringE ( content )
if err != nil {
return nil , err
}
if len ( limit ) == 0 {
return re . FindAllString ( conv , - 1 ) , nil
}
lim , err := cast . ToIntE ( limit [ 0 ] )
if err != nil {
return nil , err
}
return re . FindAllString ( conv , lim ) , nil
}
2023-01-17 03:35:16 -05:00
// FindRESubmatch returns returns a slice of strings holding the text of the leftmost match of the regular expression in s and the matches, if any, of its subexpressions.
//
// By default all matches will be included. The number of matches can be limited with the optional limit parameter. A return value of nil indicates no match.
func ( ns * Namespace ) FindRESubmatch ( expr string , content any , limit ... any ) ( [ ] [ ] string , error ) {
re , err := reCache . Get ( expr )
if err != nil {
return nil , err
}
conv , err := cast . ToStringE ( content )
if err != nil {
return nil , err
}
n := - 1
if len ( limit ) > 0 {
n , err = cast . ToIntE ( limit [ 0 ] )
if err != nil {
return nil , err
}
}
return re . FindAllStringSubmatch ( conv , n ) , nil
}
2017-03-13 18:55:02 -04:00
// ReplaceRE returns a copy of s, replacing all matches of the regular
2020-08-28 10:29:26 -04:00
// expression pattern with the replacement text repl. The number of replacements
// can be limited with an optional fourth parameter.
2022-03-17 17:03:27 -04:00
func ( ns * Namespace ) ReplaceRE ( pattern , repl , s any , n ... any ) ( _ string , err error ) {
2017-03-13 18:55:02 -04:00
sp , err := cast . ToStringE ( pattern )
if err != nil {
return
}
sr , err := cast . ToStringE ( repl )
if err != nil {
return
}
ss , err := cast . ToStringE ( s )
if err != nil {
return
}
2020-08-28 10:29:26 -04:00
nn := - 1
if len ( n ) > 0 {
nn , err = cast . ToIntE ( n [ 0 ] )
if err != nil {
return
}
}
2017-03-13 18:55:02 -04:00
re , err := reCache . Get ( sp )
if err != nil {
return "" , err
}
2020-08-28 10:29:26 -04:00
return re . ReplaceAllStringFunc ( ss , func ( str string ) string {
if nn == 0 {
return str
}
nn -= 1
return re . ReplaceAllString ( str , sr )
} ) , nil
2017-03-13 18:55:02 -04:00
}
// regexpCache represents a cache of regexp objects protected by a mutex.
type regexpCache struct {
mu sync . RWMutex
re map [ string ] * regexp . Regexp
}
// Get retrieves a regexp object from the cache based upon the pattern.
// If the pattern is not found in the cache, create one
func ( rc * regexpCache ) Get ( pattern string ) ( re * regexp . Regexp , err error ) {
var ok bool
if re , ok = rc . get ( pattern ) ; ! ok {
re , err = regexp . Compile ( pattern )
if err != nil {
return nil , err
}
rc . set ( pattern , re )
}
return re , nil
}
func ( rc * regexpCache ) get ( key string ) ( re * regexp . Regexp , ok bool ) {
rc . mu . RLock ( )
re , ok = rc . re [ key ]
rc . mu . RUnlock ( )
return
}
func ( rc * regexpCache ) set ( key string , re * regexp . Regexp ) {
rc . mu . Lock ( )
rc . re [ key ] = re
rc . mu . Unlock ( )
}
var reCache = regexpCache { re : make ( map [ string ] * regexp . Regexp ) }