repeated.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. package cc
  2. const repTpl = `
  3. {{ $f := .Field }}{{ $r := .Rules }}{{ $typ := inType $f nil }}
  4. {{ if $r.GetIgnoreEmpty }}
  5. if ({{ accessor . }}.size() > 0) {
  6. {{ end }}
  7. {{ if $r.GetMinItems }}
  8. {{ if eq $r.GetMinItems $r.GetMaxItems }}
  9. if ({{ accessor . }}.size() != {{ $r.GetMinItems }}) {
  10. {{ err . "value must contain exactly " $r.GetMinItems " item(s)" }}
  11. }
  12. {{ else if $r.MaxItems }}
  13. if ({{ accessor . }}.size() < {{ $r.GetMinItems }} || {{ accessor . }}.size() > {{ $r.GetMaxItems }}) {
  14. {{ err . "value must contain between " $r.GetMinItems " and " $r.GetMaxItems " items, inclusive" }}
  15. }
  16. {{ else }}
  17. if ({{ accessor . }}.size() < {{ $r.GetMinItems }}) {
  18. {{ err . "value must contain at least " $r.GetMinItems " item(s)" }}
  19. }
  20. {{ end }}
  21. {{ else if $r.MaxItems }}
  22. if ({{ accessor . }}.size() > {{ $r.GetMaxItems }}) {
  23. {{ err . "value must contain no more than " $r.GetMaxItems " item(s)" }}
  24. }
  25. {{ end }}
  26. {{ if $r.GetUnique }}
  27. // Implement comparison for wrapped reference types
  28. struct cmp {
  29. bool operator() (const std::reference_wrapper<{{ $typ }}> lhs, const std::reference_wrapper<{{ $typ }}> rhs) const {
  30. return lhs.get() == rhs.get();
  31. }
  32. };
  33. // Implement hashing for wrapped reference types
  34. struct hash {
  35. std::hash<{{ $typ }}> hash_fn;
  36. bool operator() (const std::reference_wrapper<{{ $typ }}> ref) const {
  37. return hash_fn(ref.get());
  38. }
  39. };
  40. // Save a set of references to avoid copying overhead
  41. std::unordered_set<std::reference_wrapper<{{ $typ }}>, hash, cmp> {{ lookup $f "Unique" }};
  42. {{ end }}
  43. {{ if or $r.GetUnique (ne (.Elem "" "").Typ "none") }}
  44. for (int i = 0; i < {{ accessor . }}.size(); i++) {
  45. const auto& item = {{ accessor . }}.Get(i);
  46. (void)item;
  47. {{ if $r.GetUnique }}
  48. auto p = {{ lookup $f "Unique" }}.emplace(const_cast<{{ $typ }}&>(item));
  49. if (p.second == false) {
  50. {{ errIdx . "i" "repeated value must contain unique items" }}
  51. }
  52. {{ end }}
  53. {{ render (.Elem "item" "i") }}
  54. }
  55. {{ end }}
  56. {{ if $r.GetIgnoreEmpty }}
  57. }
  58. {{ end }}
  59. `