github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/golang/text/internal/number/plural.go (about)

     1  // Copyright 2016 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package number
     6  
     7  import "github.com/insionng/yougam/libraries/x/text/internal/format/plural"
     8  
     9  type pluralRules struct {
    10  	rules          []pluralCheck
    11  	index          []byte
    12  	langToIndex    []byte
    13  	inclusionMasks []uint64
    14  }
    15  
    16  var (
    17  	ordinalData = pluralRules{
    18  		ordinalRules,
    19  		ordinalIndex,
    20  		ordinalLangToIndex,
    21  		ordinalInclusionMasks[:],
    22  	}
    23  	cardinalData = pluralRules{
    24  		cardinalRules,
    25  		cardinalIndex,
    26  		cardinalLangToIndex,
    27  		cardinalInclusionMasks[:],
    28  	}
    29  )
    30  
    31  // See gen_plural.go for an explanation of the algorithm.
    32  
    33  func matchPlural(p *pluralRules, index int, n, f, v int) plural.Form {
    34  	nMask := p.inclusionMasks[n%maxMod]
    35  	// Compute the fMask inline in the rules below, as it is relatively rare.
    36  	// fMask := p.inclusionMasks[f%maxMod]
    37  	vMask := p.inclusionMasks[v%maxMod]
    38  
    39  	// Do the matching
    40  	offset := p.langToIndex[index]
    41  	rules := p.rules[p.index[offset]:p.index[offset+1]]
    42  	for i := 0; i < len(rules); i++ {
    43  		rule := rules[i]
    44  		setBit := uint64(1 << rule.setID)
    45  		var skip bool
    46  		switch op := opID(rule.cat >> opShift); op {
    47  		case opI: // i = x
    48  			skip = n >= numN || nMask&setBit == 0
    49  
    50  		case opI | opNotEqual: // i != x
    51  			skip = n < numN && nMask&setBit != 0
    52  
    53  		case opI | opMod: // i % m = x
    54  			skip = nMask&setBit == 0
    55  
    56  		case opI | opMod | opNotEqual: // i % m != x
    57  			skip = nMask&setBit != 0
    58  
    59  		case opN: // n = x
    60  			skip = f != 0 || n >= numN || nMask&setBit == 0
    61  
    62  		case opN | opNotEqual: // n != x
    63  			skip = f == 0 && n < numN && nMask&setBit != 0
    64  
    65  		case opN | opMod: // n % m = x
    66  			skip = f != 0 || nMask&setBit == 0
    67  
    68  		case opN | opMod | opNotEqual: // n % m != x
    69  			skip = f == 0 && nMask&setBit != 0
    70  
    71  		case opF: // f = x
    72  			skip = f >= numN || p.inclusionMasks[f%maxMod]&setBit == 0
    73  
    74  		case opF | opNotEqual: // f != x
    75  			skip = f < numN && p.inclusionMasks[f%maxMod]&setBit != 0
    76  
    77  		case opF | opMod: // f % m = x
    78  			skip = p.inclusionMasks[f%maxMod]&setBit == 0
    79  
    80  		case opF | opMod | opNotEqual: // f % m != x
    81  			skip = p.inclusionMasks[f%maxMod]&setBit != 0
    82  
    83  		case opV: // v = x
    84  			skip = v < numN && vMask&setBit == 0
    85  
    86  		case opV | opNotEqual: // v != x
    87  			skip = v < numN && vMask&setBit != 0
    88  
    89  		case opW: // w == 0
    90  			skip = f != 0
    91  
    92  		case opW | opNotEqual: // w != 0
    93  			skip = f == 0
    94  
    95  		// Hard-wired rules that cannot be handled by our algorithm.
    96  
    97  		case opBretonM:
    98  			skip = f != 0 || n == 0 || n%1000000 != 0
    99  
   100  		case opAzerbaijan00s:
   101  			// 100,200,300,400,500,600,700,800,900
   102  			skip = n == 0 || n >= 1000 || n%100 != 0
   103  
   104  		case opItalian800:
   105  			skip = (f != 0 || n >= numN || nMask&setBit == 0) && n != 800
   106  		}
   107  		if skip {
   108  			// advance over AND entries.
   109  			for ; i < len(rules) && rules[i].cat&formMask == andNext; i++ {
   110  			}
   111  			continue
   112  		}
   113  		// return if we have a final entry.
   114  		if cat := rule.cat & formMask; cat != andNext {
   115  			return plural.Form(cat)
   116  		}
   117  	}
   118  	return plural.Other
   119  }