github.com/qioalice/ekago/v3@v3.3.2-0.20221202205325-5c262d586ee4/ekastr/interpolation.go (about)

     1  // Copyright © 2020. All rights reserved.
     2  // Author: Ilya Stroy.
     3  // Contacts: iyuryevich@pm.me, https://github.com/qioalice
     4  // License: https://opensource.org/licenses/MIT
     5  
     6  package ekastr
     7  
     8  /*
     9  
    10   */
    11  func Interpolate(s string, cbVerbFound, cbTextFound func(v string)) {
    12  	f1 := func(v []byte) { cbVerbFound(B2S(v)) }
    13  	f2 := func(v []byte) { cbTextFound(B2S(v)) }
    14  	Interpolateb(S2B(s), f1, f2)
    15  }
    16  
    17  /*
    18  
    19   */
    20  func Interpolateb(p []byte, cbVerbFound, cbTextFound func(v []byte)) {
    21  
    22  	var (
    23  		part   []byte
    24  		isVerb bool
    25  	)
    26  
    27  	if len(p) == 0 {
    28  		return
    29  	}
    30  
    31  	for len(p) > 0 {
    32  		part, p, isVerb = i9nGetNext(p)
    33  		if isVerb {
    34  			cbVerbFound(part)
    35  		} else {
    36  			cbTextFound(part)
    37  		}
    38  	}
    39  }
    40  
    41  /*
    42  
    43   */
    44  // parseFirstVerb parses 'format', extracts first verb (even if it's "just text"
    45  // verb), saves it to ce.formatParts and then returns the rest of 'format' string.
    46  func i9nGetNext(p []byte) (part, nextP []byte, isVerb bool) {
    47  
    48  	if len(p) == 0 {
    49  		return nil, nil, false
    50  	}
    51  
    52  	//goland:noinspection GoSnakeCaseUsage
    53  	const (
    54  		VERB_START_INDICATOR byte = '{'
    55  		VERB_END_INDICATOR   byte = '}'
    56  	)
    57  
    58  	var (
    59  		i   = 0
    60  		pc  byte // prev char
    61  		wv  bool // true if current parsing verb is complex verb (not "just text")
    62  		wve bool // true if complex verb has been closed correctly
    63  	)
    64  
    65  	for _, c := range p {
    66  		switch {
    67  		case c == VERB_START_INDICATOR && pc == VERB_START_INDICATOR && wv:
    68  			// unexpected "{{" inside complex verb, treat all prev as "just text",
    69  			// try to treat as starting complex verb
    70  			wv = false
    71  			i--
    72  
    73  		case c == VERB_START_INDICATOR && pc == VERB_START_INDICATOR && i > 1:
    74  			// > 1 (not > 0) because if string started with "{{", after first "{"
    75  			// i already == 1.
    76  			//
    77  			// was "just text", found complex verb start
    78  			i--
    79  
    80  		case c == VERB_END_INDICATOR && pc == VERB_END_INDICATOR && wv:
    81  			// ending of complex verb
    82  			wve = true
    83  			i++
    84  
    85  		case c == VERB_START_INDICATOR && pc == VERB_START_INDICATOR:
    86  			// this is the beginning of 'format' and of complex verb
    87  			wv = true
    88  			i++
    89  			continue
    90  
    91  		default:
    92  			pc = c
    93  			i++
    94  			continue
    95  		}
    96  		break
    97  	}
    98  
    99  	return p[:i], p[i:], wv && wve
   100  }