Copyright 2001–4 Martin Bright, Mark Banner and Richard Smith
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the section entitled “GNU Free Documentation License”.
The Ringing Class Library (ringing-lib) is a library of C++ classes designed for writing change ringing application programs.
This menu lists the available topics in the documentation. This documentation is also available in GNU Info and PDF versions.
The Ringing Class Library is a collection of C++ classes which implement various concepts found in change ringing, and make it possible to implement programs which use these concepts without having to write the basic algorithms over and over again.
The library is split into several sections:
Thus it is possible to use whatever part of the library is necessary for your program; for example, a method editing program would use the method classes, whereas a program to simulate call changes would just use the row and change classes.
There are also several utilities included with the library. These demonstrate how to use the Ringing Class Library in your own programs, and are useful in their own right. Currently included are gsiril, a peal proving program with an interface similar to the popular MicroSIRIL program; psline, a utility to print lines for methods in PDF or PostScript; and methsearch, a program which searches for methods satisfying various given criteria. These utilities may be found in the apps subdirectory.
To get information about latest releases of the Ringing Class Library, to report bugs, request features, use forums and access the CVS repository, visit the project web page at http://ringing-lib.sourceforge.net.
The Ringing Class Library has been developed primarily for use on Unix-like and Microsoft Windows platforms. As the library is written in portable C++ and uses only standard library functions, it should be possible to use it on any standard-conforming platform. If you do find a platform on which it is not possible to compile and use the library, the authors would be interested to hear about it.
Various characteristics of the C++ compiler need to be determined before compiling the library, and are assumed to be that same when the library is compiled and linked into an application. If you get a new C++ compiler or a new standard C++ library, you should reconfigure and (probably) recompile the library before trying to use it in an application. The necessary data is stored in ringing/common.h: on Unix systems this file is generated automatically; on other systems, you may have to generate it by hand from the template in ringing/common.h.in.
As of version 0.2.9, the Ringing Class Library is split into two parts, which are licensed differently. This is explained again in the file COPYING in the distribution. A summary is given here, but to be sure you should consult individual files for their licensing conditions.
Important: Using any part of the library in a commercial program, except for those parts specifically stated to be under the weaker LGPL, is against the terms of the licence. If in doubt, ask the authors.
Before you can use the Ringing Class Library, you will need to have a copy of the Standard Template Library (STL) which works with your compiler. The STL is a set of templates which define containers such as lists and sets, iterators to move through them, and various other useful things. If your compiler complains about not being able to find files such as vector.h and list.h then this probably means that you don't have the STL and need to get hold of it.
A suitable version of the STL is included with most major C++ compilers. If you don't have a working version, you may be able to download one: in particular, there is a free implementation of the STL available currently at http://www.sgi.com/tech/stl. Implementations differ slightly in how the header files are named and whether namespaces are used. If you are compiling the Ringing Class Library on a Unix-like platform, the configuration process should take care of finding out how your particular implementation works. Otherwise, you will need to edit the file ringing/common.h.in before compiling.
The Ringing Class Library package uses the GNU tool autoconf to take away the problems of coping with differences between platforms. This means that you should be able to change to the top-level directory of the source distribution and type
./configure
to configure the package. This will determine the characteristics of your C++ compiler and create a file ringing/common.h which defines various symbols used in the compilation. This file is also installed with the rest of the class library, so that the installed header files will have access to it.
You can control many aspects of how the package is compiled and installed by passing arguments to the configure script; for example, you can control where the library is installed (for example, in /usr/lib or /usr/local/lib). For details of all the options which are accepted, type
./configure --help
in the top-level directory of the distribution. Some more instructions for using the configure script are given in the file INSTALL.
On most platforms, it should be possible to build and install either static or dynamic libraries, or both.
When compiling on Microsoft Windows, the range of different compilers and lack of a standard powerful scripting language make it difficult to provide a genuinely portable infrastructure to the package. However, the task of compiling and installing the library is not complicated, and easy to achieve by hand. The following steps are necessary:
Note that the header files are designed to be included from a subdirectory called ringing within your system's collection of header files.
If you wish to compile only the part of the library which is licensed for use in commercial programs, make sure you only compile and link those files which explicitly state that they are under the Lesser GNU Public License LGPL. See Licensing.
If you are using Microsoft Developer Studio, then you can use the supplied workspace file ringing-lib.dsw to accomplish the compiling and linking of the library without any effort. In addition, with the Microsoft Visual Studio compiler you do not need to edit ringing/common-ac.h by hand: there is a ready-customised version, called common-msvc.h, which will be found and used automatically.
Currently the class library should normally be compiled into a static library (.lib file). It is not yet straightforward to make the library into a DLL; if you choose to do this, you are on your own but the authors would be please to hear of any success.
The library is provided with basic test facilities that exercise the main classes and provide confidence that they are working correctly.
The tests are found under the tests directory and are linked into one executable called test. If all tests are succesfully a message will be printed stating this on the last line of output of the program.
To use the Ringing Class Library in your programs, you simply include the relevant header files in your source code, and then link the library into your final program.
Header files are expected to be found in the subdirectory ringing; thus you might type
#include <ringing/row.h> #include <ringing/proof.h>
at the top of a C++ source code file. If this does not work, either your
compiler is not looking in the right place for the header files, or you
have not installed them in the right place. You may be able to correct
this by adding an option (-I
on most systems) to your compiler
command line.
To link to the installed library, simply add the appropriate option to
the command line when linking your program. On most Unix systems, you
will have to add -lringing
to link with the library.
Classes for manupulating rows and changes, and all the other classes and functions described in this chapter, are declared in ringing/row.h.
For ease of notation, we use the idea that a row is an individual permutation of bells (such as 13572468), and a change is a means of getting from one row to another, by swapping pairs of bells; the most convenient way to write a change is a place notation (for example X or 1258).
Rows have a set of operations which we can use on them; in mathematical terms, they form a group. The most important operation is that of row multiplication or transposition - in this operation, the bells in one row are rearranged according to the order given by another row.
For example,
21345678 * 13572468 = 23571468
and
13572468 * 21345678 = 31572468
Note that the two above examples do not give the same result; that is, the order in which two things are multiplied does matter.
As an example of how row multiplication is used, suppose that we want to know the 4th row of the lead of Plain Bob Major with lead head 17856342. The 4th row of the first lead (which has a lead head of rounds) is 42618375. Multiplying these together gives us the answer we are looking for, namely 57312846.
The identity for this operation is rounds; in other words, any row multiplied by rounds gives itself, and rounds multiplied by any row gives that row.
It is possible to define the inverse of a row as the row which, when multiplied by that row, will give rounds. For example, the inverse of 13572468 is 15263748, as
13572468 * 15263748 = 12345678
The opposite of row multiplication is row division. If a * b = c, we can define c / b = a. Using the same example as above, suppose we have a lead of Plain Bob Major and we know that the fourth row is 57312846, and we wish to find the lead head. Just divide by the fourth row of the plain course (42618375) to get the answer.
There are several properties of rows which arise from group theory and can be useful in looking at properties of methods.
The order of a row is the number of times which that row has to be multiplied by itself before it gets back to rounds. For example, the row 21436587 has order 2, because if it is multiplied by itself twice, you get back to rounds. Similarly the row 23145678 has order 3, and the row 23456781 has order 8. This can be useful, for example, in seeing how many leads of a method are needed in a plain course before it comes round.
Another useful concept is the sign or parity of a row. A row is considered even if it takes an even number of swaps of pairs of bells to get from rounds to that row, and odd if it takes an odd number of swaps. (It can be shown that whether the number is odd or even doesn't depend on exactly what the sequence of swaps is).
Finally, every row can be expressed as a set of cycles. A cycle is a set of bells which move round in a sequential way as the row is repeated; for example, 21345678 has only one cycle, which is (12); and 12356478 has one cycle, which is (456). Combining these two cycles will give us the row 213564678.
A change is a means for getting from one row to another. It works by swapping over pairs of bells, and no bell may move more than one place.
The normal way of representing a change is by place notation; a single change is represented by a series of numbers which each correspond to a place being made; for example, 12 means that all bells swap, apart from the 1 and the 2, which stay in the same place. If all the bells swap, the place notation is X.
bell
class
The bell
class represents a single bell. An object of type
bell
is essentially an integer, and bells are numbered starting
with the treble as 0. Member functions are provided to convert between
this numerical representation and a printable character. The class
library can cope with up to 256 bells, though only bells numbered from 0
to 32 may be described by a printable character.
This class is not derived from any other classes.
class bell;
This constructor initialises the bell object to the integer i, where bells are numbered starting from 0.
This assigns the integer value i to the bell object, where bells are numbered starting from 0.
This operator writes the character representing the bell b to the output stream o.
This function interprets the character c as a bell, and assigns that value to the bell object. See the next function for the mapping between characters and bells. If the character does not represent a valid bell, then an exception of the class
bell::invalid
is thrown; if you have disabled exceptions, the bell is set to the valuebell::MAX_BELLS
. The function returns*this
.
This function returns a character indicating the bell represented by the object. The characters used are, in order:
1234567890ETABCDFGHJKLMNPQRSUVWYZ
row
class
The row
class stores a single row. It provides extensive
functions to manipulate rows and perform operations on them.
This class is not derived from any other classes.
class row;
This constructs an empty row, where bells is the number of bells which the row is to contain. Note that it is not initialised to anything.
This constructs a row from a string, which should be the textual representation of the row you wish to construct, for example "135246" or "2143658709TE". If the string does not contain a valid row, and if exceptions are enabled, an exception of class
row::invalid
is thrown.
This is the copy constructor; it creates a copy of the given row.
This sets the value of a row, given a string. The string s should contain a textual representation of a row, such as 21436587. If the string is not valid, a
row::invalid
exception is thrown.
These compare two rows.
This returns the ith bell in the row. Note that this is not an lvalue, so you cannot assign a value to an individual bell in a row.
These functions multiply two rows together as explained above. If the rows are not of the same length, the shorter row is considered to be first padded out to the length of the longer row by adding the extra bells in order at the end.
These functions divide two rows, as explained above. If the rows are not of the same length, the shorter row is padded as for multiplication.
These functions apply a change to a row. If the number of bells c differs from the number of bells in r, then c is considered to be padded or truncated in the obvious way.
This writes the row to the given output stream, in the same format as returned by
row::print()
.
These functions perform a lexicographical comparison of the two rows. They are necessary in order that rows may be put into certain containers.
This function swaps this row with other in an efficient manner.
This function locates the bell, b, in this row and returns its place.
This returns true if the row is rounds, and false otherwise.
If the row is a lead head of Plain Bob, Grandsire or, more generally, of the Plain Bob type method with any number of hunt bells, then this function returns an integer indicating which lead head it is. Otherwise, it returns 0.
If the row is a lead head of Plain Bob, Grandsire or, more generally, of the Plain Bob type method with h hunt bells, then this function returns an integer indicating which lead head it is. Otherwise, it returns 0.
This returns the sign or parity of a row: 1 for even, -1 for odd.
This expresses the row as separate cycles. The returned string will afterwards contain a list of all the cycles in the row, separated by commas; for example
row("21453678").cycles()
will return the string"12,345,6,7,8"
.
This specialised the
swap
function which is defined in the standard library. The result is that certain standard algorithms may become much more efficient. Note that according to your namespace setup,swap
may need to be in namespacestd
; similarly,row
may or may not be in namespaceringing
. This is all taken care of.
static
functionsThese return the row corresponding to rounds, queens, kings, tittums and reverse rounds respectively on n bells.
This returns the first lead head of Plain Bob (h = 1), Grandsire (h = 2), or more generally the Plain Bob type method on n bells with h hunt bells.
This returns a cyclic row on n bells with h initial fixed (hunt) bells. The variable c controls the number of bells moved from the front of the row to the end. Thus,
cyclic(6,1,2) == "145623"
.
change
class
The change
class stores a single change, i.e. a means of getting
from one row to another.
This class is not derived from any other classes.
class change;
This constructs an empty change for n bells, which will initially contain no swaps, that is, all bells will remain in the same place.
This is the copy constructor; it makes a new copy of c.
This constructs a change on n bells, with place notation as given in pn. This should consist of a sequence of characters which signify the places to be made, arranged in ascending order. If no places are to be made, the string
"X"
should be used. Note that you can miss out external places, unless no internal places are made at all. If the place notation is not valid, this constructor will throw an exception of classchange::invalid
.
This assigns the value of one change to another.
These compare two changes. Note that to be equal, the changes must be defined on the same number of bells; for example, "12" on 4 bells is different from "12" on 6 bells.
These return the effect of applying the change c to the bell b. For example,
3 * change(4,"34") == 4
. This is useful in tracing the path of one particular bell through a series of changes.
This writes the place notation for the change c to the given output stream.
If both changes have the same number of bells, these performs a lexicographical comparison on the swaps present in each changes; for example
change(6, "14")
compares less thanchange(6, "1236")
.If the two changes have different numbers of bells the one with fewer bells compares less than the one with more bells.
This function swaps this change with the change given by c in an efficient manner.
This returns the number of bells on which the change is defined.
This returns the sign of the change: -1 if an odd number of pairs are swapped, +1 if an even number of pairs are swapped.
Returns true if the change swaps bells i and i+1, and false otherwise.
Returns true if the change doesn't move the bell in the ith place (i.e. if iths place is made), and false otherwise.
This function returns the number of places made in the change.
If the change doesn't currently swap bells i and i+1, then this will add that swap. If those bells are swapped, this will remove the swap. If the bells i-1 and i, or i+1 and i+2, are currently swapped, those swaps are removed.
This returns true if after the function call, the pair of bells i and i+1 are swapped, and false otherwise. If exceptions are enabled and the bell i+1 is greater the number of bells in the change, an exception of class
change::out_of_range
will be thrown.This function makes it possible for the user to edit changes in such a way that they will always end up in a sensible state.
This returns the reverse of a change; that is, the change is flipped over so that on 8 bells for example, 2nds place becomes 7ths place and so on.
This returns true if the change contains internal places, and false otherwise.
This function prints the place notation for the change to a string.
This specialised the
swap
function which is defined in the standard library. The result is that certain standard algorithms may become much more efficient. Note that according to your namespace setup,swap
may need to be in namespacestd
; similarly,change
may or may not be in namespaceringing
. This is all taken care of.
permute
function
The permute
function is a utility function which makes it possible to
use some of the standard algorithms contained in the C++ library. There are
two forms of the function: the first takes an unsigned integer as
its argument, and the second takes a reference to a row. In either case,
a function object (of type permuter
or row_permuter
) is returned,
which can be used with standard algorithms.
This global function returns a function object of type
permuter
, which contains a row initialised to rounds on n bells. When the function object is called with an argument of either a row or change, its internal row is multiplied by that row or change and then returned.
This global function creates a
row_permuter
function object, which contains a reference to the row r. When the function object is called with a row or change as an argument, the row r will be multiplied by that row or change.
These operators multiply the permutation contained in the
permuter
object by the given row or change, and return the new permutation.
These operators multiply the row which the
row_permuter
object refers to by the given row or change. A reference to that row is returned.
row_block
class
The row_block
class is an array of rows which has associated with
it a reference to an array of changes, and can recalculate itself from
those changes. For example, suppose that the variable c
of type
vector<change>
holds one lead of a method; then it is possible to
define a variable of type row_class
which, once it is told what
the lead head is, will calculate the rows for one lead of the method.
Note that the row_block
object does not store its own copy of the
vector<change>
object from which it is calculated. This means
that the changes may be altered and the resulting rows recalculated
easily; it also means that the changes must not be deallocated while the
row_block
object is in existence.
The row_block
class is derived from vector<row>
.
class row_block : public vector<row>;
This creates a block of rows using the changes in c, starting from rounds.
This creates a block of rows using the changes in c, starting from the row given in r.
This template function is for expanding place notation into changes. The arguments are as follows: bells is the number of bells; start and finish should be forward iterators with value type
char
, and indicate a string of characters containing the place notation; and out is an output iterator of value typechange
, to which the changes will be written.The syntax of the place notation is as follows: place notation consists of a sequence of blocks, which are delimited by commas. Each block is a sequence of changes, with X or - meaning a cross change. Changes other than cross changes are separated by full stops. A block may optionally be preceded by an ampersand &, which means that the entire block, except the last change, is repeated backwards. All other characters are ignored.
For examples of this function in use, look at one of the
method
constructors in ringing/method.h or in the example code.
The Ringing Class Library provides many useful functions for dealing with methods, finding information about them and classifying them.
A method consists of one block of changes which is repeated over and over again; this is called a lead. If, at the end of one lead, every bell is in a different position, then the method is called a principle and the leads are called divisions. Any bells is a method which end up in the same place at the end of a lead are called hunt bells.
The Ringing Class Library defines an object method
which is
simply a block of changes (it is derived from vector<change>
) and
which provides a large range of member functions. Many of these are
used for finding out things about the method, such as the number of
leads in the plain course, the type of method, the full name and so on.
method
class
The method
class represents a method by storing the changes which
make up one lead of the method. This class is declared in
ringing/method.h.
A method may have a name, which is a string variable. This name is the base name of the method, that is, it is the name without any extra bits such as `Surprise' or `Triples'. For example, the base name of Plain Bob Major is simply `Plain'. The parts of the name other than the base can be worked out by the Ringing Class Library.
The method
class is derived from vector<change>
:
class method : public vector<change>
This constructor creates an empty method on bells bells, with length changes in the lead, and with name name. All the bells stay in the same place for the entire lead.
This constructor creates a method on bells bells from the given place notation, which should be an entire lead. The method is given the base name name. For information on how to specify the place notation, see the discussion of
interpret_pn
in Other functions in row.h.
This returns the base name of the method. Note that this may be an empty string, for example in Little Bob.
This sets the base name of the method to name.
This returns the number of bells on which the method is defined.
This returns the number of changes in a lead of the method.
These utility functions add a change to the end of the method. In the first case, c is the change to be added; in the second case, s is place notation for the change to be added.
This returns true if the method is symmetrical about the half lead (and has an even number of changes in the lead), or false otherwise.
This returns true if the method is double, or false otherwise. Note that double does not imply symmetrical.
This returns true if the method is regular (that is, has Plain Bob lead heads), or false otherwise.
This returns the number of hunt bells in the method.
This returns the number of leads in the plain course of the method.
This returns the standard code for the lead end and lead head of the method. The result is stored in a static internal buffer.
This returns true if the path of bell b in a lead of the method is symmetrical about the half lead, or false otherwise.
This returns true if bell b plain hunts for the whole lead of the method, or false otherwise.
This returns true if bell b dodges during the lead, or false otherwise.
This returns true if bell b makes any internal places during the lead, or false otherwise.
This function returns an integer which depends on the class of the method. The following values are defined:
enum method::m_class { M_UNKNOWN, M_PRINCIPLE, M_BOB, M_PLACE, M_TREBLE_BOB, M_SURPRISE, M_DELIGHT, M_TREBLE_PLACE, M_ALLIANCE, M_HYBRID, M_SLOW_COURSE, M_MASK = 0x0f, M_DIFFERENTIAL = 0x10, M_LITTLE = 0x80 };The
M_DIFFERENTIAL
andM_LITTLE
bits are flags which will be either set or cleared accordingly. (For the purpose of this function, “Differential” is considered a method class. Differential hunters will have theM_DIFFERENTIAL
bit set, together with one of the other classes; differential methods will returnM_DIFFERENTIAL | M_PRINCIPLE
.)
This function places the full name of the method in buffer, which should be long enough to receive it, and returns a pointer to it. The full name consists of:
- the base name of the method;
- the word “Little”, if appropriate;
- the class of the method, or none if it is a principle;
- the stage (number of bells) of the method.
Note that Grandsire, Union and their related methods are treated specially: the full name of these methods does not include their class, nor in the case of Little Grandsire does it contain “Little”.
This function returns the full name of the method as a string.
This function returns the maximum consecutive blows made in any place in this method. (If the method has one bell fixed throughout, the lead length is returned.)
static
functionsThis function returns a pointer to a string describing the stage of bells bells: thus
"Minimus"
,"Doubles"
, and so on. For stages above Sixteen, the number is given in digits.
This function returns a string describing the method class given in class, which should be as indicated in the explanation of
method::methclass()
above. For the purpose of this function, “Differential” and “Little” are both considered to be method classes.
static
variablesThe Ringing Class Library provides a extensible framework for loading and manipulating method libraries (collections) of various types. The classes that provide this framework are declared in ringing/library.h.
The class library contains built-in code for accessing certain types of libraries. Currently these are:
The class framework is designed so that programmers can easily add their own types of libraries, and handle them in exactly the same way as the build-in types.
When opening a library, it is not necessary to specify what type of library it is: usually this can be detected automatically.
This section describes how to open and read method libraries.
Before the auto-detection of libraries will work, the library
class needs to know which library types it should try when opening a
library. This is done by registering the different library types,
and should be done sometime during program startup. To make this as
simple as possible, each of the built-in library types has a static
member function called registerlib
for this purpose.
#include <ringing/xmllib.h> #include <ringing/cclib.h> xmllib::registerlib(); cclib::registerlib(); // Now we can open XML and Central Council libraries automatically
The order in which library types are registered is the order in which they will be tried when opening a library.
library
class
The library
class provides all the functions you need for opening
and accessing method libraries. These include:
Note that the names of methods in libraries may not be what the user expects. For example, in MicroSIRIL libraries, method names are run together into one word, say Doubledublin.
This class is not derived from any other classes.
class library;
This constructor attempts to automatically detect what type of library filename is, and create an appropriate
library
object to interpret it. For a library type to be correctly auto-detected, that type must be registered see Initialisation for libraries.After constructing a library, the
library::good
function can be used to see whether auto-detection succeeded.
In addition to this constructor, which auto-detects the type of library, it is also possible to open a library of a fixed type, by constructing an object for a specific library type. See Built-in library types.
The library
class has an associated iterator class.
In the language of the Standard Template Library, this is an input iterator. This means that you may only use it to read methods from the library in order, starting at the beginning. The value type of the iterator is
library_entry
see The library_entry class.
These functions return iterators pointing to the beginning and end of the library, respectively.
This is how these functions may be used to iterate through the library:
// Open a library library l("my_library.xml"); library::const_iterator i; // Print the base name of each method in it for(i = l.begin(); i != l.end(); ++i) cout << i->base_name() << endl;
This function returns true if the library is open and ready to read methods, and false otherwise.
This function loads a method from the library by name. Note that the names under which methods are stored in a library depend entirely on the type of library.
If no such method is found, if exceptions are enabled, an exception of class
library_base::invalid_name
will be thrown; otherwise, the method returned will be an empty method with the name "Not Found".
This function returns a list of the names of the methods in the library.
This function loads all the methods in the library and returns them as a list.
library_entry
class
The library_entry
class is the value type of the iterator on a
library. It is used to get information about the method from the
library without constructing a method
object.
This returns the method's name in whatever form the library stores it internally. Thus it may or may not contain the class name(s) or stage name of the method. In the case of MicroSIRIL libraries, it will not even have whitespace in the name.
This returns the base name of the method (i.e. the name with the class name(s) and stage name removed). The value returned is suitable for passing to the
method
constructor.
This returns a string containing the method's place notation.
This returns the number of bells on which the method is defined.
This function returns
true
if the method entry contains information about the given facet. Note that just because a method library type supports a certain facet, that does not necessarily mean that every method in the library actually has that facet. For example, an entry in a Central Council library may not contain any information about the first peals in a method; or an entry in an XML library may not contain certain elements.The contents of the argument f are not used, but this may be used to indicate the type of the facet as an alternative to explicit template instantiation.
This function returns the value of the specified facet of the method entry.
The contents of the argument f are not used, but this may be used to indicate the type of the facet as an alternative to explicit template instantiation.
For more information on facets and an example of how these functions are used, see Facets.
In addition to usual information such as name, stage and place notation, some method collections contain further information. For example, the Central Council method collections contain the date and place of the first peal in each method. To give access to such information, the Ringing Class Library has a fully typed system of method facets.
A facet is something which has a C++ type, and which may or may not be part of an entry in a method library. A few facets are declared as standard; library types are free to declare new facets of their own.
For example, one of the standard facets is called rw_ref
and is
of type string
. The facet is intended to contain a string citing
the method's appearance in the Ringing World. The following code
checks to see whether the first entry in the library l
contains
this information, and if so prints it.
library::iterator i = l.begin(); if( i->has_facet< rw_ref >() ) cout << i->get_facet< rw_ref >();
For more information on these functions, see The library_entry class.
Some facets are declared in ringing/peal.h. These facets are available in some of the built-in library types.
rw_ref
string
, contains a reference to the method's
appearance in the Ringing World.
first_tower_peal
peal
, contains the date and place of the
first tower bell peal in the method.
first_hand_peal
peal
, contains the date and place of the
first handbell peal in the method.
The last two are of type peal
, which is a class also declared in
ringing/peal.h. It is a very simple class and defines the
following functions.
These functions construct objects in the obvious way.
The peal::date
type is also very simple.
struct peal::date { int day, month, year; };
These functions construct objects in the obvious way.
A specification for method libraries in XML can be found at http://methods.ringing.org/. This site is also home to a server which serves XML method data in response to HTTP queries. The classes declared in ringing/xmllib.h can not only parse the XML data, but can also automatically download method data from the server.
To use XML method libraries, you need to have the Xerces library from the Apache project, available at http://xml.apache.org/.
xmllib
class
The xmllib
class is derived from the library
class.
class xmllib : public library;
This constructor opens an XML library. The first argument TYPE describes what sort of resource is to be opened, and should be one of the following:
xmllib::filename
- Open a file; NAME contains the name of the file.
xmllib::url
- Open a URL; NAME contains the URL. To use this, Xerces must have been built with Internet access.
xmllib::default_url
- Query the online method database at http://methods.ringing.org/. The argument NAME contains the query string, that is, the part of the URL after the ? character. For information on what this should contain, see the detailed information on the database's web site.
// Query the database for all methods named Lincolnshire xmllib l(xmllib::default_url, "name=Lincolnshire");
An XML method collection in a file may also be opened using the library
auto-detection mechanism, by simply constructing a library
object. See library constructors.
This function registers the XML library type with the library auto-detection mechanism.
The XML library type supports only the built-in facets. See Built-in facets.
The Methods Committee of the Central Council publishes collections of methods on its web site, in a text format. The classes declared in ringing/cclib.h can read these method collections.
cclib
classThe cclib
class is derived from the library
class.
class cclib : public library;
There is one constructor.
This function attempts to open the given file as a Central Council method library.
This function registers the Central Council library type with the library auto-detection mechanism. It will agree to open any file which has the correct CC copyright notice in the first line.
The Central Council library type supports the built-in facets see Built-in facets and one further facet.
cclib::ref
int
, contains the reference number of the
method in the library file. This is the number which appears at the
beginning of the line containing the method.
MicroSIRIL was an ingenious and widely-used early peal proving program for PCs. The method libraries used are in a simple text format, with one method per line; they contain, for each method, simply the name, lead head code and place notation.
The Ringing Class Library can read MicroSIRIL libraries, providing they satisfy one requirement: the last portion of the filename, before any extension, must be the number of bells on which all the methods in the file are. This is because it is impossible to tell the stage from just the place notation. So, for example, a method library file might be called s8 or new_principles10.txt.
Beware that the MicroSIRIL library interface will agree to open any file having a name satisfying the above requirement. For this reason, if auto-detecting method library types, you may want to put the MicroSIRIL library type at the end of your list.
When reading methods from MicroSIRIL libraries, remember that the name of each method may only consist of a single word; usually names consisting of several words are run together into one.
mslib
classThe mslib
class is derived from the library
class.
class mslib : public library;
There is one constructor.
This function attempts to open the given file as a MicroSIRIL method library.
This function registers the MicroSIRIL library type with the library auto-detection mechanism. It will agree to open any file which has a name containing a number just before any extension.
There are no facets available for MicroSIRIL libraries.
This section describes in greater detail how the various classes which implement method libraries interact. It is intended for those writing new classes to support new library types.
The basic library framework comprises five classes, all of which are declared in the header file ringing/library.h.
This is the basic interface that all implementations will need to implement. It describes how to iterate through a library, and provides hooks that can be used to provide more efficient algorithms for searching through the library.
The
library
class serves two purposes: it acts as a shared pointer to a library_base, and it handles the auto-detection of libraries. Implementations only need to derive from this if they want to provide an alternative to the standard auto-detection mechansim.
This class represents an entry in a library. It has value semantics; thus it is safe to hold onto multiple entries from a single library.
This is an input iterator that iterates over the entries in a library. Dereferencing the iterator returns a
library_entry
.
Each
library_entry
class holds onto a pointer to one of these. It provides an interface to read library entries that all library implementations must implement.
library_base
class
The library_base
class provides the interface that library
implementations must implement to create iterators on a library. It also has
virtual functions can be overriden to provide more efficient ways to search
and list libraries.
This should be overriden to construct a
library_base::const_iterator
pointing to the start of the library.
This returns a default constructed
library_base::const_iterator
representing one past the end of the library.
This function should be overriden to return true if a valid library is currently loaded and false otherwise.
The default implementation of
load
iterates through the library searching for an entry with the correct name. When comparing method names, it does so in a case-insensitive manner. If stage is non-zero,load
requires that the method is on that number of bells.If no such method is found, if exceptions are enabled, an exception of class
library_base::invalid_name
will be thrown; otherwise, the method returned will be an empty method with the name "Not Found".Library implementations may wish to override this if there is a more efficient way to locate the method.
The default implementations of
dir
andmdir
iterate through the library, pushing each name (in the case ofdir
) or method (in the case ofmdir
) onto result. The return value is the number of values pushed ontoresult
.Library implementations may wish to override this if there is a more efficient way to locate the method.
These functions are for writing to method libraries. This functionality is still experimental.
library_base::const_iterator
class
In the terminology of the STL, the library_entry::const_iterator
class
is an Input Iterator but not a Forward Iterator. This means that multiple
iterators on the same library will not work as expected.
This is the default constructor. It is undefined behaviour to dereference or increment the default constructed
library_base::const_iterator
.
This constructor creates an iterator on library lb and with a library entry implementation of val. The constructor takes ownership of val, which must have been allocated using
new
; it does not take ownership of lb. Typically, this function should only be called by thebegin
function of classes derived fromlibrary_base
.
Compare two iterators. It is undefined behaviour to compare two iterators from different libraries.
Dereferences an iterator to retrieve the current
library_entry
. It is undefined behaviour to dereference an iterator that compares equal to the end iterator of that library.
The prefix and postfix increment operators move the iterator on to point to the next entry in the library. If there are no further entries in the library, the iterator will compare equal to the library's end iterator.
library
internalsDefault constructs a library holding a
NULL
library_base
pointer.
This constructor attempts to automatically detect what type of library filename is, and create an appropriate
library_base
to interpret it. For a library type to be correctly auto-detected a function of typelibrary::init_function
must be registered withlibrary::addtype
. After constructing a library, thelibrary::good
function can be used see if auto-detection succeeded.
This constructor is provided to allow libraries the flexibility not to use the auto-detection mechanism. The argument, lb, must have allocated by
new
and gets deleted by thelibrary
's destructor. For more information on how to use this, see Alternative creation mechanisms.
Functions with this signature are used by the
library
construtor to attempt to load a library. Each derived library class that supports auto-detection should register a function of this signature with thelibrary
class by calling thelibrary::addtype
function. When these functions get called, filename is the name of the library file. If a library can read the file it should return a pointer to a class derived fromlibrary_base
allocated withnew
; otherwise the function should return NULL.
This is used to register a specific (derived) library class to the list of classes that can be auto-detected. This function is typically called by the static function
registerlib
in the derived classes.
If the library holds a
library_base
, these function call down to the corresponding functions on that, otherwise both functions return a default constructedconst_iterator
.
This function returns true if the library is valid, and false otherwise.
These functions all call down to the corresponding functions on the
library_base
; see The library_base class for details. They must not be called iflibrary::good()
is false.
library_entry
internals
The library_entry
class holds a pointer to a class derived from
library_entry::impl
which reads data from a particular library entry.
This constructor initialises the
library_entry
with aNULL
library_entry::impl
pointer. It is undefined behaviour to call any accessor functions on a default constructedlibrary_entry
.
This constructor creates a new object from the given pointer.
These functions all call the corresponding function on the
library_entry::impl
object.
library_entry::impl
class
The library_entry::impl
class provides the interface that library
implementations must implement to parse individual library entries. Each
library_entry
and library::const_iterator
holds onto one of
these.
This must be overriden to perform a deep copy of the library. Almost always this should be implemented as follows:
virtual library_entry::impl* mylib::entry_type::clone() const { return new mylib::entry_type(*this); }
The function should be overriden to read the next entry from the library and return true unless the end of the library has been reached. The source of the data should be held within the
library_base
implementation, and not this class. For example, if the library implementation reads from a file via anifstream
, thelibrary_base
class should contain theifstream
and this class should access it via lb:virtual bool mylib::entry_type::readentry( library_base& lb ) { ifstream& ifs = dynamic_cast< mylib& >( lb ).ifs; std::getline( ifs, this->entry ); }None of
library_entry
's other functions should ever access the parentlibrary_base
class.This function gets called whenever a
library::const_iterator
is constructed or incremented.
These should be overriden to return the name of the current entry. The
name
function should return a name which is unique within the library (this may require the class name(s) and/or stage name be included); thebase_name
function should return the name without either the class or stage name.These functions may be implemented to simply return a name that was parsed by
readentry
; alternatively it might be implemented to parse some internal representation of the entry (such as a string containing the whole entry). It must not attempt to access the parentlibrary_base
which may no longer exist. Thereadentry
function will always have been called before this function gets called.
This should be overriden to return the place notation of the current method.
This should be overriden to return the number of bells that the current method is on.
There are two ways to implement new library classes, depending on whether or
not the new library class can support the automatic detection of library type
done in the library(const string&
filename)
constructor. In
general, if the library is based on a single text file, the auto-detection
mechanism adequately provides a simple way for users of to transparently use
various types of library. More complicated types of library, such as those
based on a database, or on multiple files, fit less well with the
auto-detection mechanism, and some alternative mechanism is often better.
The implementation of a new type of library that can be auto-detected needs to
register a function with the signature library::init_function
with
library::addtype
. This gets used by the library class when it attempts
to open a file. It is often convenient to provide
the library user with a registerlib
function that handles this
registration. For example, for a type of library file that always starts
with the line “My Library File”, the following might be used.
class mylibrary : public library_base { public: // Allow the user to initialise the library static void registerlib(void) { library::addtype(&canread); } private: static library_base *canread(const string& name) { ifstream ifs(name); string first_line; getline(ifs, first_line); if (first_line == "My Library File") return new mylibrary(name); return NULL; } mylibrary(const string &name); };
In addition, the implementation must override the library_base::good
and library_base::begin
virtual functions. This is discussed elsewhere.
In cases where it is inappropriate to use the auto-detection mechanism an
alternative way of initialising library
with a pointer to a subclass of
library_base
must be provided. To do this, the implementation should
provide subclasses of both library
and library_base
. The
constructor of the subclass of library
should call down to
protected library::library (library_base*
lb)
constrctor with
a newly allocated subclass of library_base
. For example,
class mylibrary : public library { private: class impl : public library_base { // override virtual functions }; impl *init_library() { // Do any necessary initialisation return new impl; } public: mylibrary() : library( init_library() ) {} };
Usually it is sensible to avoid putting any data members or virtual
functions in mylibrary
, and to put them into mylibrary::impl
instead. This means that if a mylibrary
class is sliced to a
library
during a copy (for example when passing to a function taking
a library
by value) the class will still work correctly.
Note that library::~library
is not virtual, and thus,
if mylibrary
is ever allocated on the heap, care is required to avoid
deletion via a pointer to its base class.
In addition to providing mechanism for opening libraries, implementations
of new library types must also override at least the library_base::good
and library_base::begin
virtual functions. The implementation of the
good
function is usually trivial, and begin
only slightly less
so. Continuing with the example used in Supporting auto-detection, they
might be as follows:
class mylibrary : public library_base { mylibrary(const string &filename) : ifs(filename) {} class entry_type : public library_entry { // ... }; const_iterator make_begin() { ifs.clear(); ifs.seekg(0, ios::beg); // Rewind the stream return const_iterator( this, new entry_type ); } virtual bool good() const { return ifs; } virtual const_iterator begin() const { return const_cast< mylibrary* >( this )->make_begin(); } ifstream ifs; }
Notice the slight awkwardness of the const_cast
in begin
. This
is necessary because the begin
function is sematically constant—it
does not change the visible state of the library—but it needs to rewind
ifs. The stream's position is not part of the visible state
of the library because the library::const_iterator
is only an
Input Iterator and so only one of them can ever be present at any time.
The last step of implementing a library is to provide a class that implements
the library_entry::impl
interface, and most importantly, the
library_entry::impl::readentry
function. There are various possible
implementation strategies: the simplest is to get readentry
to parse
the whole of the library entry, store the name, place notation and so on in
data members, and then have the name
, pn
, etc. functions return
these. This is illustrated below:
class mylibrary : public library_base { class my_library::entry_type : public library_entry::impl { // Do a deep-copy of the entry virtual library_entry::impl* clone() const { return new entry_type(*this); } // Parse the entry virtual bool readentry( library_bas& lb ) { ifstream &ifs = dynamic_cast< cclib& >( lb ).ifs; if (!ifs) return false; // Have we reached the end of file? string entry; getline( ifs, entry ); // Assume the entry is in the format Method Name:Place Notation string::size_type p = linebuf.find(':'); name_ = string( entry, 0, p ); pn_ = string( entry, p+1, string::npos ); return true; } // Access parts of the entry virtual string name() const { return name_; } virtual string pn() const { return pn_; } string name_, pn_; }; ifstream ifs; };
An alternative implementation strategy would be to have readline
store
the whole line in data member (i.e. make entry a data member), and
then get name
and pn
to generate these on-the-fly from the
entry string.
proof
classThe proof class provides a simple way of checking that a block of rows are true. It provides functions for finding out where a particular block has failed. Additionally, it will can check blocks that are more than one extent long.
It is a template class, defined as template <class RowIterator>
class proof;
. You can therefore decide on your own method of
generating rows, as long as you can provide an iterator (see the
STL) for it.
It will check ALL rows given; therefore, if rounds are at the start and end, then one of them should be removed before passing to the object.
The proof class only stores the results: it does not make a copy of the actual rows. However, pointers to false rows will be stored, so don't destroy your rows before getting all the proof results. This may be changed in a later release.
Note: To avoid problems, make sure that all the rows have the same number of bells in them, otherwise 12345 will not 123456.
This class is not derived from any other classes.
template <class RowIterator> class proof;
Where the variable qp is passed into a function, if this is set to true, the proof class will only check until the row blocks are found to be false, as soon as this is the case, the function will end and store the true/false result. No details will be stored about what lines the row block failed on.
Default Constructor. Sets trueness to false. Use the prove function to provide the rows to prove.
This checks for repeated rows from first to last. Expects up to 1 extent only. Result is stored in class for later retrieval.
This checks for repeated rows from first to last. Expects up to max extents. Result is stored in class for later retrieval.
This constructor takes two blocks of rows as it parameters. true_first to true_last are assumed to be a block of rows that are true. No trueness checking is performed on these rows. The function looks at rows unknown_first to unknown_last comparing them to the true block, and to the unknown block to see if they are repeated anywhere. The failure information is reset before the analysis takes place, hence any falseness details obtained will be for the new block only.
This constructor acts like the previous, except it will expect up to max extents (and hence repititions).
Where the variable qp is passed into a function, if this is set to true, the proof class will only check until the row blocks are found to be false, as soon as this is the case, the function will end and store the true/false result. No details will be stored about what lines the row block failed on.
This checks for repeated rows from first to last. Expects up to 1 extent only. Full result is stored in class for later retrieval, but trueness of rows is returned. This function will erase any falseness details stored in the class.
This checks for repeated rows from first to last. Expects up to max extents. Full result is stored in class for later retrieval, but trueness of rows is returned. This function will erase any falseness details stored in the class.
This function takes two blocks of rows as it parameters. true_first to true_last are assumed to be a block of rows that are true. No trueness checking is performed on these rows. The function looks at rows unknown_first to unknown_last comparing them to the true block, and to the unknown block to see if they are repeated anywhere. The failure information is reset before the analysis takes place, hence any falseness details obtained will be for the new block only.
This function acts like the previous, except it will expect up to max extents (and hence repititions).
Output of the proof class is achieved in one of two ways. Either, the functions proof::int and failed() are used, or an overloaded ostream operator for a fixed format.
When the proof class finds two or more rows that are the same, it stores the details in a private variable, where. This can be retrieved by the function failed
. The variable is defined as:
typedef list<linedetail> proof::failinfo; failinfo where;
linedetail is a struct defined as:
struct linedetail { row _row; list<int> _lines; };
When a row is repeated more than once, a new linedetail item is added to where. In the linedetail data is stored a pointer, _row, to the first of the matching rows, and the row numbers are put into _lines. If the first row given to the class matches the 11th row, then 0 and 10 will be placed into _lines. If there are three or more rows that all match, then the relevant numbers will be placed into the _lines list without repeating any.
There are two ways that the class can prove blocks of rows depending on if the number of rows is less or greater than an extent. In both methods, the procedures are carried through to the end to allow the user to see where the block of rows is false in all places, not just the first.
If the single extent version of the function proof::prove
is called, then we follow this procedure.
Here we look at the first row and compare it to the rest. Then we proceed to the second and compare that to the rest (starting from the third, and going to the end). We then continue this until we have completed all the rows. If two rows match the details are stored and the trueness is set to false.
If the multiple extent version of the function proof::prove
is called, then we follow this procedure.
Now we proceed through the list just once. Each row is put into a multimap, if at any time the amount of rows in this map exceed the maximum number of extents then the details are added into the failed information and the trueness is set to false.
The music class provides analysis for music within a set of rows. The class has been designed around providing a regular-expression style matching algorithm. This provides flexibility in the way the user can enter their own music. Additionally, for each 'regular-expression' a score can be allocated. For a full description of the regular expressions the ringing library currently provides see Music Regular Expressions.
The music class processes each row just once, it does not store any rows. It assumes that the first row given is a handstroke row. The class should be able to handle any number of bells that the row class can. Note, that matches for complete rows should be done on a same number of bells basis.
Each time the analysis function is called, the results stored in the class are reset to zero, and then incremented based on the rows given.
Part of the music class functionality is to allow handstrokes and
backstrokes to be specified independently, or together. An enumeration,
EStroke
is provided to enable this to take place.
It is defined as follows:
enum EStroke { eHandstroke, eBackstroke, eBoth };
The music_details
class provides the means to describe musical
rows to the music
class. The music_details
class stores
details of the expression to be matched (as a string) and an associated
rating, if the user so desires.
Ratings may be positive or negative, this allows a total weighted score to be calculated from the sum of the result scores. For example, 678s may be rated at a +2, but 87s at backstroke rated as -10.
When a match sequence is run via the music class, if a row matches that
described by the details provided to a music_details
object, then
the count will be incremented.
The result can either be returned as a raw count, or as a score calculated from the multiplication of the count and the given rating.
If it is specified, then the count or score can be return for just the handstroke, backstroke or both.
Further details relating to the music_details class can be accessed from the menu below:
The regular expression strings describing rows that can be matched as 'musical' can be specified using the following characters:
Representing a bell:
1234567890ETABCDFGHJKLMNPQRSUVWYZ
Representing any bell:
?
Representing any bells in any order:
*
Representing one of several bells in a set position:
[34]
These constructs can be formed into the following (in all these cases we are matching with a 6 bell method):
"12??56" In this case we are wishing to know how many rows occur that are 124356 or 123456.
"135246" In this case we are wishing to know how many times queens occur.
"*456" In this case we wish to know how many rows there are that finish in 456.
"654*" In this case we wish to know how many rows there are that start with 654.
"*456*" In this case we wish to know how many rows have 456 in the middle of them, note this includes rows that start 456 and end 456 as well.
"*[56]78" in this case we wish to know how many rows end in 578 or 678.
The music_details class allows the specification of music via a regular expression to the music class. Although functions are provided to return the score, they are mainly intended for use by the music class itself. It should be noted that the music class takes a copy of the music_details object rather than a pointer.
Creates the object and sets the initial expression to e and the score to use to s. By default the score is 1. If the specified expression is invalid, the class will throw an
music_details::invalid_regex
exception (if they are enabled) or reset the expression to "".
Sets the expression to e and the score to s. It will also reset the counts of rows matched.
Returns the maximum number of possible matches (in one true extent) for the currently specified expression. bells must be specified as the
music_details
class has no knowledge of this under normal circumstances.
Returns the maximum possible score (based on one true extent) for the currently specified expression. bells must be specified as the
music_details
class has no knowledge of this under normal circumstances.
Returns the number of rows matched based on the stroke that is passed in. If eBoth is passed, then the result will be the handstroke count plus the backstroke count.
Returns the total score based on the stroke that is passed in. If eBoth is passed, then the result will be the handstroke score plus the backstroke score.
The basic process of using the music class is to create it, specify to it the music that you wish to look for in a set of rows, tell it to process the rows and then obtain the results.
We now describe this in more detail. First create an instance of the music class, specifying to it the number of bells you wish to work with:
music mu(5);
Now specify the music that you are looking for via the music details class (see Expression Language for how to do this). The music class behaves like a vector<music_details>
structure so you can access the elements individually before and after. To add a music specification, do something like this:
music_details md("*45"); mu.push_back(md);
If you want, more can be added in the same way or by modifying md and pushing the new structure onto the back of the music list:
md.set("*345*"); mu.push_back(md);
Now you can supply the music class with rows to search against the specified music (note pbdoubles is a vector<row>)
mu.process_rows(pbdoubles.begin(), pbdoubles.end());
Now you can obtain the results from the music class. You can do this in several ways. The first is to obtain the overall total score, for both strokes, or for one:
cout << "Total Score: " << mu.get_score() << endl; cout << "Total Score (Backstroke): " << mu.get_score(eBackStroke) << endl;
The second way is to obtain results for individual items:
music::const_iterator k; for (k = mu.begin(); k != mu.end(); k++) cout << "Total for " << k->get() << ": " << t->count() << " : " << k->total() << endl;
This produces three columns, the first is the music expression that was searched for, the second is the number of matches, the third is the number of matches based on the score. See the Music_Details class for more details on these functions.
The music
class is the main control of the music classes; it stores music_details
objects to match music against and controls the construction of the music_node
tree (see music node class definition.
The class must know the number of bells in the rows that are to be examined before the music_class
objects are passed to it; this allows it to create trees of the correct depth and structure to store the regular expressions in search format.
The music_detail
objects are stored in a vector<music_details>
structure, this is accessible via the functions provided (detailed below).
This class is not derived from any other classes.
class music;
This constructor initialises the number of bells to zero. If you don't specify bells here, you should specify the number of bells by the
set_bells()
function before adding expressions to be matched.
This section details the type definitions that the music class creates for the user to use.
This type defines the storage vector that records the expressions to be matched and is also used to obtain the results.
This type defines a general iterator that can be used to iterate through the stored expressions.
This type defines the type of variable returned from the
size()
function.
This function adds a
music_details
expression onto the vector of expressions to be matched. It will also add it to the tree ready for processing against rows.
These functions return an iterator that points at the beginning of the expression list.
These functions return an iterator that points past the end of the expression list.
This function returns the number of expressions currently stored.
This function sets the number of bells that will be in the matched rows to
b
.
This function first resets the all of the music counts, and then processes the supplied rows. If backstroke is true, then a backstroke is assumed to be the first row, otherwise it will be noted as a handstroke. The stroke will be toggled for every row processed.
Returns the score for music matched at the specified stroke. If eBoth is specified as the stroke, then scores for both strokes are added together and returned.
Returns the total number of matches for all music expressions at the specified stroke. If eBoth is specified, then the counts for both strokes are added and returned.
This function returns the maximum possible score that could be obtained matching the expressions currently stored against a true extent on the number of bells previously specified.
The music_node
class provides the main expression matching routines for the music
class. A music
object stores one TopNode
object, (of type music_node
), when expressions are added to the music
object, via a music_details
class, a tree is formed under the TopNode
object.
The music_node
class is normally hidden from the user by the music
class, however, it's functionality is described here to aid maintainance and understanding.
Each node in the tree stores the expressions that finish at the node, and pointers to nodes below them, if any have been created. Note, for any node there are a maximum of n pointers, where n is the number of bells, plus one; The extra case in this instance is for a ? or * expression to match any bell.
When a row is to be matched against the expressions stored, each bell in the row is examined individually. If a pointer to a node for the same number as the current bell exists, the matching passes onto the node pointed at. For all cases, if an 'any' pointer exists, then the matching will be passes onto the any node.
When the expression matching comes up against a node where an expression is specified to finish at that node, then the counter for matches against the node is incremented. If there are no matches to the current bell, and the any pointer does not exist, then the matching simply finishes and returns back up the tree.
This is probably better explained by means of an example. Suppose the expression 321654 is added to the TopNode. If + is a node, and |n is a pointer between the nodes, where n is the number of bell pointed to, then the following tree is formed:
TopNode
|3
+
|2
+
|1
+
|6
+
|5
+
|4
+ 321654 finishes here.
When the row 326154 is attempted to be matched, the following happens:
TopNode -> Pointer to 3 exists, so go to the next node. |3 + -> Pointer to 2 exists, so go to the next node. |2 + -> Pointer to 6 (or to any node) does not exist, so terminate. |1
Now suppose 321* and ?2* is added to the list, the following tree is formed:
TopNode | ------------------------------- |3 |any + + |2 |2 + + ?2* finishes here. |1 + 321* finishes here. |6 + |5 + |4 + 321654 finishes here.
Now, when the row 321654 is put through the matching process, the following happens. Taking first the pointer to bell '3' option of TopNode:
TopNode -> Pointer to 3 exists, so go to the next node. |3 + -> Pointer to 2 exists, so go to the next node. |2 + -> Pointer to 1 exists, so go to the next node. |1 + -> 321* finishes here so increment, and then as pointer to 6 exists, carry on to the next node. |6 + -> Pointer to 5 exists, so go on. |5 + -> Pointer to 4 exists, so go on. |4 + -> 321654 finishes here so increment matches. No further pointers, so go back up the tree checking for any pointers
When the matching gets back to the top of the tree and finds the any pointer in the top node, it will follow it as below:
TopNode -> Any pointer exists, so follow it |any + -> Note, we are now on the second bell of the row, which in our case is 2, pointer exists, so follow it. |2 + -> ?2* finishes here so increment matches.
From these examples it can be seen that an optimisation is performed when there is a single * left, which saves the matching algorithm going through exvery any node.
This class is not derived from any other classes.
class music_node;
The constructor initialises the object and sets the number of bells in the rows that will be matched. If the default constructor is used, then the
set_bells()
function should be used to perform this action.
The destructor will go through the tree structure, deleting the sub-nodes of the current node.
This map is used to form the structure of the tree. The branches are stored in the structure, with the unsigned int being an index by bell number. Index 0 is for matching any bell. Note, where a node of the tree has no branches coming off of it (because it is the end, or there is nothing else to match against) the map will be empty.
This type definition is used to provide a shorter type name to iterate the map described above.
This type definition defines the vector that is used to store the id of the music_details expressions that end at this node.
This type definition is used to provide a shorter type name to iterate the details vector defined above.
This function is used to set the number of bells that will be in the rows to be matched against. This provides a way for the algorithms to know when they are finished processing the expressions or row.
This function is used to add the supplied expression (
md
), to the tree. The location in the expression to look at is supplied byi
, thekey
is the reference number that themusic
class stores themd
expression against, and thepos
is the number of bells deep we are in the tree.Depending on the item in the expression at index
i
, the algorithm will do different things, normally, it will call theadd_to_subtree(...)
function which in turn will usually call this function again; sometimes it will call itself (in the case of a '*') to move along the current expression without necessarily adding it to a subtree. Hence, theadd(...)
function is an iterative one.
This private function is used to create a branch (if required) and add an expression to a branch of a node. If it cannot allocate memory for the new node, it will either throw a
memory_error
exception (if enabled), or it will simply return without going any further.The
place
parameter provides the branch number (= bell) to create and add to, theprocess_star
parameter is used to indicate if the number of *s remaining should be processed or ignored. The rest of the parameters are as for theadd(...)
function.
This function is iterative and is used to match the expressions stored to a row,
r
. If a node is found to have an expression ending there, the number of counts for that expression are incremented according to the specifiedstroke
. Thepos
parameter is used to specify the current position in the rowr
, and theresults
parameter is the expressions for which the indexes have previously been stored, and against which the count should be incremented as appropriate.
There is one exception defined for this class:
struct memory_error : public overflow_error() { memory_error() }; music_node::memory_error::memory_error() : overflow_error("Not enough memory to allocate to music_node item") {}
This is used to indicate that there is not enough memory to add a music_node item.
The Ringing Class Library provides a flexible mechanism for producing printed output of rows, methods and lines. The way this mechanism is designed means that the low-level details of printing are hidden from the programmer. Currently the classes in the library support output in PostScript and PDF formats, and the modularity of the printing system makes it easy to extend the library to provide other output formats.
Basic printing is provided in two classes: the printpage
class
and the printrow
class. The first of these deals with placing
text and other objects directly on the page; the second allows for
formatted output of rows and lines. These classes are both pure virtual
classes, which are specialised by subclasses to allow for different
output formats.
Printing of whole methods is accomplished by the printmethod
object. This is not as flexible as the more generic functions of the
lower-level printing objects, but exists to provide a quick and easy way
to print out methods in a moderately variable format.
There are certain rules which should be followed when using the printing
classes. For a single printpage
object, only one printrow
object may exist at any one time. All printrow
objects associated
to a printpage
object must be destroyed before starting a new page,
and before destroying the printpage
object. Failure to observe
these rules may result in unusable output.
The printing mechanism of the Ringing Class Library declares several auxiliary classes, for specifying printing parameters in a device-independent way. This section describes those classes.
dimension
classThe dimension
class is used extensively by the printing classes
to specify physical dimensions on the page. The class has three public
data members and one public enumerated type:
class dimension { public: enum units { points, inches, cm, mm }; int n, d; units u; }
The integers n
and d
hold the numerator and denominator
respectively of the dimension. The member u
defines which units
the dimension is given in. For example, a dimension
object
representing three quarters of an inch would have n
equal to 3,
d
equal to 4, and u
equal to dimension::inches
.
Points here are PostScript points, which are equal to 1/72 of an inch.
The dimension
class has several member functions.
This constructs a dimension equal to the fraction i/j in units u.
This operator returns the negation of the dimension.
These operators multiply the dimension by the integer i.
These operators divide the dimension by the integer i.
These operators are only useful for comparing a dimension to 0.
This returns a floating point numbers representing the dimension in points.
This function sets the dimension to an approximation of the given floating-point number value. Specifically, the denominator is set to denom, and the numerator is set to the integer closest to the product of value and denom.
These functions read a dimension from a string. The string should contain following parts:
- An optional minus sign;
- a number, in either decimal format or as a fraction;
- the units.
For example, the following strings would all be recognised: 0.4 cm; 1 1/2", 56 pt. The allowed unit names are pt, points, point, in, inch, inches, ", cm, mm.
This function writes the dimension to the string s.
colour
classThe colour
class is a structure which represents a colour. It
is defined thus:
struct colour { bool grey; float red, green, blue; };
The red-green-blue (RGB) colour space is used to specify colours. This is not particularly well suited to printing, where a subtractive colour model such as CMYK is more useful, but RGB is at least very widely used. Colours printed using the Ringing Class Library will probably vary quite a lot from one device to another, but your blue lines will be blue and your red lines will be red.
To specify a colour in a colour
object, simply set grey
to
false
and set the other three members to numbers between 0 and 1,
inclusive. You can also specify a shade of grey by setting grey
to
true
; then the red
element specifies the shade of grey, from
0 (black) to 1 (white).
text_style
classThe text_style
class is a structure which represents a text
style. It contains a font name, a size in tenths of a point and a
colour. It also defines an enumerated type which may be used to
describe text alignment.
struct text_style { string font; int size; colour col; enum alignment { left, right, centre }; };
Font names are dependent on the output device; as the only output device currently supported is a PostScript device, the font name should be a PostScript font name such as Helvetica-Oblique or Times-Roman.
printpage
classThe printpage
class takes control of producing printed output on
a page. To start printing, an object of some subclass of
printpage
is created, which will handle all further printing.
For example, to print to a PostScript stream or file, an object of class
printpage_ps
would be created. Once the printpage
class
has been created, it can be used to place text directly on the page. It
can also be used to create printrow
objects for printing rows and
lines.
Note that positions on the page are always measured from the bottom left corner.
The printpage
class is a pure virtual class: the only way to create
one is by constructing an object of a derived class.
This tells the
printpage
object to finish printing the current page and start a new page.
This function places a text string on the page. The string is given in t and should consist of printable characters. The position at which the string is to be printed, measured from the bottom left corner of the page, is given by x and y. The alignment of the text about this point is given by a, and the text style is given by s.
printrow
classPrinting of rows and lines is handled by the printrow
class and its
subclasses. An object of type printrow
is created, attached to
a given printpage
object. After the object has been created, it
can be given rows to print. The rows can be printed in various ways: the
actual numbers representing the row may or may not be printed, and lines
can be drawn for selected bells.
printrow
classA printrow
object is created by one of the following constructors.
Note that there are certain options which cannot be changed once the
object has been created, so unless the default options are going to be
used it is necessary to use the second form of the constructor.
This constructor builds a
printrow
object associated to theprintpage
object given by pp. The options are initialised to the default options.
This constructor builds a
printrow
object associated to theprintpage
object given by pp, and initialised the options to op.
Once the printrow
object has been created, it must be positioned
on the page before any rows can be printed.
This function sets the position of the
printrow
object to the given place on the page, measured from the bottom left. The position given is where the first bell of the next row printed will appear.
This function is like the preceding one, but the position given by x and y are taken relative to the current position of the
printrow
object. The current position is either the place where the top left bell of the last column printed appeared, or as set by aset_position
ormove_position
function call, whichever is more recent.
Certain options (see Row printing options) may be changed while the
printrow
object exists.
This function returns the current options.
This function sets the options to those given by o. Note that only certain option changes will have any effect once the object has been constructed.
After setting the position, rows can be printed.
This operator is used to print a row r using the
printrow
object pr. This prints the numbers of the row if thenumbers
flag of the options is set, and also draws the lines for any bells which have been specified in the options. The row is printed underneath the previous row.
This function draws a horizontal rule below the last row printed.
This function draws a small dot at the place where bell i was in the last row printed. If i is -1, prints dots for all bells which are having lines drawn.
This function finds what place the bell i was at in the last row printed, and then prints this number in a circle to the right of that row.
This function prints some text to one side of the last row printed. The text is given in t and is printed in the same style as the rows. If the boolean argument right is true, the text is printed to the right of the row; otherwise the text is printed to the left of the row. The dimension x is a distance from the leftmost or rightmost number in the row, and the text is aligned about this point as given by al (see The text_style class). If the argument between is true, then the text is not aligned vertically with the previous row, but rather appears halfway between the previous row and the next one to be printed. This last option is useful, for example, for printing place notation beside a method.
The way in which rows are printed by a printrow
object is
controlled by various options. These options are given by a
printrow::options
object.
struct options { enum o_flags { numbers = 0x01, miss_numbers = 0x02 }; unsigned int flags; text_style style; dimension xspace, yspace; struct line_style { dimension width; colour col; }; map<int, line_style> lines; void defaults(void); };
The flags
member contains various flags; bit values are given by
the enumerated type o_flags
, and possible values for flags
can be obtained by logically ORing these values together. The bits
are as follows:
options::numbers
bit controls whether the actual numbers of the
rows are printed. If this bit is not set, only lines will be printed.
options::miss_numbers
bit, then any numbers which would
appear underneath lines are missed out. An example of this may be seen
in the Ringing World diary, where all rows except lead heads are
printed with this property.
The style
member controls the style in which the rows are
printed; for the declaration of the text_style
class, see
The text_style class. This option may not be changed during printing.
The xspace
and yspace
members give the horizontal space
between numbers in a row, and the vertical space between rows, respectively.
For the declaration of the dimension
class, see
The dimension class. These options may not be changed during
printing.
The lines
member controls which “blue lines” are printed. Each
element of the map has an integer, denoting the bell number, and a
line_style
element which defines the style of the line. The two
members of line_style
are a dimension
object, giving the
width of the line, and a colour
object, giving the colour of the
line. This option may be changed in between columns, but not in the
middle of a column.
For example, suppose that we wish to print rows in 10-point Helvetica, with
spacing of 12 points horizontally and vertically. We want to draw a blue
line half a point thick for the second bell. The following code sets
up a printrow::options
object to accomplish this:
printrow::options o; o.flags = printrow::options::numbers; o.style.size = 100; o.style.font = "Helvetica"; o.xspace.n = 12; o.yspace.n = 12; line_style s; s.width.n = 1; s.width.d = 2; s.width.u = dimension::points; s.col.grey = false; s.col.red = 0; s.col.green = 0; s.col.blue = 1.0; o.lines[1] = s;
There is one member function of printrow::options
.
This function sets up the
printrow::options
object to the defaults as given in the example above.
It should be reasonably clear how the printrow
object might be
used to print out numbers and lines for a method. This simple but
tedious task is automated by the printmethod
object. The
printmethod
object is not designed to be as flexible as the rest
of the printing mechanism, but rather to accomplish its one aim, that of
printing out methods, in as simple a way as possible.
The appearance of the printed method is controlled by setting the public
data members of the printmethod
object. When all the parameters
have been set up, the function printmethod::print()
is used to
print the method to a given printpage
object.
The output consists of a series of columns, each of which contains the same number of rows. When one column is full, a new column is started to the right of the last one. A number of columns, side by side, are called a column set. When one column set is complete, a new column set is started below the last. Whenever a new column is started, the last row of the previous column is duplicated at the top of the new column.
The printmethod
object has many public data members, which
control the format of the printed method. These public data members are
described here.
This member contains the options which are used to print each separate row of the method. For more information on this object, see Row printing options. Note that the
miss_numbers
flag is overridden by the setting of thenumber_mode
member of theprintmethod
object (see below).
These two members control the horizontal gap between columns, and the vertical gap between column sets, respectively. For more information on the
dimension
class, see The dimension class.
This integer sets the total number of rows which will be printed. This total does not count those rows which are duplicated because they appear at the end of a column.
This integer controls the number of rows printed in each column. In fact each column will contain one more than this number of rows, because the last row of each column is duplicated at the top of the next column.
This integer controls the number of columns which appear in each horizontal column set, that is, the number of columns across the printed output.
This integer controls the number of column sets which appear on each page, that is, the number of columns down the printed page. If the total number of columns printed exceeds this numbers, more than one page of output will be produced.
These two members position the output on the page. Together, they contain the position of the top left bell of the top left column of the output. measured from the bottom left hand corner of the page. For more information on the
dimension
class, see The dimension class.
This member controls the printing of horizontal rules in the output. Each entry in the list is a pair (a, b) of integers; this entry means that a rule will be drawn after the ath row in each lead, and every b rows after that. For example, the usual setting for a treble dodging method would be the pair (4,4), indicating that rules should be drawn every four rows, starting with a rule after the fourth row. Similarly the usual setting for Stedman would be the pair (3,6).
This member sets the behaviour with regard to missing numbers underneath lines. There are four possible settings, described by an enumerated type:
enum number_mode_t { miss_never, miss_always, miss_column, miss_lead };The meaning of these options is as follows:
miss_never
: numbers are always drawn;miss_always
: numbers are never drawn when they appear underneath a line;miss_column
: numbers are only drawn underneath lines in the first and last rows of a column;miss_lead
: numbers are only drawn underneath lines at lead heads.
This member controls the printing of place notation next to the method. There are three possible settings, described by an enumerated type:
enum pn_mode_t { pn_none, pn_first, pn_all };These options are interpreted as follows:
pn_none
: place notation is never printed;pn_first
: place notation is printed to the left of the first lead of the method and, if the method is symmetrical about the half lead, only the first half of the place notation and the lead end are printed;pn_all
: full place notation is printed to the left of every lead.
This integer controls whether place bells are printed, and for which bell. If this member contains an integer greater than or equal to zero, then place bells are printed for the corresponding bell. To suppress the printing of place bells, set this member to
-1
.
printmethod
objectBefore printing a method using a printmethod
object, two things
must be set up: the object must be given a method to print, and the
parameters for printing described in the previous section must be
initialised.
The class has two constructors:
These two constructors create a
printmethod
object. In the first case, no method is specified; a method will have to be given later, before anything can be printed. In the second case, a reference to the method m is stored for printing after the parameters have been set up.
After the object has been created, the method can be queried and changed with these functions:
This returns the method referred to by this
printmethod
object.
This function stored a reference to the method m in the
printmethod
object, for subsequence printing.
The parameters for printing, described in the previous section, may be manipulated with several member functions.
This function sets the parameters to default values, which relate to the method to be printed; so it should not be called before a method has been given to the
printmethod
object. Specifically, the parameters are set as follows:
- Numbers are to be printed in 10-point Helvetica, and the spacing between bells is 12 points both horizontally and vertically;
- Each column contains a single lead; an entire plain course of the method will be printed, with leads side by side;
- The output is positioned at the bottom left of the page;
- Numbers will be missed underneath lines, except for lead heads;
- Place notation will be printed to the left of the first lead only;
- Each hunt bell is shown with a red line, a quarter of a point thick;
- The smallest working bell which makes a place over the lead end is shown with a blue line, half a point thick, and place bells are shown for this bell. If no working bell makes a place over the lead end, the smallest working bell is chosen instead.
This function scales and arranges the method to fit in the given space, as specified by width and height. The parameters which are calculated by this function are
rows_per_column
,columns_per_set
,hgap
,vgap
,opt.style.size
,opt.xspace
andopt.yspace
. Two possible layouts are possible: if vgap_mode isfalse
, then only one column set is used, with each column containing a whole number of leads; if vgap_mode istrue
, then each column contains precisely one lead, and as many column sets as necessary are used. The effect of this is that, in the first case, the second lead appears below the first one; in the second case, the second lead appears to the right of the first one. The last argument aspect sets the ratio ofopt.xspace
toopt.yspace
.The chosen layout is that which, given the constraints specified, allows the largest of output.
These functions give the total width and height, respectively, in points of the printed output using the current parameters.
The Ringing Class Library provides subclasses of the printpage
and
printrow
classes for producing output in the PostScript language.
These classes are declared in the ringing/print_ps.h header file.
The output conforms to the Document Structuring Conventions (DSC)
version 3.0 and uses only Level 1 language.
The printpage_ps
class is derived from printpage
, and handles
all output to a PostScript stream. The new functions in this class are
constructors and some PostScript-specific operations.
This creates a new PostScript printing object, which will send its output to the stream o.
This creates a new PostScript printing object, which will send its output to the stream o. Each page will be printed with landscape orientation; because of the way PostScript works, this means that the page height must be given.
This creates a new object which will write an Encapsulated PostScript (EPS) file to the stream o. The bounding box for the EPS file is specified in points by the arguments x0, y0, x1 and y1. This bounding box has no effect on where you can print things using this object, but other applications manipulating the EPS file may rely on the bounding box in order to work properly.
The printrow_ps
class is for printing rows to a printpage_ps
object. You will probably never have to deal with this class directly, as
it should be created and dealt with by the interface for the printrow
class.
Subclasses of the printpage
and printrow
classes are also
provided for providing output in Adobe Portable Document Format
(PDF). These classes are declared in the print_pdf.h
header file.
Some specific issues must be considered when creating PDF files. Firstly, although the classes support output to an arbitrary stream, some care must be taken. This is because PDF files contain tables which cross-reference different parts of the file; and these tables therefore contain byte offsets into the file. If you use the PDF printing classes to write to a text-mode file on some system, such as Microsoft Windows, which convert single line feeds to carriage-return and line-feed pairs, then this byte count will be incorrect. The safe way round this is to always open PDF output streams in binary mode.
The second specific issue which arises when creating a PDF file is that of fonts. In order to position text correctly on the page, the class library needs to know the metrics of every character in each font used. As a result, it is only possible to use the standard 14 PDF fonts when printing from the Ringing Class Library. These standard fonts are:
The printpage_pdf
class is derived from printpage
. The only
new functions defined in this class are its two constructors:
This constructor creates an object for writing a PDF file to the output stream o. The page width and height are set to width and height respectively. If the Boolean parameter l is set, the page will be printed in landscape format.
This constructor works as the previous one, but the page size is set to A4.
The subclass of printrow
for printing to a PDF file is called
printrow_pdf
; but as an object of this class will always be created
through the parent printpage
object, the programmer should never
need to deal with the printrow_pdf
class.
Copyright © 2000 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
The purpose of this License is to make a manual, textbook, or other written document free in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others.
This License is a kind of “copyleft”, which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software.
We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference.
This License applies to any manual or other work that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. The “Document”, below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as “you”.
A “Modified Version” of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language.
A “Secondary Section” is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document's overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (For example, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them.
The “Invariant Sections” are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License.
The “Cover Texts” are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License.
A “Transparent” copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, whose contents can be viewed and edited directly and straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup has been designed to thwart or discourage subsequent modification by readers is not Transparent. A copy that is not “Transparent” is called “Opaque”.
Examples of suitable formats for Transparent copies include plain ascii without markup, Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, and standard-conforming simple HTML designed for human modification. Opaque formats include PostScript, PDF, proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML produced by some word processors for output purposes only.
The “Title Page” means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, “Title Page” means the text near the most prominent appearance of the work's title, preceding the beginning of the body of the text.
You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3.
You may also lend copies, under the same conditions stated above, and you may publicly display copies.
If you publish printed copies of the Document numbering more than 100, and the Document's license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects.
If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages.
If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a publicly-accessible computer-network location containing a complete Transparent copy of the Document, free of added material, which the general network-using public has access to download anonymously at no charge using public-standard network protocols. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public.
It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document.
You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version:
If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version's license notice. These titles must be distinct from any other section titles.
You may add a section entitled “Endorsements”, provided it contains nothing but endorsements of your Modified Version by various parties—for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard.
You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one.
The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version.
You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice.
The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work.
In the combination, you must combine any sections entitled “History” in the various original documents, forming one section entitled “History”; likewise combine any sections entitled “Acknowledgments”, and any sections entitled “Dedications”. You must delete all sections entitled “Endorsements.”
You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects.
You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document.
A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, does not as a whole count as a Modified Version of the Document, provided no compilation copyright is claimed for the compilation. Such a compilation is called an “aggregate”, and this License does not apply to the other self-contained works thus compiled with the Document, on account of their being thus compiled, if they are not themselves derivative works of the Document.
If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one quarter of the entire aggregate, the Document's Cover Texts may be placed on covers that surround only the Document within the aggregate. Otherwise they must appear on covers around the whole aggregate.
Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License provided that you also include the original English version of this License. In case of a disagreement between the translation and the original English version of this License, the original English version will prevail.
You may not copy, modify, sublicense, or distribute the Document except as expressly provided for under this License. Any other attempt to copy, modify, sublicense or distribute the Document is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See http://www.gnu.org/copyleft/.
Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License “or any later version” applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation.
To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page:
Copyright (C) year your name. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with the Invariant Sections being list their titles, with the Front-Cover Texts being list, and with the Back-Cover Texts being list. A copy of the license is included in the section entitled ``GNU Free Documentation License''.
If you have no Invariant Sections, write “with no Invariant Sections” instead of saying which ones are invariant. If you have no Front-Cover Texts, write “no Front-Cover Texts” instead of “Front-Cover Texts being list”; likewise for Back-Cover Texts.
If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software license, such as the GNU General Public License, to permit their use in free software.
bell
class: The bell Classchange
class: The change Classlibrary
class: The library classlibrary
internals: library internalslibrary::const_iterator
class: The library_base const_iterator classlibrary_base
class: The library_base classlibrary_base::const_iterator
class: The library_base const_iterator classlibrary_entry
class: The library_entry classlibrary_entry
internals: library_entry internalslibrary_entry::impl
class: The library_entry impl classmethod
class: The method Classpermute
function: The permute functionproof
class: Proofrow
class: The row Classrow_block
class: The row_block classxmllib
class: The xmllib class