This is the C++ implementation of CCS.
CCS is a language for config files, and libraries to read those files and configure applications. The documentation is currently quite poor, but the Java and C++ implementations are mature and have been used in production for many years.
There's a presentation about the language here, but it's a little sketchy without someone talking along with it.
CCS is built with CMake. You can set the usual options to control your compiler, build type, etc., but the crash course is:
$ git submodule update --init
$ mkdir build
$ cd build
$ cmake ..
$ make
You can run unit tests with pretty output using:
$ make unittest
CMake can install everything for you, but in any case the client-facing
headers are in the api
directory.
Sets "context" for the rest of the ruleset. Must appear prior to any other rules. Equivalent to:
a.b c, d { /* rest of file */ }
Property definition. Property name will have the specified value in the current context. The syntax of values is conventional: true, false, 64-bit signed integers (may be specified in hex as 0x1a2bc), doubles, and strings.
name may be enclosed in quotes and written as a string literal if it contains spaces or other non-identifier characters.
Overriding property definition. For a given property, any definition marked @override will take precedence over any normal definition, regardless of the relative specificities of the two definitions. If more than one @override definition applies in a particular context, the most specific wins.
Strings may be enclosed in single or double quotes. Environment variables may
be interpolated with ${VAR}
. Special characters may be escaped with a
backslash. Recognized escape sequences include: \t \n \r \' \" \\ \$
.
A string may be broken across multiple lines by ending a line with a single
backslash.
The non-delimiting quote character need not be escaped.
Import a ruleset into the current ruleset. The entire imported ruleset will be
nested in the current context, so for example the second example above further
constrains all imported settings to the context a b.c d
.
Further constrain the context. This is equivalent to further constraining the
context using the context.constrain(...)
API call.
Of course, this is most useful when applied only in a particular selected context, in which case it allows for some additional reuse and modularity within CCS rulesets (activating additional sets of rules in particular cases, for example).
Constrain rules to apply only in the selected context. rule is any of: an import, a property setting, a constraint, or a selector and further nested rules. Selector syntax is documented below...
Matches a constraint of type a
with values b
and c
. Note
that this matches only a single constraint with both values. Multiple
constraints of the same type are allowed (thus preserving monotonicity), so
a.b.c
is not equivalent to a.b a.c
in every case.
Rarely needed.
Matches a simultaneous occurence of constraints of type a
and type
c
. Again, this is not generally equivalent to a c
, as it only
matches when the two constraints are applied in the same single step.
Conjunction, disjunction, and descendant selection, respectively. The first
form matches in any context containing both a.b
and c.d
.
The second matches in any context containing either one.
The third form matches in any context containing c.d
, itself in a
context containing a.b
. This form is infrequently used in CCS (although it
is of course the default operator in CSS).
Precedence of operators is as follows, from highest to lowest:
>
(descendant)- juxtaposition (conjunction)
,
(disjunction)
Parentheses may be used to enforce grouping. So, for example, a, c > d e
is equivalent to a, ((c > d) e)
. Since >
is infrequently used,
the rules are generally simple and intuitive.
Note that rules may be separated by semicolons for clarity, but this is always completely optional and will never affect the way the ruleset is parsed.
- Aggregate values: lists, maps.
- For aggregate values, allow modification of inherited value as well as replacement??