32 template <
typename CharPo
interType>
33 class OSCPatternMatcherImpl
35 using CharPtr = CharPointerType;
39 static bool match (CharPtr pattern, CharPtr patternEnd, CharPtr target, CharPtr targetEnd)
41 if (pattern == patternEnd)
42 return matchTerminator (target, targetEnd);
44 auto c = pattern.getAndAdvance();
48 case '?':
return matchAnyChar (pattern, patternEnd, target, targetEnd);
49 case '*':
return matchAnyOrNoChars (pattern, patternEnd, target, targetEnd);
50 case '{':
return matchInsideStringSet (pattern, patternEnd, target, targetEnd);
51 case '[':
return matchInsideCharSet (pattern, patternEnd, target, targetEnd);
52 default:
return matchChar (c, pattern, patternEnd, target, targetEnd);
58 static bool matchTerminator (CharPtr target, CharPtr targetEnd)
60 return target == targetEnd;
64 static bool matchChar (
juce_wchar c, CharPtr pattern, CharPtr patternEnd, CharPtr target, CharPtr targetEnd)
66 if (target == targetEnd || c != target.getAndAdvance())
69 return match (pattern, patternEnd, target, targetEnd);
73 static bool matchAnyChar (CharPtr pattern, CharPtr patternEnd, CharPtr target, CharPtr targetEnd)
75 if (target == targetEnd)
78 return match (pattern, patternEnd, ++target, targetEnd);
82 static bool matchAnyOrNoChars (CharPtr pattern, CharPtr patternEnd, CharPtr target, CharPtr targetEnd)
84 if (target == targetEnd)
85 return pattern == patternEnd;
87 if (match (pattern, patternEnd, target, targetEnd))
90 return matchAnyOrNoChars (pattern, patternEnd, ++target, targetEnd);
94 static bool matchInsideStringSet (CharPtr pattern, CharPtr patternEnd, CharPtr target, CharPtr targetEnd)
96 if (pattern == patternEnd)
103 String currentElement;
105 while (pattern != patternEnd)
107 auto c = pattern.getAndAdvance();
112 set.add (currentElement);
113 currentElement.clear();
114 return matchStringSet (set, pattern, patternEnd, target, targetEnd);
117 set.add (currentElement);
118 currentElement.clear();
131 static bool matchStringSet (
const StringArray& set, CharPtr pattern,
132 CharPtr patternEnd, CharPtr target, CharPtr targetEnd)
135 return match (pattern, patternEnd, target, targetEnd);
137 for (
auto& str : set)
138 if (str.getCharPointer().compareUpTo (target, str.length()) == 0)
139 if (match (pattern, patternEnd, target + str.length(), targetEnd))
146 static bool matchInsideCharSet (CharPtr pattern, CharPtr patternEnd,
147 CharPtr target, CharPtr targetEnd)
149 if (pattern == patternEnd)
152 Array<juce_wchar> set;
153 bool setIsNegated =
false;
155 while (pattern != patternEnd)
157 auto c = pattern.getAndAdvance();
162 return matchCharSet (set, setIsNegated, pattern, patternEnd, target, targetEnd);
165 if (! addCharRangeToSet (set, pattern, patternEnd, target, targetEnd))
171 if (set.size() == 0 && setIsNegated ==
false)
189 static bool matchCharSet (
const Array<juce_wchar>& set,
bool setIsNegated,
190 CharPtr pattern, CharPtr patternEnd, CharPtr target, CharPtr targetEnd)
193 return match (pattern, patternEnd, target, targetEnd);
195 if (target == targetEnd)
198 return setIsNegated ? matchCharSetNegated (set, pattern, patternEnd, target, targetEnd)
199 : matchCharSetNotNegated (set, pattern, patternEnd, target, targetEnd);
203 static bool matchCharSetNegated (
const Array<juce_wchar>& set, CharPtr pattern,
204 CharPtr patternEnd, CharPtr target, CharPtr targetEnd)
210 return match (pattern, patternEnd, target + 1, targetEnd);
214 static bool matchCharSetNotNegated (
const Array<juce_wchar>& set, CharPtr pattern,
215 CharPtr patternEnd, CharPtr target, CharPtr targetEnd)
219 if (match (pattern, patternEnd, target + 1, targetEnd))
226 static bool addCharRangeToSet (Array<juce_wchar>& set, CharPtr pattern,
227 CharPtr , CharPtr target, CharPtr targetEnd)
229 if (target == targetEnd)
232 auto rangeStart = set.getLast();
233 auto rangeEnd = pattern.getAndAdvance();
241 if (rangeEnd ==
',' || rangeEnd ==
'{' || rangeEnd ==
'}' || set.size() == 0)
244 while (rangeEnd > rangeStart)
245 set.add (++rangeStart);
252 static bool matchOscPattern (
const String& pattern,
const String& target)
254 return OSCPatternMatcherImpl<String::CharPointerType>::match (pattern.getCharPointer(),
255 pattern.getCharPointer().findTerminatingNull(),
256 target.getCharPointer(),
257 target.getCharPointer().findTerminatingNull());
261 template <
typename OSCAddressType>
struct OSCAddressTokeniserTraits;
262 template <>
struct OSCAddressTokeniserTraits<OSCAddress> {
static const char* getDisallowedChars() {
return " #*,?/[]{}"; } };
263 template <>
struct OSCAddressTokeniserTraits<OSCAddressPattern> {
static const char* getDisallowedChars() {
return " #/"; } };
266 template <
typename OSCAddressType>
267 struct OSCAddressTokeniser
269 using Traits = OSCAddressTokeniserTraits<OSCAddressType>;
272 static bool isPrintableASCIIChar (
juce_wchar c)
noexcept
274 return c >=
' ' && c <=
'~';
277 static bool isDisallowedChar (
juce_wchar c)
noexcept
279 return CharPointer_ASCII (Traits::getDisallowedChars()).indexOf (c,
false) >= 0;
282 static bool containsOnlyAllowedPrintableASCIIChars (
const String&
string)
noexcept
284 for (
auto charPtr =
string.getCharPointer(); ! charPtr.isEmpty();)
286 auto c = charPtr.getAndAdvance();
288 if (! isPrintableASCIIChar (c) || isDisallowedChar (c))
296 static StringArray tokenise (
const String& address)
298 if (address.isEmpty())
299 throw OSCFormatError (
"OSC format error: address string cannot be empty.");
301 if (! address.startsWithChar (
'/'))
302 throw OSCFormatError (
"OSC format error: address string must start with a forward slash.");
304 StringArray oscSymbols;
305 oscSymbols.addTokens (address,
"/", StringRef());
306 oscSymbols.removeEmptyStrings (
false);
308 for (
auto& token : oscSymbols)
309 if (! containsOnlyAllowedPrintableASCIIChars (token))
310 throw OSCFormatError (
"OSC format error: encountered characters not allowed in address string.");
320 : oscSymbols (OSCAddressTokeniser<
OSCAddress>::tokenise (address)),
321 asString (address.trimCharactersAtEnd (
"/"))
326 : oscSymbols (OSCAddressTokeniser<
OSCAddress>::tokenise (
String (address))),
327 asString (
String (address).trimCharactersAtEnd (
"/"))
334 return asString == other.asString;
339 return ! operator== (other);
351 asString (address.trimCharactersAtEnd (
"/")),
352 wasInitialisedWithWildcards (asString.containsAnyOf (
"*?{}[]"))
359 asString (
String (address).trimCharactersAtEnd (
"/")),
360 wasInitialisedWithWildcards (asString.containsAnyOf (
"*?{}[]"))
367 return asString == other.asString;
372 return ! operator== (other);
378 if (! containsWildcards())
379 return asString == address.asString;
381 if (oscSymbols.size() != address.oscSymbols.size())
384 for (
int i = 0; i < oscSymbols.size(); ++i)
385 if (! matchOscPattern (oscSymbols[i], address.oscSymbols[i]))
402class OSCAddressTests final :
public UnitTest
406 :
UnitTest (
"OSCAddress class", UnitTestCategories::osc)
409 void runTest()
override
411 beginTest (
"construction and parsing");
423 expectThrowsType (OSCAddress (
"/notallowedchar}andsomemorechars"), OSCFormatError);
424 expectThrowsType (OSCAddress (String::fromUTF8 (
"/nonasciicharacter\xc3\xbc""blabla")), OSCFormatError);
425 expectThrowsType (OSCAddress (
"/nonprintableasciicharacter\t"), OSCFormatError);
436 beginTest (
"conversion to/from String");
438 OSCAddress address (
"/this/is/a/very/long/address/");
439 expectEquals (address.toString(), String (
"/this/is/a/very/long/address"));
444static OSCAddressTests OSCAddressUnitTests;
448class OSCAddressPatternTests final :
public UnitTest
451 OSCAddressPatternTests()
452 : UnitTest (
"OSCAddressPattern class", UnitTestCategories::osc)
455 void runTest()
override
457 beginTest (
"construction and parsing");
462 expectThrowsType (OSCAddressPattern (
"/notallowedchar#andsomemorechars"), OSCFormatError);
463 expectThrowsType (OSCAddressPattern (String::fromUTF8 (
"/nonasciicharacter\xc3\xbc""blabla")), OSCFormatError);
464 expectThrowsType (OSCAddressPattern (
"/nonprintableasciicharacter\t"), OSCFormatError);
471 expectDoesNotThrow (OSCAddressPattern (
"/allowedprintablecharacters!$%&()+-.:;<=>@^_`|~"));
475 beginTest (
"construction and parsing - with wildcards");
484 beginTest (
"construction and parsing - with match expressions");
501 beginTest (
"equality comparison");
504 OSCAddressPattern lhs (
"/test/1");
505 OSCAddressPattern rhs (
"/test/1");
507 expect (! (lhs != rhs));
510 OSCAddressPattern lhs (
"/test/1");
511 OSCAddressPattern rhs (
"/test/1/");
513 expect (! (lhs != rhs));
516 OSCAddressPattern lhs (
"/test/1");
517 OSCAddressPattern rhs (
"/test/2");
518 expect (! (lhs == rhs));
523 beginTest (
"basic string matching");
529 OSCAddressPattern pattern (
"/foo/bar");
530 expect (! pattern.containsWildcards());
532 OSCAddress address (
"/foo/bar");
533 expect (pattern.matches (address));
536 OSCAddressPattern pattern (
"/foo/bar/");
537 expect (! pattern.containsWildcards());
539 OSCAddress address (
"/foo/bar");
540 expect (pattern.matches (address));
543 OSCAddressPattern pattern (
"/");
544 expect (! pattern.containsWildcards());
546 OSCAddress address (
"/");
547 expect (pattern.matches (address));
550 OSCAddressPattern pattern (
"/foo/bar");
551 expect (! pattern.containsWildcards());
553 expect (! pattern.matches (OSCAddress (
"/foo/baz")));
554 expect (! pattern.matches (OSCAddress (
"/foo/bar/baz")));
555 expect (! pattern.matches (OSCAddress (
"/foo")));
559 beginTest (
"string matching with wildcards");
561 OSCAddressPattern pattern (
"/*/*put/slider[0-9]");
562 expect (pattern.containsWildcards());
564 expect (pattern.matches (OSCAddress (
"/mypatch/input/slider0")));
565 expect (pattern.matches (OSCAddress (
"/myotherpatch/output/slider9")));
566 expect (! pattern.matches (OSCAddress (
"/myotherpatch/output/slider10")));
567 expect (! pattern.matches (OSCAddress (
"/output/slider9")));
568 expect (! pattern.matches (OSCAddress (
"/myotherpatch/output/slider9/position")));
571 beginTest (
"conversion to/from String");
574 OSCAddressPattern ap (
"/this/is/a/very/long/address/");
575 expectEquals (ap.toString(), String (
"/this/is/a/very/long/address"));
578 OSCAddressPattern ap (
"/*/*put/{fader,slider,knob}[0-9]/ba?/");
579 expectEquals (ap.toString(), String (
"/*/*put/{fader,slider,knob}[0-9]/ba?"));
585static OSCAddressPatternTests OSCAddressPatternUnitTests;
589class OSCPatternMatcherTests final :
public UnitTest
592 OSCPatternMatcherTests()
593 : UnitTest (
"OSCAddress class / pattern matching", UnitTestCategories::osc)
596 void runTest()
override
598 beginTest (
"basic string matching");
600 expect (matchOscPattern (
"",
""));
601 expect (! matchOscPattern (
"",
"x"));
602 expect (! matchOscPattern (
"x",
""));
603 expect (matchOscPattern (
"foo",
"foo"));
604 expect (! matchOscPattern (
"foo",
"bar"));
605 expect (! matchOscPattern (
"ooooo",
"oooooo"));
608 beginTest (
"string matching with '?' wildcard");
610 expect (matchOscPattern (
"?",
"x"));
611 expect (! matchOscPattern (
"?",
""));
612 expect (! matchOscPattern (
"?",
"xx"));
613 expect (! matchOscPattern (
"b?r",
"br"));
614 expect (matchOscPattern (
"b?r",
"bar"));
615 expect (! matchOscPattern (
"b?r",
"baar"));
616 expect (matchOscPattern (
"f???o",
"fabco"));
617 expect (! matchOscPattern (
"f???o",
"fabo"));
620 beginTest (
"string matching with '*' wildcard");
622 expect (matchOscPattern (
"*",
""));
623 expect (matchOscPattern (
"*",
"x"));
624 expect (matchOscPattern (
"*",
"foo"));
625 expect (matchOscPattern (
"*c",
"aaaaaaabc"));
626 expect (matchOscPattern (
"*c",
"aaaaaaabbbcccc"));
627 expect (! matchOscPattern (
"*c",
"aaaaaaabbbcccca"));
628 expect (matchOscPattern (
"c*",
"ccccbbbbaaaa"));
629 expect (! matchOscPattern (
"c*",
"accccbbbaaaa"));
631 expect (matchOscPattern (
"f*o",
"fo"));
632 expect (matchOscPattern (
"f*o",
"fuo"));
633 expect (matchOscPattern (
"f*o",
"fuvwxyzo"));
635 expect (matchOscPattern (
"*reallyreallylongstringstringstring",
"reallyreallylongstringstringstrNOT"
636 "reallyreallylongstringstringstrNOT"
637 "reallyreallylongstringstringstrNOT"
638 "reallyreallylongstringstringstrNOT"
639 "reallyreallylongstringstringstrNOT"
640 "reallyreallylongstringstringstring"));
643 beginTest (
"string matching with '{..., ...}' pattern");
645 expect (matchOscPattern (
"{}",
""));
646 expect (! matchOscPattern (
"{}",
"x"));
647 expect (matchOscPattern (
"{abcde}",
"abcde"));
648 expect (matchOscPattern (
"{abcde,f}",
"f"));
649 expect (! matchOscPattern (
"{abcde,f}",
"ff"));
650 expect (matchOscPattern (
"a{bcd}e",
"abcde"));
651 expect (matchOscPattern (
"a{bcd,bce}e",
"abcde"));
652 expect (! matchOscPattern (
"a{bce,bcf}e",
"abcde"));
653 expect (! matchOscPattern (
"a{bce,bcf}e",
"ae"));
654 expect (matchOscPattern (
"a{bce,,bcf}e",
"ae"));
655 expect (matchOscPattern (
"a{bcd,bcd,bcd}e",
"abcde"));
656 expect (matchOscPattern (
"aaa{bc,def,ghij,klmnopqrstu}eee",
"aaaghijeee"));
657 expect (matchOscPattern (
"{a,b,c}bcde",
"abcde"));
658 expect (! matchOscPattern (
"{abc}bcde",
"abcde"));
659 expect (matchOscPattern (
"bcde{a,b,c}",
"bcdea"));
660 expect (! matchOscPattern (
"bcde{abc}",
"bcdea"));
661 expect (matchOscPattern (
"f{o,}o",
"fo"));
662 expect (matchOscPattern (
"f{,,,,,}o",
"fo"));
663 expect (matchOscPattern (
"foo{b,ba,bar}x",
"foobarx"));
664 expect (matchOscPattern (
"a{bc,de}fg{hij,klm}{n}{}",
"adefghijn"));
667 expect (! matchOscPattern (
"not{closing",
"notclosing"));
668 expect (! matchOscPattern (
"not}opening",
"notopening"));
669 expect (! matchOscPattern (
"{{nested}}",
"nested"));
670 expect (! matchOscPattern (
"{a-c}bcde",
"abcde"));
671 expect (! matchOscPattern (
"bcde{a-c}",
"abcde"));
675 beginTest (
"string matching with '[...]' pattern");
679 expect (matchOscPattern (
"[]",
""));
680 expect (! matchOscPattern (
"[]",
"x"));
681 expect (! matchOscPattern (
"[abcde]",
"abcde"));
682 expect (matchOscPattern (
"[abcde]",
"a"));
683 expect (matchOscPattern (
"[abcde]",
"b"));
684 expect (matchOscPattern (
"[abcde]",
"c"));
685 expect (matchOscPattern (
"[abcde]",
"d"));
686 expect (matchOscPattern (
"[abcde]",
"e"));
687 expect (! matchOscPattern (
"[abcde]",
"f"));
689 expect (matchOscPattern (
"f[oo]",
"fo"));
690 expect (! matchOscPattern (
"f[oo]",
"foo"));
692 expect (matchOscPattern (
"fooba[rxz]foo",
"foobarfoo"));
693 expect (matchOscPattern (
"fooba[rxz]foo",
"foobaxfoo"));
694 expect (matchOscPattern (
"fooba[rxz]foo",
"foobazfoo"));
695 expect (! matchOscPattern (
"fooba[rxz]foo",
"foobasfoo"));
697 expect (matchOscPattern (
"foo[abc]foo[defgh]foo[i]foo[]foo",
"foobfoohfooifoofoo"));
701 expect (matchOscPattern (
"fooba[r-z]foo",
"foobarfoo"));
702 expect (matchOscPattern (
"fooba[r-z]foo",
"foobaxfoo"));
703 expect (matchOscPattern (
"fooba[r-z]foo",
"foobazfoo"));
704 expect (matchOscPattern (
"fooba[r-z]foo",
"foobasfoo"));
705 expect (! matchOscPattern (
"fooba[r-z]foo",
"foobaRfoo"));
707 expect (! matchOscPattern (
"foo[1-8]bar",
"foo0bar"));
708 expect (matchOscPattern (
"foo[1-8]bar",
"foo1bar"));
709 expect (matchOscPattern (
"foo[1-8]bar",
"foo6bar"));
710 expect (matchOscPattern (
"foo[1-8]bar",
"foo8bar"));
711 expect (! matchOscPattern (
"foo[1-8]bar",
"foo9bar"));
715 expect (matchOscPattern (
"foo[abc-]bar",
"fooabar"));
716 expect (matchOscPattern (
"foo[abc-]bar",
"foo-bar"));
717 expect (matchOscPattern (
"foo[-]bar",
"foo-bar"));
721 expect (matchOscPattern (
"foo[ae-iko-uz1-8D-FX]b[a-b]r",
"fooabar"));
722 expect (! matchOscPattern (
"foo[ae-iko-uz1-8D-FX]b[a-a]r",
"foobbar"));
723 expect (! matchOscPattern (
"foo[ae-iko-uz1-8D-FX]b[aaaa-aaaa-aaaa]r",
"foodbar"));
724 expect (matchOscPattern (
"foo[ae-iko-uz1-8D-FX]bar",
"fooebar"));
725 expect (matchOscPattern (
"foo[ae-iko-uz1-8D-FX]bar",
"foogbar"));
726 expect (matchOscPattern (
"foo[ae-iko-uz1-8D-FX]bar",
"fooibar"));
727 expect (! matchOscPattern (
"foo[ae-iko-uz1-8D-FX]bar",
"foojbar"));
728 expect (matchOscPattern (
"foo[ae-iko-uz1-8D-FX]bar",
"fookbar"));
729 expect (! matchOscPattern (
"foo[ae-iko-uz1-8D-FX]bar",
"foolbar"));
730 expect (matchOscPattern (
"foo[ae-iko-uz1-8D-FX]bar",
"fooobar"));
731 expect (matchOscPattern (
"foo[ae-iko-uz1-8D-FX]bar",
"foopbar"));
732 expect (matchOscPattern (
"foo[ae-iko-uz1-8D-FX]bar",
"fooubar"));
733 expect (! matchOscPattern (
"foo[ae-iko-uz1-8D-FX]bar",
"fooybar"));
734 expect (matchOscPattern (
"foo[ae-iko-uz1-8D-FX]bar",
"foozbar"));
735 expect (! matchOscPattern (
"foo[ae-iko-uz1-8D-FX]bar",
"foo0bar"));
736 expect (matchOscPattern (
"foo[ae-iko-uz1-8D-FX]bar",
"foo1bar"));
737 expect (matchOscPattern (
"foo[ae-iko-uz1-8D-FX]bar",
"foo5bar"));
738 expect (matchOscPattern (
"foo[ae-iko-uz1-8D-FX]bar",
"foo8bar"));
739 expect (! matchOscPattern (
"foo[ae-iko-uz1-8D-FX]bar",
"foo9bar"));
740 expect (! matchOscPattern (
"foo[ae-iko-uz1-8D-FX]bar",
"fooCbar"));
741 expect (matchOscPattern (
"foo[ae-iko-uz1-8D-FX]bar",
"fooDbar"));
742 expect (matchOscPattern (
"foo[ae-iko-uz1-8D-FX]bar",
"fooEbar"));
743 expect (matchOscPattern (
"foo[ae-iko-uz1-8D-FX]bar",
"fooFbar"));
744 expect (! matchOscPattern (
"foo[ae-iko-uz1-8D-FX]bar",
"fooGbar"));
745 expect (matchOscPattern (
"foo[ae-iko-uz1-8D-FX]bar",
"fooXbar"));
746 expect (! matchOscPattern (
"foo[ae-iko-uz1-8D-FX]ba[Rr]",
"fooZbar"));
747 expect (! matchOscPattern (
"foo[ae-iko-uz1-8D-FX]ba[Rr]",
"foobar"));
748 expect (! matchOscPattern (
"foo[ae-iko-uz1-8D-FX]ba[Rr]",
"fooFXbar"));
752 expect (! matchOscPattern (
"fooba[!rxz]foo",
"foobarfoo"));
753 expect (! matchOscPattern (
"fooba[!rxz]foo",
"foobaxfoo"));
754 expect (! matchOscPattern (
"fooba[!rxz]foo",
"foobazfoo"));
755 expect (matchOscPattern (
"fooba[!rxz]foo",
"foobasfoo"));
757 expect (! matchOscPattern (
"fooba[!r-z]foo",
"foobarfoo"));
758 expect (! matchOscPattern (
"fooba[!r-z]foo",
"foobaxfoo"));
759 expect (! matchOscPattern (
"fooba[!r-z]foo",
"foobazfoo"));
760 expect (! matchOscPattern (
"fooba[!r-z]foo",
"foobasfoo"));
761 expect (matchOscPattern (
"fooba[!r-z]foo",
"foobaRfoo"));
765 expect (matchOscPattern (
"foo[ab!c]bar",
"fooabar"));
766 expect (matchOscPattern (
"foo[ab!c]bar",
"foo!bar"));
767 expect (! matchOscPattern (
"foo[ab!c]bar",
"fooxbar"));
768 expect (! matchOscPattern (
"foo[!!]bar",
"foo!bar"));
769 expect (matchOscPattern (
"foo[!!]bar",
"fooxbar"));
770 expect (! matchOscPattern (
"foo[!!]bar",
"foobar"));
774 expect (! matchOscPattern (
"notclosin[g",
"notclosing"));
775 expect (! matchOscPattern (
"n]otopening",
"notopening"));
776 expect (! matchOscPattern (
"[[nested]]",
"nested"));
777 expect (! matchOscPattern (
"norangestar[-t]",
"norangestart"));
778 expect (! matchOscPattern (
"norangestar[-t]",
"norangestar-"));
781 beginTest (
"string matching combining patterns");
783 expect (matchOscPattern (
"*ea*ll[y-z0-9X-Zvwx]??m[o-q]l[e]x{fat,mat,pat}te{}r*?",
"reallycomplexpattern"));
788static OSCPatternMatcherTests OSCPatternMatcherUnitTests;
bool matches(const OSCAddress &address) const noexcept
Checks if the OSCAddressPattern matches an OSC address with the wildcard rules defined by the OpenSou...
bool operator!=(const OSCAddressPattern &other) const noexcept
Compares two OSCAddressPattern objects.
OSCAddressPattern(const String &address)
Constructs a new OSCAddressPattern from a String.
bool operator==(const OSCAddressPattern &other) const noexcept
Compares two OSCAddressPattern objects.
String toString() const noexcept
Converts the OSCAddressPattern to a String.
String toString() const noexcept
Converts the OSCAddress to a String.
bool operator==(const OSCAddress &other) const noexcept
Compares two OSCAddress objects.
OSCAddress(const String &address)
Constructs a new OSCAddress from a String.
bool operator!=(const OSCAddress &other) const noexcept
Compares two OSCAddress objects.
This is a base class for classes that perform a unit test.
#define expectDoesNotThrow(expr)
Checks that the result of an expression does not throw an exception.
#define expectThrowsType(expr, type)
Checks that the result of an expression throws an exception of a certain type.
wchar_t juce_wchar
A platform-independent 32-bit unicode character type.