github.com/iDigitalFlame/xmt@v0.5.4/util/text/match.go (about)

     1  // Copyright (C) 2020 - 2023 iDigitalFlame
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU General Public License as published by
     5  // the Free Software Foundation, either version 3 of the License, or
     6  // any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU General Public License
    14  // along with this program.  If not, see <https://www.gnu.org/licenses/>.
    15  //
    16  
    17  package text
    18  
    19  import (
    20  	"sync"
    21  
    22  	"github.com/iDigitalFlame/xmt/util"
    23  )
    24  
    25  var (
    26  	// MatchAny is a Matcher that can be used to match any string or byte array.
    27  	MatchAny anyRegexp
    28  	// MatchNone is a Matcher that can be used to NOT match any string or byte
    29  	// array.
    30  	MatchNone falseRegexp
    31  
    32  	builders = sync.Pool{
    33  		New: func() interface{} {
    34  			return new(util.Builder)
    35  		},
    36  	}
    37  )
    38  
    39  // String is a wrapper for strings to support the Stringer interface.
    40  type String string
    41  
    42  // Matcher is an alias of a string that can contain specific variable
    43  // instructions to be replaced when calling the 'String' function. This alias
    44  // provides the 'Match' function, which returns a Regexp struct that will match
    45  // any value generated.
    46  //
    47  // # Matcher Verb Guide
    48  //
    49  // <N> indicates a non-negative number value that is REQUIRED.
    50  // [N] indicated a non-negative number value that is OPTIONAL.
    51  //   - If omitted, a random positive 8 to 32bit value will be used.
    52  //
    53  // If the number is followed bfy a 'f', this will FORCE the count and will use it
    54  // directly instead of a range to N. Otherwise, a [1, N] (inclusive) value will
    55  // be generated to be used instead.
    56  //
    57  // In both cases, the '<', '[', ']', and '>' are only used to indicate usage,
    58  // and are not actually used in the string value.
    59  //
    60  //	| Verb   | Description                                         | RegEx            |
    61  //	| ------ | --------------------------------------------------- | ---------------- |
    62  //	| %<N>n  | 1 to N count of random single-digit numbers         | [0-9]{1,N}       |
    63  //	| %<N>fn | N count of random single-digit numbers              | [0-9]{N}         |
    64  //	| %<N>c  | 1 to N count of random ASCII non-number characters  | [a-zA-Z]{1,N}    |
    65  //	| %<N>fc | N count of random ASCII non-number characters       | [a-zA-Z]{N}      |
    66  //	| %<N>u  | 1 to N count of random ASCII uppercase characters   | [A-Z]{1,N}       |
    67  //	| %<N>fu | N count of random ASCII uppercase characters        | [A-Z]{N}         |
    68  //	| %<N>l  | 1 to N count of random ASCII lowercase characters   | [a-z]{1,N}       |
    69  //	| %<N>fl | N count of random ASCII lowercase characters        | [a-z]{n}         |
    70  //	| %s     | Random 1 to 256 count of random ASCII characters    | ([a-zA-Z0-9]+)   |
    71  //	| %[N]s  | 1 to N (or random) count of random ASCII characters | [a-zA-Z0-9]{1,N} |
    72  //	| %<N>fs | N count of random ASCII characters                  | [a-zA-Z0-9]{N}   |
    73  //	| %d     | String literal number 0 to 4,294,967,296            | ([0-9]+)         |
    74  //	| %<N>d  | String literal number 0 to N                        | ([0-9]+)         |
    75  //	| %<N>fd | String literal number N                             | ([0-9]+)         |
    76  //	| %h     | Hex string literal number 0 to 4,294,967,296        | ([a-fA-F0-9]+)   |
    77  //	| %<N>h  | Hex string literal number 0 to N                    | ([a-fA-F0-9]+)   |
    78  //	| %<N>fh | Hex string literal number N                         | ([a-fA-F0-9]+)   |
    79  //
    80  // All other values are ignored and directly added to the resulting string value.
    81  type Matcher string
    82  type anyRegexp struct{}
    83  
    84  // Regexp is a compatibility interface that is used to allow for UnMatch values
    85  // to be used lacking the ability of RE2 used in Golang to do negative lookahead.
    86  type Regexp interface {
    87  	String() string
    88  	Match([]byte) bool
    89  	MatchString(string) bool
    90  }
    91  type falseRegexp struct{}
    92  
    93  // Raw returns the raw string value of this Matcher without preforming any
    94  // replacements.
    95  func (s Matcher) Raw() string {
    96  	return string(s)
    97  }
    98  
    99  // String returns the string value of itself.
   100  func (s String) String() string {
   101  	return string(s)
   102  }
   103  
   104  // Match returns a valid Regexp struct that is guaranteed to match any string
   105  // generated by the  Matcher's 'String' function.
   106  func (s Matcher) Match() Regexp {
   107  	return s.MatchEx(true)
   108  }
   109  func (anyRegexp) String() string {
   110  	return "*"
   111  }
   112  
   113  // UnMatch returns a valid Regexp struct that is guaranteed to not match any
   114  // string generated by the Matcher's 'String' function.
   115  func (s Matcher) UnMatch() Regexp {
   116  	return s.MatchEx(false)
   117  }
   118  func (falseRegexp) String() string {
   119  	return "false"
   120  }
   121  func (anyRegexp) Match(_ []byte) bool {
   122  	return true
   123  }
   124  func (falseRegexp) Match(_ []byte) bool {
   125  	return false
   126  }
   127  func (anyRegexp) MatchString(_ string) bool {
   128  	return true
   129  }
   130  func (falseRegexp) MatchString(_ string) bool {
   131  	return false
   132  }