diff --git a/9781430261933.jpg b/9781430261933.jpg new file mode 100644 index 0000000..e80daee Binary files /dev/null and b/9781430261933.jpg differ diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..327acd0 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,27 @@ +Freeware License, some rights reserved + +Copyright (c) 2013 Ray Lischner + +Permission is hereby granted, free of charge, to anyone obtaining a copy +of this software and associated documentation files (the "Software"), +to work with the Software within the limits of freeware distribution and fair use. +This includes the rights to use, copy, and modify the Software for personal use. +Users are also allowed and encouraged to submit corrections and modifications +to the Software for the benefit of other users. + +It is not allowed to reuse, modify, or redistribute the Software for +commercial use in any way, or for a user’s educational materials such as books +or blog articles without prior permission from the copyright holder. + +The above copyright notice and this permission notice need to be included +in all copies or substantial portions of the software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS OR APRESS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + diff --git a/README.md b/README.md new file mode 100644 index 0000000..99ad302 --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +#Apress Source Code + +This repository accompanies [*Exploring C++ 11*](http://www.apress.com/9781430261933) by Ray Lischner (Apress, 2013). + +![Cover image](9781430261933.jpg) + +Download the files as a zip using the green button, or clone the repository to your machine using Git. + +##Releases + +Release v1.0 corresponds to the code in the published book, without corrections or updates. + +##Contributions + +See the file Contributing.md for more information on how you can contribute to this repository. diff --git a/contributing.md b/contributing.md new file mode 100644 index 0000000..f6005ad --- /dev/null +++ b/contributing.md @@ -0,0 +1,14 @@ +# Contributing to Apress Source Code + +Copyright for Apress source code belongs to the author(s). However, under fair use you are encouraged to fork and contribute minor corrections and updates for the benefit of the author(s) and other readers. + +## How to Contribute + +1. Make sure you have a GitHub account. +2. Fork the repository for the relevant book. +3. Create a new branch on which to make your change, e.g. +`git checkout -b my_code_contribution` +4. Commit your change. Include a commit message describing the correction. Please note that if your commit message is not clear, the correction will not be accepted. +5. Submit a pull request. + +Thank you for your contribution! \ No newline at end of file diff --git a/exploring-cpp-2e/chapter01/list0102.cpp b/exploring-cpp-2e/chapter01/list0102.cpp new file mode 100644 index 0000000..50504a0 --- /dev/null +++ b/exploring-cpp-2e/chapter01/list0102.cpp @@ -0,0 +1,97 @@ +// Listing 1-2. Testing Your Compiler +/// Sort the standard input alphabetically. +/// Read lines of text, sort them, and print the results to the standard output. +/// If the command line names a file, read from that file. Otherwise, read from +/// the standard input. The entire input is stored in memory, so don’t try +/// this with input files that exceed available RAM. +/// +/// Comparison uses a locale named on the command line, or the default, unnamed +/// locale if no locale is named on the command line. + +#include +#include +#include +#include +#include +#include +#include +#include + +template +struct text : std::basic_string +{ + text() : text{""} {} + text(char const* s) : std::basic_string(s) {} + text(text&&) = default; + text(text const&) = default; + text& operator=(text const&) = default; + text& operator=(text&&) = default; +}; + +/// Read lines of text from @p in to @p iter. Lines are appended to @p iter. +/// @param in the input stream +/// @param iter an output iterator +template +auto read(std::basic_istream& in) -> std::vector> +{ + std::vector> result; + text line; + + while (std::getline(in, line)) + result.push_back(line); + + return result; +} + +/// Main program. +int main(int argc, char* argv[]) +try +{ + // Throw an exception if an unrecoverable input error occurs, e.g., + // disk failure. + std::cin.exceptions(std::ios_base::badbit); + + // Part 1. Read the entire input into text. If the command line names a file, + // read that file. Otherwise, read the standard input. + std::vector> text; ///< Store the lines of text here + if (argc < 2) + text = read(std::cin); + else + { + std::ifstream in(argv[1]); + if (not in) + { + std::perror(argv[1]); + return EXIT_FAILURE; + } + text = read(in); + } + + // Part 2. Sort the text. The second command line argument, if present, + // names a locale, to control the sort order. Without a command line + // argument, use the default locale (which is obtained from the OS). + std::locale const& loc{ std::locale(argc >= 3 ? argv[2] : "") }; + std::collate const& collate( std::use_facet>(loc) ); + std::sort(text.begin(), text.end(), + [&collate](std::string const& a, std::string const& b) + { + return collate.compare(a.data(), a.data()+a.size(), + b.data(), b.data()+b.size()) < 0; + } + ); + + // Part 3. Print the sorted text. + for (auto const& line : text) + std::cout << line << '\n'; +} +catch (std::exception& ex) +{ + std::cerr << "Caught exception: " << ex.what() << '\n'; + std::cerr << "Terminating program.\n"; + std::exit(EXIT_FAILURE); +} +catch (...) +{ + std::cerr << "Caught unknown exception type.\nTerminating program.\n"; + std::exit(EXIT_FAILURE); +} diff --git a/exploring-cpp-2e/chapter02/list0201.cpp b/exploring-cpp-2e/chapter02/list0201.cpp new file mode 100644 index 0000000..db856d2 --- /dev/null +++ b/exploring-cpp-2e/chapter02/list0201.cpp @@ -0,0 +1,24 @@ +// Listing 2-1. Reading Test +/// Read the program and determine what the program does. + +#include +#include + +int main() +{ + int min{std::numeric_limits::max()}; + int max{std::numeric_limits::min()}; + bool any{false}; + int x; + while (std::cin >> x) + { + any = true; + if (x < min) + min = x; + if (x > max) + max = x; + } + + if (any) + std::cout << "min = " << min << "\nmax = " << max << '\n'; +} diff --git a/exploring-cpp-2e/chapter02/list0203.cpp b/exploring-cpp-2e/chapter02/list0203.cpp new file mode 100644 index 0000000..bffa841 --- /dev/null +++ b/exploring-cpp-2e/chapter02/list0203.cpp @@ -0,0 +1,9 @@ +// Listing 2-3. Determining the Number of Bits in a bool +#include +#include + +int main() +{ + // Note that "digits" means binary digits, i.e., bits. + std::cout << "bits per bool: " << std::numeric_limits::digits << '\n'; +} diff --git a/exploring-cpp-2e/chapter03/list0301.cpp b/exploring-cpp-2e/chapter03/list0301.cpp new file mode 100644 index 0000000..6c39f24 --- /dev/null +++ b/exploring-cpp-2e/chapter03/list0301.cpp @@ -0,0 +1,18 @@ +// Listing 3-1. Integer Arithmetic +/// Read the program and determine what the program does. + +#include + +int main() +{ + int sum{0}; + int count{}; + int x; + while (std::cin >> x) + { + sum = sum + x; + count = count + 1; + } + + std::cout << "average = " << sum / count << '\n'; +} diff --git a/exploring-cpp-2e/chapter03/list0302.cpp b/exploring-cpp-2e/chapter03/list0302.cpp new file mode 100644 index 0000000..7adc03a --- /dev/null +++ b/exploring-cpp-2e/chapter03/list0302.cpp @@ -0,0 +1,20 @@ +// Listing 3-2. Print Average, Testing for a Zero Count +/// Read integers and print their average. +/// Print nothing if the input is empty. + +#include + +int main() +{ + int sum{0}; + int count{}; + int x; + while (std::cin >> x) + { + sum = sum + x; + count = count + 1; + } + + if (count != 0) + std::cout << "average = " << sum / count << '\n'; +} diff --git a/exploring-cpp-2e/chapter03/list0303.cpp b/exploring-cpp-2e/chapter03/list0303.cpp new file mode 100644 index 0000000..bb7b710 --- /dev/null +++ b/exploring-cpp-2e/chapter03/list0303.cpp @@ -0,0 +1,15 @@ +// Listing 3-3. Testing for Even or Odd Integers +/// Read integers and print a message that tells the user +/// whether the number is even or odd. + +#include + +int main() +{ + int x; + while (std::cin >> x) + if ( ) // Fill in the condition. + std::cout << x << " is odd.\n"; + else + std::cout << x << " is even.\n"; +} diff --git a/exploring-cpp-2e/chapter03/list0304.cpp b/exploring-cpp-2e/chapter03/list0304.cpp new file mode 100644 index 0000000..8ab61f1 --- /dev/null +++ b/exploring-cpp-2e/chapter03/list0304.cpp @@ -0,0 +1,15 @@ +// Listing 3-4. Testing for Even or Odd Integers +/// Read integers and print a message that tells the user +/// whether the number is even or odd. + +#include + +int main() +{ + int x; + while (std::cin >> x) + if ( ) // Fill in the condition. + std::cout << x << " is even.\n"; + else + std::cout << x << " is odd.\n"; +} diff --git a/exploring-cpp-2e/chapter03/list0305.cpp b/exploring-cpp-2e/chapter03/list0305.cpp new file mode 100644 index 0000000..6f6bf8f --- /dev/null +++ b/exploring-cpp-2e/chapter03/list0305.cpp @@ -0,0 +1,22 @@ +// Listing 3-5. Print Average, Testing for a Zero Count +/// Read integers and print their average. +/// Print nothing if the input is empty. + +#include + +int main() +{ + int sum{0}; + int count{}; + int x; + while (std::cin >> x) + { + sum = sum + x; + count = count + 1; + } + + if (count == 0) + std::cout << "No data.\n"; + else + std::cout << "average = " << sum / count << '\n'; +} diff --git a/exploring-cpp-2e/chapter04/list0401.cpp b/exploring-cpp-2e/chapter04/list0401.cpp new file mode 100644 index 0000000..76c5868 --- /dev/null +++ b/exploring-cpp-2e/chapter04/list0401.cpp @@ -0,0 +1,9 @@ +// Listing 4-1. Different Styles of String Output +#include + +int main() +{ + std::cout << "Shape\tSides\n" << "-----\t-----\n"; + std::cout << "Square\t" << 4 << '\n' << + "Circle\t?\n"; +} diff --git a/exploring-cpp-2e/chapter04/list0402.cpp b/exploring-cpp-2e/chapter04/list0402.cpp new file mode 100644 index 0000000..512d110 --- /dev/null +++ b/exploring-cpp-2e/chapter04/list0402.cpp @@ -0,0 +1,7 @@ +// Listing 4-2. Printing a Double-Quote Character +#include + +int main() +{ + std::cout << "\"\n"; +} diff --git a/exploring-cpp-2e/chapter04/list0403.cpp b/exploring-cpp-2e/chapter04/list0403.cpp new file mode 100644 index 0000000..cd2b291 --- /dev/null +++ b/exploring-cpp-2e/chapter04/list0403.cpp @@ -0,0 +1,11 @@ +// Listing 4-3. Adding a Triangle and Keeping the Columns Aligned +#include + +int main() +{ + std::cout << "Shape\t\tSides\n" << + "-----\t\t-----\n"; + std::cout << "Square\t\t" << 4 << '\n' << + "Circle\t\t?\n" + "Triangle\t" << 3 << '\n'; +} diff --git a/exploring-cpp-2e/chapter04/list0404.cpp b/exploring-cpp-2e/chapter04/list0404.cpp new file mode 100644 index 0000000..610a4e9 --- /dev/null +++ b/exploring-cpp-2e/chapter04/list0404.cpp @@ -0,0 +1,15 @@ +// Listing 4-4. Printing Information That Is Stored in Variables +#include +#include + +int main() +{ + std::string shape{"Triangle"}; + int sides{3}; + + std::cout << "Shape\t\tSides\n" << + "-----\t\t-----\n"; + std::cout << "Square\t\t" << 4 << '\n' << + "Circle\t\t?\n"; + std::cout << shape << '\t' << sides << '\n'; +} diff --git a/exploring-cpp-2e/chapter04/list0405.cpp b/exploring-cpp-2e/chapter04/list0405.cpp new file mode 100644 index 0000000..0a5714f --- /dev/null +++ b/exploring-cpp-2e/chapter04/list0405.cpp @@ -0,0 +1,9 @@ +// Listing 4-5. Defining and Printing an Empty String +#include +#include + +int main() +{ + std::string empty; + std::cout << "|" << empty << "|\n"; +} diff --git a/exploring-cpp-2e/chapter04/list0406.cpp b/exploring-cpp-2e/chapter04/list0406.cpp new file mode 100644 index 0000000..d9e4c5f --- /dev/null +++ b/exploring-cpp-2e/chapter04/list0406.cpp @@ -0,0 +1,15 @@ +// Listing 4-6. Demonstrating Uninitialized Variables +#include +#include + +int main() +{ + std::string shape; + int sides; + + std::cout << "Shape\t\tSides\n" << + "-----\t\t-----\n"; + std::cout << "Square\t\t" << 4 << '\n' << + "Circle\t\t?\n"; + std::cout << shape << '\t' << sides << '\n'; +} diff --git a/exploring-cpp-2e/chapter05/list0501.cpp b/exploring-cpp-2e/chapter05/list0501.cpp new file mode 100644 index 0000000..bffaf40 --- /dev/null +++ b/exploring-cpp-2e/chapter05/list0501.cpp @@ -0,0 +1,15 @@ +// Listing 5-1. Demonstrating Input and Output +#include + +int main() +{ + std::cout << "Enter a number: "; + int x; + std::cin >> x; + std::cout << "Enter another number: "; + int y; + std::cin >> y; + + int z{x + y}; + std::cout << "The sum of " << x << " and " << y << " is " << z << "\n"; +} diff --git a/exploring-cpp-2e/chapter05/list0502.cpp b/exploring-cpp-2e/chapter05/list0502.cpp new file mode 100644 index 0000000..0f5b372 --- /dev/null +++ b/exploring-cpp-2e/chapter05/list0502.cpp @@ -0,0 +1,14 @@ +// Listing 5-2. Reading Strings +#include +#include + +int main() +{ + std::cout << "What is your name? "; + std::string name{}; + std::cin >> name; + std::cout << "Hello, " << name << ", how are you? "; + std::string response{}; + std::cin >> response; + std::cout << "Good-bye, " << name << ". I'm glad you feel " << response << "\n"; +} diff --git a/exploring-cpp-2e/chapter05/list0503.cpp b/exploring-cpp-2e/chapter05/list0503.cpp new file mode 100644 index 0000000..30b038a --- /dev/null +++ b/exploring-cpp-2e/chapter05/list0503.cpp @@ -0,0 +1,19 @@ +// Listing 5-3. Getting the User’s Name and Age +#include +#include + +int main() +{ + std::cout << "What is your name? "; + std::string name{}; + std::cin >> name; + + std::cout << "Hello, " << name << ", how old are you? "; + int age{}; + std::cin >> age; + + std::cout << "Good-bye, " << name << ". You are " << age << " year"; + if (age != 1) + std::cout << 's'; + std::cout << " old.\n"; +} diff --git a/exploring-cpp-2e/chapter05/list0504.cpp b/exploring-cpp-2e/chapter05/list0504.cpp new file mode 100644 index 0000000..249a5e7 --- /dev/null +++ b/exploring-cpp-2e/chapter05/list0504.cpp @@ -0,0 +1,19 @@ +// Listing 5-4. Getting the User’s Age and Then Name +#include +#include + +int main() +{ + std::cout << "How old are you? "; + int age{}; + std::cin >> age; + + std::cout << "What is your name? "; + std::string name{}; + std::cin >> name; + + std::cout << "Good-bye, " << name << ". You are " << age << " year"; + if (age != 1) + std::cout << 's'; + std::cout << " old.\n"; +} diff --git a/exploring-cpp-2e/chapter06/list0601.cpp b/exploring-cpp-2e/chapter06/list0601.cpp new file mode 100644 index 0000000..1b6c303 --- /dev/null +++ b/exploring-cpp-2e/chapter06/list0601.cpp @@ -0,0 +1,21 @@ +// Listing 6-1. Deliberate Errors +#include +// Look for errors +int main() +[ + std::cout < "This program prints a table of squares.\n"; + "Enter the starting value for the table: "; + int start{0}; + std::cin >> start; + std::cout << "Enter the ending value for the table: "; + int end(start); + std::cin << endl + std::cout << "# #^2\n"; + int x{start}; + end = end + 1; // exit loop when x reaches end + while (x != end) + { + std:cout << x << " " << x*x << "\n"; + x = x + 1; + } +} diff --git a/exploring-cpp-2e/chapter07/list0701.cpp b/exploring-cpp-2e/chapter07/list0701.cpp new file mode 100644 index 0000000..e6ab3a7 --- /dev/null +++ b/exploring-cpp-2e/chapter07/list0701.cpp @@ -0,0 +1,8 @@ +// Listing 7-1. Using a for Loop to Print Ten Non-Negative Numbers +#include + +int main() +{ + for (int i{0}; i != 10; i = i + 1) + std::cout << i << '\n'; +} diff --git a/exploring-cpp-2e/chapter07/list0702.cpp b/exploring-cpp-2e/chapter07/list0702.cpp new file mode 100644 index 0000000..f7c6a6d --- /dev/null +++ b/exploring-cpp-2e/chapter07/list0702.cpp @@ -0,0 +1,9 @@ +// Listing 7-2. You Cannot Use the Loop Control Variable Outside the Loop +#include + +int main() +{ + for (int i{0}; i != 10; i = i + 1) + std::cout << i << '\n'; + std::cout << "i=" << i << '\n'; // error: i is undefined outside the loop +} diff --git a/exploring-cpp-2e/chapter07/list0703.cpp b/exploring-cpp-2e/chapter07/list0703.cpp new file mode 100644 index 0000000..b9d1c11 --- /dev/null +++ b/exploring-cpp-2e/chapter07/list0703.cpp @@ -0,0 +1,22 @@ +// Listing 7-3. Using and Reusing a Loop Control Variable Name +#include + +int main() +{ + std::cout << '+'; + for (int i{0}; i != 20; i = i + 1) + std::cout << '-'; + std::cout << "+\n|"; + + for (int i{0}; i != 3; i = i + 1) + std::cout << ' '; + std::cout << "Hello, reader!"; + + for (int i{0}; i != 3; i = i + 1) + std::cout << ' '; + std::cout << "|\n+"; + + for (int i{0}; i != 20; i = i + 1) + std::cout << '-'; + std::cout << "+\n"; +} diff --git a/exploring-cpp-2e/chapter07/list0704.cpp b/exploring-cpp-2e/chapter07/list0704.cpp new file mode 100644 index 0000000..df122b4 --- /dev/null +++ b/exploring-cpp-2e/chapter07/list0704.cpp @@ -0,0 +1,11 @@ +// Listing 7-4. Compute Sum of Integers from 10 to 20 +#include + +int main() +{ + int sum{0}; + + // Write the loop here. + + std::cout << "Sum of 10 to 20 = " << sum << '\n'; +} diff --git a/exploring-cpp-2e/chapter07/list0705.cpp b/exploring-cpp-2e/chapter07/list0705.cpp new file mode 100644 index 0000000..ae2fd0d --- /dev/null +++ b/exploring-cpp-2e/chapter07/list0705.cpp @@ -0,0 +1,10 @@ +// Listing 7-5. Compute Sum of Integers from 10 to 20 (Completed) +#include + +int main() +{ + int sum{0}; + for (int i{10}; i != 21; i = i + 1) + sum = sum + i; + std::cout << "Sum of 10 to 20 = " << sum << '\n'; +} diff --git a/exploring-cpp-2e/chapter08/list0801.cpp b/exploring-cpp-2e/chapter08/list0801.cpp new file mode 100644 index 0000000..eb089c3 --- /dev/null +++ b/exploring-cpp-2e/chapter08/list0801.cpp @@ -0,0 +1,12 @@ +// Listing 8-1. Print a Table of Squares and Cubes +#include +#include + +int main() +{ + std::cout << " N N^2 N^3\n"; + for (int i{1}; i != 21; ++i) + { + // write the loop body here + } +} diff --git a/exploring-cpp-2e/chapter08/list0802.cpp b/exploring-cpp-2e/chapter08/list0802.cpp new file mode 100644 index 0000000..e914e4d --- /dev/null +++ b/exploring-cpp-2e/chapter08/list0802.cpp @@ -0,0 +1,13 @@ +// Listing 8-2. Printing a Table of Powers the Right Way +#include +#include + +int main() +{ + std::cout << " N N^2 N^3\n"; + for (int i{1}; i != 21; ++i) + std::cout << std::setw(2) << i + << std::setw(6) << i*i + << std::setw(7) << i*i*i + << '\n'; +} diff --git a/exploring-cpp-2e/chapter08/list0803.cpp b/exploring-cpp-2e/chapter08/list0803.cpp new file mode 100644 index 0000000..f80558e --- /dev/null +++ b/exploring-cpp-2e/chapter08/list0803.cpp @@ -0,0 +1,23 @@ +// Listing 8-3. Using Alternative Fill Characters +#include +#include + +int main() +{ + using namespace std; + + int day{14}; + int month{3}; + int year{2006}; + int dollars{42}; + int cents{7}; + + // Print date in USA order. Later in the book, you will learn how to + // handle internationalization. + cout << "Date: " << setfill('0') << setw(2) << month + << '/' << setw(2) << day + << '/' << setw(2) << year << '\n'; + cout << "Pay to the order of: CASH\n"; + cout << "The amount of $" << setfill('*') << setw(8) << dollars << '.' + << setfill('0') << setw(2) << cents << '\n'; +} diff --git a/exploring-cpp-2e/chapter08/list0804.cpp b/exploring-cpp-2e/chapter08/list0804.cpp new file mode 100644 index 0000000..3a0edf1 --- /dev/null +++ b/exploring-cpp-2e/chapter08/list0804.cpp @@ -0,0 +1,12 @@ +// Listing 8-4. Exploring Field Width, Fill Character, and Alignment +#include +#include + +int main() +{ + using namespace std; + cout << '|' << setfill('*') << setw(6) << 1234 << '|' << '\n'; + cout << '|' << left << setw(6) << 1234 << '|' << '\n'; + cout << '|' << setw(6) << -1234 << '|' << '\n'; + cout << '|' << right << setw(6) << -1234 << '|' << '\n'; +} diff --git a/exploring-cpp-2e/chapter08/list0805.cpp b/exploring-cpp-2e/chapter08/list0805.cpp new file mode 100644 index 0000000..df1aeef --- /dev/null +++ b/exploring-cpp-2e/chapter08/list0805.cpp @@ -0,0 +1,13 @@ +// Listing 8-5. Program to Produce Formatted Output +#include +#include + +int main() +{ + using namespace std; + + cout << setfill('0') << setw(6) << 42 << '\n'; + cout << left << setw(6) << 42 << '\n'; + cout << 42 << '\n'; + cout << setfill('-') << setw(4) << -42 << '\n'; +} diff --git a/exploring-cpp-2e/chapter08/list0806.cpp b/exploring-cpp-2e/chapter08/list0806.cpp new file mode 100644 index 0000000..a58516b --- /dev/null +++ b/exploring-cpp-2e/chapter08/list0806.cpp @@ -0,0 +1,18 @@ +// Listing 8-6. A Copy of Listing 8-5, but Using Member Functions +#include + +int main() +{ + using namespace std; + + cout.fill('0'); + cout.width(6); + cout << 42 << '\n'; + cout.setf(ios_base::left, ios_base::adjustfield); + cout.width(6); + cout << 42 << '\n'; + cout << 42 << '\n'; + cout.fill('-'); + cout.width(4); + cout << -42 << '\n'; +} diff --git a/exploring-cpp-2e/chapter08/list0807.cpp b/exploring-cpp-2e/chapter08/list0807.cpp new file mode 100644 index 0000000..5a2cc02 --- /dev/null +++ b/exploring-cpp-2e/chapter08/list0807.cpp @@ -0,0 +1,42 @@ +// Listing 8-7. Printing a Multiplication Table +#include +#include + +int main() +{ + using namespace std; + + int const low{1}; ///< Minimum value for the table + int const high{10}; ///< Maximum value for the table + int const colwidth{4}; ///< Fixed width for all columns + + // All numbers must be right-aligned. + cout << right; + + // First print the header. + cout << setw(colwidth) << '*' + << '|'; + for (int i{low}; i <= high; i = i + 1) + cout << setw(colwidth) << i; + cout << '\n'; + + // Print the table rule by using the fill character. + cout << setfill('-') + << setw(colwidth) << "" // one column's worth of "-" + << '+' // the vert. & horz. intersection + << setw((high-low+1) * colwidth) << "" // the rest of the line + << '\n'; + + // Reset the fill character. + cout << setfill(' '); + + // For each row... + for (int row{low}; row <= high; row = row + 1) + { + cout << setw(colwidth) << row << '|'; + // Print all the columns. + for (int col{low}; col <= high; col = col + 1) + cout << setw(colwidth) << row * col; + cout << '\n'; + } +} diff --git a/exploring-cpp-2e/chapter09/list0901.cpp b/exploring-cpp-2e/chapter09/list0901.cpp new file mode 100644 index 0000000..e4dc105 --- /dev/null +++ b/exploring-cpp-2e/chapter09/list0901.cpp @@ -0,0 +1,22 @@ +// Listing 9-1. Sorting Integers +#include +#include +#include + +int main() +{ + std::vector data{}; // initialized to be empty + int x{}; + + // Read integers one at a time. + while (std::cin >> x) + // Store each integer in the vector. + data.push_back(x); + + // Sort the vector. + std::sort(data.begin(), data.end()); + + // Print the vector, one number per line. + for (std::vector::size_type i{0}, end{data.size()}; i != end; ++i) + std::cout << data.at(i) << '\n'; +} diff --git a/exploring-cpp-2e/chapter10/list1001.cpp b/exploring-cpp-2e/chapter10/list1001.cpp new file mode 100644 index 0000000..02a2dba --- /dev/null +++ b/exploring-cpp-2e/chapter10/list1001.cpp @@ -0,0 +1,15 @@ +// Listing 10-1. Demonstrating the std::copy Function +#include +#include + +#include + +int main() +{ + std::vector input{ 10, 20, 30 }; + std::vector output{}; + output.resize(input.size()); + std::copy(input.begin(), input.end(), output.begin()); + // Now output has a complete copy of input. + assert(input == output); +} diff --git a/exploring-cpp-2e/chapter10/list1002.cpp b/exploring-cpp-2e/chapter10/list1002.cpp new file mode 100644 index 0000000..357f1ed --- /dev/null +++ b/exploring-cpp-2e/chapter10/list1002.cpp @@ -0,0 +1,22 @@ +// Listing 10-2. Sorting Integers by Using Iterators to Print the Results +#include +#include +#include + +int main() +{ + std::vector data{}; // initialized to be empty + int x{}; + + // Read integers one at a time. + while (std::cin >> x) + // Store each integer in the vector. + data.push_back(x); + + // Sort the vector. + std::sort(data.begin(), data.end()); + + // Print the vector, one number per line. + for (std::vector::iterator i{data.begin()}, end{data.end()}; i != end; ++i) + std::cout << *i << '\n'; +} diff --git a/exploring-cpp-2e/chapter10/list1003.cpp b/exploring-cpp-2e/chapter10/list1003.cpp new file mode 100644 index 0000000..09c8922 --- /dev/null +++ b/exploring-cpp-2e/chapter10/list1003.cpp @@ -0,0 +1,22 @@ +// Listing 10-3. Sorting Integers by Using Only Generic Algorithms and Iterator Adapters +#include +#include +#include +#include + +int main() +{ + std::vector data{}; + + // Read integers one at a time. + std::copy(std::istream_iterator(std::cin), + std::istream_iterator(), + std::back_inserter(data)); + + // Sort the vector. + std::sort(data.begin(), data.end()); + + // Print the vector, one number per line. + std::copy(data.begin(), data.end(), + std::ostream_iterator(std::cout, "\n")); +} diff --git a/exploring-cpp-2e/chapter10/list1004.cpp b/exploring-cpp-2e/chapter10/list1004.cpp new file mode 100644 index 0000000..ffbd712 --- /dev/null +++ b/exploring-cpp-2e/chapter10/list1004.cpp @@ -0,0 +1,18 @@ +// Listing 10-4. Doubling and Squaring Input Values in a Vector by Using Iterators +#include +#include +#include + +int main() +{ + std::vector data{}; + int x{}; + + while (std::cin >> x) + data.push_back(x); + + for (std::vector::iterator i{data.begin()}, end{data.end()}; i != end; ++i) + std::cout << std::setw(2) << *i << + std::setw(3) << *i* 2 << + std::setw(4) << *i * *i << '\n'; +} diff --git a/exploring-cpp-2e/chapter10/list1005.cpp b/exploring-cpp-2e/chapter10/list1005.cpp new file mode 100644 index 0000000..634d5b2 --- /dev/null +++ b/exploring-cpp-2e/chapter10/list1005.cpp @@ -0,0 +1,19 @@ +// Listing 10-5. Doubling and Squaring Input Values in a Vector by Using a Range-Based Loop +#include +#include +#include + +int main() +{ + std::vector data{}; + int x{}; + + while (std::cin >> x) + data.push_back(x); + + std::cout.fill(' '); + for (int element : data) + std::cout << std::setw(2) << element << + std::setw(3) << element * 2 << + std::setw(4) << element * element << '\n'; +} diff --git a/exploring-cpp-2e/chapter11/list1101.cpp b/exploring-cpp-2e/chapter11/list1101.cpp new file mode 100644 index 0000000..ac4c55f --- /dev/null +++ b/exploring-cpp-2e/chapter11/list1101.cpp @@ -0,0 +1,13 @@ +// Listing 11-1. Demonstrating the Difference Between Prefix and Postfix Increment +#include + +int main() +{ + int x{42}; + + std::cout << "x = " << x << "\n"; + std::cout << "++x = " << ++x << "\n"; + std::cout << "x = " << x << "\n"; + std::cout << "x++ = " << x++ << "\n"; + std::cout << "x = " << x << "\n"; +} diff --git a/exploring-cpp-2e/chapter11/list1102.cpp b/exploring-cpp-2e/chapter11/list1102.cpp new file mode 100644 index 0000000..60505ef --- /dev/null +++ b/exploring-cpp-2e/chapter11/list1102.cpp @@ -0,0 +1,13 @@ +// Listing 11-2. Erroneous Program That Applies Decrement to an Output Iterator +#include +#include +#include + +int main() +{ + std::vector data{ 10, 42 }; + std::ostream_iterator out{ std::ostream_iterator(std::cout, "") }; + std::copy(data.begin(), data.end(), out); + --out; + +} diff --git a/exploring-cpp-2e/chapter11/list1103.cpp b/exploring-cpp-2e/chapter11/list1103.cpp new file mode 100644 index 0000000..c011cac --- /dev/null +++ b/exploring-cpp-2e/chapter11/list1103.cpp @@ -0,0 +1,27 @@ +// Listing 11-3. Reversing the Input Order +#include +#include +#include +#include + +int main() +{ + std::vector data{}; + int x{}; + while (std::cin >> x) + data.push_back(x); + + for (std::vector::iterator start{data.begin()}, end{data.end()}; + start != end; + /*empty*/) + { + --end; + if (start != end) + { + std::iter_swap(start, end); + ++start; + } + } + + std::copy(data.begin(), data.end(), std::ostream_iterator(std::cout, "\n")); +} diff --git a/exploring-cpp-2e/chapter11/list1104.cpp b/exploring-cpp-2e/chapter11/list1104.cpp new file mode 100644 index 0000000..84cb621 --- /dev/null +++ b/exploring-cpp-2e/chapter11/list1104.cpp @@ -0,0 +1,22 @@ +// Listing 11-4. Rewriting the for Loop +#include +#include +#include +#include + +int main() +{ + std::vector data{}; + int x{}; + while (std::cin >> x) + data.push_back(x); + + for (std::vector::iterator start{data.begin()}, end{data.end()}; + start != end and start != --end; + ++start) + { + std::iter_swap(start, end); + } + + std::copy(data.begin(), data.end(), std::ostream_iterator(std::cout, "\n")); +} diff --git a/exploring-cpp-2e/chapter11/list1105.cpp b/exploring-cpp-2e/chapter11/list1105.cpp new file mode 100644 index 0000000..8d82ad7 --- /dev/null +++ b/exploring-cpp-2e/chapter11/list1105.cpp @@ -0,0 +1,20 @@ +// Listing 11-5. Taking Advantage of the Standard Library +#include +#include +#include +#include + +int main() +{ + std::vector data{}; + + // Read integers from the standard input, and append them to the end of data. + data.insert(data.end(), + std::istream_iterator(std::cin), std::istream_iterator()); + + // Reverse the order of the contents of data. + std::reverse(data.begin(), data.end()); + + // Print data, one number per line. + std::copy(data.begin(), data.end(), std::ostream_iterator(std::cout, "\n")); +} diff --git a/exploring-cpp-2e/chapter12/list1201.cpp b/exploring-cpp-2e/chapter12/list1201.cpp new file mode 100644 index 0000000..a8e44bd --- /dev/null +++ b/exploring-cpp-2e/chapter12/list1201.cpp @@ -0,0 +1,11 @@ +// Listing 12-1. Printing bool Values +#include + +int main() +{ + std::cout << "true=" << true << '\n'; + std::cout << "false=" << false << '\n'; + std::cout << std::boolalpha; + std::cout << "true=" << true << '\n'; + std::cout << "false=" << false << '\n'; +} diff --git a/exploring-cpp-2e/chapter12/list1202.cpp b/exploring-cpp-2e/chapter12/list1202.cpp new file mode 100644 index 0000000..f230c99 --- /dev/null +++ b/exploring-cpp-2e/chapter12/list1202.cpp @@ -0,0 +1,22 @@ +// Listing 12-2. Automatic Type Conversion to bool +#include + +int main() +{ + if (true) std::cout << "true\n"; + if (false) std::cout << "false\n"; + if (42) std::cout << "42\n"; + if (0) std::cout << "0\n"; + if (42.4242) std::cout << "42.4242\n"; + if (0.0) std::cout << "0.0\n"; + if (-0.0) std::cout << "-0.0\n"; + if (-1) std::cout << "-1\n"; + if ('\0') std::cout << "'\\0'\n"; + if ('\1') std::cout << "'\\1'\n"; + if ("1") std::cout << "\"1\"\n"; + if ("false") std::cout << "\"false\"\n"; + if (std::cout) std::cout << "std::cout\n"; + if (std::cin) std::cout << "std::cin\n"; + + +} diff --git a/exploring-cpp-2e/chapter12/list1203.cpp b/exploring-cpp-2e/chapter12/list1203.cpp new file mode 100644 index 0000000..09f6c49 --- /dev/null +++ b/exploring-cpp-2e/chapter12/list1203.cpp @@ -0,0 +1,14 @@ +// Listing 12-3. Converting a std::string to bool +#include +#include + +int main() +{ + std::string empty{}; + + if (empty) + std::cout << "empty is true\n"; + else + std::cout << "empty is false\n"; + +} diff --git a/exploring-cpp-2e/chapter12/list1204.cpp b/exploring-cpp-2e/chapter12/list1204.cpp new file mode 100644 index 0000000..df05f95 --- /dev/null +++ b/exploring-cpp-2e/chapter12/list1204.cpp @@ -0,0 +1,20 @@ +// Listing 12-4. Using Short-Circuiting to Test for Nonzero Vector Elements +#include +#include +#include + +int main() +{ + std::vector data{}; + data.insert(data.begin(), + std::istream_iterator(std::cin), + std::istream_iterator()); + + std::vector::iterator iter{}, end{data.end()}; + for (iter = data.begin(); iter != end and *iter == 0; ++iter) + /*empty*/; + if (iter == data.end()) + std::cout << "data contains all zeroes\n"; + else + std::cout << "data does not contain all zeroes\n"; +} diff --git a/exploring-cpp-2e/chapter12/list1205.cpp b/exploring-cpp-2e/chapter12/list1205.cpp new file mode 100644 index 0000000..45be869 --- /dev/null +++ b/exploring-cpp-2e/chapter12/list1205.cpp @@ -0,0 +1,31 @@ +// Listing 12-5. Comparing Vectors +#include +#include + +int main() +{ + std::vector a{ 10, 20, 30 }, b{ 10, 20, 30 }; + + if (a != b) std::cout << "wrong: a != b\n"; + if (a < b) std::cout << "wrong: a < b\n"; + if (a > b) std::cout << "wrong: a > b\n"; + if (a == b) std::cout << "okay: a == b\n"; + if (a >= b) std::cout << "okay: a >= b\n"; + if (a <= b) std::cout << "okay: a <= b\n"; + + a.push_back(40); + if (a != b) std::cout << "okay: a != b\n"; + if (a < b) std::cout << "wrong: a < b\n"; + if (a > b) std::cout << "okay: a > b\n"; + if (a == b) std::cout << "wrong: a == b\n"; + if (a >= b) std::cout << "okay: a >= b\n"; + if (a <= b) std::cout << "wrong: a <= b\n"; + + b.push_back(42); + if (a != b) std::cout << "okay: a != b\n"; + if (a < b) std::cout << "okay: a < b\n"; + if (a > b) std::cout << "wrong: a > b\n"; + if (a == b) std::cout << "wrong: a == b\n"; + if (a >= b) std::cout << "wrong: a >= b\n"; + if (a <= b) std::cout << "okay: a <= b\n"; +} diff --git a/exploring-cpp-2e/chapter12/list1206.cpp b/exploring-cpp-2e/chapter12/list1206.cpp new file mode 100644 index 0000000..77fe35d --- /dev/null +++ b/exploring-cpp-2e/chapter12/list1206.cpp @@ -0,0 +1,30 @@ +// Listing 12-6. Demonstrating How C++ Compares Strings +#include +#include + +int main() +{ + std::string a{"abc"}, b{"abc"}; + if (a != b) std::cout << "wrong: abc != abc\n"; + if (a < b) std::cout << "wrong: abc < abc\n"; + if (a > b) std::cout << "wrong: abc > abc\n"; + if (a == b) std::cout << "okay: abc == abc\n"; + if (a >= b) std::cout << "okay: abc >= abc\n"; + if (a <= b) std::cout << "okay: abc <= abc\n"; + + a.push_back('d'); + if (a != b) std::cout << "okay: abcd != abc\n"; + if (a < b) std::cout << "wrong: abcd < abc\n"; + if (a > b) std::cout << "okay: abcd > abc\n"; + if (a == b) std::cout << "wrong: abcd == abc\n"; + if (a >= b) std::cout << "okay: abcd >= abc\n"; + if (a <= b) std::cout << "wrong: abcd <= abc\n"; + + b.push_back('e'); + if (a != b) std::cout << "okay: abcd != abce\n"; + if (a < b) std::cout << "okay: abcd < abce\n"; + if (a > b) std::cout << "wrong: abcd > abce\n"; + if (a == b) std::cout << "wrong: abcd == abce\n"; + if (a >= b) std::cout << "wrong: abcd >= abce\n"; + if (a <= b) std::cout << "okay: abcd <= abce\n"; +} diff --git a/exploring-cpp-2e/chapter13/list1301.cpp b/exploring-cpp-2e/chapter13/list1301.cpp new file mode 100644 index 0000000..69ff1d5 --- /dev/null +++ b/exploring-cpp-2e/chapter13/list1301.cpp @@ -0,0 +1,19 @@ +// Listing 13-1. Finding Statement Errors +#include +#include +// find errors in this program +int main() +{ + std::vector positive_data{}, negative_data{}; + + for (int x{0}; std::cin >> x ;) { + if (x < 0); + { + negative_data.push_back(x) + }; + else + { + positive_data.push_back(x) + } + }; +} diff --git a/exploring-cpp-2e/chapter13/list1302.cpp b/exploring-cpp-2e/chapter13/list1302.cpp new file mode 100644 index 0000000..e09ddcb --- /dev/null +++ b/exploring-cpp-2e/chapter13/list1302.cpp @@ -0,0 +1,65 @@ +// Listing 13-2. Local Variable Definitions +#include +#include +#include +#include +#include +#include + +int main() +{ + std::vector data{}; + data.insert(data.begin(), std::istream_iterator(std::cin), + std::istream_iterator()); + + // Silly way to sort a vector. Assume that the initial portion + // of the vector has already been sorted, up to the iterator iter. + // Find where *iter belongs in the already sorted portion of the vector. + // Erase *iter from the vector and re-insert it at its sorted position. + // Use binary search to speed up the search for the proper position. + // Invariant: elements in range [begin(), iter are already sorted. + for (std::vector::iterator iter{data.begin()}, end{data.end()}; iter != end; ) + { + // Find where *iter belongs by calling the standard algorithm + // lower_bound, which performs a binary search and returns an iterator + // that points into data at a position where the value should be inserted. + int value{*iter}; + std::vector::iterator here{std::lower_bound(data.begin(), iter, value)}; + if (iter == here) + ++iter; // already in sorted position + else + { + + // erase the out-of-position item, advancing iter at the same time. + + iter = data.erase(iter); + // re-insert the value at the correct position. + + data.insert(here, value); + + } + } + + // Debugging code: check that the vector is actually sorted. Do this by comparing + // each element with the preceding element in the vector. + for (std::vector::iterator iter{data.begin()}, prev{data.end()}, end{data.end()}; + iter != end; + ++iter) + { + if (prev != data.end()) + assert(not (*iter < *prev)); + prev = iter; + } + + // Print the sorted vector all on one line. Start the line with "{" and + // end it with "}". Separate elements with commas. + // An empty vector prints as "{ }". + std::cout << '{'; + std::string separator{" "}; + for (int element : data) + { + std::cout << separator << element; + separator = ", "; + } + std::cout << " }\n"; +} diff --git a/exploring-cpp-2e/chapter13/list1303.cpp b/exploring-cpp-2e/chapter13/list1303.cpp new file mode 100644 index 0000000..eaf9c2f --- /dev/null +++ b/exploring-cpp-2e/chapter13/list1303.cpp @@ -0,0 +1,31 @@ +// Listing 13-3. Local Variable Definitions in a Nested Block +#include +#include +#include +#include +#include +#include + +int main() +{ + std::vector data{}; + data.insert(data.begin(), std::istream_iterator(std::cin), + std::istream_iterator()); + + std::sort(data.begin(), data.end()); + + { + // Print the sorted vector all on one line. Start the line with "{" and + // end it with "}". Separate elements with commas. An empty vector prints + // as "{ }". + std::cout << '{'; + std::string separator{" "}; + for (int element : data) + { + std::cout << separator << element; + separator = ", "; + } + std::cout << " }\n"; + } + // Cannot use separator out here. +} diff --git a/exploring-cpp-2e/chapter13/list1304.cpp b/exploring-cpp-2e/chapter13/list1304.cpp new file mode 100644 index 0000000..257eff6 --- /dev/null +++ b/exploring-cpp-2e/chapter13/list1304.cpp @@ -0,0 +1,44 @@ +// Listing 13-4. Mystery Function +#include +#include +#include +#include +#include +#include + +int main() +{ + int v{}; + std::vector data{}; + std::vector::iterator i{}, p{}; + std::string s{}; + + std::copy(std::istream_iterator(std::cin), + std::istream_iterator(), + std::back_inserter(data)); + i = data.begin(); + + while (i != data.end()) + { + v = *i; + p = std::lower_bound(data.begin(), i, v); + i = data.erase(i); + data.insert(p, v); + } + + s = " "; + for (p = i, i = data.begin(); i != data.end(); p = i, ++i) + { + if (p != data.end()) + assert(not (*i < *p)); + } + + std::cout << '{'; + for (i = data.begin(); i != data.end(); ++i) + { + v = *p; + std::cout << s << v; + s = ", "; + } + std::cout << " }\n"; +} diff --git a/exploring-cpp-2e/chapter14/list1401.cpp b/exploring-cpp-2e/chapter14/list1401.cpp new file mode 100644 index 0000000..e1193be --- /dev/null +++ b/exploring-cpp-2e/chapter14/list1401.cpp @@ -0,0 +1,19 @@ +// Listing 14-1. Copying Integers from a File to Standard Output +#include +#include +#include + +int main() +{ + std::ifstream in{"list1401.txt"}; + if (not in) + std::perror("list1401.txt"); + else + { + int x{}; + while (in >> x) + std::cout << x << '\n'; + in.close(); + + } +} diff --git a/exploring-cpp-2e/chapter14/list1401.txt b/exploring-cpp-2e/chapter14/list1401.txt new file mode 100644 index 0000000..fc63eda --- /dev/null +++ b/exploring-cpp-2e/chapter14/list1401.txt @@ -0,0 +1,7 @@ +1 +2 +3 +4 +5 6 7 8 9 + +10 diff --git a/exploring-cpp-2e/chapter14/list1402.cpp b/exploring-cpp-2e/chapter14/list1402.cpp new file mode 100644 index 0000000..20f7359 --- /dev/null +++ b/exploring-cpp-2e/chapter14/list1402.cpp @@ -0,0 +1,25 @@ +// Listing 14-2. Copying Integers from a Named File to a Named File +#include +#include +#include + +int main() +{ + std::ifstream in{"list1402.in"}; + if (not in) + std::perror("list1402.in"); + else + { + std::ofstream out{"list1402.out"}; + if (not out) + std::perror("list1402.out"); + else + { + int x{}; + while (in >> x) + out << x << '\n'; + out.close(); + in.close(); + } + } +} diff --git a/exploring-cpp-2e/chapter14/list1402.in b/exploring-cpp-2e/chapter14/list1402.in new file mode 100644 index 0000000..fc63eda --- /dev/null +++ b/exploring-cpp-2e/chapter14/list1402.in @@ -0,0 +1,7 @@ +1 +2 +3 +4 +5 6 7 8 9 + +10 diff --git a/exploring-cpp-2e/chapter14/list1403.cpp b/exploring-cpp-2e/chapter14/list1403.cpp new file mode 100644 index 0000000..16166a5 --- /dev/null +++ b/exploring-cpp-2e/chapter14/list1403.cpp @@ -0,0 +1,26 @@ +// Listing 14-3. Copying Integers, with Minimal Error-Checking +#include +#include +#include + +int main() +{ + std::ifstream in{"list1402.in"}; + if (not in) + std::perror("list1402.in"); + else + { + std::ofstream out{"list1402.out"}; + if (not out) + std::perror("list1402.out"); + else + { + int x{}; + while (in >> x) + out << x << '\n'; + out.close(); + if (not out) + std::perror("list1402.out"); + } + } +} diff --git a/exploring-cpp-2e/chapter15/explore15.txt b/exploring-cpp-2e/chapter15/explore15.txt new file mode 100644 index 0000000..84e08b3 --- /dev/null +++ b/exploring-cpp-2e/chapter15/explore15.txt @@ -0,0 +1,18 @@ +The Map Data Structure + +Now that you understand the basics, it’s time to move on to more exciting +challenges. Let’s write a real program—something nontrivial but still simple +enough to master this early in the book. Your task is to write a program that +reads words and counts the frequency of each unique word. For the sake of +simplicity, a word is a string of non-space characters separated by white +space. Be aware, however, that by this definition, words end up including +punctuation characters, but we’ll worry about fixing that problem later. + +This is a complicated program, touching on everything you’ve learned about C++ +so far. If you want to exercise your new understanding of file I/O, read from +a named file. If you prefer the simplicity, read from the standard +input. Before jumping in and trying to write a program, take a moment to think +about the problem and the tools you need to solve it. Write pseudo-code for +the program. Try to write C++ code where you can, and make up whatever else +you need to tackle the problem. Keep it simple—and don’t dwell on trying to +get syntax details correct. diff --git a/exploring-cpp-2e/chapter15/list1501.cpp b/exploring-cpp-2e/chapter15/list1501.cpp new file mode 100644 index 0000000..93219d8 --- /dev/null +++ b/exploring-cpp-2e/chapter15/list1501.cpp @@ -0,0 +1,13 @@ +// Listing 15-1. Counting Occurrences of Unique Words +#include +#include +#include + +int main() +{ + std::map counts{}; + std::string word{}; + while (std::cin >> word) + ++counts[word]; + // TODO: Print the results. +} diff --git a/exploring-cpp-2e/chapter15/list1502.cpp b/exploring-cpp-2e/chapter15/list1502.cpp new file mode 100644 index 0000000..bfaf49b --- /dev/null +++ b/exploring-cpp-2e/chapter15/list1502.cpp @@ -0,0 +1,20 @@ +// Listing 15-2. Printing Word Frequencies +#include +#include +#include + +int main() +{ + std::map counts{}; + + // Read words from the standard input and count the number of times + // each word occurs. + std::string word{}; + while (std::cin >> word) + ++counts[word]; + + // For each word/count pair... + for (auto element : counts) + // Print the word, tab, the count, newline. + std::cout << element.first << '\t' << element.second << '\n'; +} diff --git a/exploring-cpp-2e/chapter15/list1503.cpp b/exploring-cpp-2e/chapter15/list1503.cpp new file mode 100644 index 0000000..bce6c60 --- /dev/null +++ b/exploring-cpp-2e/chapter15/list1503.cpp @@ -0,0 +1,29 @@ +// Listing 15-3. Aligning Words and Counts Neatly +#include +#include +#include +#include + +int main() +{ + std::map counts{}; + + // Read words from the standard input and count the number of times + // each word occurs. + std::string word{}; + while (std::cin >> word) + ++counts[word]; + + // Determine the longest word. + std::string::size_type longest{}; + for (auto element : counts) + if (element.first.size() > longest) + longest = element.first.size(); + + // For each word/count pair... + const int count_size{10}; // Number of places for printing the count + for (auto element : counts) + // Print the word, count, newline. Keep the columns neatly aligned. + std::cout << std::setw(longest) << std::left << element.first << + std::setw(count_size) << std::right << element.second << '\n'; +} diff --git a/exploring-cpp-2e/chapter15/list1504.cpp b/exploring-cpp-2e/chapter15/list1504.cpp new file mode 100644 index 0000000..b98eb27 --- /dev/null +++ b/exploring-cpp-2e/chapter15/list1504.cpp @@ -0,0 +1,25 @@ +// Listing 15-4. Searching for a Word in a Map +#include +#include +#include +#include + +int main() +{ + std::map counts{}; + + // Read words from the standard input and count the number of times + // each word occurs. + std::string word{}; + while (std::cin >> word) + ++counts[word]; + + std::map::iterator the{counts.find("the")}; + if (the == counts.end()) + std::cout << "\"the\": not found\n"; + else if (the->second == 1) + std::cout << "\"the\": occurs " << the->second << " time\n"; + else + std::cout << "\"the\": occurs " << the->second << " times\n"; +} + diff --git a/exploring-cpp-2e/chapter16/list1601.cpp b/exploring-cpp-2e/chapter16/list1601.cpp new file mode 100644 index 0000000..f9ee696 --- /dev/null +++ b/exploring-cpp-2e/chapter16/list1601.cpp @@ -0,0 +1,28 @@ +// Listing 16-1. Counting Words, with a Clean Program That Uses typedef +#include +#include +#include +#include + +int main() +{ + std::map counts{}; + typedef std::map count_map; + typedef count_map::iterator count_iterator; + + + // Read words from the standard input and count the number of times + // each word occurs. + std::string word{}; + while (std::cin >> word) + ++counts[word]; + + count_iterator the{counts.find("the")}; + + if (the == counts.end()) + std::cout << "\"the\": not found\n"; + else if (the->second == 1) + std::cout << "\"the\": occurs " << the->second << " time\n"; + else + std::cout << "\"the\": occurs " << the->second << " times\n"; +} diff --git a/exploring-cpp-2e/chapter17/list1701.cpp b/exploring-cpp-2e/chapter17/list1701.cpp new file mode 100644 index 0000000..8893a1b --- /dev/null +++ b/exploring-cpp-2e/chapter17/list1701.cpp @@ -0,0 +1,37 @@ +// Listing 17-1. Working and Playing with Characters +#include + +int main() +{ + int value{}; + bool have_value{false}; + char ch{}; + + while (std::cin.get(ch)) + { + if (ch >= '0' and ch <= '9') + { + value = ch - '0'; + have_value = true; + while (std::cin.get(ch) and ch >= '0' and ch <= '9') + value = value * 10 + ch - '0'; + + } + if (ch == '\n') + { + if (have_value) + { + std::cout << value << '\n'; + have_value = false; + } + } + else if (ch != ' ' and ch != '\t') + { + std::cout << '\a'; + have_value = false; + + while (std::cin.get(ch) and ch != '\n') + /*empty*/; + } + } +} diff --git a/exploring-cpp-2e/chapter17/list1702.cpp b/exploring-cpp-2e/chapter17/list1702.cpp new file mode 100644 index 0000000..63b292d --- /dev/null +++ b/exploring-cpp-2e/chapter17/list1702.cpp @@ -0,0 +1,10 @@ +// Listing 17-2. Echoing Input to Output, One Character at a Time +#include + +int main() +{ + std::cin >> std::noskipws; + char ch; + while (std::cin >> ch) + std::cout << ch; +} diff --git a/exploring-cpp-2e/chapter17/list1703.cpp b/exploring-cpp-2e/chapter17/list1703.cpp new file mode 100644 index 0000000..4d8c348 --- /dev/null +++ b/exploring-cpp-2e/chapter17/list1703.cpp @@ -0,0 +1,28 @@ +// Listing 17-3. Finding the Points with the Largest x and y Values +#include +#include +#include +#include + +int main() +{ + typedef std::vector intvec; + typedef intvec::iterator iterator; + + intvec xs, ys; // store the xs and ys + + { // local block to keep I/O variables local + int x{}, y{}; // variables for I/O + char sep{}; + // Loop while the input stream has an integer (x), a character (sep), + // and another integer (y); then test that the separator is a comma. + while (std::cin >> x >> sep and sep == ',' and std::cin >> y) + { + xs.push_back(x); + ys.push_back(y); + } + } + + for (iterator x{xs.begin()}, y{ys.begin()}; x != xs.end(); ++x, ++y) + std::cout << *x << ',' << *y << '\n'; +} diff --git a/exploring-cpp-2e/chapter18/list1801.cpp b/exploring-cpp-2e/chapter18/list1801.cpp new file mode 100644 index 0000000..8824cfa --- /dev/null +++ b/exploring-cpp-2e/chapter18/list1801.cpp @@ -0,0 +1,45 @@ +// Listing 18-1. Counting Words: Restricting Words to Letters and Letter-Like Characters +#include +#include +#include +#include + +int main() +{ + typedef std::map count_map; + typedef std::string::size_type str_size; + + count_map counts{}; + + // Read words from the standard input and count the number of times + // each word occurs. + std::string okay{"ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789-_"}; + std::string word{}; + while (std::cin >> word) + { + // Make a copy of word, keeping only the characters that appear in okay. + std::string copy{}; + for (char ch : word) + if (okay.find(ch) != std::string::npos) + copy.push_back(ch); + // The "word" might be all punctuation, so the copy would be empty. + // Don't count empty strings. + if (not copy.empty()) + ++counts[copy]; + } + + // Determine the longest word. + str_size longest{0}; + for (auto pair : counts) + if (pair.first.size() > longest) + longest = pair.first.size(); + + // For each word/count pair... + const int count_size{10}; // Number of places for printing the count + for (auto pair : counts) + // Print the word, count, newline. Keep the columns neatly aligned. + std::cout << std::setw(longest) << std::left << pair.first << + std::setw(count_size) << std::right << pair.second << '\n'; +} diff --git a/exploring-cpp-2e/chapter18/list1802.cpp b/exploring-cpp-2e/chapter18/list1802.cpp new file mode 100644 index 0000000..0beb2cd --- /dev/null +++ b/exploring-cpp-2e/chapter18/list1802.cpp @@ -0,0 +1,32 @@ +// Listing 18-2. Testing a Character by Calling std::isalnum +#include +#include +#include +#include + +int main() +{ + typedef std::map count_map; + + count_map counts{}; + + // Read words from the standard input and count the number of times + // each word occurs. + std::string word{}; + while (std::cin >> word) + { + // Make a copy of word, keeping only alphabetic characters. + std::string copy{}; + for (char ch : word) + if (std::isalnum(ch, std::locale{""})) + copy.push_back(ch); + // The "word" might be all punctuation, so the copy would be empty. + // Don't count empty strings. + if (not copy.empty()) + ++counts[copy]; + } + + // For each word/count pair, print the word & count on one line. + for (auto pair : counts) + std::cout << pair.first << '\t' << pair.second << '\n'; +} diff --git a/exploring-cpp-2e/chapter18/list1803.cpp b/exploring-cpp-2e/chapter18/list1803.cpp new file mode 100644 index 0000000..36338b1 --- /dev/null +++ b/exploring-cpp-2e/chapter18/list1803.cpp @@ -0,0 +1,14 @@ +// Listing 18-3. Using the Native Locale for Output +#include +#include + +int main() +{ + std::cout.imbue(std::locale{""}); + + int sum{0}; + int x{}; + while (std::cin >> x) + sum = sum + x; + std::cout << "sum = " << sum << '\n'; +} diff --git a/exploring-cpp-2e/chapter18/list1804.cpp b/exploring-cpp-2e/chapter18/list1804.cpp new file mode 100644 index 0000000..7c2f9a4 --- /dev/null +++ b/exploring-cpp-2e/chapter18/list1804.cpp @@ -0,0 +1,36 @@ +// Listing18-4. Creating and Sharing a Single Locale Object +#include +#include +#include +#include + +int main() +{ + typedef std::map count_map; + + std::locale native{""}; // get the native locale + std::cin.imbue(native); // interpret the input and output according to + std::cout.imbue(native); // the native locale + + count_map counts{}; + + // Read words from the standard input and count the number of times + // each word occurs. + std::string word{}; + while (std::cin >> word) + { + // Make a copy of word, keeping only alphabetic characters. + std::string copy{}; + for (char ch : word) + if (std::isalnum(ch, native)) + copy.push_back(ch); + // The "word" might be all punctuation, so the copy would be empty. + // Don't count empty strings. + if (not copy.empty()) + ++counts[copy]; + } + + // For each word/count pair, print the word & count on one line. + for (auto pair : counts) + std::cout << pair.first << '\t' << pair.second << '\n'; +} diff --git a/exploring-cpp-2e/chapter19/list1901.cpp b/exploring-cpp-2e/chapter19/list1901.cpp new file mode 100644 index 0000000..69fdee0 --- /dev/null +++ b/exploring-cpp-2e/chapter19/list1901.cpp @@ -0,0 +1,36 @@ +// Listing 19-1. Folding Uppercase to Lowercase Prior to Counting Words +#include +#include +#include +#include + +int main() +{ + typedef std::map count_map; + + std::locale native{""}; // get the native locale + std::cin.imbue(native); // interpret the input and output according to + std::cout.imbue(native); // the native locale + + count_map counts{}; + + // Read words from the standard input and count the number of times + // each word occurs. + std::string word{}; + while (std::cin >> word) + { + // Make a copy of word, keeping only alphabetic characters. + std::string copy{}; + for (char ch : word) + if (std::isalnum(ch, native)) + copy.push_back(tolower(ch, native)); + // The "word" might be all punctuation, so the copy would be empty. + // Don't count empty strings. + if (not copy.empty()) + ++counts[copy]; + } + + // For each word/count pair, print the word & count on one line. + for (auto pair : counts) + std::cout << pair.first << '\t' << pair.second << '\n'; +} diff --git a/exploring-cpp-2e/chapter20/list2001.cpp b/exploring-cpp-2e/chapter20/list2001.cpp new file mode 100644 index 0000000..62e61dc --- /dev/null +++ b/exploring-cpp-2e/chapter20/list2001.cpp @@ -0,0 +1,62 @@ +// Listing 20-1. Examples of Functions +#include +#include + +/** Ignore the rest of the input line. */ +void ignore_line() +{ + char c{}; + while (std::cin.get(c) and c != '\n') + + /*empty*/; +} + +/** Prompt the user, then read a number, and ignore the rest of the line. + * @param prompt the prompt string + * @return the input number or 0 for end-of-file + */ +int prompted_read(std::string prompt) +{ + std::cout << prompt; + int x{0}; + std::cin >> x; + ignore_line(); + return x; +} + +/** Print the statistics. + * @param count the number of values + * @param sum the sum of the values + */ +void print_result(int count, int sum) +{ + if (count == 0) + { + std::cout << "no data\n"; + return; + } + + std::cout << "\ncount = " << count; + std::cout << "\nsum = " << sum; + std::cout << "\nmean = " << sum/count << '\n'; +} + +/** Main program. + * Read integers from the standard input and print statistics about them. + */ +int main() +{ + int sum{0}; + int count{0}; + + while (std::cin) + { + int x{ prompted_read("Value: ") }; + if (std::cin) + { + sum = sum + x; + ++count; + } + } + print_result(count, sum); +} diff --git a/exploring-cpp-2e/chapter20/list2002.cpp b/exploring-cpp-2e/chapter20/list2002.cpp new file mode 100644 index 0000000..48c6481 --- /dev/null +++ b/exploring-cpp-2e/chapter20/list2002.cpp @@ -0,0 +1,65 @@ +// Listing 20-2. Separating Function Declarations from Definitions +#include +#include + +void ignore_line(); +int prompted_read(std::string prompt); +void print_result(int count, int sum); + +/** Main program. + * Read integers from the standard input and print statistics about them. + */ +int main() +{ + int sum{0}; + int count{0}; + + while (std::cin) + { + int x{ prompted_read("Value: ") }; + if (std::cin) + { + sum = sum + x; + ++count; + } + } + print_result(count, sum); +} + +/** Prompt the user, then read a number, and ignore the rest of the line. + * @param prompt the prompt string + * @return the input number or -1 for end-of-file + */ +int prompted_read(std::string prompt) +{ + std::cout << prompt; + int x{-1}; + std::cin >> x; + ignore_line(); + return x; +} + +/** Ignore the rest of the input line. */ +void ignore_line() +{ + char c{}; + while (std::cin.get(c) and c != '\n') + /*empty*/; +} + +/** Print the statistics. + * @param count the number of values + * @param sum the sum of the values + */ +void print_result(int count, int sum) +{ + if (count == 0) + { + std::cout << "no data\n"; + return; + } + + std::cout << "\ncount = " << count; + std::cout << "\nsum = " << sum; + std::cout << "\nmean = " << sum/count << '\n'; +} diff --git a/exploring-cpp-2e/chapter20/list2003.cpp b/exploring-cpp-2e/chapter20/list2003.cpp new file mode 100644 index 0000000..20e9f24 --- /dev/null +++ b/exploring-cpp-2e/chapter20/list2003.cpp @@ -0,0 +1,99 @@ +// Listing 20-3. Using Functions to Clarify the Word-Counting Program +#include +#include +#include +#include +#include + +typedef std::map count_map; ///< Map words to counts +typedef count_map::value_type count_pair; ///< pair of a word and a count +typedef std::string::size_type str_size; ///< String size type + +/** Initialize the I/O streams by imbuing them with + * the given locale. Use this function to imbue the streams + * with the native locale. C++ initially imbues streams with + * the classic locale. + * @param locale the native locale + */ +void initialize_streams(std::locale locale) +{ + std::cin.imbue(locale); + std::cout.imbue(locale); +} + +/** Find the longest key in a map. + * @param map the map to search + * @returns the size of the longest key in @p map + */ +str_size get_longest_key(count_map map) +{ + str_size result{0}; + for (auto pair : map) + if (pair.first.size() > result) + result = pair.first.size(); + return result; +} + +/** Print the word, count, newline. Keep the columns neatly aligned. + * Rather than the tedious operation of measuring the magnitude of all + * the counts and then determining the necessary number of columns, just + * use a sufficiently large value for the counts column. + * @param iter an iterator that points to the word/count pair + * @param longest the size of the longest key; pad all keys to this size + */ +void print_pair(count_pair pair, str_size longest) +{ + const int count_size{10}; // Number of places for printing the count + std::cout << std::setw(longest) << std::left << pair.first << + std::setw(count_size) << std::right << pair.second << '\n'; +} + +/** Print the results in neat columns. + * @param counts the map of all the counts + */ +void print_counts(count_map counts) +{ + str_size longest(get_longest_key(counts)); + + // For each word/count pair... + for (count_pair pair : counts) + print_pair(pair, longest); +} + +/** Sanitize a string by keeping only alphabetic characters. + * @param str the original string + * @param loc the locale used to test the characters + * @return a santized copy of the string + */ +std::string sanitize(std::string str, std::locale loc) +{ + std::string result{}; + for (char ch : str) + if (std::isalnum(ch, loc)) + result.push_back(std::tolower(ch, loc)); + return result; +} + +/** Main program to count unique words in the standard input. */ +int main() +{ + std::locale native{""}; // get the native locale + initialize_streams(native); + + count_map counts{}; + + // Read words from the standard input and count the number of times + // each word occurs. + std::string word{}; + while (std::cin >> word) + { + std::string copy{ sanitize(word, native) }; + + // The "word" might be all punctuation, so the copy would be empty. + // Don't count empty strings. + if (not copy.empty()) + ++counts[copy]; + } + + print_counts(counts); +} diff --git a/exploring-cpp-2e/chapter21/list2101.cpp b/exploring-cpp-2e/chapter21/list2101.cpp new file mode 100644 index 0000000..b60b571 --- /dev/null +++ b/exploring-cpp-2e/chapter21/list2101.cpp @@ -0,0 +1,44 @@ +// Listing 21-1. Function Arguments and Parameters +#include +#include +#include +#include + +void modify(int x) +{ + x = 10; +} + +int triple(int x) +{ + return 3 * x; +} + +void print_vector(std::vector v) +{ + std::cout << "{ "; + std::copy(v.begin(), v.end(), std::ostream_iterator(std::cout, " ")); + std::cout << "}\n"; +} + +void add(std::vector v, int a) +{ + for (auto iter(v.begin()), end(v.end()); iter != end; ++iter) + *iter = *iter + a; +} + +int main() +{ + int a{42}; + modify(a); + std::cout << "a=" << a << '\n'; + + int b{triple(14)}; + std::cout << "b=" << b << '\n'; + + std::vector data{ 10, 20, 30, 40 }; + + print_vector(data); + add(data, 42); + print_vector(data); +} diff --git a/exploring-cpp-2e/chapter21/list2102.cpp b/exploring-cpp-2e/chapter21/list2102.cpp new file mode 100644 index 0000000..bee18b7 --- /dev/null +++ b/exploring-cpp-2e/chapter21/list2102.cpp @@ -0,0 +1,44 @@ +// Listing 21-2. Pass Parameters by Reference +#include +#include +#include +#include + +void modify(int& x) +{ + x = 10; +} + +int triple(int x) +{ + return 3 * x; +} + +void print_vector(std::vector& v) +{ + std::cout << "{ "; + std::copy(v.begin(), v.end(), std::ostream_iterator(std::cout, " ")); + std::cout << "}\n"; +} + +void add(std::vector& v, int a) +{ + for (auto iter(v.begin()), end(v.end()); iter != end; ++iter) + *iter = *iter + a; +} + +int main() +{ + int a{42}; + modify(a); + std::cout << "a=" << a << '\n'; + + int b{triple(14)}; + std::cout << "b=" << b << '\n'; + + std::vector data{ 10, 20, 30, 40 }; + + print_vector(data); + add(data, 42); + print_vector(data); +} diff --git a/exploring-cpp-2e/chapter22/list2201.cpp b/exploring-cpp-2e/chapter22/list2201.cpp new file mode 100644 index 0000000..fa19013 --- /dev/null +++ b/exploring-cpp-2e/chapter22/list2201.cpp @@ -0,0 +1,24 @@ +// Listing 22-1. Calling transform to Apply a Function to Each Element of an Array +#include +#include +#include +#include + +int times_two(int i) +{ + return i * 2; +} + +int main() +{ + std::vector data{}; + + std::copy(std::istream_iterator(std::cin), + std::istream_iterator(), + std::back_inserter(data)); + + std::transform(data.begin(), data.end(), data.begin(), times_two); + + std::copy(data.begin(), data.end(), + std::ostream_iterator(std::cout, "\n")); +} diff --git a/exploring-cpp-2e/chapter22/list2202.cpp b/exploring-cpp-2e/chapter22/list2202.cpp new file mode 100644 index 0000000..6756881 --- /dev/null +++ b/exploring-cpp-2e/chapter22/list2202.cpp @@ -0,0 +1,98 @@ +// Listing 22-2. New main Function That Sets the Global Locale +#include +#include +#include +#include +#include + +typedef std::map count_map; ///< Map words to counts +typedef count_map::value_type count_pair; ///< pair of a word and a count +typedef std::string::size_type str_size; ///< String size type + +/** Initialize the I/O streams by imbuing them with + * the global locale. Use this function to imbue the streams + * with the native locale. C++ initially imbues streams with + * the classic locale. + */ +void initialize_streams() +{ + std::cin.imbue(std::locale{}); + std::cout.imbue(std::locale{}); +} + +/** Find the longest key in a map. + * @param map the map to search + * @returns the size of the longest key in @p map + */ +str_size get_longest_key(count_map const& map) +{ + str_size result{0}; + for (auto pair : map) + if (pair.first.size() > result) + result = pair.first.size(); + return result; +} + +/** Print the word, count, newline. Keep the columns neatly aligned. + * Rather than the tedious operation of measuring the magnitude of all + * the counts and then determining the necessary number of columns, just + * use a sufficiently large value for the counts column. + * @param pair a word/count pair + * @param longest the size of the longest key; pad all keys to this size + */ +void print_pair(count_pair const& pair, str_size longest) +{ + int const count_size{10}; // Number of places for printing the count + std::cout << std::setw(longest) << std::left << pair.first << + std::setw(count_size) << std::right << pair.second << '\n'; +} + +/** Print the results in neat columns. + * @param counts the map of all the counts + */ +void print_counts(count_map counts) +{ + str_size longest{get_longest_key(counts)}; + + // For each word/count pair... + for (count_pair pair: counts) + print_pair(pair, longest); +} + +/** Sanitize a string by keeping only alphabetic characters. + * @param str the original string + * @return a santized copy of the string + */ +std::string sanitize(std::string const& str) +{ + std::string result{}; + for (char c : str) + if (std::isalnum(c, std::locale{})) + result.push_back(std::tolower(c, std::locale{})); + return result; +} + +/** Main program to count unique words in the standard input. */ +int main() +{ + // Set the global locale to the native locale. + std::locale::global(std::locale{""}); + initialize_streams(); + + count_map counts{}; + + // Read words from the standard input and count the number of times + // each word occurs. + std::string word{}; + while (std::cin >> word) + { + std::string copy{sanitize(word)}; + + // The "word" might be all punctuation, so the copy would be empty. + // Don't count empty strings. + if (not copy.empty()) + ++counts[copy]; + } + + print_counts(counts); +} diff --git a/exploring-cpp-2e/chapter22/list2203.cpp b/exploring-cpp-2e/chapter22/list2203.cpp new file mode 100644 index 0000000..d9a1be4 --- /dev/null +++ b/exploring-cpp-2e/chapter22/list2203.cpp @@ -0,0 +1,36 @@ +// Listing 22-3. Sanitizing a String by Transforming It +/** Test for non-letter. + * @param ch the character to test + * @return true if @p ch is not a character that makes up a word + */ +bool non_letter(char ch) +{ + return not std::isalnum(ch, std::locale()); +} + +/** Convert to lowercase. + * Use a canonical form by converting to uppercase first, + * and then to lowercase. + * @param ch the character to test + * @return the character converted to lowercase + */ +char lowercase(char ch) +{ + return std::tolower(ch, std::locale()); +} + +/** Sanitize a string by keeping only alphabetic characters. + * @param str the original string + * @return a santized copy of the string + */ +std::string sanitize(std::string str) +{ + // Remove all non-letters from the string, and then erase them. + str.erase(std::remove_if(str.begin(), str.end(), non_letter), + str.end()); + + // Convert the remnants of the string to lowercase. + std::transform(str.begin(), str.end(), str.begin(), lowercase); + + return str; +} diff --git a/exploring-cpp-2e/chapter22/list2204.cpp b/exploring-cpp-2e/chapter22/list2204.cpp new file mode 100644 index 0000000..41a0544 --- /dev/null +++ b/exploring-cpp-2e/chapter22/list2204.cpp @@ -0,0 +1,22 @@ +// Listing 22-4. Sorting into Descending Order +#include +#include +#include +#include + +/** Predicate for sorting into descending order. */ +int descending(int a, int b) +{ + return a > b; +} + +int main() +{ + std::vector data{}; + data.insert(data.begin(), std::istream_iterator(std::cin), + std::istream_iterator()); + + std::sort(data.begin(), data.end(), descending); + + std::copy(data.begin(), data.end(), std::ostream_iterator(std::cout, "\n")); +} diff --git a/exploring-cpp-2e/chapter22/list2205.cpp b/exploring-cpp-2e/chapter22/list2205.cpp new file mode 100644 index 0000000..36005c6 --- /dev/null +++ b/exploring-cpp-2e/chapter22/list2205.cpp @@ -0,0 +1,59 @@ +// Listing 22-5. Testing for Palindromes +#include +#include +#include +#include +#include + +/** Test for non-letter. + * @param ch the character to test + * @return true if @p ch is not a letter + */ +bool non_letter(char ch) +{ + return not std::isalpha(ch, std::locale()); +} + +/** Convert to lowercase. + * Use a canonical form by converting to uppercase first, + * and then to lowercase. + * @param ch the character to test + * @return the character converted to lowercase + */ +char lowercase(char ch) +{ + return std::tolower(ch, std::locale()); +} + +/** Compare two characters without regard to case. */ +bool is_same_char(char a, char b) +{ + return lowercase(a) == lowercase(b); +} + +/** Determine whether @p str is a palindrome. + * Only letter characters are tested. Spaces and punctuation don't count. + * Empty strings are not palindromes because that's just too easy. + * @param str the string to test + * @return true if @p str is the same forward and backward + */ +bool is_palindrome(std::string str) + +{ + std::string::iterator end{std::remove_if(str.begin(), str.end(), non_letter)}; + std::string rev{str.begin(), end}; + std::reverse(rev.begin(), rev.end()); + return not rev.empty() and std::equal(str.begin(), end, rev.begin(), is_same_char); +} + +int main() +{ + std::locale::global(std::locale{""}); + std::cin.imbue(std::locale{}); + std::cout.imbue(std::locale{}); + + std::string line{}; + while (std::getline(std::cin, line)) + if (is_palindrome(line)) + std::cout << line << '\n'; +} diff --git a/exploring-cpp-2e/chapter23/list2301.cpp b/exploring-cpp-2e/chapter23/list2301.cpp new file mode 100644 index 0000000..51b2754 --- /dev/null +++ b/exploring-cpp-2e/chapter23/list2301.cpp @@ -0,0 +1,19 @@ +// Listing 23-1. Calling transform to Apply a Lambda to Each Element of an Array +#include +#include +#include +#include + +int main() +{ + std::vector data{}; + + std::copy(std::istream_iterator(std::cin), + std::istream_iterator(), + std::back_inserter(data)); + + std::transform(data.begin(), data.end(), data.begin(), [](int x) { return x * 2; }); + + std::copy(data.begin(), data.end(), + std::ostream_iterator(std::cout, "\n")); +} diff --git a/exploring-cpp-2e/chapter23/list2302.cpp b/exploring-cpp-2e/chapter23/list2302.cpp new file mode 100644 index 0000000..8138819 --- /dev/null +++ b/exploring-cpp-2e/chapter23/list2302.cpp @@ -0,0 +1,24 @@ +// Listing 23-2. Using a Lambda to Access Local Variables +#include +#include +#include +#include + +int main() +{ + std::vector data{}; + + std::cout << "Multiplier: "; + int multiplier{}; + std::cin >> multiplier; + std::cout << "Data:\n"; + std::copy(std::istream_iterator(std::cin), + std::istream_iterator(), + std::back_inserter(data)); + + std::transform(data.begin(), data.end(), data.begin(), + [multiplier](int i){ return i * multiplier; }); + + std::copy(data.begin(), data.end(), + std::ostream_iterator(std::cout, "\n")); +} diff --git a/exploring-cpp-2e/chapter23/list2303.cpp b/exploring-cpp-2e/chapter23/list2303.cpp new file mode 100644 index 0000000..f1d86ea --- /dev/null +++ b/exploring-cpp-2e/chapter23/list2303.cpp @@ -0,0 +1,21 @@ +// Listing 23-3. Using a Lambda to Access Local Variables +#include +#include +#include +#include + +int main() +{ + std::vector data{ 1, 2, 3 }; + + int multiplier{3}; + auto times = [multiplier](int i) { return i * multiplier; }; + + std::transform(data.begin(), data.end(), data.begin(), times); + + multiplier = 20; + std::transform(data.begin(), data.end(), data.begin(), times); + + std::copy(data.begin(), data.end(), + std::ostream_iterator(std::cout, "\n")); +} diff --git a/exploring-cpp-2e/chapter23/list2304.cpp b/exploring-cpp-2e/chapter23/list2304.cpp new file mode 100644 index 0000000..318cacc --- /dev/null +++ b/exploring-cpp-2e/chapter23/list2304.cpp @@ -0,0 +1,14 @@ +// Listing 23-4. Using a Lambda to Access Local Variables +#include + +int main() +{ + int x{0}; + auto lambda = [x](int y) { + x = 1; + y = 2; + return x + y; + }; + int local{0}; + std::cout << lambda(local) << ", " << x << ", " << local << '\n'; +} diff --git a/exploring-cpp-2e/chapter23/list2305.cpp b/exploring-cpp-2e/chapter23/list2305.cpp new file mode 100644 index 0000000..57c8246 --- /dev/null +++ b/exploring-cpp-2e/chapter23/list2305.cpp @@ -0,0 +1,14 @@ +// Listing 23-5. Using the mutable Keyword in a Lambda +#include + +int main() +{ + int x{0}; + auto lambda = [x](int y) mutable { + x = 1; + y = 2; + return x + y; + }; + int local{0}; + std::cout << lambda(local) << ", " << x << ", " << local << '\n'; +} diff --git a/exploring-cpp-2e/chapter23/list2306.cpp b/exploring-cpp-2e/chapter23/list2306.cpp new file mode 100644 index 0000000..d869bf1 --- /dev/null +++ b/exploring-cpp-2e/chapter23/list2306.cpp @@ -0,0 +1,51 @@ +// Listing 23-6. Testing for Palindromes +#include +#include +#include +#include +#include + +/** Determine whether @p str is a palindrome. + * Only letter characters are tested. Spaces and punctuation don't count. + * Empty strings are not palindromes because that's just too easy. + * @param str the string to test + * @return true if @p str is the same forward and backward + */ +bool is_palindrome(std::string str) +{ + // Filter the string to keep only letters + std::string::iterator end{std::remove_if(str.begin(), str.end(), + [](char ch) + { + return not std::isalpha(ch, std::locale()); + }) + }; + + // Reverse the filtered string. + std::string rev{str.begin(), end}; + std::reverse(rev.begin(), rev.end()); + + // Compare the filtered string with its reversal, without regard to case. + return not rev.empty() and std::equal(str.begin(), end, rev.begin(), + [](char a, char b) + { + auto lowercase = [](char ch) + { + return std::tolower(ch, std::locale()); + }; + return lowercase(a) == lowercase(b); + } + ); +} + +int main() +{ + std::locale::global(std::locale{""}); + std::cin.imbue(std::locale{}); + std::cout.imbue(std::locale{}); + + std::string line{}; + while (std::getline(std::cin, line)) + if (is_palindrome(line)) + std::cout << line << '\n'; +} diff --git a/exploring-cpp-2e/chapter24/list2401.cpp b/exploring-cpp-2e/chapter24/list2401.cpp new file mode 100644 index 0000000..2ea528d --- /dev/null +++ b/exploring-cpp-2e/chapter24/list2401.cpp @@ -0,0 +1,55 @@ +// Listing 24-1. Printing Vectors by Using Overloaded Functions +#include +#include +#include +#include +#include + +void print(int i) +{ + std::cout << i; +} + +void print(int i, int width) +{ + std::cout.width(width); + std::cout << i; +} + +void print(std::vector const& vec, + int width, + std::string const& prefix, + std::string const& separator, + std::string const& postfix) +{ + std::cout << prefix; + + bool print_separator{false}; + for (auto x : vec) + { + if (print_separator) + std::cout << separator; + else + print_separator = true; + print(x, width); + } + std::cout << postfix; +} + +void print(std::vector const& vec, + std::string const& prefix, + std::string const& separator, + std::string const& postfix) +{ + print(vec, 0, prefix, separator, postfix); +} + +int main() +{ + std::vector data{ 10, 20, 30, 40, 100, 1000, }; + + std::cout << "columnar data:\n"; + print(data, 10, "", "\n", "\n"); + std::cout << "row data:\n"; + print(data, "{", ", ", "}\n"); +} diff --git a/exploring-cpp-2e/chapter24/list2402.cpp b/exploring-cpp-2e/chapter24/list2402.cpp new file mode 100644 index 0000000..195f018 --- /dev/null +++ b/exploring-cpp-2e/chapter24/list2402.cpp @@ -0,0 +1,54 @@ +// Listing 24-2. Overloading Functions in the Manner of a Library-Writer +#include +#include +#include + +bool is_alpha(char ch) +{ + return std::isalpha(ch, std::locale{}); +} + +bool is_alpha(std::string const& str) +{ + for (char ch : str) + if (not is_alpha(ch)) + return false; + return true; +} + +char to_lower(char ch) +{ + return std::tolower(ch, std::locale{}); +} + +std::string to_lower(std::string str) +{ + for (char& ch : str) + ch = to_lower(ch); + return str; +} + +char to_upper(char ch) +{ + return std::toupper(ch, std::locale{}); +} + +std::string to_upper(std::string str) +{ + for (char& ch : str) + ch = to_upper(ch); + return str; +} + +int main() +{ + std::string str{}; + while (std::cin >> str) + { + if (is_alpha(str)) + std::cout << "alpha\n"; + else + std::cout << "not alpha\n"; + std::cout << "lower: " << to_lower(str) << "\nupper: " << to_upper(str) << '\n'; + } +} diff --git a/exploring-cpp-2e/chapter25/list2501.cpp b/exploring-cpp-2e/chapter25/list2501.cpp new file mode 100644 index 0000000..ef2518d --- /dev/null +++ b/exploring-cpp-2e/chapter25/list2501.cpp @@ -0,0 +1,18 @@ +// Listing 25-1. Discovering the Number of Bits in an Integer +#include +#include + +int main() +{ + std::cout << "bits per int = "; + if (std::numeric_limits::is_signed) + std::cout << std::numeric_limits::digits + 1 << '\n'; + else + std::cout << std::numeric_limits::digits << '\n'; + + std::cout << "bits per bool = "; + if (std::numeric_limits::is_signed) + std::cout << std::numeric_limits::digits + 1 << '\n'; + else + std::cout << std::numeric_limits::digits << '\n'; +} diff --git a/exploring-cpp-2e/chapter25/list2502.cpp b/exploring-cpp-2e/chapter25/list2502.cpp new file mode 100644 index 0000000..d62fcc0 --- /dev/null +++ b/exploring-cpp-2e/chapter25/list2502.cpp @@ -0,0 +1,36 @@ +// Listing 25-2. Revealing the Number of Bits in Short and Long Integers +#include +#include + +int main() +{ + std::cout << "bits per int = "; + if (std::numeric_limits::is_signed) + std::cout << std::numeric_limits::digits + 1 << '\n'; + else + std::cout << std::numeric_limits::digits << '\n'; + + std::cout << "bits per bool = "; + if (std::numeric_limits::is_signed) + std::cout << std::numeric_limits::digits + 1 << '\n'; + else + std::cout << std::numeric_limits::digits << '\n'; + + std::cout << "bits per short int = "; + if (std::numeric_limits::is_signed) + std::cout << std::numeric_limits::digits + 1 << '\n'; + else + std::cout << std::numeric_limits::digits << '\n'; + + std::cout << "bits per long int = "; + if (std::numeric_limits::is_signed) + std::cout << std::numeric_limits::digits + 1 << '\n'; + else + std::cout << std::numeric_limits::digits << '\n'; + + std::cout << "bits per long long int = "; + if (std::numeric_limits::is_signed) + std::cout << std::numeric_limits::digits + 1 << '\n'; + else + std::cout << std::numeric_limits::digits << '\n'; +} diff --git a/exploring-cpp-2e/chapter25/list2503.cpp b/exploring-cpp-2e/chapter25/list2503.cpp new file mode 100644 index 0000000..b9c2848 --- /dev/null +++ b/exploring-cpp-2e/chapter25/list2503.cpp @@ -0,0 +1,33 @@ +// Listing 25-3. Using Overloading to Distinguish Types of Integer Literals +#include +#include + +void print(int value) +{ + std::cout << "int=" << value << '\n'; +} + +void print(long value) +{ + std::cout << "long=" << value << '\n'; +} + +void print(long long value) +{ + std::cout << "long long=" << value << '\n'; +} + +int main() +{ + std::cout.imbue(std::locale{""}); + print(0); + print(0L); + print(32768); + print(-32768); + print(2147483647); + print(-2147483647); + print(2147483648); + + print(9223372036854775807); + print(-9223372036854775807); +} diff --git a/exploring-cpp-2e/chapter25/list2504.cpp b/exploring-cpp-2e/chapter25/list2504.cpp new file mode 100644 index 0000000..b0a2434 --- /dev/null +++ b/exploring-cpp-2e/chapter25/list2504.cpp @@ -0,0 +1,52 @@ +// Listing 25-4. Using Type Casts +#include +#include + +typedef signed char byte; + +void print(byte value) +{ + // The << operator treats signed char as a mutant char, and tries to + // print a character. In order to print the value as an integer, you + // must cast it to an integer type. + std::cout << "byte=" << static_cast(value) << '\n'; +} + +void print(short value) +{ + std::cout << "short=" << value << '\n'; +} + +void print(int value) +{ + std::cout << "int=" << value << '\n'; +} + +void print(long value) +{ + std::cout << "long=" << value << '\n'; +} + +void print(long long value) +{ + std::cout << "long long=" << value << '\n'; +} + +int main() +{ + std::cout.imbue(std::locale{""}); + print(0); + print(0L); + print(static_cast(0)); + print(static_cast(0)); + print(static_cast(255)); + print(static_cast(65535)); + print(32768); + print(32768L); + print(-32768); + print(2147483647); + print(-2147483647); + print(2147483648); + print(9223372036854775807); + print(-9223372036854775807); +} diff --git a/exploring-cpp-2e/chapter25/list2505.cpp b/exploring-cpp-2e/chapter25/list2505.cpp new file mode 100644 index 0000000..433c1b2 --- /dev/null +++ b/exploring-cpp-2e/chapter25/list2505.cpp @@ -0,0 +1,23 @@ +// Listing 25-5. User-Defined Literal +#include + +short operator "" _S(unsigned long long value) +{ + return static_cast(value); +} + +void print(short s) +{ + std::cout << "short=" << s << '\n'; +} + +void print(int i) +{ + std::cout << "int=" << i << '\n'; +} + +int main() +{ + print(42); + print(42_S); +} diff --git a/exploring-cpp-2e/chapter25/list2506.cpp b/exploring-cpp-2e/chapter25/list2506.cpp new file mode 100644 index 0000000..08e0964 --- /dev/null +++ b/exploring-cpp-2e/chapter25/list2506.cpp @@ -0,0 +1,73 @@ +// Listing 25-6. Overloading Prefers Type Promotion over Type Conversion +#include + +// print is overloaded for signed char, short, int and long +void print(signed char value) +{ + std::cout << "print(signed char = " << static_cast(value) << ")\n"; +} + +void print(short value) +{ + std::cout << "print(short = " << value << ")\n"; +} + +void print(int value) +{ + std::cout << "print(int = " << value << ")\n"; +} + +void print(long value) +{ + std::cout << "print(long = " << value << ")\n"; +} + +// guess is overloaded for bool, int, and long +void guess(bool value) +{ + std::cout << "guess(bool = " << value << ")\n"; +} + +void guess(int value) +{ + std::cout << "guess(int = " << value << ")\n"; +} + +void guess(long value) +{ + std::cout << "guess(long = " << value << ")\n"; +} + +// error is overloaded for bool and long +void error(bool value) +{ + std::cout << "error(bool = " << value << ")\n"; +} + +void error(long value) +{ + std::cout << "error(long = " << value << ")\n"; +} + +int main() +{ + signed char byte{10}; + short shrt{20}; + int i{30}; + long lng{40}; + + print(byte); + print(shrt); + print(i); + print(lng); + + guess(byte); + guess(shrt); + guess(i); + guess(lng); + + error(byte); // expected error + error(shrt); // expected error + error(i); // expected error + error(lng); +} diff --git a/exploring-cpp-2e/chapter26/list2601.cpp b/exploring-cpp-2e/chapter26/list2601.cpp new file mode 100644 index 0000000..cd5de93 --- /dev/null +++ b/exploring-cpp-2e/chapter26/list2601.cpp @@ -0,0 +1,9 @@ +// Listing 26-1. Floating-Point Numbers Do Not Always Behave As You Expect +#include +int main() +{ + float a{0.03F}; + float b{10.0F}; + float c{0.3F}; + assert(a * b == c); +} diff --git a/exploring-cpp-2e/chapter26/list2602.cpp b/exploring-cpp-2e/chapter26/list2602.cpp new file mode 100644 index 0000000..ac39ed9 --- /dev/null +++ b/exploring-cpp-2e/chapter26/list2602.cpp @@ -0,0 +1,44 @@ +// Listing 26-2. Discovering the Attributes of a Floating-Point Type +#include +#include +#include + +int main() +{ + std::cout.imbue(std::locale{""}); + std::cout << std::boolalpha; + // Change float to double or long double to learn about those types. + typedef float T; + std::cout << "min=" << std::numeric_limits::min() << '\n' + << "max=" << std::numeric_limits::max() << '\n' + << "IEC 60559? " << std::numeric_limits::is_iec559 << '\n' + << "max exponent=" << std::numeric_limits::max_exponent << '\n' + << "min exponent=" << std::numeric_limits::min_exponent << '\n' + << "mantissa places=" << std::numeric_limits::digits << '\n' + << "radix=" << std::numeric_limits::radix << '\n' + << "has infinity? " << std::numeric_limits::has_infinity << '\n' + << "has quiet NaN? " << std::numeric_limits::has_quiet_NaN << '\n' + << "has signaling NaN? " << std::numeric_limits::has_signaling_NaN << '\n'; + + if (std::numeric_limits::has_infinity) + { + T zero{0}; + T one{1}; + T inf{std::numeric_limits::infinity()}; + if (one/zero == inf) + std::cout << "1.0/0.0 = infinity\n"; + if (inf + inf == inf) + std::cout << "infinity + infinity = infinity\n"; + } + if (std::numeric_limits::has_quiet_NaN) + { + // There's no guarantee that your environment produces quiet NaNs for + // these illegal arithmetic operations. It's possible that your compiler's + // default is to produce signaling NaNs, or to terminate the program + // in some other way. + T zero{}; + T inf{std::numeric_limits::infinity()}; + std::cout << "zero/zero = " << zero/zero << '\n'; + std::cout << "inf/inf = " << inf/inf << '\n'; + } +} diff --git a/exploring-cpp-2e/chapter26/list2603.cpp b/exploring-cpp-2e/chapter26/list2603.cpp new file mode 100644 index 0000000..1f29dba --- /dev/null +++ b/exploring-cpp-2e/chapter26/list2603.cpp @@ -0,0 +1,26 @@ +// Listing 26-3. Demonstrating Floating-Point Output +#include + +/// Print a floating-point number in three different formats. +/// @param precision the precision to use when printing @p value +/// @param value the floating-point number to print +void print(int precision, float value) +{ + std::cout.precision(precision); + std::cout << std::scientific << value << '\t' + << std::fixed << value << '\t' + << std::hexfloat << value << '\t'; + + // Set the format to general. + std::cout.unsetf(std::ios_base::floatfield); + std::cout << value << '\n'; +} + +/// Main program. +int main() +{ + print(6, 123456.789f); + print(4, 1.23456789f); + print(2, 123456789.f); + print(5, -1234.5678e9f); +} diff --git a/exploring-cpp-2e/chapter27/list2701.cpp b/exploring-cpp-2e/chapter27/list2701.cpp new file mode 100644 index 0000000..04cbc49 --- /dev/null +++ b/exploring-cpp-2e/chapter27/list2701.cpp @@ -0,0 +1,102 @@ +// Listing 27-1. Documenting Your Code with Doxygen +/** @file + * @brief Test strings to see whether they are palindromes. + * Read lines from the input, strip non-letters, and check whether + * the result is a palindrome. Ignore case differences when checking. + * Echo palindromes to the standard output. + */ + +/** @mainpage Palindromes + * Test input strings to see whether they are palindromes. + * + * A _palindrome_ is a string that reads the same forward and backward. + * To test for palindromes, this program needs to strip punctuation and + * other non-essential characters from the string, and compare letters without + * regard to case differences. + * + * This program reads lines of text from the standard input and echoes + * to the standard output those lines that are palindromes. + * + * Source file: [palindrome.cpp](palindrome.cpp) + + * + * @date 27-July-2013 + * @author Ray Lischner + * @version 2.0 + */ +#include +#include +#include +#include +#include + +/** @brief Test for non-letter. + * Test the character @p ch in the global locale. + * @param ch the character to test + * @return true if @p ch is not a letter + */ +bool non_letter(char ch) +{ + return not std::isalnum(ch, std::locale{}); +} + +/** @brief Convert to lowercase. + * Use a canonical form by converting to uppercase first, + * and then to lowercase. This approach does not solve the eszet + * problem (German eszet is a lowercase character that converts + * to two uppercase characters), but it's the best we can do in + * standard C++. + * + * All conversions use the global locale. + * + * @param ch the character to test + * @return the character converted to lowercase + */ +char lowercase(char ch) +{ + return std::tolower(ch, std::locale{}); +} + +/** @brief Compare two characters without regard to case. + * The comparison is limited by the `lowercase()` function. + * @param a one character to compare + * @param b the other character to compare + * @return `true` if the characters are the same in lowercase, + * `false` if they are different. + */ +bool is_same_char(char a, char b) +{ + return lowercase(a) == lowercase(b); +} + +/** @brief Determine whether @p str is a palindrome. + * Only letter characters are tested. Spaces and punctuation don't count. + * Empty strings are not palindromes because that's just too easy. + * @param str the string to test + * @return `true` if @p str is the same forward and backward and + * `not str.empty()` + + */ +bool is_palindrome(std::string str) +{ + std::string::iterator end{std::remove_if(str.begin(), str.end(), non_letter)}; + std::string rev{str.begin(), end}; + std::reverse(rev.begin(), rev.end()); + return not rev.empty() and std::equal(str.begin(), end, rev.begin(), is_same_char); +} + +/** @brief Main program. + * Set the global locale to the user's native locale. Then imbue the I/O streams + * with the native locale. + */ +int main() +{ + std::locale::global(std::locale{""}); + std::cin.imbue(std::locale{}); + std::cout.imbue(std::locale{}); + + std::string line{}; + while (std::getline(std::cin, line)) + if (is_palindrome(line)) + std::cout << line << '\n'; +} diff --git a/exploring-cpp-2e/chapter28/Doxyfile b/exploring-cpp-2e/chapter28/Doxyfile new file mode 100644 index 0000000..23589b0 --- /dev/null +++ b/exploring-cpp-2e/chapter28/Doxyfile @@ -0,0 +1,1275 @@ +# Doxyfile 1.5.3 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file that +# follow. The default is UTF-8 which is also the encoding used for all text before +# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into +# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of +# possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = "Project 1 - Body-mass index " + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian, +# Italian, Japanese, Japanese-en (Japanese with English messages), Korean, +# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian, +# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = /home/lischner/writing/books/exploring-cpp/files/projects/project1/ + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to +# include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be extracted +# and appear in the documentation as a namespace called 'anonymous_namespace{file}', +# where file will be replaced with the base name of the file that contains the anonymous +# namespace. By default anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from the +# version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text " + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = bmi.cpp + +# This tag can be used to specify the character encoding of the source files that +# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default +# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding. +# See http://www.gnu.org/software/libiconv for the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py + +FILE_PATTERNS = *.cpp + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the output. +# The symbol name can be a fully qualified name, a word, or if the wildcard * is used, +# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. If you have enabled CALL_GRAPH or CALLER_GRAPH +# then you must also enable this option. If you don't then doxygen will produce +# a warning and turn it on anyway + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentstion. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to +# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to +# specify the directory where the mscgen tool resides. If left empty the tool is assumed to +# be found in the default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will +# generate a caller dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable caller graphs for selected +# functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the number +# of direct children of the root node in a graph is already larger than +# MAX_DOT_GRAPH_NOTES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, which results in a white background. +# Warning: Depending on the platform used, enabling this option may lead to +# badly anti-aliased labels on the edges of a graph (i.e. they become hard to +# read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/exploring-cpp-2e/chapter28/Makefile b/exploring-cpp-2e/chapter28/Makefile new file mode 100644 index 0000000..dc6b36d --- /dev/null +++ b/exploring-cpp-2e/chapter28/Makefile @@ -0,0 +1,11 @@ +CXXFLAGS = -ansi -pedantic -Wall -std=c++11 + +all: bmi + +bmi: bmi.o + $(CXX) -o $@ $(CXXFLAGS) $(LDFLAGS) bmi.o + +clean: + $(RM) -r bmi bmi.o html + +.PHONY: all clean diff --git a/exploring-cpp-2e/chapter28/bmi.cpp b/exploring-cpp-2e/chapter28/bmi.cpp new file mode 100644 index 0000000..4a6b8dc --- /dev/null +++ b/exploring-cpp-2e/chapter28/bmi.cpp @@ -0,0 +1,239 @@ +/** @file + * @brief Compute body-mass index. + */ +/** @mainpage Project 1 - Body-Mass Index + * This program is Project 1 in Exploring C++, + * by Ray Lischner (Apress). + * + * Your task is to write a program that reads records, + * prints the records, and computes some statistics. + * The program starts by asking for a threshold BMI. + * Only records with a BMI greater than or equal to the + * threshold will be printed. Each record consists of a + * person's name (which might contain spaces), weight in + * kilograms, height in centimeters (not meters), and + * the person's sex ('M' or 'F'). Let the user enter + * the sex in uppercase or lowercase. + * + * Print each person's BMI after reading that person's record. + * After collecting information for everyone, print two tables + * of the information. One table is for men and the other is + * for women. Mark records for which the BMI meets or exceeds + * the threshold with an asterisk after the BMI. After each table, + * print the mean (average) and median BMI. (Median is the value + * such that half the BMI values are less than the median and half + * are greater than the median. If the user enters an even number + * of records, take the average of the two values in the middle.) + * Compute individual BMI values as integers. Compute the mean and + * median BMIs as floating point numbers, and print the mean with + * one place after the decimal point. + * + * Body-mass index is defined as weight in kg/(height in m)2, + * converted to a unitless number. + * + * Source file: + * @link bmi.cpp bmi.cpp @endlink + * @author Ray Lischner + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** @brief Compute the body-mass index (BMI). + * The height is in centimeters, so the computed value + * is off by 10,000. Integer division truncates, but we + * want to round off to nearest, so add 0.5 and then + * truncate by casting to an integer. + * + * @param height The person's height in centimeters. + * @param weight The person's weight in kilograms. + * @return the person's BMI, rounded to an integer + */ +int compute_bmi(int height, int weight) +{ + return static_cast(weight * 10000 / (height * height) + 0.5); +} + +/** @brief Skip the rest of the input line. */ +void skip_line() +{ + std::cin.ignore(std::numeric_limits::max(), '\n'); +} + +/** @brief Get a single person's record. + * Store the name, height, weight, and sex in the supplied vectors. + * @param names array of persons' full names + * @param heights array of height in centimeters + * @param weights array of weight in kilograms + * @param sexes array of persons' sex: 'M' means male and 'F' means female + * @return true to continue reading records or false to stop + */ +bool get_record(std::vector& names, + std::vector& heights, + std::vector& weights, + std::vector& sexes) +{ + std::string name{}; + int height{0}; + int weight{0}; + char sex{'?'}; + + std::cout << "Name " << names.size()+1 << ": "; + if (not std::getline(std::cin, name)) + return false; + + // Enforce minimal sanity check on the height, which must be + // between 10 and 300 cm, or baby- to giant-size. + int const min_height{10}; + int const max_height{300}; + std::cout << "Height (cm): "; + if (not (std::cin >> height)) + return false; + skip_line(); + if (height < min_height or height > max_height) + { + std::cout << "Invalid height. Aborting.\n"; + return false; + } + + // Enforce minimal sanity check on the weight, which must + // be between premature-baby and giant size. + int const min_weight{1}; + int const max_weight{500}; + std::cout << "Weight (kg): "; + if (not (std::cin >> weight)) + return false; + skip_line(); + if (weight < min_weight or weight > max_weight) + { + std::cout << "Invalid weight. Aborting.\n"; + return false; + } + + std::cout << "Sex (M or F): "; + if (not (std::cin >> sex)) + return false; + skip_line(); + sex = std::toupper(sex, std::locale()); + if (sex != 'M' and sex != 'F') + { + std::cout << "Invalid sex. Aborting.\n"; + return false; + } + + // All information has now been collected, so + // append it all to the respective vectors. + names.push_back(name); + heights.push_back(height); + weights.push_back(weight); + sexes.push_back(sex); + + return true; +} + +/** @brief Print a table. + * Print a table of height, weight, sex, BMI, and name. + * Print only records for which sex matches @p sex. + * At the end of each table, print the mean and median BMI. + * + * @param sex the sex to match + * @param heights the array of heights + * @param weights the array of weights + * @param bmis the array of BMIs + * @param sexes the array of sexes + * @param names the array of names + * @param threshold print only elements for which BMI > this + */ +void print_table(char sex, + std::vector const& heights, + std::vector const& weights, + std::vector const& bmis, + std::vector const& sexes, + std::vector const& names, + int threshold) +{ + std::cout << "Ht(cm) Wt(kg) Sex BMI Name\n"; + + float bmi_sum(0); + long int bmi_count(0); + std::vector tmpbmis; // store only the BMIs that are printed + // to compute the median + for (std::vector::size_type i(0); i != heights.size(); ++i) + if (sexes.at(i) == sex) + { + bmi_sum = bmi_sum + bmis.at(i); + ++bmi_count; + tmpbmis.push_back(bmis.at(i)); + std::cout << std::setw(6) << heights.at(i) + << std::setw(7) << weights.at(i) + << std::setw(3) << sexes.at(i) + << std::setw(6) << bmis.at(i); + if (bmis.at(i) >= threshold) + std::cout << '*'; + else + std::cout << ' '; + std::cout << ' ' << names.at(i) << '\n'; + } + + // If the vectors are not empty, print basic statistics. + if (bmi_count != 0) + { + std::cout << "Mean BMI = " + << std::setprecision(1) << std::fixed << bmi_sum / bmi_count + << '\n'; + + // Median BMI is trickier. The easy way is to sort the + // array and pick out the middle item or items. + std::sort(tmpbmis.begin(), tmpbmis.end()); + std::cout << "Median BMI = "; + // Index of median item. + int i(tmpbmis.size() / 2); + if (tmpbmis.size() % 2 == 0) + std::cout << (tmpbmis.at(i) + tmpbmis.at(i-1)) / 2.0 << '\n'; + else + std::cout << tmpbmis.at(i) << '\n'; + } +} + +/** @brief Main program to compute BMI. */ +int main() +{ + std::locale::global(std::locale{""}); + std::cout.imbue(std::locale{}); + std::cin.imbue(std::locale{}); + + std::vector names{}; + std::vector heights{}; + std::vector weights{}; + std::vector sexes{}; + std::vector bmis{}; + int threshold{}; + + std::cout << "Enter threshold BMI: "; + if (not (std::cin >> threshold)) + return EXIT_FAILURE; + skip_line(); + + std::cout << "Enter name, height (in cm)," + " and weight (in kg) for each person:\n"; + while (get_record(names, heights, weights, sexes)) + { + int bmi{compute_bmi(heights.back(), weights.back())}; + bmis.push_back(bmi); + std::cout << "BMI = " << bmi << '\n'; + } + + // Print the data. + std::cout << "\n\nMale data\n"; + print_table('M', heights, weights, bmis, sexes, names, threshold); + std::cout << "\nFemale data\n"; + print_table('F', heights, weights, bmis, sexes, names, threshold); +} diff --git a/exploring-cpp-2e/chapter28/bmi.in b/exploring-cpp-2e/chapter28/bmi.in new file mode 100644 index 0000000..511fb1f --- /dev/null +++ b/exploring-cpp-2e/chapter28/bmi.in @@ -0,0 +1,21 @@ +25 -- threshold +Ray Lischner +180 cm +90 kg +male +A. Nony Mouse +120 cm +42 kg +female +Mick E. Mouse +30 cm +2 kg +male +A. Nony Lischner +150 cm +55 kg +male +No One +250 cm +130 kg +female diff --git a/exploring-cpp-2e/chapter28/html/bc_s.png b/exploring-cpp-2e/chapter28/html/bc_s.png new file mode 100644 index 0000000..224b29a Binary files /dev/null and b/exploring-cpp-2e/chapter28/html/bc_s.png differ diff --git a/exploring-cpp-2e/chapter28/html/bdwn.png b/exploring-cpp-2e/chapter28/html/bdwn.png new file mode 100644 index 0000000..940a0b9 Binary files /dev/null and b/exploring-cpp-2e/chapter28/html/bdwn.png differ diff --git a/exploring-cpp-2e/chapter28/html/bmi_8cpp.html b/exploring-cpp-2e/chapter28/html/bmi_8cpp.html new file mode 100644 index 0000000..337176f --- /dev/null +++ b/exploring-cpp-2e/chapter28/html/bmi_8cpp.html @@ -0,0 +1,272 @@ + + + + + + +Project 1 - Body-mass index: /home/ray/writing/books/exploring-cpp-2ed/final/code/chapter28/bmi.cpp File Reference + + + + + + +
+
+ + + + + + +
+
Project 1 - Body-mass index +
+
+
+ + + + + +
+
+ +
+
bmi.cpp File Reference
+
+
+ +

Compute body-mass index. +More...

+
#include <algorithm>
+#include <cstdlib>
+#include <iomanip>
+#include <iostream>
+#include <istream>
+#include <limits>
+#include <locale>
+#include <ostream>
+#include <string>
+#include <vector>
+
+

Go to the source code of this file.

+ + + + + + + + + + + + + + + + + +

+Functions

int compute_bmi (int height, int weight)
 Compute the body-mass index (BMI). The height is in centimeters, so the computed value is off by 10,000. Integer division truncates, but we want to round off to nearest, so add 0.5 and then truncate by casting to an integer. More...
 
+void skip_line ()
 Skip the rest of the input line.
 
bool get_record (std::vector< std::string > &names, std::vector< int > &heights, std::vector< int > &weights, std::vector< char > &sexes)
 Get a single person's record. Store the name, height, weight, and sex in the supplied vectors. More...
 
void print_table (char sex, std::vector< int > const &heights, std::vector< int > const &weights, std::vector< int > const &bmis, std::vector< char > const &sexes, std::vector< std::string > const &names, int threshold)
 Print a table. Print a table of height, weight, sex, BMI, and name. Print only records for which sex matches sex. At the end of each table, print the mean and median BMI. More...
 
+int main ()
 Main program to compute BMI.
 
+

Detailed Description

+

Compute body-mass index.

+ +

Definition in file bmi.cpp.

+

Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + +
int compute_bmi (int height,
int weight 
)
+
+ +

Compute the body-mass index (BMI). The height is in centimeters, so the computed value is off by 10,000. Integer division truncates, but we want to round off to nearest, so add 0.5 and then truncate by casting to an integer.

+
Parameters
+ + + +
heightThe person's height in centimeters.
weightThe person's weight in kilograms.
+
+
+
Returns
the person's BMI, rounded to an integer
+ +

Definition at line 60 of file bmi.cpp.

+ +

Referenced by main().

+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
bool get_record (std::vector< std::string > & names,
std::vector< int > & heights,
std::vector< int > & weights,
std::vector< char > & sexes 
)
+
+ +

Get a single person's record. Store the name, height, weight, and sex in the supplied vectors.

+
Parameters
+ + + + + +
namesarray of persons' full names
heightsarray of height in centimeters
weightsarray of weight in kilograms
sexesarray of persons' sex: 'M' means male and 'F' means female
+
+
+
Returns
true to continue reading records or false to stop
+ +

Definition at line 79 of file bmi.cpp.

+ +

References skip_line().

+ +

Referenced by main().

+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void print_table (char sex,
std::vector< int > const & heights,
std::vector< int > const & weights,
std::vector< int > const & bmis,
std::vector< char > const & sexes,
std::vector< std::string > const & names,
int threshold 
)
+
+ +

Print a table. Print a table of height, weight, sex, BMI, and name. Print only records for which sex matches sex. At the end of each table, print the mean and median BMI.

+
Parameters
+ + + + + + + + +
sexthe sex to match
heightsthe array of heights
weightsthe array of weights
bmisthe array of BMIs
sexesthe array of sexes
namesthe array of names
thresholdprint only elements for which BMI > this
+
+
+ +

Definition at line 155 of file bmi.cpp.

+ +

Referenced by main().

+ +
+
+
+ + + + diff --git a/exploring-cpp-2e/chapter28/html/bmi_8cpp_source.html b/exploring-cpp-2e/chapter28/html/bmi_8cpp_source.html new file mode 100644 index 0000000..a923a5b --- /dev/null +++ b/exploring-cpp-2e/chapter28/html/bmi_8cpp_source.html @@ -0,0 +1,233 @@ + + + + + + +Project 1 - Body-mass index: /home/ray/writing/books/exploring-cpp-2ed/final/code/chapter28/bmi.cpp Source File + + + + + + +
+
+ + + + + + +
+
Project 1 - Body-mass index +
+
+
+ + + + + +
+
+
+
bmi.cpp
+
+
+Go to the documentation of this file.
1 
+
39 #include <algorithm>
+
40 #include <cstdlib>
+
41 #include <iomanip>
+
42 #include <iostream>
+
43 #include <istream>
+
44 #include <limits>
+
45 #include <locale>
+
46 #include <ostream>
+
47 #include <string>
+
48 #include <vector>
+
49 
+
60 int compute_bmi(int height, int weight)
+
61 {
+
62  return static_cast<int>(weight * 10000 / (height * height) + 0.5);
+
63 }
+
64 
+
66 void skip_line()
+
67 {
+
68  std::cin.ignore(std::numeric_limits<int>::max(), '\n');
+
69 }
+
70 
+
79 bool get_record(std::vector<std::string>& names,
+
80  std::vector<int>& heights,
+
81  std::vector<int>& weights,
+
82  std::vector<char>& sexes)
+
83 {
+
84  std::string name{};
+
85  int height{0};
+
86  int weight{0};
+
87  char sex{'?'};
+
88 
+
89  std::cout << "Name " << names.size()+1 << ": ";
+
90  if (not std::getline(std::cin, name))
+
91  return false;
+
92 
+
93  // Enforce minimal sanity check on the height, which must be
+
94  // between 10 and 300 cm, or baby- to giant-size.
+
95  int const min_height{10};
+
96  int const max_height{300};
+
97  std::cout << "Height (cm): ";
+
98  if (not (std::cin >> height))
+
99  return false;
+
100  skip_line();
+
101  if (height < min_height or height > max_height)
+
102  {
+
103  std::cout << "Invalid height. Aborting.\n";
+
104  return false;
+
105  }
+
106 
+
107  // Enforce minimal sanity check on the weight, which must
+
108  // be between premature-baby and giant size.
+
109  int const min_weight{1};
+
110  int const max_weight{500};
+
111  std::cout << "Weight (kg): ";
+
112  if (not (std::cin >> weight))
+
113  return false;
+
114  skip_line();
+
115  if (weight < min_weight or weight > max_weight)
+
116  {
+
117  std::cout << "Invalid weight. Aborting.\n";
+
118  return false;
+
119  }
+
120 
+
121  std::cout << "Sex (M or F): ";
+
122  if (not (std::cin >> sex))
+
123  return false;
+
124  skip_line();
+
125  sex = std::toupper(sex, std::locale());
+
126  if (sex != 'M' and sex != 'F')
+
127  {
+
128  std::cout << "Invalid sex. Aborting.\n";
+
129  return false;
+
130  }
+
131 
+
132  // All information has now been collected, so
+
133  // append it all to the respective vectors.
+
134  names.push_back(name);
+
135  heights.push_back(height);
+
136  weights.push_back(weight);
+
137  sexes.push_back(sex);
+
138 
+
139  return true;
+
140 }
+
141 
+
155 void print_table(char sex,
+
156  std::vector<int> const& heights,
+
157  std::vector<int> const& weights,
+
158  std::vector<int> const& bmis,
+
159  std::vector<char> const& sexes,
+
160  std::vector<std::string> const& names,
+
161  int threshold)
+
162 {
+
163  std::cout << "Ht(cm) Wt(kg) Sex BMI Name\n";
+
164 
+
165  float bmi_sum(0);
+
166  long int bmi_count(0);
+
167  std::vector<int> tmpbmis; // store only the BMIs that are printed
+
168  // to compute the median
+
169  for (std::vector<int>::size_type i(0); i != heights.size(); ++i)
+
170  if (sexes.at(i) == sex)
+
171  {
+
172  bmi_sum = bmi_sum + bmis.at(i);
+
173  ++bmi_count;
+
174  tmpbmis.push_back(bmis.at(i));
+
175  std::cout << std::setw(6) << heights.at(i)
+
176  << std::setw(7) << weights.at(i)
+
177  << std::setw(3) << sexes.at(i)
+
178  << std::setw(6) << bmis.at(i);
+
179  if (bmis.at(i) >= threshold)
+
180  std::cout << '*';
+
181  else
+
182  std::cout << ' ';
+
183  std::cout << ' ' << names.at(i) << '\n';
+
184  }
+
185 
+
186  // If the vectors are not empty, print basic statistics.
+
187  if (bmi_count != 0)
+
188  {
+
189  std::cout << "Mean BMI = "
+
190  << std::setprecision(1) << std::fixed << bmi_sum / bmi_count
+
191  << '\n';
+
192 
+
193  // Median BMI is trickier. The easy way is to sort the
+
194  // array and pick out the middle item or items.
+
195  std::sort(tmpbmis.begin(), tmpbmis.end());
+
196  std::cout << "Median BMI = ";
+
197  // Index of median item.
+
198  int i(tmpbmis.size() / 2);
+
199  if (tmpbmis.size() % 2 == 0)
+
200  std::cout << (tmpbmis.at(i) + tmpbmis.at(i-1)) / 2.0 << '\n';
+
201  else
+
202  std::cout << tmpbmis.at(i) << '\n';
+
203  }
+
204 }
+
205 
+
207 int main()
+
208 {
+
209  std::locale::global(std::locale{""});
+
210  std::cout.imbue(std::locale{});
+
211  std::cin.imbue(std::locale{});
+
212 
+
213  std::vector<std::string> names{};
+
214  std::vector<int> heights{};
+
215  std::vector<int> weights{};
+
216  std::vector<char> sexes{};
+
217  std::vector<int> bmis{};
+
218  int threshold{};
+
219 
+
220  std::cout << "Enter threshold BMI: ";
+
221  if (not (std::cin >> threshold))
+
222  return EXIT_FAILURE;
+
223  skip_line();
+
224 
+
225  std::cout << "Enter name, height (in cm),"
+
226  " and weight (in kg) for each person:\n";
+
227  while (get_record(names, heights, weights, sexes))
+
228  {
+
229  int bmi{compute_bmi(heights.back(), weights.back())};
+
230  bmis.push_back(bmi);
+
231  std::cout << "BMI = " << bmi << '\n';
+
232  }
+
233 
+
234  // Print the data.
+
235  std::cout << "\n\nMale data\n";
+
236  print_table('M', heights, weights, bmis, sexes, names, threshold);
+
237  std::cout << "\nFemale data\n";
+
238  print_table('F', heights, weights, bmis, sexes, names, threshold);
+
239 }
+
int main()
Main program to compute BMI.
Definition: bmi.cpp:207
+
void skip_line()
Skip the rest of the input line.
Definition: bmi.cpp:66
+
void print_table(char sex, std::vector< int > const &heights, std::vector< int > const &weights, std::vector< int > const &bmis, std::vector< char > const &sexes, std::vector< std::string > const &names, int threshold)
Print a table. Print a table of height, weight, sex, BMI, and name. Print only records for which sex ...
Definition: bmi.cpp:155
+
int compute_bmi(int height, int weight)
Compute the body-mass index (BMI). The height is in centimeters, so the computed value is off by 10...
Definition: bmi.cpp:60
+
bool get_record(std::vector< std::string > &names, std::vector< int > &heights, std::vector< int > &weights, std::vector< char > &sexes)
Get a single person&#39;s record. Store the name, height, weight, and sex in the supplied vectors...
Definition: bmi.cpp:79
+
+ + + + diff --git a/exploring-cpp-2e/chapter28/html/closed.png b/exploring-cpp-2e/chapter28/html/closed.png new file mode 100644 index 0000000..98cc2c9 Binary files /dev/null and b/exploring-cpp-2e/chapter28/html/closed.png differ diff --git a/exploring-cpp-2e/chapter28/html/dir_06b735e75e1729acd777fffa105eeb3c.html b/exploring-cpp-2e/chapter28/html/dir_06b735e75e1729acd777fffa105eeb3c.html new file mode 100644 index 0000000..ce27c22 --- /dev/null +++ b/exploring-cpp-2e/chapter28/html/dir_06b735e75e1729acd777fffa105eeb3c.html @@ -0,0 +1,59 @@ + + + + + + +Project 1 - Body-mass index: /home/ray/writing Directory Reference + + + + + + +
+
+ + + + + + +
+
Project 1 - Body-mass index +
+
+
+ + + + +
+
+
+
writing Directory Reference
+
+
+ + + + +

+Directories

directory  books
 
+
+ + + + diff --git a/exploring-cpp-2e/chapter28/html/dir_25d354bf040ec750e0120f0982f53261.html b/exploring-cpp-2e/chapter28/html/dir_25d354bf040ec750e0120f0982f53261.html new file mode 100644 index 0000000..a113c03 --- /dev/null +++ b/exploring-cpp-2e/chapter28/html/dir_25d354bf040ec750e0120f0982f53261.html @@ -0,0 +1,59 @@ + + + + + + +Project 1 - Body-mass index: /home/ray/writing/books/exploring-cpp-2ed Directory Reference + + + + + + +
+
+ + + + + + +
+
Project 1 - Body-mass index +
+
+
+ + + + +
+
+
+
exploring-cpp-2ed Directory Reference
+
+
+ + + + +

+Directories

directory  final
 
+
+ + + + diff --git a/exploring-cpp-2e/chapter28/html/dir_3ace0cce4a09856c37b63fc59133c1d5.html b/exploring-cpp-2e/chapter28/html/dir_3ace0cce4a09856c37b63fc59133c1d5.html new file mode 100644 index 0000000..f164b42 --- /dev/null +++ b/exploring-cpp-2e/chapter28/html/dir_3ace0cce4a09856c37b63fc59133c1d5.html @@ -0,0 +1,59 @@ + + + + + + +Project 1 - Body-mass index: /home/ray/writing/books/exploring-cpp-2ed/final Directory Reference + + + + + + +
+
+ + + + + + +
+
Project 1 - Body-mass index +
+
+
+ + + + +
+
+
+
final Directory Reference
+
+
+ + + + +

+Directories

directory  code
 
+
+ + + + diff --git a/exploring-cpp-2e/chapter28/html/dir_44a7aa12b37f765906d213dbffd75e5b.html b/exploring-cpp-2e/chapter28/html/dir_44a7aa12b37f765906d213dbffd75e5b.html new file mode 100644 index 0000000..912cd7c --- /dev/null +++ b/exploring-cpp-2e/chapter28/html/dir_44a7aa12b37f765906d213dbffd75e5b.html @@ -0,0 +1,60 @@ + + + + + + +Project 1 - Body-mass index: /home/ray/writing/books/exploring-cpp-2ed/final/code/chapter28 Directory Reference + + + + + + +
+
+ + + + + + +
+
Project 1 - Body-mass index +
+
+
+ + + + +
+
+
+
chapter28 Directory Reference
+
+
+ + + + + +

+Files

file  bmi.cpp [code]
 Compute body-mass index.
 
+
+ + + + diff --git a/exploring-cpp-2e/chapter28/html/dir_5961eda7cb40d774174e8610beb281e0.html b/exploring-cpp-2e/chapter28/html/dir_5961eda7cb40d774174e8610beb281e0.html new file mode 100644 index 0000000..ae4304f --- /dev/null +++ b/exploring-cpp-2e/chapter28/html/dir_5961eda7cb40d774174e8610beb281e0.html @@ -0,0 +1,59 @@ + + + + + + +Project 1 - Body-mass index: /home/ray Directory Reference + + + + + + +
+
+ + + + + + +
+
Project 1 - Body-mass index +
+
+
+ + + + +
+
+
+
ray Directory Reference
+
+
+ + + + +

+Directories

directory  writing
 
+
+ + + + diff --git a/exploring-cpp-2e/chapter28/html/dir_c5ea0433b6dfcb1f127a5cb7025cefc4.html b/exploring-cpp-2e/chapter28/html/dir_c5ea0433b6dfcb1f127a5cb7025cefc4.html new file mode 100644 index 0000000..b28f257 --- /dev/null +++ b/exploring-cpp-2e/chapter28/html/dir_c5ea0433b6dfcb1f127a5cb7025cefc4.html @@ -0,0 +1,59 @@ + + + + + + +Project 1 - Body-mass index: /home/ray/writing/books/exploring-cpp-2ed/final/code Directory Reference + + + + + + +
+
+ + + + + + +
+
Project 1 - Body-mass index +
+
+
+ + + + +
+
+
+
code Directory Reference
+
+
+ + + + +

+Directories

directory  chapter28
 
+
+ + + + diff --git a/exploring-cpp-2e/chapter28/html/dir_d853d10112248e27eccab5e513c2663b.html b/exploring-cpp-2e/chapter28/html/dir_d853d10112248e27eccab5e513c2663b.html new file mode 100644 index 0000000..0c3c542 --- /dev/null +++ b/exploring-cpp-2e/chapter28/html/dir_d853d10112248e27eccab5e513c2663b.html @@ -0,0 +1,59 @@ + + + + + + +Project 1 - Body-mass index: /home/ray/writing/books Directory Reference + + + + + + +
+
+ + + + + + +
+
Project 1 - Body-mass index +
+
+
+ + + + +
+
+
+
books Directory Reference
+
+
+ + + + +

+Directories

directory  exploring-cpp-2ed
 
+
+ + + + diff --git a/exploring-cpp-2e/chapter28/html/doxygen.css b/exploring-cpp-2e/chapter28/html/doxygen.css new file mode 100644 index 0000000..4699e69 --- /dev/null +++ b/exploring-cpp-2e/chapter28/html/doxygen.css @@ -0,0 +1,1357 @@ +/* The standard CSS for doxygen 1.8.5 */ + +body, table, div, p, dl { + font: 400 14px/22px Roboto,sans-serif; +} + +/* @group Heading Levels */ + +h1.groupheader { + font-size: 150%; +} + +.title { + font: 400 14px/28px Roboto,sans-serif; + font-size: 150%; + font-weight: bold; + margin: 10px 2px; +} + +h2.groupheader { + border-bottom: 1px solid #879ECB; + color: #354C7B; + font-size: 150%; + font-weight: normal; + margin-top: 1.75em; + padding-top: 8px; + padding-bottom: 4px; + width: 100%; +} + +h3.groupheader { + font-size: 100%; +} + +h1, h2, h3, h4, h5, h6 { + -webkit-transition: text-shadow 0.5s linear; + -moz-transition: text-shadow 0.5s linear; + -ms-transition: text-shadow 0.5s linear; + -o-transition: text-shadow 0.5s linear; + transition: text-shadow 0.5s linear; + margin-right: 15px; +} + +h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { + text-shadow: 0 0 15px cyan; +} + +dt { + font-weight: bold; +} + +div.multicol { + -moz-column-gap: 1em; + -webkit-column-gap: 1em; + -moz-column-count: 3; + -webkit-column-count: 3; +} + +p.startli, p.startdd, p.starttd { + margin-top: 2px; +} + +p.endli { + margin-bottom: 0px; +} + +p.enddd { + margin-bottom: 4px; +} + +p.endtd { + margin-bottom: 2px; +} + +/* @end */ + +caption { + font-weight: bold; +} + +span.legend { + font-size: 70%; + text-align: center; +} + +h3.version { + font-size: 90%; + text-align: center; +} + +div.qindex, div.navtab{ + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; +} + +div.qindex, div.navpath { + width: 100%; + line-height: 140%; +} + +div.navtab { + margin-right: 15px; +} + +/* @group Link Styling */ + +a { + color: #3D578C; + font-weight: normal; + text-decoration: none; +} + +.contents a:visited { + color: #4665A2; +} + +a:hover { + text-decoration: underline; +} + +a.qindex { + font-weight: bold; +} + +a.qindexHL { + font-weight: bold; + background-color: #9CAFD4; + color: #ffffff; + border: 1px double #869DCA; +} + +.contents a.qindexHL:visited { + color: #ffffff; +} + +a.el { + font-weight: bold; +} + +a.elRef { +} + +a.code, a.code:visited, a.line, a.line:visited { + color: #4665A2; +} + +a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited { + color: #4665A2; +} + +/* @end */ + +dl.el { + margin-left: -1cm; +} + +pre.fragment { + border: 1px solid #C4CFE5; + background-color: #FBFCFD; + padding: 4px 6px; + margin: 4px 8px 4px 2px; + overflow: auto; + word-wrap: break-word; + font-size: 9pt; + line-height: 125%; + font-family: monospace, fixed; + font-size: 105%; +} + +div.fragment { + padding: 0px; + margin: 0px; + background-color: #FBFCFD; + border: 1px solid #C4CFE5; +} + +div.line { + font-family: monospace, fixed; + font-size: 13px; + min-height: 13px; + line-height: 1.0; + text-wrap: unrestricted; + white-space: -moz-pre-wrap; /* Moz */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + white-space: pre-wrap; /* CSS3 */ + word-wrap: break-word; /* IE 5.5+ */ + text-indent: -53px; + padding-left: 53px; + padding-bottom: 0px; + margin: 0px; + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +div.line.glow { + background-color: cyan; + box-shadow: 0 0 10px cyan; +} + + +span.lineno { + padding-right: 4px; + text-align: right; + border-right: 2px solid #0F0; + background-color: #E8E8E8; + white-space: pre; +} +span.lineno a { + background-color: #D8D8D8; +} + +span.lineno a:hover { + background-color: #C8C8C8; +} + +div.ah { + background-color: black; + font-weight: bold; + color: #ffffff; + margin-bottom: 3px; + margin-top: 3px; + padding: 0.2em; + border: solid thin #333; + border-radius: 0.5em; + -webkit-border-radius: .5em; + -moz-border-radius: .5em; + box-shadow: 2px 2px 3px #999; + -webkit-box-shadow: 2px 2px 3px #999; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); + background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000); +} + +div.groupHeader { + margin-left: 16px; + margin-top: 12px; + font-weight: bold; +} + +div.groupText { + margin-left: 16px; + font-style: italic; +} + +body { + background-color: white; + color: black; + margin: 0; +} + +div.contents { + margin-top: 10px; + margin-left: 12px; + margin-right: 8px; +} + +td.indexkey { + background-color: #EBEFF6; + font-weight: bold; + border: 1px solid #C4CFE5; + margin: 2px 0px 2px 0; + padding: 2px 10px; + white-space: nowrap; + vertical-align: top; +} + +td.indexvalue { + background-color: #EBEFF6; + border: 1px solid #C4CFE5; + padding: 2px 10px; + margin: 2px 0px; +} + +tr.memlist { + background-color: #EEF1F7; +} + +p.formulaDsp { + text-align: center; +} + +img.formulaDsp { + +} + +img.formulaInl { + vertical-align: middle; +} + +div.center { + text-align: center; + margin-top: 0px; + margin-bottom: 0px; + padding: 0px; +} + +div.center img { + border: 0px; +} + +address.footer { + text-align: right; + padding-right: 12px; +} + +img.footer { + border: 0px; + vertical-align: middle; +} + +/* @group Code Colorization */ + +span.keyword { + color: #008000 +} + +span.keywordtype { + color: #604020 +} + +span.keywordflow { + color: #e08000 +} + +span.comment { + color: #800000 +} + +span.preprocessor { + color: #806020 +} + +span.stringliteral { + color: #002080 +} + +span.charliteral { + color: #008080 +} + +span.vhdldigit { + color: #ff00ff +} + +span.vhdlchar { + color: #000000 +} + +span.vhdlkeyword { + color: #700070 +} + +span.vhdllogic { + color: #ff0000 +} + +blockquote { + background-color: #F7F8FB; + border-left: 2px solid #9CAFD4; + margin: 0 24px 0 4px; + padding: 0 12px 0 16px; +} + +/* @end */ + +/* +.search { + color: #003399; + font-weight: bold; +} + +form.search { + margin-bottom: 0px; + margin-top: 0px; +} + +input.search { + font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #e8eef2; +} +*/ + +td.tiny { + font-size: 75%; +} + +.dirtab { + padding: 4px; + border-collapse: collapse; + border: 1px solid #A3B4D7; +} + +th.dirtab { + background: #EBEFF6; + font-weight: bold; +} + +hr { + height: 0px; + border: none; + border-top: 1px solid #4A6AAA; +} + +hr.footer { + height: 1px; +} + +/* @group Member Descriptions */ + +table.memberdecls { + border-spacing: 0px; + padding: 0px; +} + +.memberdecls td, .fieldtable tr { + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +.memberdecls td.glow, .fieldtable tr.glow { + background-color: cyan; + box-shadow: 0 0 15px cyan; +} + +.mdescLeft, .mdescRight, +.memItemLeft, .memItemRight, +.memTemplItemLeft, .memTemplItemRight, .memTemplParams { + background-color: #F9FAFC; + border: none; + margin: 4px; + padding: 1px 0 0 8px; +} + +.mdescLeft, .mdescRight { + padding: 0px 8px 4px 8px; + color: #555; +} + +.memSeparator { + border-bottom: 1px solid #DEE4F0; + line-height: 1px; + margin: 0px; + padding: 0px; +} + +.memItemLeft, .memTemplItemLeft { + white-space: nowrap; +} + +.memItemRight { + width: 100%; +} + +.memTemplParams { + color: #4665A2; + white-space: nowrap; + font-size: 80%; +} + +/* @end */ + +/* @group Member Details */ + +/* Styles for detailed member documentation */ + +.memtemplate { + font-size: 80%; + color: #4665A2; + font-weight: normal; + margin-left: 9px; +} + +.memnav { + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} + +.mempage { + width: 100%; +} + +.memitem { + padding: 0; + margin-bottom: 10px; + margin-right: 5px; + -webkit-transition: box-shadow 0.5s linear; + -moz-transition: box-shadow 0.5s linear; + -ms-transition: box-shadow 0.5s linear; + -o-transition: box-shadow 0.5s linear; + transition: box-shadow 0.5s linear; + display: table !important; + width: 100%; +} + +.memitem.glow { + box-shadow: 0 0 15px cyan; +} + +.memname { + font-weight: bold; + margin-left: 6px; +} + +.memname td { + vertical-align: bottom; +} + +.memproto, dl.reflist dt { + border-top: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 0px 6px 0px; + color: #253555; + font-weight: bold; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + /* opera specific markup */ + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + border-top-right-radius: 4px; + border-top-left-radius: 4px; + /* firefox specific markup */ + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + -moz-border-radius-topright: 4px; + -moz-border-radius-topleft: 4px; + /* webkit specific markup */ + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + -webkit-border-top-right-radius: 4px; + -webkit-border-top-left-radius: 4px; + +} + +.memdoc, dl.reflist dd { + border-bottom: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 10px 2px 10px; + background-color: #FBFCFD; + border-top-width: 0; + background-image:url('nav_g.png'); + background-repeat:repeat-x; + background-color: #FFFFFF; + /* opera specific markup */ + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + /* firefox specific markup */ + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-bottomright: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + /* webkit specific markup */ + -webkit-border-bottom-left-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); +} + +dl.reflist dt { + padding: 5px; +} + +dl.reflist dd { + margin: 0px 0px 10px 0px; + padding: 5px; +} + +.paramkey { + text-align: right; +} + +.paramtype { + white-space: nowrap; +} + +.paramname { + color: #602020; + white-space: nowrap; +} +.paramname em { + font-style: normal; +} +.paramname code { + line-height: 14px; +} + +.params, .retval, .exception, .tparams { + margin-left: 0px; + padding-left: 0px; +} + +.params .paramname, .retval .paramname { + font-weight: bold; + vertical-align: top; +} + +.params .paramtype { + font-style: italic; + vertical-align: top; +} + +.params .paramdir { + font-family: "courier new",courier,monospace; + vertical-align: top; +} + +table.mlabels { + border-spacing: 0px; +} + +td.mlabels-left { + width: 100%; + padding: 0px; +} + +td.mlabels-right { + vertical-align: bottom; + padding: 0px; + white-space: nowrap; +} + +span.mlabels { + margin-left: 8px; +} + +span.mlabel { + background-color: #728DC1; + border-top:1px solid #5373B4; + border-left:1px solid #5373B4; + border-right:1px solid #C4CFE5; + border-bottom:1px solid #C4CFE5; + text-shadow: none; + color: white; + margin-right: 4px; + padding: 2px 3px; + border-radius: 3px; + font-size: 7pt; + white-space: nowrap; + vertical-align: middle; +} + + + +/* @end */ + +/* these are for tree view when not used as main index */ + +div.directory { + margin: 10px 0px; + border-top: 1px solid #A8B8D9; + border-bottom: 1px solid #A8B8D9; + width: 100%; +} + +.directory table { + border-collapse:collapse; +} + +.directory td { + margin: 0px; + padding: 0px; + vertical-align: top; +} + +.directory td.entry { + white-space: nowrap; + padding-right: 6px; + padding-top: 3px; +} + +.directory td.entry a { + outline:none; +} + +.directory td.entry a img { + border: none; +} + +.directory td.desc { + width: 100%; + padding-left: 6px; + padding-right: 6px; + padding-top: 3px; + border-left: 1px solid rgba(0,0,0,0.05); +} + +.directory tr.even { + padding-left: 6px; + background-color: #F7F8FB; +} + +.directory img { + vertical-align: -30%; +} + +.directory .levels { + white-space: nowrap; + width: 100%; + text-align: right; + font-size: 9pt; +} + +.directory .levels span { + cursor: pointer; + padding-left: 2px; + padding-right: 2px; + color: #3D578C; +} + +div.dynheader { + margin-top: 8px; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +address { + font-style: normal; + color: #2A3D61; +} + +table.doxtable { + border-collapse:collapse; + margin-top: 4px; + margin-bottom: 4px; +} + +table.doxtable td, table.doxtable th { + border: 1px solid #2D4068; + padding: 3px 7px 2px; +} + +table.doxtable th { + background-color: #374F7F; + color: #FFFFFF; + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; +} + +table.fieldtable { + /*width: 100%;*/ + margin-bottom: 10px; + border: 1px solid #A8B8D9; + border-spacing: 0px; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + border-radius: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); +} + +.fieldtable td, .fieldtable th { + padding: 3px 7px 2px; +} + +.fieldtable td.fieldtype, .fieldtable td.fieldname { + white-space: nowrap; + border-right: 1px solid #A8B8D9; + border-bottom: 1px solid #A8B8D9; + vertical-align: top; +} + +.fieldtable td.fieldname { + padding-top: 3px; +} + +.fieldtable td.fielddoc { + border-bottom: 1px solid #A8B8D9; + /*width: 100%;*/ +} + +.fieldtable td.fielddoc p:first-child { + margin-top: 0px; +} + +.fieldtable td.fielddoc p:last-child { + margin-bottom: 2px; +} + +.fieldtable tr:last-child td { + border-bottom: none; +} + +.fieldtable th { + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + font-size: 90%; + color: #253555; + padding-bottom: 4px; + padding-top: 5px; + text-align:left; + -moz-border-radius-topleft: 4px; + -moz-border-radius-topright: 4px; + -webkit-border-top-left-radius: 4px; + -webkit-border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom: 1px solid #A8B8D9; +} + + +.tabsearch { + top: 0px; + left: 10px; + height: 36px; + background-image: url('tab_b.png'); + z-index: 101; + overflow: hidden; + font-size: 13px; +} + +.navpath ul +{ + font-size: 11px; + background-image:url('tab_b.png'); + background-repeat:repeat-x; + background-position: 0 -5px; + height:30px; + line-height:30px; + color:#8AA0CC; + border:solid 1px #C2CDE4; + overflow:hidden; + margin:0px; + padding:0px; +} + +.navpath li +{ + list-style-type:none; + float:left; + padding-left:10px; + padding-right:15px; + background-image:url('bc_s.png'); + background-repeat:no-repeat; + background-position:right; + color:#364D7C; +} + +.navpath li.navelem a +{ + height:32px; + display:block; + text-decoration: none; + outline: none; + color: #283A5D; + font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + text-decoration: none; +} + +.navpath li.navelem a:hover +{ + color:#6884BD; +} + +.navpath li.footer +{ + list-style-type:none; + float:right; + padding-left:10px; + padding-right:15px; + background-image:none; + background-repeat:no-repeat; + background-position:right; + color:#364D7C; + font-size: 8pt; +} + + +div.summary +{ + float: right; + font-size: 8pt; + padding-right: 5px; + width: 50%; + text-align: right; +} + +div.summary a +{ + white-space: nowrap; +} + +div.ingroups +{ + font-size: 8pt; + width: 50%; + text-align: left; +} + +div.ingroups a +{ + white-space: nowrap; +} + +div.header +{ + background-image:url('nav_h.png'); + background-repeat:repeat-x; + background-color: #F9FAFC; + margin: 0px; + border-bottom: 1px solid #C4CFE5; +} + +div.headertitle +{ + padding: 5px 5px 5px 10px; +} + +dl +{ + padding: 0 0 0 10px; +} + +/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */ +dl.section +{ + margin-left: 0px; + padding-left: 0px; +} + +dl.note +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #D0C000; +} + +dl.warning, dl.attention +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #FF0000; +} + +dl.pre, dl.post, dl.invariant +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #00D000; +} + +dl.deprecated +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #505050; +} + +dl.todo +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #00C0E0; +} + +dl.test +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #3030E0; +} + +dl.bug +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #C08050; +} + +dl.section dd { + margin-bottom: 6px; +} + + +#projectlogo +{ + text-align: center; + vertical-align: bottom; + border-collapse: separate; +} + +#projectlogo img +{ + border: 0px none; +} + +#projectname +{ + font: 300% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 2px 0px; +} + +#projectbrief +{ + font: 120% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#projectnumber +{ + font: 50% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#titlearea +{ + padding: 0px; + margin: 0px; + width: 100%; + border-bottom: 1px solid #5373B4; +} + +.image +{ + text-align: center; +} + +.dotgraph +{ + text-align: center; +} + +.mscgraph +{ + text-align: center; +} + +.caption +{ + font-weight: bold; +} + +div.zoom +{ + border: 1px solid #90A5CE; +} + +dl.citelist { + margin-bottom:50px; +} + +dl.citelist dt { + color:#334975; + float:left; + font-weight:bold; + margin-right:10px; + padding:5px; +} + +dl.citelist dd { + margin:2px 0; + padding:5px 0; +} + +div.toc { + padding: 14px 25px; + background-color: #F4F6FA; + border: 1px solid #D8DFEE; + border-radius: 7px 7px 7px 7px; + float: right; + height: auto; + margin: 0 20px 10px 10px; + width: 200px; +} + +div.toc li { + background: url("bdwn.png") no-repeat scroll 0 5px transparent; + font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif; + margin-top: 5px; + padding-left: 10px; + padding-top: 2px; +} + +div.toc h3 { + font: bold 12px/1.2 Arial,FreeSans,sans-serif; + color: #4665A2; + border-bottom: 0 none; + margin: 0; +} + +div.toc ul { + list-style: none outside none; + border: medium none; + padding: 0px; +} + +div.toc li.level1 { + margin-left: 0px; +} + +div.toc li.level2 { + margin-left: 15px; +} + +div.toc li.level3 { + margin-left: 30px; +} + +div.toc li.level4 { + margin-left: 45px; +} + +.inherit_header { + font-weight: bold; + color: gray; + cursor: pointer; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.inherit_header td { + padding: 6px 0px 2px 5px; +} + +.inherit { + display: none; +} + +tr.heading h2 { + margin-top: 12px; + margin-bottom: 4px; +} + +/* tooltip related style info */ + +.ttc { + position: absolute; + display: none; +} + +#powerTip { + cursor: default; + white-space: nowrap; + background-color: white; + border: 1px solid gray; + border-radius: 4px 4px 4px 4px; + box-shadow: 1px 1px 7px gray; + display: none; + font-size: smaller; + max-width: 80%; + opacity: 0.9; + padding: 1ex 1em 1em; + position: absolute; + z-index: 2147483647; +} + +#powerTip div.ttdoc { + color: grey; + font-style: italic; +} + +#powerTip div.ttname a { + font-weight: bold; +} + +#powerTip div.ttname { + font-weight: bold; +} + +#powerTip div.ttdeci { + color: #006318; +} + +#powerTip div { + margin: 0px; + padding: 0px; + font: 12px/16px Roboto,sans-serif; +} + +#powerTip:before, #powerTip:after { + content: ""; + position: absolute; + margin: 0px; +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.s:after, #powerTip.s:before, +#powerTip.w:after, #powerTip.w:before, +#powerTip.e:after, #powerTip.e:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.nw:after, #powerTip.nw:before, +#powerTip.sw:after, #powerTip.sw:before { + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; +} + +#powerTip.n:after, #powerTip.s:after, +#powerTip.w:after, #powerTip.e:after, +#powerTip.nw:after, #powerTip.ne:after, +#powerTip.sw:after, #powerTip.se:after { + border-color: rgba(255, 255, 255, 0); +} + +#powerTip.n:before, #powerTip.s:before, +#powerTip.w:before, #powerTip.e:before, +#powerTip.nw:before, #powerTip.ne:before, +#powerTip.sw:before, #powerTip.se:before { + border-color: rgba(128, 128, 128, 0); +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.nw:after, #powerTip.nw:before { + top: 100%; +} + +#powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after { + border-top-color: #ffffff; + border-width: 10px; + margin: 0px -10px; +} +#powerTip.n:before { + border-top-color: #808080; + border-width: 11px; + margin: 0px -11px; +} +#powerTip.n:after, #powerTip.n:before { + left: 50%; +} + +#powerTip.nw:after, #powerTip.nw:before { + right: 14px; +} + +#powerTip.ne:after, #powerTip.ne:before { + left: 14px; +} + +#powerTip.s:after, #powerTip.s:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.sw:after, #powerTip.sw:before { + bottom: 100%; +} + +#powerTip.s:after, #powerTip.se:after, #powerTip.sw:after { + border-bottom-color: #ffffff; + border-width: 10px; + margin: 0px -10px; +} + +#powerTip.s:before, #powerTip.se:before, #powerTip.sw:before { + border-bottom-color: #808080; + border-width: 11px; + margin: 0px -11px; +} + +#powerTip.s:after, #powerTip.s:before { + left: 50%; +} + +#powerTip.sw:after, #powerTip.sw:before { + right: 14px; +} + +#powerTip.se:after, #powerTip.se:before { + left: 14px; +} + +#powerTip.e:after, #powerTip.e:before { + left: 100%; +} +#powerTip.e:after { + border-left-color: #ffffff; + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.e:before { + border-left-color: #808080; + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +#powerTip.w:after, #powerTip.w:before { + right: 100%; +} +#powerTip.w:after { + border-right-color: #ffffff; + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.w:before { + border-right-color: #808080; + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +@media print +{ + #top { display: none; } + #side-nav { display: none; } + #nav-path { display: none; } + body { overflow:visible; } + h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } + .summary { display: none; } + .memitem { page-break-inside: avoid; } + #doc-content + { + margin-left:0 !important; + height:auto !important; + width:auto !important; + overflow:inherit; + display:inline; + } +} + diff --git a/exploring-cpp-2e/chapter28/html/doxygen.png b/exploring-cpp-2e/chapter28/html/doxygen.png new file mode 100644 index 0000000..3ff17d8 Binary files /dev/null and b/exploring-cpp-2e/chapter28/html/doxygen.png differ diff --git a/exploring-cpp-2e/chapter28/html/dynsections.js b/exploring-cpp-2e/chapter28/html/dynsections.js new file mode 100644 index 0000000..2f15470 --- /dev/null +++ b/exploring-cpp-2e/chapter28/html/dynsections.js @@ -0,0 +1,104 @@ +function toggleVisibility(linkObj) +{ + var base = $(linkObj).attr('id'); + var summary = $('#'+base+'-summary'); + var content = $('#'+base+'-content'); + var trigger = $('#'+base+'-trigger'); + var src=$(trigger).attr('src'); + if (content.is(':visible')===true) { + content.hide(); + summary.show(); + $(linkObj).addClass('closed').removeClass('opened'); + $(trigger).attr('src',src.substring(0,src.length-8)+'closed.png'); + } else { + content.show(); + summary.hide(); + $(linkObj).removeClass('closed').addClass('opened'); + $(trigger).attr('src',src.substring(0,src.length-10)+'open.png'); + } + return false; +} + +function updateStripes() +{ + $('table.directory tr'). + removeClass('even').filter(':visible:even').addClass('even'); +} +function toggleLevel(level) +{ + $('table.directory tr').each(function(){ + var l = this.id.split('_').length-1; + var i = $('#img'+this.id.substring(3)); + var a = $('#arr'+this.id.substring(3)); + if (l + + + + + +Project 1 - Body-mass index: File List + + + + + + +
+
+ + + + + + +
+
Project 1 - Body-mass index +
+
+
+ + + + +
+
+
+
File List
+
+
+
Here is a list of all documented files with brief descriptions:
+
[detail level 12345678]
+ + + + + + + + +
\-ray
 \-writing
  \-books
   \-exploring-cpp-2ed
    \-final
     \-code
      \-chapter28
       \*bmi.cppCompute body-mass index
+
+
+ + + + diff --git a/exploring-cpp-2e/chapter28/html/ftv2blank.png b/exploring-cpp-2e/chapter28/html/ftv2blank.png new file mode 100644 index 0000000..63c605b Binary files /dev/null and b/exploring-cpp-2e/chapter28/html/ftv2blank.png differ diff --git a/exploring-cpp-2e/chapter28/html/ftv2cl.png b/exploring-cpp-2e/chapter28/html/ftv2cl.png new file mode 100644 index 0000000..132f657 Binary files /dev/null and b/exploring-cpp-2e/chapter28/html/ftv2cl.png differ diff --git a/exploring-cpp-2e/chapter28/html/ftv2doc.png b/exploring-cpp-2e/chapter28/html/ftv2doc.png new file mode 100644 index 0000000..17edabf Binary files /dev/null and b/exploring-cpp-2e/chapter28/html/ftv2doc.png differ diff --git a/exploring-cpp-2e/chapter28/html/ftv2folderclosed.png b/exploring-cpp-2e/chapter28/html/ftv2folderclosed.png new file mode 100644 index 0000000..bb8ab35 Binary files /dev/null and b/exploring-cpp-2e/chapter28/html/ftv2folderclosed.png differ diff --git a/exploring-cpp-2e/chapter28/html/ftv2folderopen.png b/exploring-cpp-2e/chapter28/html/ftv2folderopen.png new file mode 100644 index 0000000..d6c7f67 Binary files /dev/null and b/exploring-cpp-2e/chapter28/html/ftv2folderopen.png differ diff --git a/exploring-cpp-2e/chapter28/html/ftv2lastnode.png b/exploring-cpp-2e/chapter28/html/ftv2lastnode.png new file mode 100644 index 0000000..63c605b Binary files /dev/null and b/exploring-cpp-2e/chapter28/html/ftv2lastnode.png differ diff --git a/exploring-cpp-2e/chapter28/html/ftv2link.png b/exploring-cpp-2e/chapter28/html/ftv2link.png new file mode 100644 index 0000000..17edabf Binary files /dev/null and b/exploring-cpp-2e/chapter28/html/ftv2link.png differ diff --git a/exploring-cpp-2e/chapter28/html/ftv2mlastnode.png b/exploring-cpp-2e/chapter28/html/ftv2mlastnode.png new file mode 100644 index 0000000..0b63f6d Binary files /dev/null and b/exploring-cpp-2e/chapter28/html/ftv2mlastnode.png differ diff --git a/exploring-cpp-2e/chapter28/html/ftv2mnode.png b/exploring-cpp-2e/chapter28/html/ftv2mnode.png new file mode 100644 index 0000000..0b63f6d Binary files /dev/null and b/exploring-cpp-2e/chapter28/html/ftv2mnode.png differ diff --git a/exploring-cpp-2e/chapter28/html/ftv2mo.png b/exploring-cpp-2e/chapter28/html/ftv2mo.png new file mode 100644 index 0000000..4bfb80f Binary files /dev/null and b/exploring-cpp-2e/chapter28/html/ftv2mo.png differ diff --git a/exploring-cpp-2e/chapter28/html/ftv2node.png b/exploring-cpp-2e/chapter28/html/ftv2node.png new file mode 100644 index 0000000..63c605b Binary files /dev/null and b/exploring-cpp-2e/chapter28/html/ftv2node.png differ diff --git a/exploring-cpp-2e/chapter28/html/ftv2ns.png b/exploring-cpp-2e/chapter28/html/ftv2ns.png new file mode 100644 index 0000000..72e3d71 Binary files /dev/null and b/exploring-cpp-2e/chapter28/html/ftv2ns.png differ diff --git a/exploring-cpp-2e/chapter28/html/ftv2plastnode.png b/exploring-cpp-2e/chapter28/html/ftv2plastnode.png new file mode 100644 index 0000000..c6ee22f Binary files /dev/null and b/exploring-cpp-2e/chapter28/html/ftv2plastnode.png differ diff --git a/exploring-cpp-2e/chapter28/html/ftv2pnode.png b/exploring-cpp-2e/chapter28/html/ftv2pnode.png new file mode 100644 index 0000000..c6ee22f Binary files /dev/null and b/exploring-cpp-2e/chapter28/html/ftv2pnode.png differ diff --git a/exploring-cpp-2e/chapter28/html/ftv2splitbar.png b/exploring-cpp-2e/chapter28/html/ftv2splitbar.png new file mode 100644 index 0000000..fe895f2 Binary files /dev/null and b/exploring-cpp-2e/chapter28/html/ftv2splitbar.png differ diff --git a/exploring-cpp-2e/chapter28/html/ftv2vertline.png b/exploring-cpp-2e/chapter28/html/ftv2vertline.png new file mode 100644 index 0000000..63c605b Binary files /dev/null and b/exploring-cpp-2e/chapter28/html/ftv2vertline.png differ diff --git a/exploring-cpp-2e/chapter28/html/globals.html b/exploring-cpp-2e/chapter28/html/globals.html new file mode 100644 index 0000000..6524ae3 --- /dev/null +++ b/exploring-cpp-2e/chapter28/html/globals.html @@ -0,0 +1,74 @@ + + + + + + +Project 1 - Body-mass index: File Members + + + + + + +
+
+ + + + + + +
+
Project 1 - Body-mass index +
+
+
+ + + + + +
+
+
Here is a list of all documented file members with links to the documentation:
+
+ + + + diff --git a/exploring-cpp-2e/chapter28/html/globals_func.html b/exploring-cpp-2e/chapter28/html/globals_func.html new file mode 100644 index 0000000..0199244 --- /dev/null +++ b/exploring-cpp-2e/chapter28/html/globals_func.html @@ -0,0 +1,74 @@ + + + + + + +Project 1 - Body-mass index: File Members + + + + + + +
+
+ + + + + + +
+
Project 1 - Body-mass index +
+
+
+ + + + + +
+
+
+ + + + diff --git a/exploring-cpp-2e/chapter28/html/index.html b/exploring-cpp-2e/chapter28/html/index.html new file mode 100644 index 0000000..043af33 --- /dev/null +++ b/exploring-cpp-2e/chapter28/html/index.html @@ -0,0 +1,55 @@ + + + + + + +Project 1 - Body-mass index: Project 1 - Body-Mass Index + + + + + + +
+
+ + + + + + +
+
Project 1 - Body-mass index +
+
+
+ + + +
+
+
+
Project 1 - Body-Mass Index
+
+
+

This program is Project 1 in Exploring C++, by Ray Lischner (Apress).

+

Your task is to write a program that reads records, prints the records, and computes some statistics. The program starts by asking for a threshold BMI. Only records with a BMI greater than or equal to the threshold will be printed. Each record consists of a person's name (which might contain spaces), weight in kilograms, height in centimeters (not meters), and the person's sex ('M' or 'F'). Let the user enter the sex in uppercase or lowercase.

+

Print each person's BMI after reading that person's record. After collecting information for everyone, print two tables of the information. One table is for men and the other is for women. Mark records for which the BMI meets or exceeds the threshold with an asterisk after the BMI. After each table, print the mean (average) and median BMI. (Median is the value such that half the BMI values are less than the median and half are greater than the median. If the user enters an even number of records, take the average of the two values in the middle.) Compute individual BMI values as integers. Compute the mean and median BMIs as floating point numbers, and print the mean with one place after the decimal point.

+

Body-mass index is defined as weight in kg/(height in m)2, converted to a unitless number.

+

Source file: bmi.cpp

+
Author
Ray Lischner
+
+ + + + diff --git a/exploring-cpp-2e/chapter28/html/jquery.js b/exploring-cpp-2e/chapter28/html/jquery.js new file mode 100644 index 0000000..6aa2e4c --- /dev/null +++ b/exploring-cpp-2e/chapter28/html/jquery.js @@ -0,0 +1,39 @@ +/*! + * jQuery JavaScript Library v1.7.1 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Mon Nov 21 21:11:03 2011 -0500 + */ +(function(bb,L){var av=bb.document,bu=bb.navigator,bl=bb.location;var b=(function(){var bF=function(b0,b1){return new bF.fn.init(b0,b1,bD)},bU=bb.jQuery,bH=bb.$,bD,bY=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,bM=/\S/,bI=/^\s+/,bE=/\s+$/,bA=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,bN=/^[\],:{}\s]*$/,bW=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,bP=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,bJ=/(?:^|:|,)(?:\s*\[)+/g,by=/(webkit)[ \/]([\w.]+)/,bR=/(opera)(?:.*version)?[ \/]([\w.]+)/,bQ=/(msie) ([\w.]+)/,bS=/(mozilla)(?:.*? rv:([\w.]+))?/,bB=/-([a-z]|[0-9])/ig,bZ=/^-ms-/,bT=function(b0,b1){return(b1+"").toUpperCase()},bX=bu.userAgent,bV,bC,e,bL=Object.prototype.toString,bG=Object.prototype.hasOwnProperty,bz=Array.prototype.push,bK=Array.prototype.slice,bO=String.prototype.trim,bv=Array.prototype.indexOf,bx={};bF.fn=bF.prototype={constructor:bF,init:function(b0,b4,b3){var b2,b5,b1,b6;if(!b0){return this}if(b0.nodeType){this.context=this[0]=b0;this.length=1;return this}if(b0==="body"&&!b4&&av.body){this.context=av;this[0]=av.body;this.selector=b0;this.length=1;return this}if(typeof b0==="string"){if(b0.charAt(0)==="<"&&b0.charAt(b0.length-1)===">"&&b0.length>=3){b2=[null,b0,null]}else{b2=bY.exec(b0)}if(b2&&(b2[1]||!b4)){if(b2[1]){b4=b4 instanceof bF?b4[0]:b4;b6=(b4?b4.ownerDocument||b4:av);b1=bA.exec(b0);if(b1){if(bF.isPlainObject(b4)){b0=[av.createElement(b1[1])];bF.fn.attr.call(b0,b4,true)}else{b0=[b6.createElement(b1[1])]}}else{b1=bF.buildFragment([b2[1]],[b6]);b0=(b1.cacheable?bF.clone(b1.fragment):b1.fragment).childNodes}return bF.merge(this,b0)}else{b5=av.getElementById(b2[2]);if(b5&&b5.parentNode){if(b5.id!==b2[2]){return b3.find(b0)}this.length=1;this[0]=b5}this.context=av;this.selector=b0;return this}}else{if(!b4||b4.jquery){return(b4||b3).find(b0)}else{return this.constructor(b4).find(b0)}}}else{if(bF.isFunction(b0)){return b3.ready(b0)}}if(b0.selector!==L){this.selector=b0.selector;this.context=b0.context}return bF.makeArray(b0,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return bK.call(this,0)},get:function(b0){return b0==null?this.toArray():(b0<0?this[this.length+b0]:this[b0])},pushStack:function(b1,b3,b0){var b2=this.constructor();if(bF.isArray(b1)){bz.apply(b2,b1)}else{bF.merge(b2,b1)}b2.prevObject=this;b2.context=this.context;if(b3==="find"){b2.selector=this.selector+(this.selector?" ":"")+b0}else{if(b3){b2.selector=this.selector+"."+b3+"("+b0+")"}}return b2},each:function(b1,b0){return bF.each(this,b1,b0)},ready:function(b0){bF.bindReady();bC.add(b0);return this},eq:function(b0){b0=+b0;return b0===-1?this.slice(b0):this.slice(b0,b0+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(bK.apply(this,arguments),"slice",bK.call(arguments).join(","))},map:function(b0){return this.pushStack(bF.map(this,function(b2,b1){return b0.call(b2,b1,b2)}))},end:function(){return this.prevObject||this.constructor(null)},push:bz,sort:[].sort,splice:[].splice};bF.fn.init.prototype=bF.fn;bF.extend=bF.fn.extend=function(){var b9,b2,b0,b1,b6,b7,b5=arguments[0]||{},b4=1,b3=arguments.length,b8=false;if(typeof b5==="boolean"){b8=b5;b5=arguments[1]||{};b4=2}if(typeof b5!=="object"&&!bF.isFunction(b5)){b5={}}if(b3===b4){b5=this;--b4}for(;b40){return}bC.fireWith(av,[bF]);if(bF.fn.trigger){bF(av).trigger("ready").off("ready")}}},bindReady:function(){if(bC){return}bC=bF.Callbacks("once memory");if(av.readyState==="complete"){return setTimeout(bF.ready,1)}if(av.addEventListener){av.addEventListener("DOMContentLoaded",e,false);bb.addEventListener("load",bF.ready,false)}else{if(av.attachEvent){av.attachEvent("onreadystatechange",e);bb.attachEvent("onload",bF.ready);var b0=false;try{b0=bb.frameElement==null}catch(b1){}if(av.documentElement.doScroll&&b0){bw()}}}},isFunction:function(b0){return bF.type(b0)==="function"},isArray:Array.isArray||function(b0){return bF.type(b0)==="array"},isWindow:function(b0){return b0&&typeof b0==="object"&&"setInterval" in b0},isNumeric:function(b0){return !isNaN(parseFloat(b0))&&isFinite(b0)},type:function(b0){return b0==null?String(b0):bx[bL.call(b0)]||"object"},isPlainObject:function(b2){if(!b2||bF.type(b2)!=="object"||b2.nodeType||bF.isWindow(b2)){return false}try{if(b2.constructor&&!bG.call(b2,"constructor")&&!bG.call(b2.constructor.prototype,"isPrototypeOf")){return false}}catch(b1){return false}var b0;for(b0 in b2){}return b0===L||bG.call(b2,b0)},isEmptyObject:function(b1){for(var b0 in b1){return false}return true},error:function(b0){throw new Error(b0)},parseJSON:function(b0){if(typeof b0!=="string"||!b0){return null}b0=bF.trim(b0);if(bb.JSON&&bb.JSON.parse){return bb.JSON.parse(b0)}if(bN.test(b0.replace(bW,"@").replace(bP,"]").replace(bJ,""))){return(new Function("return "+b0))()}bF.error("Invalid JSON: "+b0)},parseXML:function(b2){var b0,b1;try{if(bb.DOMParser){b1=new DOMParser();b0=b1.parseFromString(b2,"text/xml")}else{b0=new ActiveXObject("Microsoft.XMLDOM");b0.async="false";b0.loadXML(b2)}}catch(b3){b0=L}if(!b0||!b0.documentElement||b0.getElementsByTagName("parsererror").length){bF.error("Invalid XML: "+b2)}return b0},noop:function(){},globalEval:function(b0){if(b0&&bM.test(b0)){(bb.execScript||function(b1){bb["eval"].call(bb,b1)})(b0)}},camelCase:function(b0){return b0.replace(bZ,"ms-").replace(bB,bT)},nodeName:function(b1,b0){return b1.nodeName&&b1.nodeName.toUpperCase()===b0.toUpperCase()},each:function(b3,b6,b2){var b1,b4=0,b5=b3.length,b0=b5===L||bF.isFunction(b3);if(b2){if(b0){for(b1 in b3){if(b6.apply(b3[b1],b2)===false){break}}}else{for(;b40&&b0[0]&&b0[b1-1])||b1===0||bF.isArray(b0));if(b3){for(;b21?aJ.call(arguments,0):bG;if(!(--bw)){bC.resolveWith(bC,bx)}}}function bz(bF){return function(bG){bB[bF]=arguments.length>1?aJ.call(arguments,0):bG;bC.notifyWith(bE,bB)}}if(e>1){for(;bv
a";bI=bv.getElementsByTagName("*");bF=bv.getElementsByTagName("a")[0];if(!bI||!bI.length||!bF){return{}}bG=av.createElement("select");bx=bG.appendChild(av.createElement("option"));bE=bv.getElementsByTagName("input")[0];bJ={leadingWhitespace:(bv.firstChild.nodeType===3),tbody:!bv.getElementsByTagName("tbody").length,htmlSerialize:!!bv.getElementsByTagName("link").length,style:/top/.test(bF.getAttribute("style")),hrefNormalized:(bF.getAttribute("href")==="/a"),opacity:/^0.55/.test(bF.style.opacity),cssFloat:!!bF.style.cssFloat,checkOn:(bE.value==="on"),optSelected:bx.selected,getSetAttribute:bv.className!=="t",enctype:!!av.createElement("form").enctype,html5Clone:av.createElement("nav").cloneNode(true).outerHTML!=="<:nav>",submitBubbles:true,changeBubbles:true,focusinBubbles:false,deleteExpando:true,noCloneEvent:true,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableMarginRight:true};bE.checked=true;bJ.noCloneChecked=bE.cloneNode(true).checked;bG.disabled=true;bJ.optDisabled=!bx.disabled;try{delete bv.test}catch(bC){bJ.deleteExpando=false}if(!bv.addEventListener&&bv.attachEvent&&bv.fireEvent){bv.attachEvent("onclick",function(){bJ.noCloneEvent=false});bv.cloneNode(true).fireEvent("onclick")}bE=av.createElement("input");bE.value="t";bE.setAttribute("type","radio");bJ.radioValue=bE.value==="t";bE.setAttribute("checked","checked");bv.appendChild(bE);bD=av.createDocumentFragment();bD.appendChild(bv.lastChild);bJ.checkClone=bD.cloneNode(true).cloneNode(true).lastChild.checked;bJ.appendChecked=bE.checked;bD.removeChild(bE);bD.appendChild(bv);bv.innerHTML="";if(bb.getComputedStyle){bA=av.createElement("div");bA.style.width="0";bA.style.marginRight="0";bv.style.width="2px";bv.appendChild(bA);bJ.reliableMarginRight=(parseInt((bb.getComputedStyle(bA,null)||{marginRight:0}).marginRight,10)||0)===0}if(bv.attachEvent){for(by in {submit:1,change:1,focusin:1}){bB="on"+by;bw=(bB in bv);if(!bw){bv.setAttribute(bB,"return;");bw=(typeof bv[bB]==="function")}bJ[by+"Bubbles"]=bw}}bD.removeChild(bv);bD=bG=bx=bA=bv=bE=null;b(function(){var bM,bU,bV,bT,bN,bO,bL,bS,bR,e,bP,bQ=av.getElementsByTagName("body")[0];if(!bQ){return}bL=1;bS="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;";bR="visibility:hidden;border:0;";e="style='"+bS+"border:5px solid #000;padding:0;'";bP="
";bM=av.createElement("div");bM.style.cssText=bR+"width:0;height:0;position:static;top:0;margin-top:"+bL+"px";bQ.insertBefore(bM,bQ.firstChild);bv=av.createElement("div");bM.appendChild(bv);bv.innerHTML="
t
";bz=bv.getElementsByTagName("td");bw=(bz[0].offsetHeight===0);bz[0].style.display="";bz[1].style.display="none";bJ.reliableHiddenOffsets=bw&&(bz[0].offsetHeight===0);bv.innerHTML="";bv.style.width=bv.style.paddingLeft="1px";b.boxModel=bJ.boxModel=bv.offsetWidth===2;if(typeof bv.style.zoom!=="undefined"){bv.style.display="inline";bv.style.zoom=1;bJ.inlineBlockNeedsLayout=(bv.offsetWidth===2);bv.style.display="";bv.innerHTML="
";bJ.shrinkWrapBlocks=(bv.offsetWidth!==2)}bv.style.cssText=bS+bR;bv.innerHTML=bP;bU=bv.firstChild;bV=bU.firstChild;bN=bU.nextSibling.firstChild.firstChild;bO={doesNotAddBorder:(bV.offsetTop!==5),doesAddBorderForTableAndCells:(bN.offsetTop===5)};bV.style.position="fixed";bV.style.top="20px";bO.fixedPosition=(bV.offsetTop===20||bV.offsetTop===15);bV.style.position=bV.style.top="";bU.style.overflow="hidden";bU.style.position="relative";bO.subtractsBorderForOverflowNotVisible=(bV.offsetTop===-5);bO.doesNotIncludeMarginInBodyOffset=(bQ.offsetTop!==bL);bQ.removeChild(bM);bv=bM=null;b.extend(bJ,bO)});return bJ})();var aS=/^(?:\{.*\}|\[.*\])$/,aA=/([A-Z])/g;b.extend({cache:{},uuid:0,expando:"jQuery"+(b.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},hasData:function(e){e=e.nodeType?b.cache[e[b.expando]]:e[b.expando];return !!e&&!S(e)},data:function(bx,bv,bz,by){if(!b.acceptData(bx)){return}var bG,bA,bD,bE=b.expando,bC=typeof bv==="string",bF=bx.nodeType,e=bF?b.cache:bx,bw=bF?bx[bE]:bx[bE]&&bE,bB=bv==="events";if((!bw||!e[bw]||(!bB&&!by&&!e[bw].data))&&bC&&bz===L){return}if(!bw){if(bF){bx[bE]=bw=++b.uuid}else{bw=bE}}if(!e[bw]){e[bw]={};if(!bF){e[bw].toJSON=b.noop}}if(typeof bv==="object"||typeof bv==="function"){if(by){e[bw]=b.extend(e[bw],bv)}else{e[bw].data=b.extend(e[bw].data,bv)}}bG=bA=e[bw];if(!by){if(!bA.data){bA.data={}}bA=bA.data}if(bz!==L){bA[b.camelCase(bv)]=bz}if(bB&&!bA[bv]){return bG.events}if(bC){bD=bA[bv];if(bD==null){bD=bA[b.camelCase(bv)]}}else{bD=bA}return bD},removeData:function(bx,bv,by){if(!b.acceptData(bx)){return}var bB,bA,bz,bC=b.expando,bD=bx.nodeType,e=bD?b.cache:bx,bw=bD?bx[bC]:bC;if(!e[bw]){return}if(bv){bB=by?e[bw]:e[bw].data;if(bB){if(!b.isArray(bv)){if(bv in bB){bv=[bv]}else{bv=b.camelCase(bv);if(bv in bB){bv=[bv]}else{bv=bv.split(" ")}}}for(bA=0,bz=bv.length;bA-1){return true}}return false},val:function(bx){var e,bv,by,bw=this[0];if(!arguments.length){if(bw){e=b.valHooks[bw.nodeName.toLowerCase()]||b.valHooks[bw.type];if(e&&"get" in e&&(bv=e.get(bw,"value"))!==L){return bv}bv=bw.value;return typeof bv==="string"?bv.replace(aU,""):bv==null?"":bv}return}by=b.isFunction(bx);return this.each(function(bA){var bz=b(this),bB;if(this.nodeType!==1){return}if(by){bB=bx.call(this,bA,bz.val())}else{bB=bx}if(bB==null){bB=""}else{if(typeof bB==="number"){bB+=""}else{if(b.isArray(bB)){bB=b.map(bB,function(bC){return bC==null?"":bC+""})}}}e=b.valHooks[this.nodeName.toLowerCase()]||b.valHooks[this.type];if(!e||!("set" in e)||e.set(this,bB,"value")===L){this.value=bB}})}});b.extend({valHooks:{option:{get:function(e){var bv=e.attributes.value;return !bv||bv.specified?e.value:e.text}},select:{get:function(e){var bA,bv,bz,bx,by=e.selectedIndex,bB=[],bC=e.options,bw=e.type==="select-one";if(by<0){return null}bv=bw?by:0;bz=bw?by+1:bC.length;for(;bv=0});if(!e.length){bv.selectedIndex=-1}return e}}},attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(bA,bx,bB,bz){var bw,e,by,bv=bA.nodeType; +if(!bA||bv===3||bv===8||bv===2){return}if(bz&&bx in b.attrFn){return b(bA)[bx](bB)}if(typeof bA.getAttribute==="undefined"){return b.prop(bA,bx,bB)}by=bv!==1||!b.isXMLDoc(bA);if(by){bx=bx.toLowerCase();e=b.attrHooks[bx]||(ao.test(bx)?aY:be)}if(bB!==L){if(bB===null){b.removeAttr(bA,bx);return}else{if(e&&"set" in e&&by&&(bw=e.set(bA,bB,bx))!==L){return bw}else{bA.setAttribute(bx,""+bB);return bB}}}else{if(e&&"get" in e&&by&&(bw=e.get(bA,bx))!==null){return bw}else{bw=bA.getAttribute(bx);return bw===null?L:bw}}},removeAttr:function(bx,bz){var by,bA,bv,e,bw=0;if(bz&&bx.nodeType===1){bA=bz.toLowerCase().split(af);e=bA.length;for(;bw=0)}}})});var bd=/^(?:textarea|input|select)$/i,n=/^([^\.]*)?(?:\.(.+))?$/,J=/\bhover(\.\S+)?\b/,aO=/^key/,bf=/^(?:mouse|contextmenu)|click/,T=/^(?:focusinfocus|focusoutblur)$/,U=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,Y=function(e){var bv=U.exec(e);if(bv){bv[1]=(bv[1]||"").toLowerCase();bv[3]=bv[3]&&new RegExp("(?:^|\\s)"+bv[3]+"(?:\\s|$)")}return bv},j=function(bw,e){var bv=bw.attributes||{};return((!e[1]||bw.nodeName.toLowerCase()===e[1])&&(!e[2]||(bv.id||{}).value===e[2])&&(!e[3]||e[3].test((bv["class"]||{}).value)))},bt=function(e){return b.event.special.hover?e:e.replace(J,"mouseenter$1 mouseleave$1")};b.event={add:function(bx,bC,bJ,bA,by){var bD,bB,bK,bI,bH,bF,e,bG,bv,bz,bw,bE;if(bx.nodeType===3||bx.nodeType===8||!bC||!bJ||!(bD=b._data(bx))){return}if(bJ.handler){bv=bJ;bJ=bv.handler}if(!bJ.guid){bJ.guid=b.guid++}bK=bD.events;if(!bK){bD.events=bK={}}bB=bD.handle;if(!bB){bD.handle=bB=function(bL){return typeof b!=="undefined"&&(!bL||b.event.triggered!==bL.type)?b.event.dispatch.apply(bB.elem,arguments):L};bB.elem=bx}bC=b.trim(bt(bC)).split(" ");for(bI=0;bI=0){bG=bG.slice(0,-1);bw=true}if(bG.indexOf(".")>=0){bx=bG.split(".");bG=bx.shift();bx.sort()}if((!bA||b.event.customEvent[bG])&&!b.event.global[bG]){return}bv=typeof bv==="object"?bv[b.expando]?bv:new b.Event(bG,bv):new b.Event(bG);bv.type=bG;bv.isTrigger=true;bv.exclusive=bw;bv.namespace=bx.join(".");bv.namespace_re=bv.namespace?new RegExp("(^|\\.)"+bx.join("\\.(?:.*\\.)?")+"(\\.|$)"):null;by=bG.indexOf(":")<0?"on"+bG:"";if(!bA){e=b.cache;for(bC in e){if(e[bC].events&&e[bC].events[bG]){b.event.trigger(bv,bD,e[bC].handle.elem,true)}}return}bv.result=L;if(!bv.target){bv.target=bA}bD=bD!=null?b.makeArray(bD):[];bD.unshift(bv);bF=b.event.special[bG]||{};if(bF.trigger&&bF.trigger.apply(bA,bD)===false){return}bB=[[bA,bF.bindType||bG]];if(!bJ&&!bF.noBubble&&!b.isWindow(bA)){bI=bF.delegateType||bG;bH=T.test(bI+bG)?bA:bA.parentNode;bz=null;for(;bH;bH=bH.parentNode){bB.push([bH,bI]);bz=bH}if(bz&&bz===bA.ownerDocument){bB.push([bz.defaultView||bz.parentWindow||bb,bI])}}for(bC=0;bCbA){bH.push({elem:this,matches:bz.slice(bA)})}for(bC=0;bC0?this.on(e,null,bx,bw):this.trigger(e)};if(b.attrFn){b.attrFn[e]=true}if(aO.test(e)){b.event.fixHooks[e]=b.event.keyHooks}if(bf.test(e)){b.event.fixHooks[e]=b.event.mouseHooks}}); +/*! + * Sizzle CSS Selector Engine + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){var bH=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,bC="sizcache"+(Math.random()+"").replace(".",""),bI=0,bL=Object.prototype.toString,bB=false,bA=true,bK=/\\/g,bO=/\r\n/g,bQ=/\W/;[0,0].sort(function(){bA=false;return 0});var by=function(bV,e,bY,bZ){bY=bY||[];e=e||av;var b1=e;if(e.nodeType!==1&&e.nodeType!==9){return[]}if(!bV||typeof bV!=="string"){return bY}var bS,b3,b6,bR,b2,b5,b4,bX,bU=true,bT=by.isXML(e),bW=[],b0=bV;do{bH.exec("");bS=bH.exec(b0);if(bS){b0=bS[3];bW.push(bS[1]);if(bS[2]){bR=bS[3];break}}}while(bS);if(bW.length>1&&bD.exec(bV)){if(bW.length===2&&bE.relative[bW[0]]){b3=bM(bW[0]+bW[1],e,bZ)}else{b3=bE.relative[bW[0]]?[e]:by(bW.shift(),e);while(bW.length){bV=bW.shift();if(bE.relative[bV]){bV+=bW.shift()}b3=bM(bV,b3,bZ)}}}else{if(!bZ&&bW.length>1&&e.nodeType===9&&!bT&&bE.match.ID.test(bW[0])&&!bE.match.ID.test(bW[bW.length-1])){b2=by.find(bW.shift(),e,bT);e=b2.expr?by.filter(b2.expr,b2.set)[0]:b2.set[0]}if(e){b2=bZ?{expr:bW.pop(),set:bF(bZ)}:by.find(bW.pop(),bW.length===1&&(bW[0]==="~"||bW[0]==="+")&&e.parentNode?e.parentNode:e,bT);b3=b2.expr?by.filter(b2.expr,b2.set):b2.set;if(bW.length>0){b6=bF(b3)}else{bU=false}while(bW.length){b5=bW.pop();b4=b5;if(!bE.relative[b5]){b5=""}else{b4=bW.pop()}if(b4==null){b4=e}bE.relative[b5](b6,b4,bT)}}else{b6=bW=[]}}if(!b6){b6=b3}if(!b6){by.error(b5||bV)}if(bL.call(b6)==="[object Array]"){if(!bU){bY.push.apply(bY,b6)}else{if(e&&e.nodeType===1){for(bX=0;b6[bX]!=null;bX++){if(b6[bX]&&(b6[bX]===true||b6[bX].nodeType===1&&by.contains(e,b6[bX]))){bY.push(b3[bX])}}}else{for(bX=0;b6[bX]!=null;bX++){if(b6[bX]&&b6[bX].nodeType===1){bY.push(b3[bX])}}}}}else{bF(b6,bY)}if(bR){by(bR,b1,bY,bZ);by.uniqueSort(bY)}return bY};by.uniqueSort=function(bR){if(bJ){bB=bA;bR.sort(bJ);if(bB){for(var e=1;e0};by.find=function(bX,e,bY){var bW,bS,bU,bT,bV,bR;if(!bX){return[]}for(bS=0,bU=bE.order.length;bS":function(bW,bR){var bV,bU=typeof bR==="string",bS=0,e=bW.length;if(bU&&!bQ.test(bR)){bR=bR.toLowerCase();for(;bS=0)){if(!bS){e.push(bV)}}else{if(bS){bR[bU]=false}}}}return false},ID:function(e){return e[1].replace(bK,"")},TAG:function(bR,e){return bR[1].replace(bK,"").toLowerCase()},CHILD:function(e){if(e[1]==="nth"){if(!e[2]){by.error(e[0])}e[2]=e[2].replace(/^\+|\s*/g,"");var bR=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(e[2]==="even"&&"2n"||e[2]==="odd"&&"2n+1"||!/\D/.test(e[2])&&"0n+"+e[2]||e[2]);e[2]=(bR[1]+(bR[2]||1))-0;e[3]=bR[3]-0}else{if(e[2]){by.error(e[0])}}e[0]=bI++;return e},ATTR:function(bU,bR,bS,e,bV,bW){var bT=bU[1]=bU[1].replace(bK,"");if(!bW&&bE.attrMap[bT]){bU[1]=bE.attrMap[bT]}bU[4]=(bU[4]||bU[5]||"").replace(bK,"");if(bU[2]==="~="){bU[4]=" "+bU[4]+" "}return bU},PSEUDO:function(bU,bR,bS,e,bV){if(bU[1]==="not"){if((bH.exec(bU[3])||"").length>1||/^\w/.test(bU[3])){bU[3]=by(bU[3],null,null,bR)}else{var bT=by.filter(bU[3],bR,bS,true^bV);if(!bS){e.push.apply(e,bT)}return false}}else{if(bE.match.POS.test(bU[0])||bE.match.CHILD.test(bU[0])){return true}}return bU},POS:function(e){e.unshift(true);return e}},filters:{enabled:function(e){return e.disabled===false&&e.type!=="hidden"},disabled:function(e){return e.disabled===true},checked:function(e){return e.checked===true},selected:function(e){if(e.parentNode){e.parentNode.selectedIndex}return e.selected===true},parent:function(e){return !!e.firstChild},empty:function(e){return !e.firstChild},has:function(bS,bR,e){return !!by(e[3],bS).length},header:function(e){return(/h\d/i).test(e.nodeName)},text:function(bS){var e=bS.getAttribute("type"),bR=bS.type;return bS.nodeName.toLowerCase()==="input"&&"text"===bR&&(e===bR||e===null)},radio:function(e){return e.nodeName.toLowerCase()==="input"&&"radio"===e.type},checkbox:function(e){return e.nodeName.toLowerCase()==="input"&&"checkbox"===e.type},file:function(e){return e.nodeName.toLowerCase()==="input"&&"file"===e.type},password:function(e){return e.nodeName.toLowerCase()==="input"&&"password"===e.type},submit:function(bR){var e=bR.nodeName.toLowerCase();return(e==="input"||e==="button")&&"submit"===bR.type},image:function(e){return e.nodeName.toLowerCase()==="input"&&"image"===e.type},reset:function(bR){var e=bR.nodeName.toLowerCase();return(e==="input"||e==="button")&&"reset"===bR.type},button:function(bR){var e=bR.nodeName.toLowerCase();return e==="input"&&"button"===bR.type||e==="button"},input:function(e){return(/input|select|textarea|button/i).test(e.nodeName)},focus:function(e){return e===e.ownerDocument.activeElement}},setFilters:{first:function(bR,e){return e===0},last:function(bS,bR,e,bT){return bR===bT.length-1},even:function(bR,e){return e%2===0},odd:function(bR,e){return e%2===1 +},lt:function(bS,bR,e){return bRe[3]-0},nth:function(bS,bR,e){return e[3]-0===bR},eq:function(bS,bR,e){return e[3]-0===bR}},filter:{PSEUDO:function(bS,bX,bW,bY){var e=bX[1],bR=bE.filters[e];if(bR){return bR(bS,bW,bX,bY)}else{if(e==="contains"){return(bS.textContent||bS.innerText||bw([bS])||"").indexOf(bX[3])>=0}else{if(e==="not"){var bT=bX[3];for(var bV=0,bU=bT.length;bV=0)}}},ID:function(bR,e){return bR.nodeType===1&&bR.getAttribute("id")===e},TAG:function(bR,e){return(e==="*"&&bR.nodeType===1)||!!bR.nodeName&&bR.nodeName.toLowerCase()===e},CLASS:function(bR,e){return(" "+(bR.className||bR.getAttribute("class"))+" ").indexOf(e)>-1},ATTR:function(bV,bT){var bS=bT[1],e=by.attr?by.attr(bV,bS):bE.attrHandle[bS]?bE.attrHandle[bS](bV):bV[bS]!=null?bV[bS]:bV.getAttribute(bS),bW=e+"",bU=bT[2],bR=bT[4];return e==null?bU==="!=":!bU&&by.attr?e!=null:bU==="="?bW===bR:bU==="*="?bW.indexOf(bR)>=0:bU==="~="?(" "+bW+" ").indexOf(bR)>=0:!bR?bW&&e!==false:bU==="!="?bW!==bR:bU==="^="?bW.indexOf(bR)===0:bU==="$="?bW.substr(bW.length-bR.length)===bR:bU==="|="?bW===bR||bW.substr(0,bR.length+1)===bR+"-":false},POS:function(bU,bR,bS,bV){var e=bR[2],bT=bE.setFilters[e];if(bT){return bT(bU,bS,bR,bV)}}}};var bD=bE.match.POS,bx=function(bR,e){return"\\"+(e-0+1)};for(var bz in bE.match){bE.match[bz]=new RegExp(bE.match[bz].source+(/(?![^\[]*\])(?![^\(]*\))/.source));bE.leftMatch[bz]=new RegExp(/(^(?:.|\r|\n)*?)/.source+bE.match[bz].source.replace(/\\(\d+)/g,bx))}var bF=function(bR,e){bR=Array.prototype.slice.call(bR,0);if(e){e.push.apply(e,bR);return e}return bR};try{Array.prototype.slice.call(av.documentElement.childNodes,0)[0].nodeType}catch(bP){bF=function(bU,bT){var bS=0,bR=bT||[];if(bL.call(bU)==="[object Array]"){Array.prototype.push.apply(bR,bU)}else{if(typeof bU.length==="number"){for(var e=bU.length;bS";e.insertBefore(bR,e.firstChild);if(av.getElementById(bS)){bE.find.ID=function(bU,bV,bW){if(typeof bV.getElementById!=="undefined"&&!bW){var bT=bV.getElementById(bU[1]);return bT?bT.id===bU[1]||typeof bT.getAttributeNode!=="undefined"&&bT.getAttributeNode("id").nodeValue===bU[1]?[bT]:L:[]}};bE.filter.ID=function(bV,bT){var bU=typeof bV.getAttributeNode!=="undefined"&&bV.getAttributeNode("id");return bV.nodeType===1&&bU&&bU.nodeValue===bT}}e.removeChild(bR);e=bR=null})();(function(){var e=av.createElement("div");e.appendChild(av.createComment(""));if(e.getElementsByTagName("*").length>0){bE.find.TAG=function(bR,bV){var bU=bV.getElementsByTagName(bR[1]);if(bR[1]==="*"){var bT=[];for(var bS=0;bU[bS];bS++){if(bU[bS].nodeType===1){bT.push(bU[bS])}}bU=bT}return bU}}e.innerHTML="";if(e.firstChild&&typeof e.firstChild.getAttribute!=="undefined"&&e.firstChild.getAttribute("href")!=="#"){bE.attrHandle.href=function(bR){return bR.getAttribute("href",2)}}e=null})();if(av.querySelectorAll){(function(){var e=by,bT=av.createElement("div"),bS="__sizzle__";bT.innerHTML="

";if(bT.querySelectorAll&&bT.querySelectorAll(".TEST").length===0){return}by=function(b4,bV,bZ,b3){bV=bV||av;if(!b3&&!by.isXML(bV)){var b2=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b4);if(b2&&(bV.nodeType===1||bV.nodeType===9)){if(b2[1]){return bF(bV.getElementsByTagName(b4),bZ)}else{if(b2[2]&&bE.find.CLASS&&bV.getElementsByClassName){return bF(bV.getElementsByClassName(b2[2]),bZ)}}}if(bV.nodeType===9){if(b4==="body"&&bV.body){return bF([bV.body],bZ)}else{if(b2&&b2[3]){var bY=bV.getElementById(b2[3]);if(bY&&bY.parentNode){if(bY.id===b2[3]){return bF([bY],bZ)}}else{return bF([],bZ)}}}try{return bF(bV.querySelectorAll(b4),bZ)}catch(b0){}}else{if(bV.nodeType===1&&bV.nodeName.toLowerCase()!=="object"){var bW=bV,bX=bV.getAttribute("id"),bU=bX||bS,b6=bV.parentNode,b5=/^\s*[+~]/.test(b4);if(!bX){bV.setAttribute("id",bU)}else{bU=bU.replace(/'/g,"\\$&")}if(b5&&b6){bV=bV.parentNode}try{if(!b5||b6){return bF(bV.querySelectorAll("[id='"+bU+"'] "+b4),bZ)}}catch(b1){}finally{if(!bX){bW.removeAttribute("id")}}}}}return e(b4,bV,bZ,b3)};for(var bR in e){by[bR]=e[bR]}bT=null})()}(function(){var e=av.documentElement,bS=e.matchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.msMatchesSelector;if(bS){var bU=!bS.call(av.createElement("div"),"div"),bR=false;try{bS.call(av.documentElement,"[test!='']:sizzle")}catch(bT){bR=true}by.matchesSelector=function(bW,bY){bY=bY.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!by.isXML(bW)){try{if(bR||!bE.match.PSEUDO.test(bY)&&!/!=/.test(bY)){var bV=bS.call(bW,bY);if(bV||!bU||bW.document&&bW.document.nodeType!==11){return bV}}}catch(bX){}}return by(bY,null,null,[bW]).length>0}}})();(function(){var e=av.createElement("div");e.innerHTML="
";if(!e.getElementsByClassName||e.getElementsByClassName("e").length===0){return}e.lastChild.className="e";if(e.getElementsByClassName("e").length===1){return}bE.order.splice(1,0,"CLASS");bE.find.CLASS=function(bR,bS,bT){if(typeof bS.getElementsByClassName!=="undefined"&&!bT){return bS.getElementsByClassName(bR[1])}};e=null})();function bv(bR,bW,bV,bZ,bX,bY){for(var bT=0,bS=bZ.length;bT0){bU=e;break}}}e=e[bR]}bZ[bT]=bU}}}if(av.documentElement.contains){by.contains=function(bR,e){return bR!==e&&(bR.contains?bR.contains(e):true)}}else{if(av.documentElement.compareDocumentPosition){by.contains=function(bR,e){return !!(bR.compareDocumentPosition(e)&16)}}else{by.contains=function(){return false}}}by.isXML=function(e){var bR=(e?e.ownerDocument||e:0).documentElement;return bR?bR.nodeName!=="HTML":false};var bM=function(bS,e,bW){var bV,bX=[],bU="",bY=e.nodeType?[e]:e;while((bV=bE.match.PSEUDO.exec(bS))){bU+=bV[0];bS=bS.replace(bE.match.PSEUDO,"")}bS=bE.relative[bS]?bS+"*":bS;for(var bT=0,bR=bY.length;bT0){for(bB=bA;bB=0:b.filter(e,this).length>0:this.filter(e).length>0)},closest:function(by,bx){var bv=[],bw,e,bz=this[0];if(b.isArray(by)){var bB=1;while(bz&&bz.ownerDocument&&bz!==bx){for(bw=0;bw-1:b.find.matchesSelector(bz,by)){bv.push(bz);break}else{bz=bz.parentNode;if(!bz||!bz.ownerDocument||bz===bx||bz.nodeType===11){break}}}}bv=bv.length>1?b.unique(bv):bv;return this.pushStack(bv,"closest",by)},index:function(e){if(!e){return(this[0]&&this[0].parentNode)?this.prevAll().length:-1}if(typeof e==="string"){return b.inArray(this[0],b(e))}return b.inArray(e.jquery?e[0]:e,this)},add:function(e,bv){var bx=typeof e==="string"?b(e,bv):b.makeArray(e&&e.nodeType?[e]:e),bw=b.merge(this.get(),bx);return this.pushStack(C(bx[0])||C(bw[0])?bw:b.unique(bw))},andSelf:function(){return this.add(this.prevObject)}});function C(e){return !e||!e.parentNode||e.parentNode.nodeType===11}b.each({parent:function(bv){var e=bv.parentNode;return e&&e.nodeType!==11?e:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(bv,e,bw){return b.dir(bv,"parentNode",bw)},next:function(e){return b.nth(e,2,"nextSibling")},prev:function(e){return b.nth(e,2,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(bv,e,bw){return b.dir(bv,"nextSibling",bw)},prevUntil:function(bv,e,bw){return b.dir(bv,"previousSibling",bw)},siblings:function(e){return b.sibling(e.parentNode.firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:b.makeArray(e.childNodes)}},function(e,bv){b.fn[e]=function(by,bw){var bx=b.map(this,bv,by);if(!ab.test(e)){bw=by}if(bw&&typeof bw==="string"){bx=b.filter(bw,bx)}bx=this.length>1&&!ay[e]?b.unique(bx):bx;if((this.length>1||a9.test(bw))&&aq.test(e)){bx=bx.reverse()}return this.pushStack(bx,e,P.call(arguments).join(","))}});b.extend({filter:function(bw,e,bv){if(bv){bw=":not("+bw+")"}return e.length===1?b.find.matchesSelector(e[0],bw)?[e[0]]:[]:b.find.matches(bw,e)},dir:function(bw,bv,by){var e=[],bx=bw[bv];while(bx&&bx.nodeType!==9&&(by===L||bx.nodeType!==1||!b(bx).is(by))){if(bx.nodeType===1){e.push(bx)}bx=bx[bv]}return e},nth:function(by,e,bw,bx){e=e||1;var bv=0;for(;by;by=by[bw]){if(by.nodeType===1&&++bv===e){break}}return by},sibling:function(bw,bv){var e=[];for(;bw;bw=bw.nextSibling){if(bw.nodeType===1&&bw!==bv){e.push(bw)}}return e}});function aG(bx,bw,e){bw=bw||0;if(b.isFunction(bw)){return b.grep(bx,function(bz,by){var bA=!!bw.call(bz,by,bz);return bA===e})}else{if(bw.nodeType){return b.grep(bx,function(bz,by){return(bz===bw)===e})}else{if(typeof bw==="string"){var bv=b.grep(bx,function(by){return by.nodeType===1});if(bp.test(bw)){return b.filter(bw,bv,!e)}else{bw=b.filter(bw,bv)}}}}return b.grep(bx,function(bz,by){return(b.inArray(bz,bw)>=0)===e})}function a(e){var bw=aR.split("|"),bv=e.createDocumentFragment();if(bv.createElement){while(bw.length){bv.createElement(bw.pop())}}return bv}var aR="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",ag=/ jQuery\d+="(?:\d+|null)"/g,ar=/^\s+/,R=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,d=/<([\w:]+)/,w=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},ac=a(av); +ax.optgroup=ax.option;ax.tbody=ax.tfoot=ax.colgroup=ax.caption=ax.thead;ax.th=ax.td;if(!b.support.htmlSerialize){ax._default=[1,"div
","
"]}b.fn.extend({text:function(e){if(b.isFunction(e)){return this.each(function(bw){var bv=b(this);bv.text(e.call(this,bw,bv.text()))})}if(typeof e!=="object"&&e!==L){return this.empty().append((this[0]&&this[0].ownerDocument||av).createTextNode(e))}return b.text(this)},wrapAll:function(e){if(b.isFunction(e)){return this.each(function(bw){b(this).wrapAll(e.call(this,bw))})}if(this[0]){var bv=b(e,this[0].ownerDocument).eq(0).clone(true);if(this[0].parentNode){bv.insertBefore(this[0])}bv.map(function(){var bw=this;while(bw.firstChild&&bw.firstChild.nodeType===1){bw=bw.firstChild}return bw}).append(this)}return this},wrapInner:function(e){if(b.isFunction(e)){return this.each(function(bv){b(this).wrapInner(e.call(this,bv))})}return this.each(function(){var bv=b(this),bw=bv.contents();if(bw.length){bw.wrapAll(e)}else{bv.append(e)}})},wrap:function(e){var bv=b.isFunction(e);return this.each(function(bw){b(this).wrapAll(bv?e.call(this,bw):e)})},unwrap:function(){return this.parent().each(function(){if(!b.nodeName(this,"body")){b(this).replaceWith(this.childNodes)}}).end()},append:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.appendChild(e)}})},prepend:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.insertBefore(e,this.firstChild)}})},before:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bv){this.parentNode.insertBefore(bv,this)})}else{if(arguments.length){var e=b.clean(arguments);e.push.apply(e,this.toArray());return this.pushStack(e,"before",arguments)}}},after:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bv){this.parentNode.insertBefore(bv,this.nextSibling)})}else{if(arguments.length){var e=this.pushStack(this,"after",arguments);e.push.apply(e,b.clean(arguments));return e}}},remove:function(e,bx){for(var bv=0,bw;(bw=this[bv])!=null;bv++){if(!e||b.filter(e,[bw]).length){if(!bx&&bw.nodeType===1){b.cleanData(bw.getElementsByTagName("*"));b.cleanData([bw])}if(bw.parentNode){bw.parentNode.removeChild(bw)}}}return this},empty:function(){for(var e=0,bv;(bv=this[e])!=null;e++){if(bv.nodeType===1){b.cleanData(bv.getElementsByTagName("*"))}while(bv.firstChild){bv.removeChild(bv.firstChild)}}return this},clone:function(bv,e){bv=bv==null?false:bv;e=e==null?bv:e;return this.map(function(){return b.clone(this,bv,e)})},html:function(bx){if(bx===L){return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(ag,""):null}else{if(typeof bx==="string"&&!ae.test(bx)&&(b.support.leadingWhitespace||!ar.test(bx))&&!ax[(d.exec(bx)||["",""])[1].toLowerCase()]){bx=bx.replace(R,"<$1>");try{for(var bw=0,bv=this.length;bw1&&bw0?this.clone(true):this).get();b(bC[bA])[bv](by);bz=bz.concat(by)}return this.pushStack(bz,e,bC.selector)}}});function bg(e){if(typeof e.getElementsByTagName!=="undefined"){return e.getElementsByTagName("*")}else{if(typeof e.querySelectorAll!=="undefined"){return e.querySelectorAll("*")}else{return[]}}}function az(e){if(e.type==="checkbox"||e.type==="radio"){e.defaultChecked=e.checked}}function E(e){var bv=(e.nodeName||"").toLowerCase();if(bv==="input"){az(e)}else{if(bv!=="script"&&typeof e.getElementsByTagName!=="undefined"){b.grep(e.getElementsByTagName("input"),az)}}}function al(e){var bv=av.createElement("div");ac.appendChild(bv);bv.innerHTML=e.outerHTML;return bv.firstChild}b.extend({clone:function(by,bA,bw){var e,bv,bx,bz=b.support.html5Clone||!ah.test("<"+by.nodeName)?by.cloneNode(true):al(by);if((!b.support.noCloneEvent||!b.support.noCloneChecked)&&(by.nodeType===1||by.nodeType===11)&&!b.isXMLDoc(by)){ai(by,bz);e=bg(by);bv=bg(bz);for(bx=0;e[bx];++bx){if(bv[bx]){ai(e[bx],bv[bx])}}}if(bA){t(by,bz);if(bw){e=bg(by);bv=bg(bz);for(bx=0;e[bx];++bx){t(e[bx],bv[bx])}}}e=bv=null;return bz},clean:function(bw,by,bH,bA){var bF;by=by||av;if(typeof by.createElement==="undefined"){by=by.ownerDocument||by[0]&&by[0].ownerDocument||av}var bI=[],bB;for(var bE=0,bz;(bz=bw[bE])!=null;bE++){if(typeof bz==="number"){bz+=""}if(!bz){continue}if(typeof bz==="string"){if(!W.test(bz)){bz=by.createTextNode(bz)}else{bz=bz.replace(R,"<$1>");var bK=(d.exec(bz)||["",""])[1].toLowerCase(),bx=ax[bK]||ax._default,bD=bx[0],bv=by.createElement("div");if(by===av){ac.appendChild(bv)}else{a(by).appendChild(bv)}bv.innerHTML=bx[1]+bz+bx[2];while(bD--){bv=bv.lastChild}if(!b.support.tbody){var e=w.test(bz),bC=bK==="table"&&!e?bv.firstChild&&bv.firstChild.childNodes:bx[1]===""&&!e?bv.childNodes:[];for(bB=bC.length-1;bB>=0;--bB){if(b.nodeName(bC[bB],"tbody")&&!bC[bB].childNodes.length){bC[bB].parentNode.removeChild(bC[bB])}}}if(!b.support.leadingWhitespace&&ar.test(bz)){bv.insertBefore(by.createTextNode(ar.exec(bz)[0]),bv.firstChild)}bz=bv.childNodes}}var bG;if(!b.support.appendChecked){if(bz[0]&&typeof(bG=bz.length)==="number"){for(bB=0;bB=0){return bx+"px"}}else{return bx}}}});if(!b.support.opacity){b.cssHooks.opacity={get:function(bv,e){return au.test((e&&bv.currentStyle?bv.currentStyle.filter:bv.style.filter)||"")?(parseFloat(RegExp.$1)/100)+"":e?"1":""},set:function(by,bz){var bx=by.style,bv=by.currentStyle,e=b.isNumeric(bz)?"alpha(opacity="+bz*100+")":"",bw=bv&&bv.filter||bx.filter||"";bx.zoom=1;if(bz>=1&&b.trim(bw.replace(ak,""))===""){bx.removeAttribute("filter");if(bv&&!bv.filter){return}}bx.filter=ak.test(bw)?bw.replace(ak,e):bw+" "+e}}}b(function(){if(!b.support.reliableMarginRight){b.cssHooks.marginRight={get:function(bw,bv){var e;b.swap(bw,{display:"inline-block"},function(){if(bv){e=Z(bw,"margin-right","marginRight")}else{e=bw.style.marginRight}});return e}}}});if(av.defaultView&&av.defaultView.getComputedStyle){aI=function(by,bw){var bv,bx,e;bw=bw.replace(z,"-$1").toLowerCase();if((bx=by.ownerDocument.defaultView)&&(e=bx.getComputedStyle(by,null))){bv=e.getPropertyValue(bw);if(bv===""&&!b.contains(by.ownerDocument.documentElement,by)){bv=b.style(by,bw)}}return bv}}if(av.documentElement.currentStyle){aX=function(bz,bw){var bA,e,by,bv=bz.currentStyle&&bz.currentStyle[bw],bx=bz.style;if(bv===null&&bx&&(by=bx[bw])){bv=by}if(!bc.test(bv)&&bn.test(bv)){bA=bx.left;e=bz.runtimeStyle&&bz.runtimeStyle.left;if(e){bz.runtimeStyle.left=bz.currentStyle.left}bx.left=bw==="fontSize"?"1em":(bv||0);bv=bx.pixelLeft+"px";bx.left=bA;if(e){bz.runtimeStyle.left=e}}return bv===""?"auto":bv}}Z=aI||aX;function p(by,bw,bv){var bA=bw==="width"?by.offsetWidth:by.offsetHeight,bz=bw==="width"?an:a1,bx=0,e=bz.length; +if(bA>0){if(bv!=="border"){for(;bx)<[^<]*)*<\/script>/gi,q=/^(?:select|textarea)/i,h=/\s+/,br=/([?&])_=[^&]*/,K=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,A=b.fn.load,aa={},r={},aE,s,aV=["*/"]+["*"];try{aE=bl.href}catch(aw){aE=av.createElement("a");aE.href="";aE=aE.href}s=K.exec(aE.toLowerCase())||[];function f(e){return function(by,bA){if(typeof by!=="string"){bA=by;by="*"}if(b.isFunction(bA)){var bx=by.toLowerCase().split(h),bw=0,bz=bx.length,bv,bB,bC;for(;bw=0){var e=bw.slice(by,bw.length);bw=bw.slice(0,by)}var bx="GET";if(bz){if(b.isFunction(bz)){bA=bz;bz=L}else{if(typeof bz==="object"){bz=b.param(bz,b.ajaxSettings.traditional);bx="POST"}}}var bv=this;b.ajax({url:bw,type:bx,dataType:"html",data:bz,complete:function(bC,bB,bD){bD=bC.responseText;if(bC.isResolved()){bC.done(function(bE){bD=bE});bv.html(e?b("
").append(bD.replace(a6,"")).find(e):bD)}if(bA){bv.each(bA,[bD,bB,bC])}}});return this},serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?b.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||q.test(this.nodeName)||aZ.test(this.type))}).map(function(e,bv){var bw=b(this).val();return bw==null?null:b.isArray(bw)?b.map(bw,function(by,bx){return{name:bv.name,value:by.replace(bs,"\r\n")}}):{name:bv.name,value:bw.replace(bs,"\r\n")}}).get()}});b.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(e,bv){b.fn[bv]=function(bw){return this.on(bv,bw)}});b.each(["get","post"],function(e,bv){b[bv]=function(bw,by,bz,bx){if(b.isFunction(by)){bx=bx||bz;bz=by;by=L}return b.ajax({type:bv,url:bw,data:by,success:bz,dataType:bx})}});b.extend({getScript:function(e,bv){return b.get(e,L,bv,"script")},getJSON:function(e,bv,bw){return b.get(e,bv,bw,"json")},ajaxSetup:function(bv,e){if(e){am(bv,b.ajaxSettings)}else{e=bv;bv=b.ajaxSettings}am(bv,e);return bv},ajaxSettings:{url:aE,isLocal:aM.test(s[1]),global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":aV},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":bb.String,"text html":true,"text json":b.parseJSON,"text xml":b.parseXML},flatOptions:{context:true,url:true}},ajaxPrefilter:f(aa),ajaxTransport:f(r),ajax:function(bz,bx){if(typeof bz==="object"){bx=bz;bz=L}bx=bx||{};var bD=b.ajaxSetup({},bx),bS=bD.context||bD,bG=bS!==bD&&(bS.nodeType||bS instanceof b)?b(bS):b.event,bR=b.Deferred(),bN=b.Callbacks("once memory"),bB=bD.statusCode||{},bC,bH={},bO={},bQ,by,bL,bE,bI,bA=0,bw,bK,bJ={readyState:0,setRequestHeader:function(bT,bU){if(!bA){var e=bT.toLowerCase();bT=bO[e]=bO[e]||bT;bH[bT]=bU}return this},getAllResponseHeaders:function(){return bA===2?bQ:null},getResponseHeader:function(bT){var e;if(bA===2){if(!by){by={};while((e=aD.exec(bQ))){by[e[1].toLowerCase()]=e[2]}}e=by[bT.toLowerCase()]}return e===L?null:e},overrideMimeType:function(e){if(!bA){bD.mimeType=e}return this},abort:function(e){e=e||"abort";if(bL){bL.abort(e)}bF(0,e);return this}};function bF(bZ,bU,b0,bW){if(bA===2){return}bA=2;if(bE){clearTimeout(bE)}bL=L;bQ=bW||"";bJ.readyState=bZ>0?4:0;var bT,b4,b3,bX=bU,bY=b0?bj(bD,bJ,b0):L,bV,b2;if(bZ>=200&&bZ<300||bZ===304){if(bD.ifModified){if((bV=bJ.getResponseHeader("Last-Modified"))){b.lastModified[bC]=bV}if((b2=bJ.getResponseHeader("Etag"))){b.etag[bC]=b2}}if(bZ===304){bX="notmodified";bT=true}else{try{b4=G(bD,bY);bX="success";bT=true}catch(b1){bX="parsererror";b3=b1}}}else{b3=bX;if(!bX||bZ){bX="error";if(bZ<0){bZ=0}}}bJ.status=bZ;bJ.statusText=""+(bU||bX);if(bT){bR.resolveWith(bS,[b4,bX,bJ])}else{bR.rejectWith(bS,[bJ,bX,b3])}bJ.statusCode(bB);bB=L;if(bw){bG.trigger("ajax"+(bT?"Success":"Error"),[bJ,bD,bT?b4:b3])}bN.fireWith(bS,[bJ,bX]);if(bw){bG.trigger("ajaxComplete",[bJ,bD]);if(!(--b.active)){b.event.trigger("ajaxStop")}}}bR.promise(bJ);bJ.success=bJ.done;bJ.error=bJ.fail;bJ.complete=bN.add;bJ.statusCode=function(bT){if(bT){var e;if(bA<2){for(e in bT){bB[e]=[bB[e],bT[e]]}}else{e=bT[bJ.status];bJ.then(e,e)}}return this};bD.url=((bz||bD.url)+"").replace(bq,"").replace(c,s[1]+"//");bD.dataTypes=b.trim(bD.dataType||"*").toLowerCase().split(h);if(bD.crossDomain==null){bI=K.exec(bD.url.toLowerCase());bD.crossDomain=!!(bI&&(bI[1]!=s[1]||bI[2]!=s[2]||(bI[3]||(bI[1]==="http:"?80:443))!=(s[3]||(s[1]==="http:"?80:443))))}if(bD.data&&bD.processData&&typeof bD.data!=="string"){bD.data=b.param(bD.data,bD.traditional)}aW(aa,bD,bx,bJ);if(bA===2){return false}bw=bD.global;bD.type=bD.type.toUpperCase();bD.hasContent=!aQ.test(bD.type);if(bw&&b.active++===0){b.event.trigger("ajaxStart")}if(!bD.hasContent){if(bD.data){bD.url+=(M.test(bD.url)?"&":"?")+bD.data;delete bD.data}bC=bD.url;if(bD.cache===false){var bv=b.now(),bP=bD.url.replace(br,"$1_="+bv);bD.url=bP+((bP===bD.url)?(M.test(bD.url)?"&":"?")+"_="+bv:"")}}if(bD.data&&bD.hasContent&&bD.contentType!==false||bx.contentType){bJ.setRequestHeader("Content-Type",bD.contentType)}if(bD.ifModified){bC=bC||bD.url;if(b.lastModified[bC]){bJ.setRequestHeader("If-Modified-Since",b.lastModified[bC])}if(b.etag[bC]){bJ.setRequestHeader("If-None-Match",b.etag[bC])}}bJ.setRequestHeader("Accept",bD.dataTypes[0]&&bD.accepts[bD.dataTypes[0]]?bD.accepts[bD.dataTypes[0]]+(bD.dataTypes[0]!=="*"?", "+aV+"; q=0.01":""):bD.accepts["*"]);for(bK in bD.headers){bJ.setRequestHeader(bK,bD.headers[bK])}if(bD.beforeSend&&(bD.beforeSend.call(bS,bJ,bD)===false||bA===2)){bJ.abort();return false}for(bK in {success:1,error:1,complete:1}){bJ[bK](bD[bK])}bL=aW(r,bD,bx,bJ);if(!bL){bF(-1,"No Transport")}else{bJ.readyState=1;if(bw){bG.trigger("ajaxSend",[bJ,bD])}if(bD.async&&bD.timeout>0){bE=setTimeout(function(){bJ.abort("timeout")},bD.timeout)}try{bA=1;bL.send(bH,bF)}catch(bM){if(bA<2){bF(-1,bM)}else{throw bM}}}return bJ},param:function(e,bw){var bv=[],by=function(bz,bA){bA=b.isFunction(bA)?bA():bA;bv[bv.length]=encodeURIComponent(bz)+"="+encodeURIComponent(bA)};if(bw===L){bw=b.ajaxSettings.traditional}if(b.isArray(e)||(e.jquery&&!b.isPlainObject(e))){b.each(e,function(){by(this.name,this.value)})}else{for(var bx in e){v(bx,e[bx],bw,by)}}return bv.join("&").replace(k,"+")}});function v(bw,by,bv,bx){if(b.isArray(by)){b.each(by,function(bA,bz){if(bv||ap.test(bw)){bx(bw,bz)}else{v(bw+"["+(typeof bz==="object"||b.isArray(bz)?bA:"")+"]",bz,bv,bx)}})}else{if(!bv&&by!=null&&typeof by==="object"){for(var e in by){v(bw+"["+e+"]",by[e],bv,bx)}}else{bx(bw,by)}}}b.extend({active:0,lastModified:{},etag:{}});function bj(bD,bC,bz){var bv=bD.contents,bB=bD.dataTypes,bw=bD.responseFields,by,bA,bx,e;for(bA in bw){if(bA in bz){bC[bw[bA]]=bz[bA]}}while(bB[0]==="*"){bB.shift();if(by===L){by=bD.mimeType||bC.getResponseHeader("content-type")}}if(by){for(bA in bv){if(bv[bA]&&bv[bA].test(by)){bB.unshift(bA);break}}}if(bB[0] in bz){bx=bB[0]}else{for(bA in bz){if(!bB[0]||bD.converters[bA+" "+bB[0]]){bx=bA;break}if(!e){e=bA}}bx=bx||e}if(bx){if(bx!==bB[0]){bB.unshift(bx)}return bz[bx]}}function G(bH,bz){if(bH.dataFilter){bz=bH.dataFilter(bz,bH.dataType)}var bD=bH.dataTypes,bG={},bA,bE,bw=bD.length,bB,bC=bD[0],bx,by,bF,bv,e;for(bA=1;bA=bw.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();bw.animatedProperties[this.prop]=true;for(bA in bw.animatedProperties){if(bw.animatedProperties[bA]!==true){e=false}}if(e){if(bw.overflow!=null&&!b.support.shrinkWrapBlocks){b.each(["","X","Y"],function(bC,bD){bz.style["overflow"+bD]=bw.overflow[bC]})}if(bw.hide){b(bz).hide()}if(bw.hide||bw.show){for(bA in bw.animatedProperties){b.style(bz,bA,bw.orig[bA]);b.removeData(bz,"fxshow"+bA,true);b.removeData(bz,"toggle"+bA,true)}}bv=bw.complete;if(bv){bw.complete=false;bv.call(bz)}}return false}else{if(bw.duration==Infinity){this.now=bx}else{bB=bx-this.startTime;this.state=bB/bw.duration;this.pos=b.easing[bw.animatedProperties[this.prop]](this.state,bB,0,1,bw.duration);this.now=this.start+((this.end-this.start)*this.pos)}this.update()}return true}};b.extend(b.fx,{tick:function(){var bw,bv=b.timers,e=0;for(;e").appendTo(e),bw=bv.css("display");bv.remove();if(bw==="none"||bw===""){if(!a8){a8=av.createElement("iframe");a8.frameBorder=a8.width=a8.height=0}e.appendChild(a8);if(!m||!a8.createElement){m=(a8.contentWindow||a8.contentDocument).document;m.write((av.compatMode==="CSS1Compat"?"":"")+"");m.close()}bv=m.createElement(bx);m.body.appendChild(bv);bw=b.css(bv,"display");e.removeChild(a8)}Q[bx]=bw}return Q[bx]}var V=/^t(?:able|d|h)$/i,ad=/^(?:body|html)$/i;if("getBoundingClientRect" in av.documentElement){b.fn.offset=function(bI){var by=this[0],bB;if(bI){return this.each(function(e){b.offset.setOffset(this,bI,e)})}if(!by||!by.ownerDocument){return null}if(by===by.ownerDocument.body){return b.offset.bodyOffset(by)}try{bB=by.getBoundingClientRect()}catch(bF){}var bH=by.ownerDocument,bw=bH.documentElement;if(!bB||!b.contains(bw,by)){return bB?{top:bB.top,left:bB.left}:{top:0,left:0}}var bC=bH.body,bD=aK(bH),bA=bw.clientTop||bC.clientTop||0,bE=bw.clientLeft||bC.clientLeft||0,bv=bD.pageYOffset||b.support.boxModel&&bw.scrollTop||bC.scrollTop,bz=bD.pageXOffset||b.support.boxModel&&bw.scrollLeft||bC.scrollLeft,bG=bB.top+bv-bA,bx=bB.left+bz-bE;return{top:bG,left:bx}}}else{b.fn.offset=function(bF){var bz=this[0];if(bF){return this.each(function(bG){b.offset.setOffset(this,bF,bG)})}if(!bz||!bz.ownerDocument){return null}if(bz===bz.ownerDocument.body){return b.offset.bodyOffset(bz)}var bC,bw=bz.offsetParent,bv=bz,bE=bz.ownerDocument,bx=bE.documentElement,bA=bE.body,bB=bE.defaultView,e=bB?bB.getComputedStyle(bz,null):bz.currentStyle,bD=bz.offsetTop,by=bz.offsetLeft;while((bz=bz.parentNode)&&bz!==bA&&bz!==bx){if(b.support.fixedPosition&&e.position==="fixed"){break}bC=bB?bB.getComputedStyle(bz,null):bz.currentStyle;bD-=bz.scrollTop;by-=bz.scrollLeft;if(bz===bw){bD+=bz.offsetTop;by+=bz.offsetLeft;if(b.support.doesNotAddBorder&&!(b.support.doesAddBorderForTableAndCells&&V.test(bz.nodeName))){bD+=parseFloat(bC.borderTopWidth)||0;by+=parseFloat(bC.borderLeftWidth)||0}bv=bw;bw=bz.offsetParent}if(b.support.subtractsBorderForOverflowNotVisible&&bC.overflow!=="visible"){bD+=parseFloat(bC.borderTopWidth)||0;by+=parseFloat(bC.borderLeftWidth)||0}e=bC}if(e.position==="relative"||e.position==="static"){bD+=bA.offsetTop;by+=bA.offsetLeft}if(b.support.fixedPosition&&e.position==="fixed"){bD+=Math.max(bx.scrollTop,bA.scrollTop);by+=Math.max(bx.scrollLeft,bA.scrollLeft)}return{top:bD,left:by}}}b.offset={bodyOffset:function(e){var bw=e.offsetTop,bv=e.offsetLeft;if(b.support.doesNotIncludeMarginInBodyOffset){bw+=parseFloat(b.css(e,"marginTop"))||0;bv+=parseFloat(b.css(e,"marginLeft"))||0}return{top:bw,left:bv}},setOffset:function(bx,bG,bA){var bB=b.css(bx,"position");if(bB==="static"){bx.style.position="relative"}var bz=b(bx),bv=bz.offset(),e=b.css(bx,"top"),bE=b.css(bx,"left"),bF=(bB==="absolute"||bB==="fixed")&&b.inArray("auto",[e,bE])>-1,bD={},bC={},bw,by;if(bF){bC=bz.position();bw=bC.top;by=bC.left}else{bw=parseFloat(e)||0;by=parseFloat(bE)||0}if(b.isFunction(bG)){bG=bG.call(bx,bA,bv)}if(bG.top!=null){bD.top=(bG.top-bv.top)+bw}if(bG.left!=null){bD.left=(bG.left-bv.left)+by}if("using" in bG){bG.using.call(bx,bD)}else{bz.css(bD)}}};b.fn.extend({position:function(){if(!this[0]){return null}var bw=this[0],bv=this.offsetParent(),bx=this.offset(),e=ad.test(bv[0].nodeName)?{top:0,left:0}:bv.offset();bx.top-=parseFloat(b.css(bw,"marginTop"))||0;bx.left-=parseFloat(b.css(bw,"marginLeft"))||0;e.top+=parseFloat(b.css(bv[0],"borderTopWidth"))||0;e.left+=parseFloat(b.css(bv[0],"borderLeftWidth"))||0;return{top:bx.top-e.top,left:bx.left-e.left}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||av.body;while(e&&(!ad.test(e.nodeName)&&b.css(e,"position")==="static")){e=e.offsetParent}return e})}});b.each(["Left","Top"],function(bv,e){var bw="scroll"+e;b.fn[bw]=function(bz){var bx,by;if(bz===L){bx=this[0];if(!bx){return null}by=aK(bx);return by?("pageXOffset" in by)?by[bv?"pageYOffset":"pageXOffset"]:b.support.boxModel&&by.document.documentElement[bw]||by.document.body[bw]:bx[bw]}return this.each(function(){by=aK(this);if(by){by.scrollTo(!bv?bz:b(by).scrollLeft(),bv?bz:b(by).scrollTop())}else{this[bw]=bz}})}});function aK(e){return b.isWindow(e)?e:e.nodeType===9?e.defaultView||e.parentWindow:false}b.each(["Height","Width"],function(bv,e){var bw=e.toLowerCase();b.fn["inner"+e]=function(){var bx=this[0];return bx?bx.style?parseFloat(b.css(bx,bw,"padding")):this[bw]():null};b.fn["outer"+e]=function(by){var bx=this[0];return bx?bx.style?parseFloat(b.css(bx,bw,by?"margin":"border")):this[bw]():null};b.fn[bw]=function(bz){var bA=this[0];if(!bA){return bz==null?null:this}if(b.isFunction(bz)){return this.each(function(bE){var bD=b(this);bD[bw](bz.call(this,bE,bD[bw]()))})}if(b.isWindow(bA)){var bB=bA.document.documentElement["client"+e],bx=bA.document.body;return bA.document.compatMode==="CSS1Compat"&&bB||bx&&bx["client"+e]||bB}else{if(bA.nodeType===9){return Math.max(bA.documentElement["client"+e],bA.body["scroll"+e],bA.documentElement["scroll"+e],bA.body["offset"+e],bA.documentElement["offset"+e])}else{if(bz===L){var bC=b.css(bA,bw),by=parseFloat(bC);return b.isNumeric(by)?by:bC}else{return this.css(bw,typeof bz==="string"?bz:bz+"px")}}}}});bb.jQuery=bb.$=b;if(typeof define==="function"&&define.amd&&define.amd.jQuery){define("jquery",[],function(){return b +})}})(window); +/*! + PowerTip - v1.2.0 - 2013-04-03 + http://stevenbenner.github.com/jquery-powertip/ + Copyright (c) 2013 Steven Benner (http://stevenbenner.com/). + Released under MIT license. + https://raw.github.com/stevenbenner/jquery-powertip/master/LICENSE.txt +*/ +(function(a){if(typeof define==="function"&&define.amd){define(["jquery"],a)}else{a(jQuery)}}(function(k){var A=k(document),s=k(window),w=k("body");var n="displayController",e="hasActiveHover",d="forcedOpen",u="hasMouseMove",f="mouseOnToPopup",g="originalTitle",y="powertip",o="powertipjq",l="powertiptarget",E=180/Math.PI;var c={isTipOpen:false,isFixedTipOpen:false,isClosing:false,tipOpenImminent:false,activeHover:null,currentX:0,currentY:0,previousX:0,previousY:0,desyncTimeout:null,mouseTrackingActive:false,delayInProgress:false,windowWidth:0,windowHeight:0,scrollTop:0,scrollLeft:0};var p={none:0,top:1,bottom:2,left:4,right:8};k.fn.powerTip=function(F,N){if(!this.length){return this}if(k.type(F)==="string"&&k.powerTip[F]){return k.powerTip[F].call(this,this,N)}var O=k.extend({},k.fn.powerTip.defaults,F),G=new x(O);h();this.each(function M(){var R=k(this),Q=R.data(y),P=R.data(o),T=R.data(l),S;if(R.data(n)){k.powerTip.destroy(R)}S=R.attr("title");if(!Q&&!T&&!P&&S){R.data(y,S);R.data(g,S);R.removeAttr("title")}R.data(n,new t(R,O,G))});if(!O.manual){this.on({"mouseenter.powertip":function J(P){k.powerTip.show(this,P)},"mouseleave.powertip":function L(){k.powerTip.hide(this)},"focus.powertip":function K(){k.powerTip.show(this)},"blur.powertip":function H(){k.powerTip.hide(this,true)},"keydown.powertip":function I(P){if(P.keyCode===27){k.powerTip.hide(this,true)}}})}return this};k.fn.powerTip.defaults={fadeInTime:200,fadeOutTime:100,followMouse:false,popupId:"powerTip",intentSensitivity:7,intentPollInterval:100,closeDelay:100,placement:"n",smartPlacement:false,offset:10,mouseOnToPopup:false,manual:false};k.fn.powerTip.smartPlacementLists={n:["n","ne","nw","s"],e:["e","ne","se","w","nw","sw","n","s","e"],s:["s","se","sw","n"],w:["w","nw","sw","e","ne","se","n","s","w"],nw:["nw","w","sw","n","s","se","nw"],ne:["ne","e","se","n","s","sw","ne"],sw:["sw","w","nw","s","n","ne","sw"],se:["se","e","ne","s","n","nw","se"],"nw-alt":["nw-alt","n","ne-alt","sw-alt","s","se-alt","w","e"],"ne-alt":["ne-alt","n","nw-alt","se-alt","s","sw-alt","e","w"],"sw-alt":["sw-alt","s","se-alt","nw-alt","n","ne-alt","w","e"],"se-alt":["se-alt","s","sw-alt","ne-alt","n","nw-alt","e","w"]};k.powerTip={show:function z(F,G){if(G){i(G);c.previousX=G.pageX;c.previousY=G.pageY;k(F).data(n).show()}else{k(F).first().data(n).show(true,true)}return F},reposition:function r(F){k(F).first().data(n).resetPosition();return F},hide:function D(G,F){if(G){k(G).first().data(n).hide(F)}else{if(c.activeHover){c.activeHover.data(n).hide(true)}}return G},destroy:function C(G){k(G).off(".powertip").each(function F(){var I=k(this),H=[g,n,e,d];if(I.data(g)){I.attr("title",I.data(g));H.push(y)}I.removeData(H)});return G}};k.powerTip.showTip=k.powerTip.show;k.powerTip.closeTip=k.powerTip.hide;function b(){var F=this;F.top="auto";F.left="auto";F.right="auto";F.bottom="auto";F.set=function(H,G){if(k.isNumeric(G)){F[H]=Math.round(G)}}}function t(K,N,F){var J=null;function L(P,Q){M();if(!K.data(e)){if(!P){c.tipOpenImminent=true;J=setTimeout(function O(){J=null;I()},N.intentPollInterval)}else{if(Q){K.data(d,true)}F.showTip(K)}}}function G(P){M();c.tipOpenImminent=false;if(K.data(e)){K.data(d,false);if(!P){c.delayInProgress=true;J=setTimeout(function O(){J=null;F.hideTip(K);c.delayInProgress=false},N.closeDelay)}else{F.hideTip(K)}}}function I(){var Q=Math.abs(c.previousX-c.currentX),O=Math.abs(c.previousY-c.currentY),P=Q+O;if(P",{id:Q.popupId});if(w.length===0){w=k("body")}w.append(O)}if(Q.followMouse){if(!O.data(u)){A.on("mousemove",M);s.on("scroll",M);O.data(u,true)}}if(Q.mouseOnToPopup){O.on({mouseenter:function L(){if(O.data(f)){if(c.activeHover){c.activeHover.data(n).cancel()}}},mouseleave:function N(){if(c.activeHover){c.activeHover.data(n).hide()}}})}function I(S){S.data(e,true);O.queue(function R(T){H(S);T()})}function H(S){var U;if(!S.data(e)){return}if(c.isTipOpen){if(!c.isClosing){K(c.activeHover)}O.delay(100).queue(function R(V){H(S);V()});return}S.trigger("powerTipPreRender");U=B(S);if(U){O.empty().append(U)}else{return}S.trigger("powerTipRender");c.activeHover=S;c.isTipOpen=true;O.data(f,Q.mouseOnToPopup);if(!Q.followMouse){G(S);c.isFixedTipOpen=true}else{M()}O.fadeIn(Q.fadeInTime,function T(){if(!c.desyncTimeout){c.desyncTimeout=setInterval(J,500)}S.trigger("powerTipOpen")})}function K(R){c.isClosing=true;c.activeHover=null;c.isTipOpen=false;c.desyncTimeout=clearInterval(c.desyncTimeout);R.data(e,false);R.data(d,false);O.fadeOut(Q.fadeOutTime,function S(){var T=new b();c.isClosing=false;c.isFixedTipOpen=false;O.removeClass();T.set("top",c.currentY+Q.offset);T.set("left",c.currentX+Q.offset);O.css(T);R.trigger("powerTipClose")})}function M(){if(!c.isFixedTipOpen&&(c.isTipOpen||(c.tipOpenImminent&&O.data(u)))){var R=O.outerWidth(),V=O.outerHeight(),U=new b(),S,T;U.set("top",c.currentY+Q.offset);U.set("left",c.currentX+Q.offset);S=m(U,R,V);if(S!==p.none){T=a(S);if(T===1){if(S===p.right){U.set("left",c.windowWidth-R)}else{if(S===p.bottom){U.set("top",c.scrollTop+c.windowHeight-V)}}}else{U.set("left",c.currentX-R-Q.offset);U.set("top",c.currentY-V-Q.offset)}}O.css(U)}}function G(S){var R,T;if(Q.smartPlacement){R=k.fn.powerTip.smartPlacementLists[Q.placement];k.each(R,function(U,W){var V=m(F(S,W),O.outerWidth(),O.outerHeight());T=W;if(V===p.none){return false}})}else{F(S,Q.placement);T=Q.placement}O.addClass(T)}function F(U,T){var R=0,S,W,V=new b();V.set("top",0);V.set("left",0);O.css(V);do{S=O.outerWidth();W=O.outerHeight();V=P.compute(U,T,S,W,Q.offset);O.css(V)}while(++R<=5&&(S!==O.outerWidth()||W!==O.outerHeight()));return V}function J(){var R=false;if(c.isTipOpen&&!c.isClosing&&!c.delayInProgress){if(c.activeHover.data(e)===false||c.activeHover.is(":disabled")){R=true}else{if(!v(c.activeHover)&&!c.activeHover.is(":focus")&&!c.activeHover.data(d)){if(O.data(f)){if(!v(O)){R=true}}else{R=true}}}if(R){K(c.activeHover)}}}this.showTip=I;this.hideTip=K;this.resetPosition=G}function q(F){return window.SVGElement&&F[0] instanceof SVGElement}function h(){if(!c.mouseTrackingActive){c.mouseTrackingActive=true;k(function H(){c.scrollLeft=s.scrollLeft();c.scrollTop=s.scrollTop();c.windowWidth=s.width();c.windowHeight=s.height()});A.on("mousemove",i);s.on({resize:function G(){c.windowWidth=s.width();c.windowHeight=s.height()},scroll:function F(){var I=s.scrollLeft(),J=s.scrollTop();if(I!==c.scrollLeft){c.currentX+=I-c.scrollLeft;c.scrollLeft=I}if(J!==c.scrollTop){c.currentY+=J-c.scrollTop;c.scrollTop=J}}})}}function i(F){c.currentX=F.pageX;c.currentY=F.pageY}function v(F){var H=F.offset(),J=F[0].getBoundingClientRect(),I=J.right-J.left,G=J.bottom-J.top;return c.currentX>=H.left&&c.currentX<=H.left+I&&c.currentY>=H.top&&c.currentY<=H.top+G}function B(I){var G=I.data(y),F=I.data(o),K=I.data(l),H,J;if(G){if(k.isFunction(G)){G=G.call(I[0])}J=G}else{if(F){if(k.isFunction(F)){F=F.call(I[0])}if(F.length>0){J=F.clone(true,true)}}else{if(K){H=k("#"+K);if(H.length>0){J=H.html()}}}}return J}function m(M,L,K){var G=c.scrollTop,J=c.scrollLeft,I=G+c.windowHeight,F=J+c.windowWidth,H=p.none;if(M.topI||Math.abs(M.bottom-c.windowHeight)>I){H|=p.bottom}if(M.leftF){H|=p.left}if(M.left+L>F||M.right + +/// Represent a rational number. +struct rational +{ + int numerator; ///< numerator gets the sign of the rational value + int denominator; ///< denominator is always positive +}; + +int main() +{ + rational pi{}; + pi.numerator = 355; + pi.denominator = 113; + std::cout << "pi is approximately " << pi.numerator << "/" << pi.denominator << '\n'; +} diff --git a/exploring-cpp-2e/chapter29/list2903.cpp b/exploring-cpp-2e/chapter29/list2903.cpp new file mode 100644 index 0000000..b487e16 --- /dev/null +++ b/exploring-cpp-2e/chapter29/list2903.cpp @@ -0,0 +1,41 @@ +// Listing 29-3. Adding the reduce Member Function +#include +#include +#include + +/// Compute the greatest common divisor of two integers, using Euclid’s algorithm. +int gcd(int n, int m) +{ + n = std::abs(n); + while (m != 0) { + int tmp{n % m}; + n = m; + m = tmp; + } + return n; +} + +/// Represent a rational number. +struct rational +{ + /// Reduce the numerator and denominator by their GCD. + void reduce() + { + assert(denominator != 0); + int div{gcd(numerator, denominator)}; + numerator = numerator / div; + denominator = denominator / div; + } + + int numerator; ///< numerator gets the sign of the rational value + int denominator; ///< denominator is always positive +}; + +int main() +{ + rational pi{}; + pi.numerator = 1420; + pi.denominator = 452; + pi.reduce(); + std::cout << "pi is approximately " << pi.numerator << "/" << pi.denominator << '\n'; +} diff --git a/exploring-cpp-2e/chapter29/list2904.cpp b/exploring-cpp-2e/chapter29/list2904.cpp new file mode 100644 index 0000000..bb8f74a --- /dev/null +++ b/exploring-cpp-2e/chapter29/list2904.cpp @@ -0,0 +1,50 @@ +// Listing 29-4. Adding the assign Member Function +#include +#include +#include + +/// Compute the greatest common divisor of two integers, using Euclid's algorithm. +int gcd(int n, int m) +{ + n = std::abs(n); + while (m != 0) { + int tmp(n % m); + n = m; + m = tmp; + } + return n; +} + +/// Represent a rational number. +struct rational +{ + /// Assign a numerator and a denominator, then reduce to normal form. + /// @param num numerator + /// @param den denominator + /// @pre denominator > 0 + void assign(int num, int den) + { + numerator = num; + denominator = den; + reduce(); + } + + /// Reduce the numerator and denominator by their GCD. + void reduce() + { + assert(denominator != 0); + int div{gcd(numerator, denominator)}; + numerator = numerator / div; + denominator = denominator / div; + } + + int numerator; ///< numerator gets the sign of the rational value + int denominator; ///< denominator is always positive +}; + +int main() +{ + rational pi{}; + pi.assign(1420, 452); + std::cout << "pi is approximately " << pi.numerator << "/" << pi.denominator << '\n'; +} diff --git a/exploring-cpp-2e/chapter29/list2905.cpp b/exploring-cpp-2e/chapter29/list2905.cpp new file mode 100644 index 0000000..87c8efb --- /dev/null +++ b/exploring-cpp-2e/chapter29/list2905.cpp @@ -0,0 +1,60 @@ +// Listing 29-5. Adding the Ability to Initialize a rational Object +#include +#include +#include + +/// Compute the greatest common divisor of two integers, using Euclid’s algorithm. +int gcd(int n, int m) +{ + n = std::abs(n); + while (m != 0) { + int tmp(n % m); + n = m; + m = tmp; + } + return n; +} + +/// Represent a rational number. +struct rational +{ + /// Construct a rational object, given a numerator and a denominator. + /// Always reduce to normal form. + /// @param num numerator + /// @param den denominator + /// @pre denominator > 0 + rational(int num, int den) + : numerator{num}, denominator{den} + { + reduce(); + } + + /// Assign a numerator and a denominator, then reduce to normal form. + /// @param num numerator + /// @param den denominator + /// @pre denominator > 0 + void assign(int num, int den) + { + numerator = num; + denominator = den; + reduce(); + } + + /// Reduce the numerator and denominator by their GCD. + void reduce() + { + assert(denominator != 0); + int div{gcd(numerator, denominator)}; + numerator = numerator / div; + denominator = denominator / div; + } + + int numerator; ///< numerator gets the sign of the rational value + int denominator; ///< denominator is always positive +}; + +int main() +{ + rational pi{1420, 452}; + std::cout << "pi is about " << pi.numerator << "/" << pi.denominator << '\n'; +} diff --git a/exploring-cpp-2e/chapter29/list2906.cpp b/exploring-cpp-2e/chapter29/list2906.cpp new file mode 100644 index 0000000..f692a2e --- /dev/null +++ b/exploring-cpp-2e/chapter29/list2906.cpp @@ -0,0 +1,14 @@ +// Listing 29-6. Modifying the reduce Member Function to Accept a Negative Denominator + /// Reduce the numerator and denominator by their GCD. + void reduce() + { + assert(denominator != 0); + if (denominator < 0) + { + denominator = -denominator; + numerator = -numerator; + } + int div{gcd(numerator, denominator)}; + numerator = numerator / div; + denominator = denominator / div; + } diff --git a/exploring-cpp-2e/chapter30/list3001.cpp b/exploring-cpp-2e/chapter30/list3001.cpp new file mode 100644 index 0000000..454f24d --- /dev/null +++ b/exploring-cpp-2e/chapter30/list3001.cpp @@ -0,0 +1,57 @@ +// Listing 30-1. Overloading the Equality Operator +/// Represent a rational number. +struct rational +{ + /// Construct a rational object, given a numerator and a denominator. + /// Always reduce to normal form. + /// @param num numerator + /// @param den denominator + /// @pre denominator > 0 + rational(int num, int den) + : numerator{num}, denominator{den} + { + reduce(); + } + + /// Assign a numerator and a denominator, then reduce to normal form. + /// @param num numerator + /// @param den denominator + /// @pre denominator > 0 + void assign(int num, int den) + { + numerator = num; + denominator = den; + reduce(); + } + + /// Reduce the numerator and denominator by their GCD. + void reduce() + { + assert(denominator != 0); + if (denominator < 0) + { + denominator = -denominator; + numerator = -numerator; + } + int div{gcd(numerator, denominator)}; + numerator = numerator / div; + denominator = denominator / div; + } + + int numerator; ///< numerator gets the sign of the rational value + int denominator; ///< denominator is always positive +}; + +/// Compare two rational numbers for equality. +/// @pre @p a and @p b are reduced to normal form +bool operator==(rational const& a, rational const& b) +{ + return a.numerator == b.numerator and a.denominator == b.denominator; +} + +/// Compare two rational numbers for inequality. +/// @pre @p a and @p b are reduced to normal form +bool operator!=(rational const& a, rational const& b) +{ + return not (a == b); +} diff --git a/exploring-cpp-2e/chapter30/list3002.cpp b/exploring-cpp-2e/chapter30/list3002.cpp new file mode 100644 index 0000000..26321ad --- /dev/null +++ b/exploring-cpp-2e/chapter30/list3002.cpp @@ -0,0 +1,14 @@ +// Listing 30-2. Using inline for Trivial Functions +/// Compare two rational numbers for equality. +/// @pre @p a and @p b are reduced to normal form +bool operator==(rational const& a, rational const& b) +{ + return a.numerator == b.numerator and a.denominator == b.denominator; +} + +/// Compare two rational numbers for inequality. +/// @pre @p a and @p b are reduced to normal form +inline bool operator!=(rational const& a, rational const& b) +{ + return not (a == b); +} diff --git a/exploring-cpp-2e/chapter30/list3003.cpp b/exploring-cpp-2e/chapter30/list3003.cpp new file mode 100644 index 0000000..fd26809 --- /dev/null +++ b/exploring-cpp-2e/chapter30/list3003.cpp @@ -0,0 +1,12 @@ +// Listing 30-3. Implementing the < Operator for rational +/// Compare two rational numbers for less-than. +bool operator<(rational const& a, rational const& b) +{ + return a.numerator * b.denominator < b.numerator * a.denominator; +} + +/// Compare two rational numbers for less-than-or-equal. +inline bool operator<=(rational const& a, rational const& b) +{ + return not (b < a); +} diff --git a/exploring-cpp-2e/chapter30/list3004.cpp b/exploring-cpp-2e/chapter30/list3004.cpp new file mode 100644 index 0000000..7e423cb --- /dev/null +++ b/exploring-cpp-2e/chapter30/list3004.cpp @@ -0,0 +1,12 @@ +// Listing 30-4. Implementing the > and >= Operators in Terms of < +/// Compare two rational numbers for greater-than. +inline bool operator>(rational const& a, rational const& b) +{ + return b < a; +} + +/// Compare two rational numbers for greater-than-or-equal. +inline bool operator>=(rational const& a, rational const& b) +{ + return not (b > a); +} diff --git a/exploring-cpp-2e/chapter30/list3005.cpp b/exploring-cpp-2e/chapter30/list3005.cpp new file mode 100644 index 0000000..0a175e3 --- /dev/null +++ b/exploring-cpp-2e/chapter30/list3005.cpp @@ -0,0 +1,137 @@ +// Listing 30-5. Testing the rational Comparison Operators +#include +#include +#include +#include "test.hpp" + +// Listing 29-3. Adding the reduce Member Function +/// Compute the greatest common divisor of two integers, using Euclid’s algorithm. +int gcd(int n, int m) +{ + n = std::abs(n); + while (m != 0) { + int tmp{n % m}; + n = m; + m = tmp; + } + return n; +} + +// Listing 30-1. Overloading the Equality Operator +/// Represent a rational number. +struct rational +{ + /// Construct a rational object, given a numerator and a denominator. + /// Always reduce to normal form. + /// @param num numerator + /// @param den denominator + /// @pre denominator > 0 + rational(int num, int den) + : numerator{num}, denominator{den} + { + reduce(); + } + + /// Assign a numerator and a denominator, then reduce to normal form. + /// @param num numerator + /// @param den denominator + /// @pre denominator > 0 + void assign(int num, int den) + { + numerator = num; + denominator = den; + reduce(); + } + + /// Reduce the numerator and denominator by their GCD. + void reduce() + { + assert(denominator != 0); + if (denominator < 0) + { + denominator = -denominator; + numerator = -numerator; + } + int div{gcd(numerator, denominator)}; + numerator = numerator / div; + denominator = denominator / div; + } + + int numerator; ///< numerator gets the sign of the rational value + int denominator; ///< denominator is always positive +}; + +// Listing 30-2. Using inline for Trivial Functions +/// Compare two rational numbers for equality. +/// @pre @p a and @p b are reduced to normal form +bool operator==(rational const& a, rational const& b) +{ + return a.numerator == b.numerator and a.denominator == b.denominator; +} + +/// Compare two rational numbers for inequality. +/// @pre @p a and @p b are reduced to normal form +inline bool operator!=(rational const& a, rational const& b) +{ + return not (a == b); +} + +// Listing 30-3. Implementing the < Operator for rational +/// Compare two rational numbers for less-than. +bool operator<(rational const& a, rational const& b) +{ + return a.numerator * b.denominator < b.numerator * a.denominator; +} + +/// Compare two rational numbers for less-than-or-equal. +inline bool operator<=(rational const& a, rational const& b) +{ + return not (b < a); +} + +// Listing 30-4. Implementing the > and >= Operators in Terms of < +/// Compare two rational numbers for greater-than. +inline bool operator>(rational const& a, rational const& b) +{ + return b < a; +} + +/// Compare two rational numbers for greater-than-or-equal. +inline bool operator>=(rational const& a, rational const& b) +{ + return not (b > a); +} + +int main() +{ + rational a{60, 5}; + rational b{12, 1}; + rational c{-24, -2}; + TEST(a == b); + TEST(a >= b); + TEST(a <= b); + TEST(b <= a); + TEST(b >= a); + TEST(b == c); + TEST(b >= c); + TEST(b <= c); + TEST(a == c); + TEST(a >= c); + TEST(a <= c); + + rational d{109, 10}; + TEST(d < a); + TEST(d <= a); + TEST(d != a); + TEST(a > d); + TEST(a >= d); + TEST(a != d); + + rational e{241, 20}; + TEST(e > a); + TEST(e >= a); + TEST(e != a); + TEST(a < e); + TEST(a <= e); + TEST(a != e); +} diff --git a/exploring-cpp-2e/chapter30/list3006.cpp b/exploring-cpp-2e/chapter30/list3006.cpp new file mode 100644 index 0000000..bf2c44f --- /dev/null +++ b/exploring-cpp-2e/chapter30/list3006.cpp @@ -0,0 +1,11 @@ +// Listing 30-6. Addition Operator for the rational Type +rational operator+(rational const& lhs, rational const& rhs) +{ + return rational{lhs.numerator * rhs.denominator + rhs.numerator * lhs.denominator, + lhs.denominator * rhs.denominator}; +} + +rational operator-(rational const& r) +{ + return rational{-r.numerator, r.denominator}; +} diff --git a/exploring-cpp-2e/chapter30/list3007.cpp b/exploring-cpp-2e/chapter30/list3007.cpp new file mode 100644 index 0000000..d74b1bb --- /dev/null +++ b/exploring-cpp-2e/chapter30/list3007.cpp @@ -0,0 +1,16 @@ +// Listing 30-7. Arithmetic Operators for the rational Type +rational operator-(rational const& lhs, rational const& rhs) +{ + return rational{lhs.numerator * rhs.denominator - rhs.numerator * lhs.denominator, + lhs.denominator * rhs.denominator}; +} + +rational operator*(rational const& lhs, rational const& rhs) +{ + return rational{lhs.numerator * rhs.numerator, lhs.denominator * rhs.denominator}; +} + +rational operator/(rational const& lhs, rational const& rhs) +{ + return rational{lhs.numerator * rhs.denominator, lhs.denominator * rhs.numerator}; +} diff --git a/exploring-cpp-2e/chapter30/list3008.cpp b/exploring-cpp-2e/chapter30/list3008.cpp new file mode 100644 index 0000000..9ac1273 --- /dev/null +++ b/exploring-cpp-2e/chapter30/list3008.cpp @@ -0,0 +1,144 @@ +// Listing 30-8. Test Program for Multiplying an Integer and a Rational Number +#include +#include +#include + +// Listing 29-3. Adding the reduce Member Function +/// Compute the greatest common divisor of two integers, using Euclid’s algorithm. +int gcd(int n, int m) +{ + n = std::abs(n); + while (m != 0) { + int tmp{n % m}; + n = m; + m = tmp; + } + return n; +} + +// Listing 30-1. Overloading the Equality Operator +/// Represent a rational number. +struct rational +{ + /// Construct a rational object, given a numerator and a denominator. + /// Always reduce to normal form. + /// @param num numerator + /// @param den denominator + /// @pre denominator > 0 + rational(int num, int den) + : numerator{num}, denominator{den} + { + reduce(); + } + + /// Construct a rational object, given a numerator. + /// No need to reduce to normal form because denominator is always 1. + /// @param num numerator + rational(int num) + : numerator{num}, denominator{1} + {} + + /// Assign a numerator and a denominator, then reduce to normal form. + /// @param num numerator + /// @param den denominator + /// @pre denominator > 0 + void assign(int num, int den) + { + numerator = num; + denominator = den; + reduce(); + } + + /// Reduce the numerator and denominator by their GCD. + void reduce() + { + assert(denominator != 0); + if (denominator < 0) + { + denominator = -denominator; + numerator = -numerator; + } + int div{gcd(numerator, denominator)}; + numerator = numerator / div; + denominator = denominator / div; + } + + int numerator; ///< numerator gets the sign of the rational value + int denominator; ///< denominator is always positive +}; + +// Listing 30-2. Using inline for Trivial Functions +/// Compare two rational numbers for equality. +/// @pre @p a and @p b are reduced to normal form +bool operator==(rational const& a, rational const& b) +{ + return a.numerator == b.numerator and a.denominator == b.denominator; +} + +/// Compare two rational numbers for inequality. +/// @pre @p a and @p b are reduced to normal form +inline bool operator!=(rational const& a, rational const& b) +{ + return not (a == b); +} + +// Listing 30-3. Implementing the < Operator for rational +/// Compare two rational numbers for less-than. +bool operator<(rational const& a, rational const& b) +{ + return a.numerator * b.denominator < b.numerator * a.denominator; +} + +/// Compare two rational numbers for less-than-or-equal. +inline bool operator<=(rational const& a, rational const& b) +{ + return not (b < a); +} + +// Listing 30-4. Implementing the > and >= Operators in Terms of < +/// Compare two rational numbers for greater-than. +inline bool operator>(rational const& a, rational const& b) +{ + return b < a; +} + +/// Compare two rational numbers for greater-than-or-equal. +inline bool operator>=(rational const& a, rational const& b) +{ + return not (b > a); +} + +// Listing 30-6. Addition Operator for the rational Type +rational operator+(rational const& lhs, rational const& rhs) +{ + return rational{lhs.numerator * rhs.denominator + rhs.numerator * lhs.denominator, + lhs.denominator * rhs.denominator}; +} + +rational operator-(rational const& r) +{ + return rational{-r.numerator, r.denominator}; +} + +// Listing 30-7. Arithmetic Operators for the rational Type +rational operator-(rational const& lhs, rational const& rhs) +{ + return rational{lhs.numerator * rhs.denominator - rhs.numerator * lhs.denominator, + lhs.denominator * rhs.denominator}; +} + +rational operator*(rational const& lhs, rational const& rhs) +{ + return rational{lhs.numerator * rhs.numerator, lhs.denominator * rhs.denominator}; +} + +rational operator/(rational const& lhs, rational const& rhs) +{ + return rational{lhs.numerator * rhs.denominator, lhs.denominator * rhs.numerator}; +} + +int main() +{ + rational result{3 * rational{1, 3}}; + std::cout << result.numerator << '/' << result.denominator << '\n'; +} diff --git a/exploring-cpp-2e/chapter30/list3009.cpp b/exploring-cpp-2e/chapter30/list3009.cpp new file mode 100644 index 0000000..277f430 --- /dev/null +++ b/exploring-cpp-2e/chapter30/list3009.cpp @@ -0,0 +1,41 @@ +// Listing 30-9. Constructing a Rational Number from a Floating-Point Argument +struct rational +{ + rational(int num, int den) + : numerator{num}, denominator{den} + { + reduce(); + } + + rational(double r) + : rational{static_cast(r * 10000), 10000} + {} + + /// Assign a numerator and a denominator, then reduce to normal form. + /// @param num numerator + /// @param den denominator + /// @pre denominator > 0 + void assign(int num, int den) + { + numerator = num; + denominator = den; + reduce(); + } + + /// Reduce the numerator and denominator by their GCD. + void reduce() + { + assert(denominator != 0); + if (denominator < 0) + { + denominator = -denominator; + numerator = -numerator; + } + int div{gcd(numerator, denominator)}; + numerator = numerator / div; + denominator = denominator / div; + } + + int numerator; + int denominator; +}; diff --git a/exploring-cpp-2e/chapter30/list3010.cpp b/exploring-cpp-2e/chapter30/list3010.cpp new file mode 100644 index 0000000..c3379e6 --- /dev/null +++ b/exploring-cpp-2e/chapter30/list3010.cpp @@ -0,0 +1,11 @@ +// Listing 30-10. Optimizing Operators for a Specific Operand Type +rational operator*(rational const& rat, int mult) +{ + return rational{rat.numerator * mult, rat.denominator}; +} + +inline rational operator*(int mult, rational const& rat) +{ + return rat * mult; +} + diff --git a/exploring-cpp-2e/chapter30/list3011.cpp b/exploring-cpp-2e/chapter30/list3011.cpp new file mode 100644 index 0000000..415861e --- /dev/null +++ b/exploring-cpp-2e/chapter30/list3011.cpp @@ -0,0 +1,5 @@ +// Listing 30-11. Computing the Absolute Value of a Rational Number +rational absval(rational const& r) +{ + return rational{std::abs(r.numerator), r.denominator}; +} diff --git a/exploring-cpp-2e/chapter30/list3012.cpp b/exploring-cpp-2e/chapter30/list3012.cpp new file mode 100644 index 0000000..fdec387 --- /dev/null +++ b/exploring-cpp-2e/chapter30/list3012.cpp @@ -0,0 +1,87 @@ +#include +#include +#include + +// Listing 29-3. Adding the reduce Member Function +/// Compute the greatest common divisor of two integers, using Euclid’s algorithm. +int gcd(int n, int m) +{ + n = std::abs(n); + while (m != 0) { + int tmp{n % m}; + n = m; + m = tmp; + } + return n; +} + +// Listing 30-12. Converting to Floating-Point Types +struct rational +{ + float as_float() + { + return static_cast(numerator) / denominator; + } + + double as_double() + { + return numerator / static_cast(denominator); + } + + long double as_long_double() + { + return static_cast(numerator) / + static_cast(denominator); + } + + /// Construct a rational object, given a numerator and a denominator. + /// Always reduce to normal form. + /// @param num numerator + /// @param den denominator + /// @pre denominator > 0 + rational(int num, int den) + : numerator{num}, denominator{den} + { + reduce(); + } + + /// Assign a numerator and a denominator, then reduce to normal form. + /// @param num numerator + /// @param den denominator + /// @pre denominator > 0 + void assign(int num, int den) + { + numerator = num; + denominator = den; + reduce(); + } + + /// Reduce the numerator and denominator by their GCD. + void reduce() + { + assert(denominator != 0); + if (denominator < 0) + { + denominator = -denominator; + numerator = -numerator; + } + int div{gcd(numerator, denominator)}; + numerator = numerator / div; + denominator = denominator / div; + } + + int numerator; ///< numerator gets the sign of the rational value + int denominator; ///< denominator is always positive +}; + +int main() +{ + rational pi{355, 113}; + rational bmi{90*100*100, 180*180}; // Body-mass index of 90 kg, 180 cm + double circumference{0}, radius{10}; + + circumference = 2 * pi.as_double() * radius; + std::cout << "circumference of circle with radius " << radius << " is about " + << circumference << '\n'; + std::cout << "bmi = " << bmi.as_float() << '\n'; +} diff --git a/exploring-cpp-2e/chapter30/test.hpp b/exploring-cpp-2e/chapter30/test.hpp new file mode 100644 index 0000000..6ec2a91 --- /dev/null +++ b/exploring-cpp-2e/chapter30/test.hpp @@ -0,0 +1,55 @@ +#ifndef TEST_HPP_ +#define TEST_HPP_ + +#include +#include + +// For internal use by the TEST() macro. +// Turn the macro argument into a character string literal +#define TEST_STRINGIFY(x) #x + +// For internal use by the TEST() macro. +// Report a test failure. +inline void test_failed(char const* expr, char const* file, int line) +{ + std::cerr << file << ", line " << line << ": test failed: " << expr << '\n'; +} + +// For internal use by the TEST() macro +// Run a test. Report a failure if the condition is false or +inline void test_run(bool condition, char const* expr, char const* file, int line) +{ + if (not condition) + test_failed(expr, file, line); +} + +// For internal use by the TEST() macro. +// Report an exception. +inline void test_exception(std::exception const& ex, char const* expr, char const* file, int line) +{ + std::string msg{ expr }; + msg += " threw an exception: "; + msg += ex.what(); + test_failed(msg.c_str(), file, line); +} + +/// Test a condition, @p x. +/// If @p x evaluates to @c true the test passes. +/// If not, the test fails, and a message is printed to @c cerr. +/// The text of @p x, plus the file name and line number are printed. +/// +/// See Google Test (http://code.google.com/p/googletest/) or +/// Boost.Test (www.boost.org/doc/libs/1_54_0/libs/test) for a real test framework +/// +/// @param x A condition to test; the condition must be able to be converted implicitly to @c bool. +#define TEST(x) \ +try {\ + test_run(x, TEST_STRINGIFY(x), __FILE__, __LINE__);\ +}\ +catch(std::exception const& ex)\ +{\ + test_exception(ex, TEST_STRINGIFY(x), __FILE__, __LINE__);\ +} + +#endif + diff --git a/exploring-cpp-2e/chapter31/list3101.cpp b/exploring-cpp-2e/chapter31/list3101.cpp new file mode 100644 index 0000000..ff5931d --- /dev/null +++ b/exploring-cpp-2e/chapter31/list3101.cpp @@ -0,0 +1,29 @@ +// Listing 31-1. Input Operator +#include // declares failbit, etc. +#include // declares std::istream and the necessary >> operators + +std::istream& operator>>(std::istream& in, rational& rat) +{ + int n{0}, d{0}; + char sep{'\0'}; + if (not (in >> n >> sep)) + // Error reading the numerator or the separator character. + in.setstate(std::cin.failbit); + else if (sep != '/') + { + // Read numerator successfully, but it is not followed by /. + // Push sep back into the input stream, so the next input operation + // will read it. + in.unget(); + rat.assign(n, 1); + } + else if (in >> d) + // Successfully read numerator, separator, and denominator. + rat.assign(n, d); + else + // Error reading denominator. + in.setstate(std::cin.failbit); + + return in; +} + diff --git a/exploring-cpp-2e/chapter31/list3102.cpp b/exploring-cpp-2e/chapter31/list3102.cpp new file mode 100644 index 0000000..89f26f7 --- /dev/null +++ b/exploring-cpp-2e/chapter31/list3102.cpp @@ -0,0 +1,15 @@ +// Listing 31-2. Output Operator +#include // declares the necessary << operators +#include // declares the std::ostringstream type + +std::ostream& operator<<(std::ostream& out, rational const& rat) +{ + std::ostringstream tmp{}; + tmp << rat.numerator; + if (rat.denominator != 1) + tmp << '/' << rat.denominator; + out << tmp.str(); + + return out; +} + diff --git a/exploring-cpp-2e/chapter31/list3103.cpp b/exploring-cpp-2e/chapter31/list3103.cpp new file mode 100644 index 0000000..344dba9 --- /dev/null +++ b/exploring-cpp-2e/chapter31/list3103.cpp @@ -0,0 +1,205 @@ +// Listing 31-3. Testing the I/O Operators + +#include +#include +#include +#include +#include + +// Listing 29-3. Adding the reduce Member Function +/// Compute the greatest common divisor of two integers, using Euclid’s algorithm. +int gcd(int n, int m) +{ + n = std::abs(n); + while (m != 0) { + int tmp{n % m}; + n = m; + m = tmp; + } + return n; +} + +// Listing 30-1. Overloading the Equality Operator +/// Represent a rational number. +struct rational +{ + /// Construct a rational object, given a numerator and a denominator. + /// Always reduce to normal form. + /// @param num numerator + /// @param den denominator + /// @pre denominator > 0 + rational(int num, int den) + : numerator{num}, denominator{den} + { + reduce(); + } + + /// Construct a rational object, given a numerator. + /// No need to reduce to normal form because denominator is always 1. + /// @param num numerator + rational(int num) + : numerator{num}, denominator{1} + {} + + /// Assign a numerator and a denominator, then reduce to normal form. + /// @param num numerator + /// @param den denominator + /// @pre denominator > 0 + void assign(int num, int den) + { + numerator = num; + denominator = den; + reduce(); + } + + /// Reduce the numerator and denominator by their GCD. + void reduce() + { + assert(denominator != 0); + if (denominator < 0) + { + denominator = -denominator; + numerator = -numerator; + } + int div{gcd(numerator, denominator)}; + numerator = numerator / div; + denominator = denominator / div; + } + + int numerator; ///< numerator gets the sign of the rational value + int denominator; ///< denominator is always positive +}; + +// Listing 30-2. Using inline for Trivial Functions +/// Compare two rational numbers for equality. +/// @pre @p a and @p b are reduced to normal form +bool operator==(rational const& a, rational const& b) +{ + return a.numerator == b.numerator and a.denominator == b.denominator; +} + +/// Compare two rational numbers for inequality. +/// @pre @p a and @p b are reduced to normal form +inline bool operator!=(rational const& a, rational const& b) +{ + return not (a == b); +} + +// Listing 30-3. Implementing the < Operator for rational +/// Compare two rational numbers for less-than. +bool operator<(rational const& a, rational const& b) +{ + return a.numerator * b.denominator < b.numerator * a.denominator; +} + +/// Compare two rational numbers for less-than-or-equal. +inline bool operator<=(rational const& a, rational const& b) +{ + return not (b < a); +} + +// Listing 30-4. Implementing the > and >= Operators in Terms of < +/// Compare two rational numbers for greater-than. +inline bool operator>(rational const& a, rational const& b) +{ + return b < a; +} + +/// Compare two rational numbers for greater-than-or-equal. +inline bool operator>=(rational const& a, rational const& b) +{ + return not (b > a); +} + +// Listing 30-6. Addition Operator for the rational Type +rational operator+(rational const& lhs, rational const& rhs) +{ + return rational{lhs.numerator * rhs.denominator + rhs.numerator * lhs.denominator, + lhs.denominator * rhs.denominator}; +} + +rational operator-(rational const& r) +{ + return rational{-r.numerator, r.denominator}; +} + +// Listing 30-7. Arithmetic Operators for the rational Type +rational operator-(rational const& lhs, rational const& rhs) +{ + return rational{lhs.numerator * rhs.denominator - rhs.numerator * lhs.denominator, + lhs.denominator * rhs.denominator}; +} + +rational operator*(rational const& lhs, rational const& rhs) +{ + return rational{lhs.numerator * rhs.numerator, lhs.denominator * rhs.denominator}; +} + +rational operator/(rational const& lhs, rational const& rhs) +{ + return rational{lhs.numerator * rhs.denominator, lhs.denominator * rhs.numerator}; +} + +std::istream& operator>>(std::istream& in, rational& rat) +{ + int n{0}, d{0}; + char sep{'\0'}; + if (not (in >> n >> sep)) + // Error reading the numerator or the separator character. + in.setstate(std::cin.failbit); + else if (sep != '/') + { + // Read numerator successfully, but it is not followed by /. + // Push sep back into the input stream, so the next input operation + // will read it. + in.unget(); + rat.assign(n, 1); + } + else if (in >> d) + // Successfully read numerator, separator, and denominator. + rat.assign(n, d); + else + // Error reading denominator. + in.setstate(std::cin.failbit); + + return in; +} + +std::ostream& operator<<(std::ostream& out, rational const& rat) +{ + std::ostringstream tmp{}; + tmp << rat.numerator; + if (rat.denominator != 1) + tmp << '/' << rat.denominator; + out << tmp.str(); + + return out; +} + +/// Tests for failbit only +bool iofailure(std::istream& in) +{ + return in.fail() and not in.bad(); +} + +int main() +{ + rational r{0}; + + while (std::cin) + { + if (std::cin >> r) + // Read succeeded, so no failure state is set in the stream. + std::cout << r << '\n'; + else if (iofailure(std::cin)) + { + // Only failbit is set, meaning invalid input. Clear the state, + // and then skip the rest of the input line. + std::cin.clear(); + std::cin.ignore(std::numeric_limits::max(), '\n'); + } + } + + if (std::cin.bad()) + std::cerr << "Unrecoverable input failure\n"; +} diff --git a/exploring-cpp-2e/chapter32/list3201.cpp b/exploring-cpp-2e/chapter32/list3201.cpp new file mode 100644 index 0000000..8f7a21c --- /dev/null +++ b/exploring-cpp-2e/chapter32/list3201.cpp @@ -0,0 +1,19 @@ +// Listing 32-1. First Version of the Assignment Operator +struct rational +{ + rational(int num, int den) + : numerator{num}, denominator{den} + { + reduce(); + } + + rational& operator=(rational const& rhs) + { + numerator = rhs.numerator; + denominator = rhs.denominator; + reduce(); + return *this; + } + int numerator; + int denominator; +}; diff --git a/exploring-cpp-2e/chapter32/list3202.cpp b/exploring-cpp-2e/chapter32/list3202.cpp new file mode 100644 index 0000000..3084710 --- /dev/null +++ b/exploring-cpp-2e/chapter32/list3202.cpp @@ -0,0 +1,8 @@ +// Listing 32-2. Assignment Operator with Explicit Use of this-> +rational& operator=(rational const& that) +{ + this->numerator = that.numerator; + this->denominator = that.denominator; + reduce(); + return *this; +} diff --git a/exploring-cpp-2e/chapter32/list3203.cpp b/exploring-cpp-2e/chapter32/list3203.cpp new file mode 100644 index 0000000..554f9d2 --- /dev/null +++ b/exploring-cpp-2e/chapter32/list3203.cpp @@ -0,0 +1,7 @@ +// Listing 32-3. Assignment of an Integer to a rational +rational& operator=(int num) +{ + this->numerator = num; + this->denominator = 1; // no need to call reduce() + return *this; +} diff --git a/exploring-cpp-2e/chapter32/list3204.cpp b/exploring-cpp-2e/chapter32/list3204.cpp new file mode 100644 index 0000000..795f3b9 --- /dev/null +++ b/exploring-cpp-2e/chapter32/list3204.cpp @@ -0,0 +1,5 @@ +// Listing 32-4. Overloaded Constructors for rational +rational() +: numerator{0}, denominator{1} +{} + diff --git a/exploring-cpp-2e/chapter32/list3205.cpp b/exploring-cpp-2e/chapter32/list3205.cpp new file mode 100644 index 0000000..e45b63c --- /dev/null +++ b/exploring-cpp-2e/chapter32/list3205.cpp @@ -0,0 +1,199 @@ +// Listing 32-5. Complete Definition of rational and Its Operators +#include +#include +#include +#include +#include + +/// Compute the greatest common divisor of two integers, using Euclid’s algorithm. +int gcd(int n, int m) +{ + n = std::abs(n); + while (m != 0) { + int tmp(n % m); + n = m; + m = tmp; + } + return n; +} + +/// Represent a rational number (fraction) as a numerator and denominator. +struct rational +{ + rational() + : numerator{0}, denominator{1} + {/*empty*/} + + rational(int num) + : numerator{num}, denominator{1} + {/*empty*/} + + rational(int num, int den) + : numerator{num}, denominator{den} + { + reduce(); + } + + rational(double r) + : rational{static_cast(r * 10000), 10000} + {/*empty*/} + + rational& operator=(rational const& that) + { + this->numerator = that.numerator; + this->denominator = that.denominator; + reduce(); + return *this; + } + + float as_float() + { + return static_cast(numerator) / denominator; + } + + double as_double() + { + return static_cast(numerator) / denominator; + } + + long double as_long_double() + { + return static_cast(numerator) / + denominator; + } + + /// Assign a numerator and a denominator, then reduce to normal form. + void assign(int num, int den) + { + numerator = num; + denominator = den; + reduce(); + } + + /// Reduce the numerator and denominator by their GCD. + void reduce() + { + assert(denominator != 0); + if (denominator < 0) + { + denominator = -denominator; + numerator = -numerator; + } + int div{gcd(numerator, denominator)}; + numerator = numerator / div; + denominator = denominator / div; + } + + int numerator; + int denominator; +}; + +/// Absolute value of a rational number. +rational abs(rational const& r) +{ + return rational{std::abs(r.numerator), r.denominator}; +} + +/// Unary negation of a rational number. +rational operator-(rational const& r) +{ + return rational{-r.numerator, r.denominator}; +} + +/// Add rational numbers. +rational operator+(rational const& lhs, rational const& rhs) +{ + return rational{lhs.numerator * rhs.denominator + rhs.numerator * lhs.denominator, + lhs.denominator * rhs.denominator}; +} + +/// Subtraction of rational numbers. +rational operator-(rational const& lhs, rational const& rhs) +{ + return rational{lhs.numerator * rhs.denominator - rhs.numerator * lhs.denominator, + lhs.denominator * rhs.denominator}; +} + +/// Multiplication of rational numbers. +rational operator*(rational const& lhs, rational const& rhs) +{ + return rational{lhs.numerator * rhs.numerator, lhs.denominator * rhs.denominator}; +} + +/// Division of rational numbers. +/// TODO: check for division-by-zero +rational operator/(rational const& lhs, rational const& rhs) +{ + return rational{lhs.numerator * rhs.denominator, lhs.denominator * rhs.numerator}; +} + +/// Compare two rational numbers for equality. +bool operator==(rational const& a, rational const& b) +{ + return a.numerator == b.numerator and a.denominator == b.denominator; +} + +/// Compare two rational numbers for inequality. +inline bool operator!=(rational const& a, rational const& b) +{ + return not (a == b); +} +/// Compare two rational numbers for less-than. +bool operator<(rational const& a, rational const& b) +{ + return a.numerator * b.denominator < b.numerator * a.denominator; +} + +/// Compare two rational numbers for less-than-or-equal. +inline bool operator<=(rational const& a, rational const& b) +{ + return not (b < a); +} +/// Compare two rational numbers for greater-than. +inline bool operator>(rational const& a, rational const& b) +{ + return b < a; +} + +/// Compare two rational numbers for greater-than-or-equal. +inline bool operator>=(rational const& a, rational const& b) +{ + return not (b > a); +} + +/// Read a rational number. +/// Format is @em integer @c / @em integer. +std::istream& operator>>(std::istream& in, rational& rat) +{ + int n{0}, d{0}; + char sep{'\0'}; + if (not (in >> n >> sep)) + // Error reading the numerator or the separator character. + in.setstate(in.failbit); + else if (sep != '/') + { + // Push sep back into the input stream, so the next input operation + // will read it. + in.unget(); + rat.assign(n, 1); + } + else if (in >> d) + // Successfully read numerator, separator, and denominator. + rat.assign(n, d); + else + // Error reading denominator. + in.setstate(in.failbit); + + return in; +} + +/// Write a rational numbers. +/// Format is @em numerator @c / @em denominator. +std::ostream& operator<<(std::ostream& out, rational const& rat) +{ + std::ostringstream tmp{}; + tmp << rat.numerator << '/' << rat.denominator; + out << tmp.str(); + + return out; +} diff --git a/exploring-cpp-2e/chapter33/list3301.cpp b/exploring-cpp-2e/chapter33/list3301.cpp new file mode 100644 index 0000000..aae771f --- /dev/null +++ b/exploring-cpp-2e/chapter33/list3301.cpp @@ -0,0 +1,6 @@ +// Listing 33-1. Class Definition for a Cartesian Point +struct point +{ + double x; + double y; +}; diff --git a/exploring-cpp-2e/chapter33/list3302.cpp b/exploring-cpp-2e/chapter33/list3302.cpp new file mode 100644 index 0000000..a1ed31f --- /dev/null +++ b/exploring-cpp-2e/chapter33/list3302.cpp @@ -0,0 +1,5 @@ +// Listing 33-2. Multiple Data Members in One Declaration +struct point +{ + double x, y; +}; diff --git a/exploring-cpp-2e/chapter33/list3303.cpp b/exploring-cpp-2e/chapter33/list3303.cpp new file mode 100644 index 0000000..62d7247 --- /dev/null +++ b/exploring-cpp-2e/chapter33/list3303.cpp @@ -0,0 +1,19 @@ +// Listing 33-3. Using a Class and Its Members +#include + +struct point +{ + double x; + double y; +}; + +int main() +{ + point origin{}, unity{}; + origin.x = 0; + origin.y = 0; + unity.x = 1; + unity.y = 1; + std::cout << "origin = (" << origin.x << ", " << origin.y << ")\n"; + std::cout << "unity = (" << unity.x << ", " << unity.y << ")\n"; +} diff --git a/exploring-cpp-2e/chapter33/list3304.cpp b/exploring-cpp-2e/chapter33/list3304.cpp new file mode 100644 index 0000000..b26fed8 --- /dev/null +++ b/exploring-cpp-2e/chapter33/list3304.cpp @@ -0,0 +1,42 @@ +// Listing 33-4. Member Functions for Class point +#include // for sqrt and atan2 + +struct point +{ + /// Distance to the origin. + double distance() + { + return std::sqrt(x*x + y*y); + } + /// Angle relative to x-axis. + double angle() + { + return std::atan2(y, x); + } + + /// Add an offset to x and y. + void offset(double off) + { + offset(off, off); + } + /// Add an offset to x and an offset to y + void offset(double xoff, double yoff) + { + x = x + xoff; + y = y + yoff; + } + + /// Scale x and y. + void scale(double mult) + { + this->scale(mult, mult); + } + /// Scale x and y. + void scale(double xmult, double ymult) + { + this->x = this->x * xmult; + this->y = this->y * ymult; + } + double x; + double y; +}; diff --git a/exploring-cpp-2e/chapter33/list3305.cpp b/exploring-cpp-2e/chapter33/list3305.cpp new file mode 100644 index 0000000..484bc67 --- /dev/null +++ b/exploring-cpp-2e/chapter33/list3305.cpp @@ -0,0 +1,15 @@ +// Listing 33-5. Constructors for Class point +struct point +{ + point() + : point{0.0, 0.0} + {} + point(double x, double y) + : x_{x}, y_{y} + {} + point(point const& pt) + : point{pt.x_, pt.y_} + {} + double x_; + double y_; +}; diff --git a/exploring-cpp-2e/chapter33/list3306.cpp b/exploring-cpp-2e/chapter33/list3306.cpp new file mode 100644 index 0000000..c47de7b --- /dev/null +++ b/exploring-cpp-2e/chapter33/list3306.cpp @@ -0,0 +1,28 @@ +// Listing 33-6. Visual Constructors +#include + +struct demo +{ + demo() : demo{0} { std::cout << "default constructor\n"; } + demo(int x) : x_{x} { std::cout << "constructor(" << x << ")\n"; } + demo(demo const& that) + : x_{that.x_} + { + std::cout << "copy constructor(" << x_ << ")\n"; + } + int x_; +}; + +demo addone(demo d) +{ + ++d.x_; + return d; +} + +int main() +{ + demo d1{}; + demo d2{d1}; + demo d3{42}; + demo d4{addone(d3)}; +} diff --git a/exploring-cpp-2e/chapter34/list3401.cpp b/exploring-cpp-2e/chapter34/list3401.cpp new file mode 100644 index 0000000..77b26f1 --- /dev/null +++ b/exploring-cpp-2e/chapter34/list3401.cpp @@ -0,0 +1,164 @@ +// Listing 34-1. New BMI Program +#include +#include +#include +#include +#include +#include +#include +#include + +/// Compute body-mass index from height in centimeters and weight in kilograms. +int compute_bmi(int height, int weight) +{ + return static_cast(weight * 10000 / (height * height) + 0.5); +} + +/// Skip the rest of the input line. +void skip_line(std::istream& in) +{ + in.ignore(std::numeric_limits::max(), '\n'); +} + +/// Represent one person's record, storing the person's name, height, weight, +/// sex, and body-mass index (BMI), which is computed from the height and weight. +struct record +{ + record() : height_{0}, weight_{0}, bmi_{0}, sex_{'?'}, name_{} + {} + + /// Get this record, overwriting the data members. + /// Error-checking omitted for brevity. + /// @return true for success or false for eof or input failure + bool read(std::istream& in, int num) + { + std::cout << "Name " << num << ": "; + std::string name{}; + if (not std::getline(in, name)) + return false; + + std::cout << "Height (cm): "; + int height{}; + if (not (in >> height)) + return false; + skip_line(in); + + std::cout << "Weight (kg): "; + int weight{}; + if (not (in >> weight)) + return false; + skip_line(in); + + std::cout << "Sex (M or F): "; + char sex{}; + if (not (in >> sex)) + return false; + skip_line(in); + sex = std::toupper(sex, std::locale()); + + // Store information into data members only after reading + // everything successfully. + name_ = name; + height_ = height; + weight_ = weight; + sex_ = sex; + bmi_ = compute_bmi(height_, weight_); + return true; + } + + /// Print this record to @p out. + void print(std::ostream& out, int threshold) + { + out << std::setw(6) << height_ + << std::setw(7) << weight_ + << std::setw(3) << sex_ + << std::setw(6) << bmi_; + if (bmi_ >= threshold) + out << '*'; + else + out << ' '; + out << ' ' << name_ << '\n'; + } + + int height_; ///< height in centimeters + int weight_; ///< weight in kilograms + int bmi_; ///< Body-mass index + char sex_; ///< 'M' for male or 'F' for female + std::string name_; ///< Person’s name +}; + + +/** Print a table. + * Print a table of height, weight, sex, BMI, and name. + * Print only records for which sex matches @p sex. + * At the end of each table, print the mean and median BMI. + */ +void print_table(char sex, std::vector& records, int threshold) +{ + std::cout << "Ht(cm) Wt(kg) Sex BMI Name\n"; + + float bmi_sum{}; + long int bmi_count{}; + std::vector tmpbmis{}; // store only the BMIs that are printed + // in order to compute the median + for (auto rec : records) + { + if (rec.sex_ == sex) + { + bmi_sum = bmi_sum + rec.bmi_; + ++bmi_count; + tmpbmis.push_back(rec.bmi_); + rec.print(std::cout, threshold); + } + } + + // If the vectors are not empty, print basic statistics. + if (bmi_count != 0) + { + std::cout << "Mean BMI = " + << std::setprecision(1) << std::fixed << bmi_sum / bmi_count + << '\n'; + + // Median BMI is trickier. The easy way is to sort the + // vector and pick out the middle item or items. + std::sort(tmpbmis.begin(), tmpbmis.end()); + std::cout << "Median BMI = "; + // Index of median item. + std::size_t i{tmpbmis.size() / 2}; + if (tmpbmis.size() % 2 == 0) + std::cout << (tmpbmis.at(i) + tmpbmis.at(i-1)) / 2.0 << '\n'; + else + std::cout << tmpbmis.at(i) << '\n'; + } +} + +/** Main program to compute BMI. */ +int main() +{ + std::locale::global(std::locale{""}); + std::cout.imbue(std::locale{}); + std::cin.imbue(std::locale{}); + + std::vector records{}; + int threshold{}; + + std::cout << "Enter threshold BMI: "; + if (not (std::cin >> threshold)) + return EXIT_FAILURE; + skip_line(std::cin); + + std::cout << "Enter name, height (in cm)," + " and weight (in kg) for each person:\n"; + record rec{}; + while (rec.read(std::cin, records.size()+1)) + { + records.push_back(rec); + std::cout << "BMI = " << rec.bmi_ << '\n'; + } + + // Print the data. + std::cout << "\n\nMale data\n"; + print_table('M', records, threshold); + std::cout << "\nFemale data\n"; + print_table('F', records, threshold); +} diff --git a/exploring-cpp-2e/chapter34/list3402.cpp b/exploring-cpp-2e/chapter34/list3402.cpp new file mode 100644 index 0000000..dde89d7 --- /dev/null +++ b/exploring-cpp-2e/chapter34/list3402.cpp @@ -0,0 +1,15 @@ +// Listing 34-2. Adding the const Modifier to print + /// Print this record to @p out. + void print(std::ostream& out, int threshold) + const + { + out << std::setw(6) << height_ + << std::setw(7) << weight_ + << std::setw(3) << sex_ + << std::setw(6) << bmi_; + if (bmi_ >= threshold) + out << '*'; + else + out << ' '; + out << ' ' << name_ << '\n'; + } diff --git a/exploring-cpp-2e/chapter34/list3403.cpp b/exploring-cpp-2e/chapter34/list3403.cpp new file mode 100644 index 0000000..32235c3 --- /dev/null +++ b/exploring-cpp-2e/chapter34/list3403.cpp @@ -0,0 +1,44 @@ +// Listing 34-3. const Member Functions for Class point +#include // for sqrt and atan2 + +struct point +{ + /// Distance to the origin. + double distance() + const + { + return std::sqrt(x*x + y*y); + } + /// Angle relative to x-axis. + double angle() + const + { + return std::atan2(y, x); + } + + /// Add an offset to x and y. + void offset(double off) + { + offset(off, off); + } + /// Add an offset to x and an offset to y + void offset(double xoff, double yoff) + { + x = x + xoff; + y = y + yoff; + } + + /// Scale x and y. + void scale(double mult) + { + this->scale(mult, mult); + } + /// Scale x and y. + void scale(double xmult, double ymult) + { + this->x = this->x * xmult; + this->y = this->y * ymult; + } + double x; + double y; +}; diff --git a/exploring-cpp-2e/chapter34/list3404.cpp b/exploring-cpp-2e/chapter34/list3404.cpp new file mode 100644 index 0000000..df3bf0f --- /dev/null +++ b/exploring-cpp-2e/chapter34/list3404.cpp @@ -0,0 +1,73 @@ +// Listing 34-4. Calling const and Non-const Member Functions +#include +#include + +// Use the same point definition as Listing 34-3 +struct point +{ + /// Distance to the origin. + double distance() + const + { + return std::sqrt(x*x + y*y); + } + /// Angle relative to x-axis. + double angle() + const + { + return std::atan2(y, x); + } + + /// Add an offset to x and y. + void offset(double off) + { + offset(off, off); + } + /// Add an offset to x and an offset to y + void offset(double xoff, double yoff) + { + x = x + xoff; + y = y + yoff; + } + + /// Scale x and y. + void scale(double mult) + { + this->scale(mult, mult); + } + /// Scale x and y. + void scale(double xmult, double ymult) + { + this->x = this->x * xmult; + this->y = this->y * ymult; + } + double x; + double y; +}; + +void print_polar(point const& pt) +{ + std::cout << "{ r=" << pt.distance() << ", angle=" << pt.angle() << " }\n"; +} + +void print_cartesian(point const& pt) +{ + std::cout << "{ x=" << pt.x << ", y=" << pt.y << " }\n"; +} + +int main() +{ + point p1{}, p2{}; + double const pi{3.141592653589792}; + p1.x = std::cos(pi / 3); + p1.y = std::sin(pi / 3); + print_polar(p1); + print_cartesian(p1); + p2 = p1; + p2.scale(4.0); + print_polar(p2); + print_cartesian(p2); + p2.offset(0.0, -2.0); + print_polar(p2); + print_cartesian(p2); +} diff --git a/exploring-cpp-2e/chapter35/list3501.cpp b/exploring-cpp-2e/chapter35/list3501.cpp new file mode 100644 index 0000000..27ee393 --- /dev/null +++ b/exploring-cpp-2e/chapter35/list3501.cpp @@ -0,0 +1,38 @@ +// Listing 35-1. The point Class with Access-Level Specifiers +struct point +{ +public: + point() : point{0.0, 0.0} {} + point(double x, double y) : x_{x}, y_{y} {} + point(point const&) = default; + + double x() const { return x_; } + double y() const { return y_; } + + double angle() const { return std::atan2(y(), x()); } + double distance() const { return std::sqrt(x()*x() + y()*y()); } + + void move_cartesian(double x, double y) + { + x_ = x; + y_ = y; + } + void move_polar(double r, double angle) + { + move_cartesian(r * std::cos(angle), r * std::sin(angle)); + } + + void scale_cartesian(double s) { scale_cartesian(s, s); } + void scale_cartesian(double xs, double ys) + { + move_cartesian(x() * xs, y() * ys); + } + void scale_polar(double r) { move_polar(distance() * r, angle()); } + void rotate(double a) { move_polar(distance(), angle() + a); } + void offset(double o) { offset(o, o); } + void offset(double xo, double yo) { move_cartesian(x() + xo, y() + yo); } + +private: + double x_; + double y_; +}; diff --git a/exploring-cpp-2e/chapter35/list3502.cpp b/exploring-cpp-2e/chapter35/list3502.cpp new file mode 100644 index 0000000..9b77d1e --- /dev/null +++ b/exploring-cpp-2e/chapter35/list3502.cpp @@ -0,0 +1,38 @@ +// Listing 35-2. The point Class Changed to Store Polar Coordinates +struct point +{ +public: + point() : point{0.0, 0.0} {} + point(double x, double y) : r_{0.0}, angle_{0.0} { move_cartesian(x, y); } + point(point const&) = default; + + double x() const { return distance() * std::cos(angle()); } + double y() const { return distance() * std::sin(angle()); } + + double angle() const { return angle_; } + double distance() const { return r_; } + + void move_cartesian(double x, double y) + { + move_polar(std::sqrt(x*x + y*y), std::atan2(y, x)); + } + void move_polar(double r, double angle) + { + r_ = r; + angle_ = angle; + } + + void scale_cartesian(double s) { scale_cartesian(s, s); } + void scale_cartesian(double xs, double ys) + { + move_cartesian(x() * xs, y() * ys); + } + void scale_polar(double r) { move_polar(distance() * r, angle()); } + void rotate(double a) { move_polar(distance(), angle() + a); } + void offset(double o) { offset(o, o); } + void offset(double xo, double yo) { move_cartesian(x() + xo, y() + yo); } + +private: + double r_; + double angle_; +}; diff --git a/exploring-cpp-2e/chapter35/list3503.cpp b/exploring-cpp-2e/chapter35/list3503.cpp new file mode 100644 index 0000000..48156fa --- /dev/null +++ b/exploring-cpp-2e/chapter35/list3503.cpp @@ -0,0 +1,36 @@ +// Listing 35-3. The point Class Defined with the class Keyword +class point +{ +public: + point() : r_{0.0}, angle_{0.0} {} + + double x() const { return distance() * std::cos(angle()); } + double y() const { return distance() * std::sin(angle()); } + + double angle() const { return angle_; } + double distance() const { return r_; } + + void move_cartesian(double x, double y) + { + move_polar(std::sqrt(x*x + y*y), std::atan2(y, x)); + } + void move_polar(double r, double angle) + { + r_ = r; + angle_ = angle; + } + + void scale_cartesian(double s) { scale_cartesian(s, s); } + void scale_cartesian(double xs, double ys) + { + move_cartesian(x() * xs, y() * ys); + } + void scale_polar(double r) { move_polar(distance() * r, angle()); } + void rotate(double a) { move_polar(distance(), angle() + a); } + void offset(double o) { offset(o, o); } + void offset(double xo, double yo) { move_cartesian(x() + xo, y() + yo); } + +private: + double r_; + double angle_; +}; diff --git a/exploring-cpp-2e/chapter35/list3504.cpp b/exploring-cpp-2e/chapter35/list3504.cpp new file mode 100644 index 0000000..eaaf162 --- /dev/null +++ b/exploring-cpp-2e/chapter35/list3504.cpp @@ -0,0 +1,197 @@ +// Listing 35-4. The Latest Rewrite of the rational Class +#include +#include +#include +#include + +/// Compute the greatest common divisor of two integers, using Euclid’s algorithm. +int gcd(int n, int m) +{ + n = std::abs(n); + while (m != 0) { + int tmp(n % m); + n = m; + m = tmp; + } + return n; +} + +/// Represent a rational number (fraction) as a numerator and denominator. +class rational +{ +public: + rational(): rational{0} {} + rational(int num): numerator_{num}, denominator_{1} {} // no need to reduce + rational(rational const&) = default; + rational(int num, int den) + : numerator_{num}, denominator_{den} + { + reduce(); + } + + rational(double r) + : rational{static_cast(r * 10000), 10000} + { + reduce(); + } + + int numerator() const { return numerator_; } + int denominator() const { return denominator_; } + float to_float() + const + { + return static_cast(numerator()) / denominator(); + } + + double to_double() + const + { + return static_cast(numerator()) / denominator(); + } + + long double to_long_double() + const + { + return static_cast(numerator()) / + denominator(); + } + + /// Assign a numerator and a denominator, then reduce to normal form. + void assign(int num, int den) + { + numerator_ = num; + denominator_ = den; + reduce(); + } +private: + /// Reduce the numerator and denominator by their GCD. + void reduce() + { + assert(denominator() != 0); + if (denominator() < 0) + { + denominator_ = -denominator(); + numerator_ = -numerator(); + } + int div{gcd(numerator(), denominator())}; + numerator_ = numerator() / div; + denominator_ = denominator() / div; + } + + int numerator_; + int denominator_; +}; + +/// Absolute value of a rational number. +rational abs(rational const& r) +{ + return rational{std::abs(r.numerator()), r.denominator()}; +} + +/// Unary negation of a rational number. +rational operator-(rational const& r) +{ + return rational{-r.numerator(), r.denominator()}; +} + +/// Add rational numbers. +rational operator+(rational const& lhs, rational const& rhs) +{ + return rational{ + lhs.numerator() * rhs.denominator() + rhs.numerator() * lhs.denominator(), + lhs.denominator() * rhs.denominator()}; +} + +/// Subtraction of rational numbers. +rational operator-(rational const& lhs, rational const& rhs) +{ + return rational{ + lhs.numerator() * rhs.denominator() - rhs.numerator() * lhs.denominator(), + lhs.denominator() * rhs.denominator()}; +} + +/// Multiplication of rational numbers. +rational operator*(rational const& lhs, rational const& rhs) +{ + return rational{lhs.numerator() * rhs.numerator(), + lhs.denominator() * rhs.denominator()}; +} + +/// Division of rational numbers. +/// TODO: check for division-by-zero +rational operator/(rational const& lhs, rational const& rhs) +{ + return rational{lhs.numerator() * rhs.denominator(), + lhs.denominator() * rhs.numerator()}; +} + +/// Compare two rational numbers for equality. +bool operator==(rational const& a, rational const& b) +{ + return a.numerator() == b.numerator() and a.denominator() == b.denominator(); +} + +/// Compare two rational numbers for inequality. +inline bool operator!=(rational const& a, rational const& b) +{ + return not (a == b); +} +/// Compare two rational numbers for less-than. +bool operator<(rational const& a, rational const& b) +{ + return a.numerator() * b.denominator() < b.numerator() * a.denominator(); +} + +/// Compare two rational numbers for less-than-or-equal. +inline bool operator<=(rational const& a, rational const& b) +{ + return not (b < a); +} +/// Compare two rational numbers for greater-than. +inline bool operator>(rational const& a, rational const& b) +{ + return b < a; +} + +/// Compare two rational numbers for greater-than-or-equal. +inline bool operator>=(rational const& a, rational const& b) +{ + return not (b > a); +} + +/// Read a rational number. +/// Format is @em integer @c / @em integer. +std::istream& operator>>(std::istream& in, rational& rat) +{ + int n{}, d{}; + char sep{}; + if (not (in >> n >> sep)) + // Error reading the numerator or the separator character. + in.setstate(in.failbit); + else if (sep != '/') + { + // Push sep back into the input stream, so the next input operation + // will read it. + in.unget(); + rat.assign(n, 1); + } + else if (in >> d) + // Successfully read numerator, separator, and denominator. + rat.assign(n, d); + else + // Error reading denominator. + in.setstate(in.failbit); + + return in; +} + +/// Write a rational numbers. +/// Format is @em numerator @c / @em denominator. +std::ostream& operator<<(std::ostream& out, rational const& rat) +{ + std::ostringstream tmp{}; + tmp << rat.numerator() << '/' << rat.denominator(); + out << tmp.str(); + + return out; +} diff --git a/exploring-cpp-2e/chapter37/list3701.cpp b/exploring-cpp-2e/chapter37/list3701.cpp new file mode 100644 index 0000000..6b765b6 --- /dev/null +++ b/exploring-cpp-2e/chapter37/list3701.cpp @@ -0,0 +1,47 @@ +// Listing 37-1. Defining a Derived Class +class work +{ +public: + work() = default; + work(work const&) = default; + work(std::string const& id, std::string const& title) : id_{id}, title_{title} {} + std::string const& id() const { return id_; } + std::string const& title() const { return title_; } +private: + std::string id_; + std::string title_; +}; + +class book : public work +{ +public: + book() : work{}, author_{}, pubyear_{} {} + book(book const&) = default; + book(std::string const& id, std::string const& title, std::string const& author, + int pubyear) + : work{id, title}, author_{author}, pubyear_{pubyear} + {} + std::string const& author() const { return author_; } + int pubyear() const { return pubyear_; } +private: + std::string author_; + int pubyear_; ///< year of publication +}; + +class periodical : public work +{ +public: + periodical() : work{}, volume_{0}, number_{0}, date_{} {} + periodical(periodical const&) = default; + periodical(std::string const& id, std::string const& title, int volume, + int number, std::string const& date) + : work{id, title}, volume_{volume}, number_{number}, date_{date} + {} + int volume() const { return volume_; } + int number() const { return number_; } + std::string const& date() const { return date_; } +private: + int volume_; ///< volume number + int number_; ///< issue number + std::string date_; ///< publication date +}; diff --git a/exploring-cpp-2e/chapter37/list3702.cpp b/exploring-cpp-2e/chapter37/list3702.cpp new file mode 100644 index 0000000..d43ddde --- /dev/null +++ b/exploring-cpp-2e/chapter37/list3702.cpp @@ -0,0 +1,25 @@ +// Listing 37-2. Printing Messages from Constructors to Illustrate Order of Construction +#include + +class base +{ +public: + base() { std::cout << "base\n"; } +}; + +class middle : public base +{ +public: + middle() { std::cout << "middle\n"; } +}; + +class derived : public middle +{ +public: + derived() { std::cout << "derived\n"; } +}; + +int main() +{ + derived d; +} diff --git a/exploring-cpp-2e/chapter37/list3703.cpp b/exploring-cpp-2e/chapter37/list3703.cpp new file mode 100644 index 0000000..0e39045 --- /dev/null +++ b/exploring-cpp-2e/chapter37/list3703.cpp @@ -0,0 +1,28 @@ +// Listing 37-3. Order of Calling Destructors +#include + +class base +{ +public: + base() { std::cout << "base\n"; } + ~base() { std::cout << "~base\n"; } +}; + +class middle : public base +{ +public: + middle() { std::cout << "middle\n"; } + ~middle() { std::cout << "~middle\n"; } +}; + +class derived : public middle +{ +public: + derived() { std::cout << "derived\n"; } + ~derived() { std::cout << "~derived\n"; } +}; + +int main() +{ + derived d; +} diff --git a/exploring-cpp-2e/chapter37/list3704.cpp b/exploring-cpp-2e/chapter37/list3704.cpp new file mode 100644 index 0000000..5ee7b57 --- /dev/null +++ b/exploring-cpp-2e/chapter37/list3704.cpp @@ -0,0 +1,59 @@ +// Listing 37-4. Constructors and Destructors +#include +#include + +class base +{ +public: + base(int value) : value_{value} { std::cout << "base(" << value << ")\n"; } + base() : base{0} { std::cout << "base()\n"; } + base(base const& copy) + : value_{copy.value_} + { std::cout << "copy base(" << value_ << ")\n"; } + + ~base() { std::cout << "~base(" << value_ << ")\n"; } + int value() const { return value_; } + base& operator++() + { + ++value_; + return *this; + } +private: + int value_; +}; + +class derived : public base +{ +public: + derived(int value): base{value} { std::cout << "derived(" << value << ")\n"; } + derived() : base{} { std::cout << "derived()\n"; } + derived(derived const& copy) + : base{copy} + { std::cout << "copy derived(" << value() << "\n"; } + ~derived() { std::cout << "~derived(" << value() << ")\n"; } +}; + +derived make_derived() +{ + return derived{42}; +} + +base increment(base b) +{ + ++b; + return b; +} + +void increment_reference(base& b) +{ + ++b; +} + +int main() +{ + derived d{make_derived()}; + base b{increment(d)}; + increment_reference(d); + increment_reference(b); + derived a(d.value() + b.value()); +} diff --git a/exploring-cpp-2e/chapter37/list3705.cpp b/exploring-cpp-2e/chapter37/list3705.cpp new file mode 100644 index 0000000..9aa5904 --- /dev/null +++ b/exploring-cpp-2e/chapter37/list3705.cpp @@ -0,0 +1,23 @@ +// Listing 37-5. Accidentally Inheriting Privately +class base +{ +public: + base(int v) : value_{v} {} + int value() const { return value_; } +private: + int value_; +}; + +class derived : base +{ +public: + derived() : base{42} {} +}; + +int main() +{ + base b{42}; + int x{b.value()}; + derived d{}; + int y{d.value()}; +} diff --git a/exploring-cpp-2e/chapter38/list3801.cpp b/exploring-cpp-2e/chapter38/list3801.cpp new file mode 100644 index 0000000..920add5 --- /dev/null +++ b/exploring-cpp-2e/chapter38/list3801.cpp @@ -0,0 +1,61 @@ +// Listing 38-1. Adding a Polymorphic print Function to Every Class Derived from work +class work +{ +public: + work() = default; + work(work const&) = default; + work(std::string const& id, std::string const& title) : id_{id}, title_{title} {} + virtual ~work() {} + std::string const& id() const { return id_; } + std::string const& title() const { return title_; } + virtual void print(std::ostream&) const {} +private: + std::string id_; + std::string title_; +}; + +class book : public work +{ +public: + book() : work{}, author_{}, pubyear_{0} {} + book(book const&) = default; + book(std::string const& id, std::string const& title, std::string const& author, + int pubyear) + : work{id, title}, author_{author}, pubyear_{pubyear} + {} + std::string const& author() const { return author_; } + int pubyear() const { return pubyear_; } + void print(std::ostream& out) + const override + { + out << author() << ", " << title() << ", " << pubyear() << "."; + } +private: + std::string author_; + int pubyear_; ///< year of publication +}; + +class periodical : public work +{ +public: + periodical() : work{}, volume_{0}, number_{0}, date_{} {} + periodical(periodical const&) = default; + periodical(std::string const& id, std::string const& title, int volume, + int number, + std::string const& date) + : work{id, title}, volume_{volume}, number_{number}, date_{date} + {} + int volume() const { return volume_; } + int number() const { return number_; } + std::string const& date() const { return date_; } + void print(std::ostream& out) + const override + { + out << title() << ", " << volume() << '(' << number() << "), " << + date() << "."; + } +private: + int volume_; ///< volume number + int number_; ///< issue number + std::string date_; ///< publication date +}; diff --git a/exploring-cpp-2e/chapter38/list3802.cpp b/exploring-cpp-2e/chapter38/list3802.cpp new file mode 100644 index 0000000..f6aa0cc --- /dev/null +++ b/exploring-cpp-2e/chapter38/list3802.cpp @@ -0,0 +1,84 @@ +// Listing 38-2. Calling the print Function +#include +#include + +// Listing 38-1. Adding a Polymorphic print Function to Every Class Derived from work +class work +{ +public: + work() = default; + work(work const&) = default; + work(std::string const& id, std::string const& title) : id_{id}, title_{title} {} + virtual ~work() {} + std::string const& id() const { return id_; } + std::string const& title() const { return title_; } + virtual void print(std::ostream&) const {} +private: + std::string id_; + std::string title_; +}; + +class book : public work +{ +public: + book() : work{}, author_{}, pubyear_{0} {} + book(book const&) = default; + book(std::string const& id, std::string const& title, std::string const& author, + int pubyear) + : work{id, title}, author_{author}, pubyear_{pubyear} + {} + std::string const& author() const { return author_; } + int pubyear() const { return pubyear_; } + void print(std::ostream& out) + const override + { + out << author() << ", " << title() << ", " << pubyear() << "."; + } +private: + std::string author_; + int pubyear_; ///< year of publication +}; + +class periodical : public work +{ +public: + periodical() : work{}, volume_{0}, number_{0}, date_{} {} + periodical(periodical const&) = default; + periodical(std::string const& id, std::string const& title, int volume, + int number, + std::string const& date) + : work{id, title}, volume_{volume}, number_{number}, date_{date} + {} + int volume() const { return volume_; } + int number() const { return number_; } + std::string const& date() const { return date_; } + void print(std::ostream& out) + const override + { + out << title() << ", " << volume() << '(' << number() << "), " << + date() << "."; + } +private: + int volume_; ///< volume number + int number_; ///< issue number + std::string date_; ///< publication date +}; + +void showoff(work const& w) +{ + w.print(std::cout); + std::cout << '\n'; +} + +int main() +{ + book sc{"1", "The Sun Also Crashes", "Ernest Lemmingway", 2000}; + book ecpp{"2", "Exploring C++", "Ray Lischner", 2013}; + periodical pop{"3", "Popular C++", 13, 42, "January 1, 2000"}; + periodical today{"4", "C++ Today", 1, 1, "January 13, 1984"}; + + showoff(sc); + showoff(ecpp); + showoff(pop); + showoff(today); +} diff --git a/exploring-cpp-2e/chapter38/list3803.cpp b/exploring-cpp-2e/chapter38/list3803.cpp new file mode 100644 index 0000000..a5e20bf --- /dev/null +++ b/exploring-cpp-2e/chapter38/list3803.cpp @@ -0,0 +1,6 @@ +// Listing 38-3. Output Operator for Class work +std::ostream& operator<<(std::ostream& out, work const& w) +{ + w.print(out); + return out; +} diff --git a/exploring-cpp-2e/chapter38/list3804.cpp b/exploring-cpp-2e/chapter38/list3804.cpp new file mode 100644 index 0000000..c274057 --- /dev/null +++ b/exploring-cpp-2e/chapter38/list3804.cpp @@ -0,0 +1,13 @@ +// Listing 38-4. Adding a Class movie +class movie : public work +{ +public: + movie() : work{}, runtime_{0} {} + movie(movie const&) = default; + movie(std::string const& id, std::string const& title, int runtime) + : work{id, title}, runtime_{runtime} + {} + int runtime() const { return runtime_; } +private: + int runtime_; ///< running length in minutes +}; diff --git a/exploring-cpp-2e/chapter38/list3805.cpp b/exploring-cpp-2e/chapter38/list3805.cpp new file mode 100644 index 0000000..1fd67f5 --- /dev/null +++ b/exploring-cpp-2e/chapter38/list3805.cpp @@ -0,0 +1,101 @@ +// Listing 38-5. Using the New movie Class +#include +#include + +// Listing 38-1. Adding a Polymorphic print Function to Every Class Derived from work +class work +{ +public: + work() = default; + work(work const&) = default; + work(std::string const& id, std::string const& title) : id_{id}, title_{title} {} + virtual ~work() {} + std::string const& id() const { return id_; } + std::string const& title() const { return title_; } + virtual void print(std::ostream&) const {} +private: + std::string id_; + std::string title_; +}; + +class book : public work +{ +public: + book() : work{}, author_{}, pubyear_{0} {} + book(book const&) = default; + book(std::string const& id, std::string const& title, std::string const& author, + int pubyear) + : work{id, title}, author_{author}, pubyear_{pubyear} + {} + std::string const& author() const { return author_; } + int pubyear() const { return pubyear_; } + void print(std::ostream& out) + const override + { + out << author() << ", " << title() << ", " << pubyear() << "."; + } +private: + std::string author_; + int pubyear_; ///< year of publication +}; + +class periodical : public work +{ +public: + periodical() : work{}, volume_{0}, number_{0}, date_{} {} + periodical(periodical const&) = default; + periodical(std::string const& id, std::string const& title, int volume, + int number, + std::string const& date) + : work{id, title}, volume_{volume}, number_{number}, date_{date} + {} + int volume() const { return volume_; } + int number() const { return number_; } + std::string const& date() const { return date_; } + void print(std::ostream& out) + const override + { + out << title() << ", " << volume() << '(' << number() << "), " << + date() << "."; + } +private: + int volume_; ///< volume number + int number_; ///< issue number + std::string date_; ///< publication date +}; + +// Listing 38-3. Output Operator for Class work +std::ostream& operator<<(std::ostream& out, work const& w) +{ + w.print(out); + return out; +} + +// Listing 38-4. Adding a Class movie +class movie : public work +{ +public: + movie() : work{}, runtime_{0} {} + movie(movie const&) = default; + movie(std::string const& id, std::string const& title, int runtime) + : work{id, title}, runtime_{runtime} + {} + int runtime() const { return runtime_; } +private: + int runtime_; ///< running length in minutes +}; + +int main() +{ + book sc{"1", "The Sun Also Crashes", "Ernest Lemmingway", 2000}; + book ecpp{"2", "Exploring C++", "Ray Lischner", 2006}; + periodical pop{"3", "Popular C++", 13, 42, "January 1, 2000"}; + periodical today{"4", "C++ Today", 1, 1, "January 13, 1984"}; + movie tr{"5", "Lord of the Token Rings", 314}; + + std::cout << sc << '\n'; + std::cout << ecpp << '\n'; + std::cout << pop << '\n'; + std::cout << today << '\n'; + std::cout << tr << '\n'; +} diff --git a/exploring-cpp-2e/chapter38/list3806.cpp b/exploring-cpp-2e/chapter38/list3806.cpp new file mode 100644 index 0000000..4682b58 --- /dev/null +++ b/exploring-cpp-2e/chapter38/list3806.cpp @@ -0,0 +1,18 @@ +// Listing 38-6. Adding a print Member Function to the movie Class +class movie : public work +{ +public: + movie() : work{}, runtime_{0} {} + movie(movie const&) = default; + movie(std::string const& id, std::string const& title, int runtime) + : work{id, title}, runtime_{runtime} + {} + int runtime() const { return runtime_; } + void print(std::ostream& out) + const override + { + out << title() << " (" << runtime() << " min)"; + } +private: + int runtime_; ///< running length in minutes +}; diff --git a/exploring-cpp-2e/chapter38/list3807.cpp b/exploring-cpp-2e/chapter38/list3807.cpp new file mode 100644 index 0000000..5e78d98 --- /dev/null +++ b/exploring-cpp-2e/chapter38/list3807.cpp @@ -0,0 +1,15 @@ +// Listing 38-7. Defining work As an Abstract Class +class work +{ +public: + work() = default; + work(work const&) = default; + work(std::string const& id, std::string const& title) : id_(id), title_(title) {} + virtual ~work() {} + std::string const& id() const { return id_; } + std::string const& title() const { return title_; } + virtual void print(std::ostream& out) const = 0; +private: + std::string id_; + std::string title_; +}; diff --git a/exploring-cpp-2e/chapter39/list3901.cpp b/exploring-cpp-2e/chapter39/list3901.cpp new file mode 100644 index 0000000..4cf2f5d --- /dev/null +++ b/exploring-cpp-2e/chapter39/list3901.cpp @@ -0,0 +1,24 @@ +// Listing 39-1. Computing BMI +#include + +typedef int height; +typedef int weight; +typedef int bmi; + +bmi compute_bmi(height h, weight w) +{ + return w * 10000 / (h * h); +} + +int main() +{ + std::cout << "Height in centimeters: "; + height h{}; + std::cin >> h; + + std::cout << "Weight in kilograms: "; + weight w{}; + std::cin >> w; + + std::cout << "Body-mass index = " << compute_bmi(w, h) << '\n'; +} diff --git a/exploring-cpp-2e/chapter39/list3902.cpp b/exploring-cpp-2e/chapter39/list3902.cpp new file mode 100644 index 0000000..ad441dd --- /dev/null +++ b/exploring-cpp-2e/chapter39/list3902.cpp @@ -0,0 +1,95 @@ +// Listing 39-2. Defining Classes for height and weight +#include + +/// Height in centimeters +class height +{ +public: + height(int h) : value_{h} {} + int value() const { return value_; } +private: + int value_; +}; + +/// Weight in kilograms +class weight +{ +public: + weight(int w) : value_{w} {} + int value() const { return value_; } +private: + int value_; +}; + +/// Body-mass index +class bmi +{ +public: + bmi() : value_{0} {} + bmi(height h, weight w) : value_{w.value() * 10000 / (h.value()*h.value())} {} + int value() const { return value_; } +private: + int value_; +}; +height operator+(height a, height b) +{ + return height{a.value() + b.value()}; +} +int operator/(height a, height b) +{ + return a.value() / b.value(); +} +std::istream& operator>>(std::istream& in, height& h) +{ + int tmp{}; + if (in >> tmp) + h = tmp; + return in; +} +std::istream& operator>>(std::istream& in, weight& w) +{ + int tmp{}; + if (in >> tmp) + w = tmp; + return in; +} +std::ostream& operator<<(std::ostream& out, bmi i) +{ + out << i.value(); + return out; +} + +// Implement other operators similarly, but implement only +// the ones that make sense. +weight operator-(weight a, weight b) +{ + return weight{a.value() - b.value()}; +} + +weight operator+(weight a, weight b) +{ + return weight{a.value() + b.value()}; +} + +weight operator*(weight a, int b) +{ + return weight{a.value() * b}; +} + +weight operator*(int a, weight b) +{ + return weight{a * b.value()}; +} + +int main() +{ + std::cout << "Height in centimeters: "; + height h{0}; + std::cin >> h; + + std::cout << "Weight in kilograms: "; + weight w{0}; + std::cin >> w; + + std::cout << "Body-mass index = " << bmi(h, w) << '\n'; +} diff --git a/exploring-cpp-2e/chapter39/list3903.cpp b/exploring-cpp-2e/chapter39/list3903.cpp new file mode 100644 index 0000000..e79fa0a --- /dev/null +++ b/exploring-cpp-2e/chapter39/list3903.cpp @@ -0,0 +1,23 @@ +// Listing 39-3. Copying vs. Moving +#include +#include +#include + +void print(std::vector const& vector) +{ + std::cout << "{ "; + for (int i : vector) + std::cout << i << ' '; + std::cout << "}\n"; +} + +int main() +{ + std::vector source{1, 2, 3 }; + print(source); + std::vector copy{source}; + print(copy); + std::vector move{std::move(source)}; + print(move); + print(source); +} diff --git a/exploring-cpp-2e/chapter39/list3904.cpp b/exploring-cpp-2e/chapter39/list3904.cpp new file mode 100644 index 0000000..bdf8a5f --- /dev/null +++ b/exploring-cpp-2e/chapter39/list3904.cpp @@ -0,0 +1,93 @@ +// Listing 39-4. The color Class +#include +#include +#include + +class color +{ +public: + color() : color{0, 0, 0} {} + color(color const&) = default; + color(int r, int g, int b) : red_{r}, green_{g}, blue_{b} {} + int red() const { return red_; } + int green() const { return green_; } + int blue() const { return blue_; } + /// Because red(), green(), and blue() are supposed to be in the range [0,255], + /// it should be possible to add them together in a single long integer. + /// TODO: handle out of range + long int combined() const { return ((red() * 256L + green()) * 256) + blue(); } +private: + int red_, green_, blue_; +}; + +inline bool operator==(color const& a, color const& b) +{ + return a.combined() == b.combined(); +} + +inline bool operator!=(color const& a, color const& b) +{ + return not (a == b); +} + +inline bool order_color(color const& a, color const& b) +{ + return a.combined() < b.combined(); +} + +/// Write a color in HTML format: #RRGGBB. +std::ostream& operator<<(std::ostream& out, color const& c) +{ + std::ostringstream tmp{}; + // The hex manipulator tells a stream to write or read in hexadecimal (base 16). + tmp << '#' << std::hex << std::setw(6) << std::setfill('0') << c.combined(); + out << tmp.str(); + return out; +} + +class ioflags +{ +public: + /// Save the formatting flags from @p stream. + ioflags(std::basic_ios& stream) : stream_(stream), flags_{stream.flags()} {} + ioflags(ioflags const&) = delete; + /// Restore the formatting flags. + ~ioflags() { stream_.flags(flags_); } +private: + std::basic_ios& stream_; + std::ios_base::fmtflags flags_; +}; + +std::istream& operator>>(std::istream& in, color& c) +{ + ioflags flags{in}; + + char hash{}; + if (not (in >> hash)) + return in; + if (hash != '#') + { + // malformed color: no leading # character + in.unget(); // return the character to the input stream + in.setstate(in.failbit); // set the failure state + return in; + } + // Read the color number, which is hexadecimal: RRGGBB. + int combined{}; + in >> std::hex >> std::noskipws; + if (not (in >> combined)) + return in; + // Extract the R, G, and B bytes. + int red, green, blue; + blue = combined % 256; + combined = combined / 256; + green = combined % 256; + combined = combined / 256; + red = combined % 256; + + // Assign to c only after successfully reading all the color components. + c = color{red, green, blue}; + + return in; +} + diff --git a/exploring-cpp-2e/chapter40/list4001.cpp b/exploring-cpp-2e/chapter40/list4001.cpp new file mode 100644 index 0000000..44fdc15 --- /dev/null +++ b/exploring-cpp-2e/chapter40/list4001.cpp @@ -0,0 +1,69 @@ +// Listing 40-1. Declarations and Definitions of Member Functions +class rational +{ +public: + rational(); + rational(int num); + rational(int num, int den); + void assign(int num, int den); + int numerator() const; + int denominator() const; + rational& operator=(int num); +private: + void reduce(); + int numerator_; + int denominator_; +}; + +rational::rational() +: rational{0} +{} + +rational::rational(int num) +: numerator_{num}, denominator_{1} +{} + +rational::rational(int num, int den) +: numerator_{num}, denominator_{den} +{ + reduce(); +} + +void rational::assign(int num, int den) +{ + numerator_ = num; + denominator_ = den; + reduce(); +} + +void rational::reduce() +{ + assert(denominator_ != 0); + if (denominator_ < 0) + { + denominator_ = -denominator_; + numerator_ = -numerator_; + } + int div{gcd(numerator_, denominator_)}; + numerator_ = numerator_ / div; + denominator_ = denominator_ / div; +} + +int rational::numerator() +const +{ + return numerator_; +} + +int rational::denominator() +const +{ + return denominator_; +} + +rational& rational::operator=(int num) +{ + numerator_ = num; + denominator_ = 1; + return *this; +} diff --git a/exploring-cpp-2e/chapter40/list4002.cpp b/exploring-cpp-2e/chapter40/list4002.cpp new file mode 100644 index 0000000..9cb1d68 --- /dev/null +++ b/exploring-cpp-2e/chapter40/list4002.cpp @@ -0,0 +1,49 @@ +// Listing 40-2. The rational Class with inline Member Functions +class rational +{ +public: + rational(int num) : numerator_{num}, denominator_{1} {} + rational(rational const&) = default; + inline rational(int num, int den); + void assign(int num, int den); + int numerator() const { return numerator_; } + int denominator() const { return denominator_; } + rational& operator=(int num); +private: + void reduce(); + int numerator_; + int denominator_; +}; + +inline rational::rational(int num, int den) +: numerator_{num}, denominator_{den} +{ + reduce(); +} + +void rational::assign(int num, int den) +{ + numerator_ = num; + denominator_ = den; + reduce(); +} + +void rational::reduce() +{ + assert(denominator_ != 0); + if (denominator_ < 0) + { + denominator_ = -denominator_; + numerator_ = -numerator_; + } + int div{gcd(numerator_, denominator_)}; + numerator_ = numerator_ / div; + denominator_ = denominator_ / div; +} + +rational& rational::operator=(int num) +{ + numerator_ = num; + denominator_ = 1; + return *this; +} diff --git a/exploring-cpp-2e/chapter40/list4003.cpp b/exploring-cpp-2e/chapter40/list4003.cpp new file mode 100644 index 0000000..a46542b --- /dev/null +++ b/exploring-cpp-2e/chapter40/list4003.cpp @@ -0,0 +1,12 @@ +// Listing 40-3. Declaring and Using References +#include + +int main() +{ + int answer{42}; // definition of a named object, also an lvalue + int& ref{answer}; // declaration of a reference named ref + ref = 10; // changes the value of answer + std::cout << answer << '\n'; + int const& cent{ref * 10}; // declaration; must be const to initialize with expr + std::cout << cent << '\n'; +} diff --git a/exploring-cpp-2e/chapter40/list4004.cpp b/exploring-cpp-2e/chapter40/list4004.cpp new file mode 100644 index 0000000..9affb2d --- /dev/null +++ b/exploring-cpp-2e/chapter40/list4004.cpp @@ -0,0 +1,21 @@ +// Listing 40-4. Finding 42 in a Data Set +#include +#include +#include +#include +#include + +int main() +{ + std::vector data{std::istream_iterator(std::cin), std::istream_iterator()}; + std::sort(data.begin(), data.end()); + // Find all values equal to 42 + auto const& range( std::equal_range(data.begin(), data.end(), 42) ); + if (range.first != range.second) + { + // Print the range indices only if at least one value is found. + std::cout << "index of start of range: " << range.first - data.begin() << '\n'; + std::cout << "index of end of range: " << range.second - data.begin() << '\n'; + } + std::cout << "size of range: " << range.second - range.first << '\n'; +} diff --git a/exploring-cpp-2e/chapter40/list4005.cpp b/exploring-cpp-2e/chapter40/list4005.cpp new file mode 100644 index 0000000..8d5394e --- /dev/null +++ b/exploring-cpp-2e/chapter40/list4005.cpp @@ -0,0 +1,7 @@ +// Listing 40-5. Generating Unique Identification Numbers +int generate_id() +{ + static int counter{0}; + ++counter; + return counter; +} diff --git a/exploring-cpp-2e/chapter40/list4006.cpp b/exploring-cpp-2e/chapter40/list4006.cpp new file mode 100644 index 0000000..220f00f --- /dev/null +++ b/exploring-cpp-2e/chapter40/list4006.cpp @@ -0,0 +1,15 @@ +// Listing 40-6. Calling generate_id to Demonstrate Static Variables +#include + +int generate_id() +{ + static int counter{0}; + ++counter; + return counter; +} + +int main() +{ + for (int i{0}; i != 10; ++i) + std::cout << generate_id() << '\n'; +} diff --git a/exploring-cpp-2e/chapter40/list4007.cpp b/exploring-cpp-2e/chapter40/list4007.cpp new file mode 100644 index 0000000..6db2bab --- /dev/null +++ b/exploring-cpp-2e/chapter40/list4007.cpp @@ -0,0 +1,16 @@ +// Listing 40-7. Declaring counter Outside of the generate_id Function +#include + +int counter; + +int generate_id() +{ + ++counter; + return counter; +} + +int main() +{ + for (int i{0}; i != 10; ++i) + std::cout << generate_id() << '\n'; +} diff --git a/exploring-cpp-2e/chapter40/list4008.cpp b/exploring-cpp-2e/chapter40/list4008.cpp new file mode 100644 index 0000000..0fa3d56 --- /dev/null +++ b/exploring-cpp-2e/chapter40/list4008.cpp @@ -0,0 +1,75 @@ +// Listing 40-8. Declaring and Defining Static Data Members +#include +#include +#include +#include + +/// Compute the greatest common divisor of two integers, using Euclid’s algorithm. +int gcd(int n, int m) +{ + n = std::abs(n); + while (m != 0) { + int tmp(n % m); + n = m; + m = tmp; + } + return n; +} + +class rational { +public: + rational(); + rational(int num); + rational(int num, int den); + int numerator() const { return numerator_; } + int denominator() const { return denominator_; } + // Some useful constants + static const rational zero; + static const rational one; + static const rational pi; +private: + void reduce(); //get definition from Listing 35-4 + + int numerator_; + int denominator_; +}; + +rational::rational() : rational{0, 1} {} +rational::rational(int num) : numerator_{num}, denominator_{1} {} +rational::rational(int num, int den) +: numerator_{num}, denominator_{den} +{ + reduce(); +} + +void rational::reduce() +{ + assert(denominator() != 0); + if (denominator() < 0) + { + denominator_ = -denominator(); + numerator_ = -numerator(); + } + int div{gcd(numerator(), denominator())}; + numerator_ = numerator() / div; + denominator_ = denominator() / div; +} + +std::ostream& operator<<(std::ostream& out, rational const& r) +{ + std::ostringstream tmp{}; + tmp << r.numerator() << '/' << r.denominator(); + out << tmp.str(); + + return out; +} + +const rational rational::zero{}; +const rational rational::one{1}; +const rational rational::pi{355, 113}; + +int main() +{ + std::cout << "pi = " << rational::pi << '\n'; +} + diff --git a/exploring-cpp-2e/chapter40/list4009.cpp b/exploring-cpp-2e/chapter40/list4009.cpp new file mode 100644 index 0000000..9087f5e --- /dev/null +++ b/exploring-cpp-2e/chapter40/list4009.cpp @@ -0,0 +1,34 @@ +// Listing 40-9. Using Static Data Members for an ID Generator +#include + +class generate_id +{ +public: + generate_id() : counter_{0} {} + long next(); +private: + short counter_; + static short prefix_; + static short const max_counter_ = 32767; +}; + +// Switch to random-number as the initial prefix for production code. +// short generate_id::prefix_(static_cast(std::rand())); +short generate_id::prefix_{1}; +short const generate_id::max_counter_; + +long generate_id::next() +{ + if (counter_ == max_counter_) + counter_ = 0; + else + ++counter_; + return static_cast(prefix_) * (max_counter_ + 1) + counter_; +} + +int main() +{ + generate_id gen; // Create an ID generator + for (int i{0}; i != 10; ++i) + std::cout << gen.next() << '\n'; +} diff --git a/exploring-cpp-2e/chapter41/generate_id.hpp b/exploring-cpp-2e/chapter41/generate_id.hpp new file mode 100644 index 0000000..df10e56 --- /dev/null +++ b/exploring-cpp-2e/chapter41/generate_id.hpp @@ -0,0 +1,12 @@ +// Listing 41-5. The #include File for the generate_id Class +/// Class for generating a unique ID number. +class generate_id +{ +public: + generate_id() : counter_{0} {} + long next(); +private: + short counter_; + static short prefix_; + static short const max_counter_{32767}; +}; diff --git a/exploring-cpp-2e/chapter41/list4101.cpp b/exploring-cpp-2e/chapter41/list4101.cpp new file mode 100644 index 0000000..5e805f8 --- /dev/null +++ b/exploring-cpp-2e/chapter41/list4101.cpp @@ -0,0 +1,25 @@ +// Listing 41-1. The Definition of generate_id’s Members in generate_id.cpp +class generate_id +{ +public: + generate_id() : counter_{0} {} + long next(); +private: + short counter_; + static short prefix_; + static short const max_counter_{32767}; +}; + +// Switch to random-number as the initial prefix for production code. +// short generate_id::prefix_{static_cast(std::rand())}; +short generate_id::prefix_{1}; +short const generate_id::max_counter_; + +long generate_id::next() +{ + if (counter_ == max_counter_) + counter_ = 0; + else + ++counter_; + return static_cast(prefix_) * (max_counter_ + 1) + counter_; +} diff --git a/exploring-cpp-2e/chapter41/list4102.cpp b/exploring-cpp-2e/chapter41/list4102.cpp new file mode 100644 index 0000000..eebea2e --- /dev/null +++ b/exploring-cpp-2e/chapter41/list4102.cpp @@ -0,0 +1,20 @@ +// Listing 41-2. The main Function for the ID-generating Program in the main.cpp File +#include + +class generate_id +{ +public: + generate_id() : counter_{0} {} + long next(); +private: + short counter_; + static short prefix_; + static short const max_counter_{32767}; +}; + +int main() +{ + generate_id gen{}; // Create an ID generator + for (int i{0}; i != 10; ++i) + std::cout << gen.next() << '\n'; +} diff --git a/exploring-cpp-2e/chapter41/list4103.cpp b/exploring-cpp-2e/chapter41/list4103.cpp new file mode 100644 index 0000000..57ca12a --- /dev/null +++ b/exploring-cpp-2e/chapter41/list4103.cpp @@ -0,0 +1,20 @@ +// Listing 41-3. Renaming a Member Function Only in main.cpp +#include + +class generate_id +{ +public: + generate_id() : counter_{0} {} + long next_id(); +private: + short counter_; + static short prefix_; + static short const max_counter_{32767}; +}; + +int main() +{ + generate_id gen{}; // Create an ID generator + for (int i{0}; i != 10; ++i) + std::cout << gen.next_id() << '\n'; +} diff --git a/exploring-cpp-2e/chapter41/list4104.cpp b/exploring-cpp-2e/chapter41/list4104.cpp new file mode 100644 index 0000000..f132e3c --- /dev/null +++ b/exploring-cpp-2e/chapter41/list4104.cpp @@ -0,0 +1,22 @@ +// Listing 41-4. Adding a New Data Member Only in main.cpp +#include +#include + +class generate_id +{ +public: + generate_id() : counter_{0} {} + long next(); +private: + int unused_; + short counter_; + static short prefix_; + static short const max_counter_{32767}; +}; + +int main() +{ + generate_id gen{}; // Create an ID generator + for (int i{0}; i != 10; ++i) + std::cout << gen.next() << '\n'; +} diff --git a/exploring-cpp-2e/chapter41/list4105.hpp b/exploring-cpp-2e/chapter41/list4105.hpp new file mode 100644 index 0000000..df10e56 --- /dev/null +++ b/exploring-cpp-2e/chapter41/list4105.hpp @@ -0,0 +1,12 @@ +// Listing 41-5. The #include File for the generate_id Class +/// Class for generating a unique ID number. +class generate_id +{ +public: + generate_id() : counter_{0} {} + long next(); +private: + short counter_; + static short prefix_; + static short const max_counter_{32767}; +}; diff --git a/exploring-cpp-2e/chapter41/list4106.cpp b/exploring-cpp-2e/chapter41/list4106.cpp new file mode 100644 index 0000000..9b1887e --- /dev/null +++ b/exploring-cpp-2e/chapter41/list4106.cpp @@ -0,0 +1,16 @@ +// Listing 41-6. Rewrite of generate_id.cpp to #include the generate_id.hpp File +#include "generate_id.hpp" + +// Switch to random-number as the initial prefix for production code. +// short generate_id::prefix_{static_cast(std::rand())}; +short generate_id::prefix_{1}; +short const generate_id::max_counter_; + +long generate_id::next() +{ + if (counter_ == max_counter_) + counter_ = 0; + else + ++counter_; + return prefix_ * (max_counter_ + 1) + counter_; +} diff --git a/exploring-cpp-2e/chapter41/list4107.cpp b/exploring-cpp-2e/chapter41/list4107.cpp new file mode 100644 index 0000000..ad81362 --- /dev/null +++ b/exploring-cpp-2e/chapter41/list4107.cpp @@ -0,0 +1,11 @@ +// Listing 41-7. Rewriting main.cpp to #include the generate_id.hpp File +#include + +#include "generate_id.hpp" + +int main() +{ + generate_id gen{}; // Create an ID generator + for (int i{0}; i != 10; ++i) + std::cout << gen.next() << '\n'; +} diff --git a/exploring-cpp-2e/chapter41/list4108.cpp b/exploring-cpp-2e/chapter41/list4108.cpp new file mode 100644 index 0000000..b3a576b --- /dev/null +++ b/exploring-cpp-2e/chapter41/list4108.cpp @@ -0,0 +1,22 @@ +// Listing 41-8. The vital_stats Class to Record a Person’s Vital Statistics +#include +#include +#include + +class vital_stats +{ +public: + vital_stats() : height_{0}, weight_{0}, bmi_{0}, sex_{'?'}, name_{} + {} + + bool read(std::istream& in, int num); + void print(std::ostream& out, int threshold) const; + +private: + int compute_bmi() const; ///< Return BMI, based on height_ and weight_ + int height_; ///< height in centimeters + int weight_; ///< weight in kilograms + int bmi_; ///< Body-mass index + char sex_; ///< 'M' for male or 'F' for female + std::string name_; ///< Person’s name +}; diff --git a/exploring-cpp-2e/chapter41/list4109.hpp b/exploring-cpp-2e/chapter41/list4109.hpp new file mode 100644 index 0000000..e4fdcc2 --- /dev/null +++ b/exploring-cpp-2e/chapter41/list4109.hpp @@ -0,0 +1,49 @@ +// Listing 41-9. The vital_stats.hpp Header File +#ifndef VITAL_STATS_HPP_ +#define VITAL_STATS_HPP_ + +#include +#include + +class vital_stats +{ +public: + /// Constructor. Initialize everything to zero or other “empty” value. + vital_stats() : height_{0}, weight_{0}, bmi_{0}, sex_{'?'}, name_{} + {} + + /// Get this record, overwriting the data members. + /// Error-checking omitted for brevity. + /// @param in the input stream + /// @param num a serial number, for use when prompting the user + /// @return true for success or false for eof or input failure + bool read(std::istream& in, int num); + + /// Print this record to @p out. + /// @param out the output stream + /// @param threshold mark records that have a BMI >= this threshold + void print(std::ostream& out, int threshold) const; + + /// Return the BMI. + int bmi() const { return bmi_; } + /// Return the height in centimeters. + int height() const { return height_; } + /// Return the weight in kilograms. + int weight() const { return weight_; } + /// Return the sex: 'M' for male or 'F' for female + char sex() const { return sex_; } + /// Return the person’s name. + std::string const& name() const { return name_; } + +private: + /// Return BMI, based on height_ and weight_ + /// This is called only from read(). + int compute_bmi() const; + int height_; ///< height in centimeters + int weight_; ///< weight in kilograms + int bmi_; ///< Body-mass index + char sex_; ///< 'M' for male or 'F' for female + std::string name_; ///< Person’s name +}; + +#endif diff --git a/exploring-cpp-2e/chapter41/list4110.cpp b/exploring-cpp-2e/chapter41/list4110.cpp new file mode 100644 index 0000000..52c98ef --- /dev/null +++ b/exploring-cpp-2e/chapter41/list4110.cpp @@ -0,0 +1,62 @@ +// Listing 41-10. The vital_stats.cpp Source File +#include +#include +#include +#include +#include + +#include "vital_stats.hpp" + +/// Skip the rest of the input line. +/// @param in the input stream +void skip_line(std::istream& in) +{ + in.ignore(std::numeric_limits::max(), '\n'); +} + +int vital_stats::compute_bmi() +const +{ + return static_cast(weight_ * 10000 / (height_ * height_) + 0.5); +} + +bool vital_stats::read(std::istream& in, int num) +{ + std::cout << "Name " << num << ": "; + if (not std::getline(in, name_)) + return false; + + std::cout << "Height (cm): "; + if (not (in >> height_)) + return false; + skip_line(in); + + std::cout << "Weight (kg): "; + if (not (in >> weight_)) + return false; + skip_line(in); + + std::cout << "Sex (M or F): "; + if (not (in >> sex_)) + return false; + skip_line(in); + sex_ = std::toupper(sex_, std::locale{}); + + bmi_ = compute_bmi(); + + return true; +} + +void vital_stats::print(std::ostream& out, int threshold) +const +{ + out << std::setw(6) << height_ + << std::setw(7) << weight_ + << std::setw(3) << sex_ + << std::setw(6) << bmi_; + if (bmi_ >= threshold) + out << '*'; + else + out << ' '; + out << ' ' << name_ << '\n'; +} diff --git a/exploring-cpp-2e/chapter41/list4111.hpp b/exploring-cpp-2e/chapter41/list4111.hpp new file mode 100644 index 0000000..2d97944 --- /dev/null +++ b/exploring-cpp-2e/chapter41/list4111.hpp @@ -0,0 +1,7 @@ +// Listing 41-11. Simple Header for Math Constants +#ifndef MATH_HPP_ +#define MATH_HPP_ + +extern double pi; + +#endif diff --git a/exploring-cpp-2e/chapter41/list4112.cpp b/exploring-cpp-2e/chapter41/list4112.cpp new file mode 100644 index 0000000..c61c32c --- /dev/null +++ b/exploring-cpp-2e/chapter41/list4112.cpp @@ -0,0 +1,5 @@ +// Listing 41-12. Definitions of Math Constants +#include "math.hpp" + +// More digits that typical implementations of double support. +double pi{3.14159265358979323846264338327}; diff --git a/exploring-cpp-2e/chapter41/list4113.hpp b/exploring-cpp-2e/chapter41/list4113.hpp new file mode 100644 index 0000000..bd2983e --- /dev/null +++ b/exploring-cpp-2e/chapter41/list4113.hpp @@ -0,0 +1,14 @@ +// Listing 41-13. The Original point.hpp File +#ifndef POINT_HPP_ +#define POINT_HPP_ +class point +{ +public: + point() : point{0, 0} {} + point(int x, int y) : x_{x}, y_{y} {} + int x() const { return x_; } + int y() const { return y_; } +private: + int y_, x_; +}; +#endif // POINT_HPP_ diff --git a/exploring-cpp-2e/chapter41/math.hpp b/exploring-cpp-2e/chapter41/math.hpp new file mode 100644 index 0000000..2d97944 --- /dev/null +++ b/exploring-cpp-2e/chapter41/math.hpp @@ -0,0 +1,7 @@ +// Listing 41-11. Simple Header for Math Constants +#ifndef MATH_HPP_ +#define MATH_HPP_ + +extern double pi; + +#endif diff --git a/exploring-cpp-2e/chapter41/point.hpp b/exploring-cpp-2e/chapter41/point.hpp new file mode 100644 index 0000000..bd2983e --- /dev/null +++ b/exploring-cpp-2e/chapter41/point.hpp @@ -0,0 +1,14 @@ +// Listing 41-13. The Original point.hpp File +#ifndef POINT_HPP_ +#define POINT_HPP_ +class point +{ +public: + point() : point{0, 0} {} + point(int x, int y) : x_{x}, y_{y} {} + int x() const { return x_; } + int y() const { return y_; } +private: + int y_, x_; +}; +#endif // POINT_HPP_ diff --git a/exploring-cpp-2e/chapter41/pragma_once.hpp b/exploring-cpp-2e/chapter41/pragma_once.hpp new file mode 100644 index 0000000..5ee1aef --- /dev/null +++ b/exploring-cpp-2e/chapter41/pragma_once.hpp @@ -0,0 +1,24 @@ +/* Another way to ensure a header is included only once + * is to use #pragma once, as shown below. By definition, + * #pragma is not portable. Compilers are free to do + * whatever they way. A growing convention is that + * #pragma once means to include the header only + * once. When implemented, it is potentially more + * efficient because the compiler doesn't even need + * to open the file. + * + * Because #pragma once is not portable, use #ifndef + * guards, too. + * + * I did not cover #pragma once in the book because + * it is not part of the C++ standard. But it is + * useful, and good to know about. + */ +#ifndef PRAGMA_ONCE_HPP_ +#define PRAGMA_ONCE_HPP_ + +#pragma once + +// put your declarations here + +#endif diff --git a/exploring-cpp-2e/chapter41/vital_stats.hpp b/exploring-cpp-2e/chapter41/vital_stats.hpp new file mode 100644 index 0000000..e4fdcc2 --- /dev/null +++ b/exploring-cpp-2e/chapter41/vital_stats.hpp @@ -0,0 +1,49 @@ +// Listing 41-9. The vital_stats.hpp Header File +#ifndef VITAL_STATS_HPP_ +#define VITAL_STATS_HPP_ + +#include +#include + +class vital_stats +{ +public: + /// Constructor. Initialize everything to zero or other “empty” value. + vital_stats() : height_{0}, weight_{0}, bmi_{0}, sex_{'?'}, name_{} + {} + + /// Get this record, overwriting the data members. + /// Error-checking omitted for brevity. + /// @param in the input stream + /// @param num a serial number, for use when prompting the user + /// @return true for success or false for eof or input failure + bool read(std::istream& in, int num); + + /// Print this record to @p out. + /// @param out the output stream + /// @param threshold mark records that have a BMI >= this threshold + void print(std::ostream& out, int threshold) const; + + /// Return the BMI. + int bmi() const { return bmi_; } + /// Return the height in centimeters. + int height() const { return height_; } + /// Return the weight in kilograms. + int weight() const { return weight_; } + /// Return the sex: 'M' for male or 'F' for female + char sex() const { return sex_; } + /// Return the person’s name. + std::string const& name() const { return name_; } + +private: + /// Return BMI, based on height_ and weight_ + /// This is called only from read(). + int compute_bmi() const; + int height_; ///< height in centimeters + int weight_; ///< weight in kilograms + int bmi_; ///< Body-mass index + char sex_; ///< 'M' for male or 'F' for female + std::string name_; ///< Person’s name +}; + +#endif diff --git a/exploring-cpp-2e/chapter42/generate_id.hpp b/exploring-cpp-2e/chapter42/generate_id.hpp new file mode 100644 index 0000000..4fcd103 --- /dev/null +++ b/exploring-cpp-2e/chapter42/generate_id.hpp @@ -0,0 +1,17 @@ +// Listing 42-1. Rewriting generate_id to Use the Function Call Operator +#ifndef GENERATE_ID_HPP_ +#define GENERATE_ID_HPP_ + +/// Class for generating a unique ID number. +class generate_id +{ +public: + generate_id() : counter_{0} {} + long operator()(); +private: + short counter_; + static short prefix_; + static short const max_counter_{32767}; +}; + +#endif diff --git a/exploring-cpp-2e/chapter42/library.hpp b/exploring-cpp-2e/chapter42/library.hpp new file mode 100644 index 0000000..e696a54 --- /dev/null +++ b/exploring-cpp-2e/chapter42/library.hpp @@ -0,0 +1,97 @@ +#ifndef LIBRARY_HPP_ +#define LIBRARY_HPP_ + +// Listing 38-5. Using the New movie Class +#include +#include + +// Listing 38-1. Adding a Polymorphic print Function to Every Class Derived from work +class work +{ +public: + work() = default; + work(work const&) = default; + work(std::string const& id, std::string const& title) : id_{id}, title_{title} {} + virtual ~work() {} + std::string const& id() const { return id_; } + std::string const& title() const { return title_; } + virtual void print(std::ostream&) const = 0; +private: + std::string id_; + std::string title_; +}; + +class book : public work +{ +public: + book() : work{}, author_{}, pubyear_{0} {} + book(book const&) = default; + book(std::string const& id, std::string const& title, std::string const& author, + int pubyear) + : work{id, title}, author_{author}, pubyear_{pubyear} + {} + std::string const& author() const { return author_; } + int pubyear() const { return pubyear_; } + void print(std::ostream& out) + const override + { + out << author() << ", " << title() << ", " << pubyear() << "."; + } +private: + std::string author_; + int pubyear_; ///< year of publication +}; + +class periodical : public work +{ +public: + periodical() : work{}, volume_{0}, number_{0}, date_{} {} + periodical(periodical const&) = default; + periodical(std::string const& id, std::string const& title, int volume, + int number, + std::string const& date) + : work{id, title}, volume_{volume}, number_{number}, date_{date} + {} + int volume() const { return volume_; } + int number() const { return number_; } + std::string const& date() const { return date_; } + void print(std::ostream& out) + const override + { + out << title() << ", " << volume() << '(' << number() << "), " << + date() << "."; + } +private: + int volume_; ///< volume number + int number_; ///< issue number + std::string date_; ///< publication date +}; + +// Listing 38-3. Output Operator for Class work +std::ostream& operator<<(std::ostream& out, work const& w) +{ + w.print(out); + return out; +} + +// Listing 38-4. Adding a Class movie +class movie : public work +{ +public: + movie() : work{}, runtime_{0} {} + movie(movie const&) = default; + movie(std::string const& id, std::string const& title, int runtime) + : work{id, title}, runtime_{runtime} + {} + int runtime() const { return runtime_; } + void print(std::ostream& out) + const override + { + out << title() << " (" << runtime() << " min)"; + } +private: + int runtime_; ///< running length in minutes +}; + +#endif + diff --git a/exploring-cpp-2e/chapter42/list4201.hpp b/exploring-cpp-2e/chapter42/list4201.hpp new file mode 100644 index 0000000..4fcd103 --- /dev/null +++ b/exploring-cpp-2e/chapter42/list4201.hpp @@ -0,0 +1,17 @@ +// Listing 42-1. Rewriting generate_id to Use the Function Call Operator +#ifndef GENERATE_ID_HPP_ +#define GENERATE_ID_HPP_ + +/// Class for generating a unique ID number. +class generate_id +{ +public: + generate_id() : counter_{0} {} + long operator()(); +private: + short counter_; + static short prefix_; + static short const max_counter_{32767}; +}; + +#endif diff --git a/exploring-cpp-2e/chapter42/list4202.cpp b/exploring-cpp-2e/chapter42/list4202.cpp new file mode 100644 index 0000000..8a2c3ed --- /dev/null +++ b/exploring-cpp-2e/chapter42/list4202.cpp @@ -0,0 +1,13 @@ +// Listing 42-2. Implementation of the generate_id Function Call Operator +#include "generate_id.hpp" + +short generate_id::prefix_{1}; + +long generate_id::operator()() +{ + if (counter_ == max_counter_) + counter_ = 0; + else + ++counter_; + return static_cast(prefix_) * (max_counter_ + 1) + counter_; +} diff --git a/exploring-cpp-2e/chapter42/list4203.cpp b/exploring-cpp-2e/chapter42/list4203.cpp new file mode 100644 index 0000000..15a84e1 --- /dev/null +++ b/exploring-cpp-2e/chapter42/list4203.cpp @@ -0,0 +1,29 @@ +// Listing 42-3. Using a generate_id Object’s Function Call Operator +#include + +#include "generate_id.hpp" +#include "library.hpp" + + +bool get_movie(std::string& title, int& runtime) +{ + std::cout << "Movie title: "; + if (not std::getline(std::cin, title)) + return false; + std::cout << "Runtime (minutes): "; + if (not (std::cin >> runtime)) + return false; + return true; +} + +int main() +{ + generate_id gen{}; // Create an ID generator + std::string title{}; + int runtime{}; + while (get_movie(title, runtime)) + { + movie m(int_to_id(gen()), title, runtime); + accession(m); + } +} diff --git a/exploring-cpp-2e/chapter42/list4204.cpp b/exploring-cpp-2e/chapter42/list4204.cpp new file mode 100644 index 0000000..7036913 --- /dev/null +++ b/exploring-cpp-2e/chapter42/list4204.cpp @@ -0,0 +1,10 @@ +// Listing 42-4. The Main Program for Generating Successive Integers +#include +#include + +int main() +{ + std::vector vec(10); + int state; + std::generate(vec.begin(), vec.end(), [&state]() { return ++state; }); +} diff --git a/exploring-cpp-2e/chapter42/list4205.cpp b/exploring-cpp-2e/chapter42/list4205.cpp new file mode 100644 index 0000000..20afcfb --- /dev/null +++ b/exploring-cpp-2e/chapter42/list4205.cpp @@ -0,0 +1,28 @@ +// Listing 42-5. The Main Program for Generating Successive Integers +#include +#include +#include +#include + +#include "sequence.hpp" + +int main() +{ + int size{}; + std::cout << "How many integers do you want? "; + std::cin >> size; + int first{}; + std::cout << "What is the first integer? "; + std::cin >> first; + int step{}; + std::cout << "What is the interval between successive integers? "; + std::cin >> step; + + std::vector data(size); + // Generate the integers to fill the vector. + std::generate(data.begin(), data.end(), sequence(first, step)); + + // Print the resulting integers, one per line. + std::copy(data.begin(), data.end(), + std::ostream_iterator(std::cout, "\n")); +} diff --git a/exploring-cpp-2e/chapter42/list4206.hpp b/exploring-cpp-2e/chapter42/list4206.hpp new file mode 100644 index 0000000..0f99f1f --- /dev/null +++ b/exploring-cpp-2e/chapter42/list4206.hpp @@ -0,0 +1,28 @@ +// Listing 42-6. The sequence.hpp File +#ifndef SEQUENCE_HPP_ +#define SEQUENCE_HPP_ + +/// Generate a sequence of integers. +class sequence +{ +public: + /// Construct the functor. + /// @param start the first value the generator returns + /// @param step increment the value by this much for each call + sequence(int start, int step ) : value_{start}, step_{step} {} + sequence(int start) : sequence{start, 1} {} + sequence() : sequence{0} {} + + /// Return the current value in the sequence, and increment the value. + int operator()() + { + int result(value_); + value_ = value_ + step_; + return result; + } +private: + int value_; + int const step_; +}; + +#endif diff --git a/exploring-cpp-2e/chapter42/sequence.hpp b/exploring-cpp-2e/chapter42/sequence.hpp new file mode 100644 index 0000000..0f99f1f --- /dev/null +++ b/exploring-cpp-2e/chapter42/sequence.hpp @@ -0,0 +1,28 @@ +// Listing 42-6. The sequence.hpp File +#ifndef SEQUENCE_HPP_ +#define SEQUENCE_HPP_ + +/// Generate a sequence of integers. +class sequence +{ +public: + /// Construct the functor. + /// @param start the first value the generator returns + /// @param step increment the value by this much for each call + sequence(int start, int step ) : value_{start}, step_{step} {} + sequence(int start) : sequence{start, 1} {} + sequence() : sequence{0} {} + + /// Return the current value in the sequence, and increment the value. + int operator()() + { + int result(value_); + value_ = value_ + step_; + return result; + } +private: + int value_; + int const step_; +}; + +#endif diff --git a/exploring-cpp-2e/chapter43/data.hpp b/exploring-cpp-2e/chapter43/data.hpp new file mode 100644 index 0000000..12defa0 --- /dev/null +++ b/exploring-cpp-2e/chapter43/data.hpp @@ -0,0 +1,37 @@ +// Listing 43-2. The data.hpp File to Support Integer Data +#ifndef DATA_HPP_ +#define DATA_HPP_ + +#include +#include +#include +#include + +/// Convenient shorthand for a vector of integers. +typedef std::vector intvector; + +/// Convenient shorthand for an intvector's iterator. +typedef intvector::iterator intvec_iterator; + +/// Read a series of integers from the standard input into @p data, +/// overwriting @p data in the process. +/// @param[in,out] data a vector of integers +inline void read_data(intvector& data) +{ + data.clear(); + data.insert(data.begin(), std::istream_iterator(std::cin), + std::istream_iterator()); +} + +/// Write a vector of integers to the standard output. Write all values on one +/// line, separated by single space characters, and surrounded by curly braces, +/// e.g., { 1 2 3 }. +/// @param data a vector of integers +inline void write_data(intvector const& data) +{ + std::cout << "{ "; + std::copy(data.begin(), data.end(), + std::ostream_iterator(std::cout, " ")); + std::cout << "}\n"; +} +#endif diff --git a/exploring-cpp-2e/chapter43/intrange.hpp b/exploring-cpp-2e/chapter43/intrange.hpp new file mode 100644 index 0000000..0f77747 --- /dev/null +++ b/exploring-cpp-2e/chapter43/intrange.hpp @@ -0,0 +1,35 @@ +// Listing 43-3. Functor intrange to Generate Integers in a Certain Range +#ifndef INTRANGE_HPP_ +#define INTRANGE_HPP_ + +#include + +/// Check whether an integer lies within an inclusive range. +class intrange +{ +public: + inline intrange(int low, int high); + inline bool operator()(int test) const; +private: + int const low_; + int const high_; +}; + +/// Construct an integer range. +/// If the parameters are in the wrong order, +/// swap them to the right order. +/// @param low the lower bound of the inclusive range +/// @param high the upper bound of the inclusive range +inline intrange::intrange(int low, int high) +: low_{std::min(low, high)}, high_{std::max(low, high)} +{} + +/// Check whether a value lies within the inclusive range. +/// @param test the value to test +inline bool intrange::operator()(int test) +const +{ + return test >= low_ and test <= high_; +} + +#endif diff --git a/exploring-cpp-2e/chapter43/list4301.cpp b/exploring-cpp-2e/chapter43/list4301.cpp new file mode 100644 index 0000000..7c0c604 --- /dev/null +++ b/exploring-cpp-2e/chapter43/list4301.cpp @@ -0,0 +1,21 @@ +// Listing 43-1. Searching for an Integer +#include +#include + +#include "data.hpp" + +int main() +{ + intvector data{}; + read_data(data); + write_data(data); + auto iter(std::find(data.begin(), data.end(), 42)); + if (iter == data.end()) + std::cout << "Value 42 not found\n"; + else + { + *iter = 0; + std::cout << "Value 42 changed to 0:\n"; + write_data(data); + } +} diff --git a/exploring-cpp-2e/chapter43/list4302.hpp b/exploring-cpp-2e/chapter43/list4302.hpp new file mode 100644 index 0000000..12defa0 --- /dev/null +++ b/exploring-cpp-2e/chapter43/list4302.hpp @@ -0,0 +1,37 @@ +// Listing 43-2. The data.hpp File to Support Integer Data +#ifndef DATA_HPP_ +#define DATA_HPP_ + +#include +#include +#include +#include + +/// Convenient shorthand for a vector of integers. +typedef std::vector intvector; + +/// Convenient shorthand for an intvector's iterator. +typedef intvector::iterator intvec_iterator; + +/// Read a series of integers from the standard input into @p data, +/// overwriting @p data in the process. +/// @param[in,out] data a vector of integers +inline void read_data(intvector& data) +{ + data.clear(); + data.insert(data.begin(), std::istream_iterator(std::cin), + std::istream_iterator()); +} + +/// Write a vector of integers to the standard output. Write all values on one +/// line, separated by single space characters, and surrounded by curly braces, +/// e.g., { 1 2 3 }. +/// @param data a vector of integers +inline void write_data(intvector const& data) +{ + std::cout << "{ "; + std::copy(data.begin(), data.end(), + std::ostream_iterator(std::cout, " ")); + std::cout << "}\n"; +} +#endif diff --git a/exploring-cpp-2e/chapter43/list4303.hpp b/exploring-cpp-2e/chapter43/list4303.hpp new file mode 100644 index 0000000..0f77747 --- /dev/null +++ b/exploring-cpp-2e/chapter43/list4303.hpp @@ -0,0 +1,35 @@ +// Listing 43-3. Functor intrange to Generate Integers in a Certain Range +#ifndef INTRANGE_HPP_ +#define INTRANGE_HPP_ + +#include + +/// Check whether an integer lies within an inclusive range. +class intrange +{ +public: + inline intrange(int low, int high); + inline bool operator()(int test) const; +private: + int const low_; + int const high_; +}; + +/// Construct an integer range. +/// If the parameters are in the wrong order, +/// swap them to the right order. +/// @param low the lower bound of the inclusive range +/// @param high the upper bound of the inclusive range +inline intrange::intrange(int low, int high) +: low_{std::min(low, high)}, high_{std::max(low, high)} +{} + +/// Check whether a value lies within the inclusive range. +/// @param test the value to test +inline bool intrange::operator()(int test) +const +{ + return test >= low_ and test <= high_; +} + +#endif diff --git a/exploring-cpp-2e/chapter43/list4304.cpp b/exploring-cpp-2e/chapter43/list4304.cpp new file mode 100644 index 0000000..fcd71d0 --- /dev/null +++ b/exploring-cpp-2e/chapter43/list4304.cpp @@ -0,0 +1,18 @@ +// Listing 43-4. Using find_if and intrange to Find an Integer That Lies Within a Range +#include +#include + +#include "data.hpp" +#include "intrange.hpp" + +int main() +{ + intvector data{}; + read_data(data); + write_data(data); + auto iter(std::find_if(data.begin(), data.end(), intrange{10, 20})); + if (iter == data.end()) + std::cout << "No values in [10,20] found\n"; + else + std::cout << "Value " << *iter << " in range [10,20].\n"; +} diff --git a/exploring-cpp-2e/chapter43/list4305.hpp b/exploring-cpp-2e/chapter43/list4305.hpp new file mode 100644 index 0000000..3324494 --- /dev/null +++ b/exploring-cpp-2e/chapter43/list4305.hpp @@ -0,0 +1,35 @@ +// Listing 43-5. Generating Random Integers +#ifndef RANDOMINT_HPP_ +#define RANDOMINT_HPP_ + +#include +#include + +/// Generate uniformly distributed random integers in a range. +class randomint +{ +public: + typedef std::default_random_engine::result_type result_type; + + /// Construct a random-number generator to produce numbers in the range [low, high]. + /// If @p low > @p high the values are reversed. + randomint(result_type low, result_type high) + // std::random_device uses a system-dependent generation of randomness + // to seed the pseudo-random-number generator. + : prng_{std::random_device{}()}, + distribution_{std::min(low, high), std::max(low, high)} + {} + + /// Generate the next random number generator. + result_type operator()() + { + return distribution_(prng_); + } + +private: + // implementation-defined pseudo-random-number generator + std::default_random_engine prng_; + // Map random numbers to a uniform distribution. + std::uniform_int_distribution distribution_; +}; +#endif diff --git a/exploring-cpp-2e/chapter43/list4306.cpp b/exploring-cpp-2e/chapter43/list4306.cpp new file mode 100644 index 0000000..211823c --- /dev/null +++ b/exploring-cpp-2e/chapter43/list4306.cpp @@ -0,0 +1,29 @@ +// Listing 43-6. Finding a Sub-range That Matches the First Four Digits of π +#include +#include +#include +#include +#include + +#include "data.hpp" +#include "randomint.hpp" + + +int main() +{ + intvector pi{ 3, 1, 4, 1 }; + intvector data(10000); + // The randomint functor generates random numbers in the range [0, 9]. + + std::generate(data.begin(), data.end(), randomint{0, 9}); + + auto iter(std::search(data.begin(), data.end(), pi.begin(), pi.end())); + if (iter == data.end()) + std::cout << "The integer range does not contain the digits of pi.\n"; + else + { + std::cout << "Easy as pi: "; + std::copy(iter, iter+pi.size(), std::ostream_iterator(std::cout, " ")); + std::cout << '\n'; + } +} diff --git a/exploring-cpp-2e/chapter43/list4307.cpp b/exploring-cpp-2e/chapter43/list4307.cpp new file mode 100644 index 0000000..57891ff --- /dev/null +++ b/exploring-cpp-2e/chapter43/list4307.cpp @@ -0,0 +1,22 @@ +// Listing 43-7. Searching for an Integer Using Binary Search +#include +#include + +#include "data.hpp" + +int main() +{ + intvector data{}; + read_data(data); + std::sort(data.begin(), data.end()); + write_data(data); + intvec_iterator iter{std::lower_bound(data.begin(), data.end(), 42)}; + if (iter == data.end()) + std::cout << "Value 42 not found\n"; + else + { + *iter = 0; + std::cout << "Value 42 changed to 0:\n"; + write_data(data); + } +} diff --git a/exploring-cpp-2e/chapter43/list4308.cpp b/exploring-cpp-2e/chapter43/list4308.cpp new file mode 100644 index 0000000..32c55a7 --- /dev/null +++ b/exploring-cpp-2e/chapter43/list4308.cpp @@ -0,0 +1,24 @@ +// Listing 43-8. Exploring the lower_bound and upper_bound Functions +#include +#include +#include + +#include "data.hpp" + +int main() +{ + intvector data{}; + read_data(data); + std::sort(data.begin(), data.end()); + write_data(data); + + std::cin.clear(); + int test{}; + while (std::cin >> test) + { + intvec_iterator lb{std::lower_bound(data.begin(), data.end(), test)}; + intvec_iterator ub{std::upper_bound(data.begin(), data.end(), test)}; + std::cout << "lower bound = " << std::distance(data.begin(), lb) << '\n' << + "upper bound = " << std::distance(data.begin(), ub) << '\n'; + } +} diff --git a/exploring-cpp-2e/chapter43/list4309.cpp b/exploring-cpp-2e/chapter43/list4309.cpp new file mode 100644 index 0000000..812af11 --- /dev/null +++ b/exploring-cpp-2e/chapter43/list4309.cpp @@ -0,0 +1,36 @@ +// Listing 43-9. Testing Various Comparison Algorithms +#include +#include +#include + +#include "data.hpp" + +int main() +{ + intvector data1{}; + intvector data2{}; + + read_data(data1); + std::cin.clear(); + read_data(data2); + + std::cout << "data1: "; + write_data(data1); + std::cout << "data2: "; + write_data(data2); + + auto data1_end(data1.begin() + std::min(data1.size(), data2.size())); + + std::cout << std::boolalpha; + std::cout << "equal(data1, data2) = " << + equal(data1.begin(), data1_end, data2.begin()) << '\n'; + + auto result(mismatch(data1.begin(), data1_end, data2.begin())); + + std::cout << "mismatch(data1, data2) = index " << + std::distance(data1.begin(), result.first) << '\n'; + + std::cout << "lex_comp(data1, data2) = " << + std::lexicographical_compare(data1.begin(), data1.end(), + data2.begin(), data2.end()) << '\n'; +} diff --git a/exploring-cpp-2e/chapter43/list4310.cpp b/exploring-cpp-2e/chapter43/list4310.cpp new file mode 100644 index 0000000..0bdcf52 --- /dev/null +++ b/exploring-cpp-2e/chapter43/list4310.cpp @@ -0,0 +1,14 @@ +// Listing 43-10. Using replace_if and intrange to Replace All Integers in [10, 20] with 0 +#include + +#include "data.hpp" +#include "intrange.hpp" + +int main() +{ + intvector data{}; + read_data(data); + write_data(data); + std::replace_if(data.begin(), data.end(), intrange{10, 20}, 0); + write_data(data); +} diff --git a/exploring-cpp-2e/chapter43/list4311.cpp b/exploring-cpp-2e/chapter43/list4311.cpp new file mode 100644 index 0000000..879ef9b --- /dev/null +++ b/exploring-cpp-2e/chapter43/list4311.cpp @@ -0,0 +1,18 @@ +// Listing 43-11. Using replace_if and intrange to Replace All Integers in [10, 20] with 0 +#include + +#include "data.hpp" +#include "intrange.hpp" + +int main() +{ + intvector data{}; + read_data(data); + write_data(data); + std::replace_if(data.begin(), data.end(), + [](int x) + { + return x >= 10 and x <= 20; + }, 0); + write_data(data); +} diff --git a/exploring-cpp-2e/chapter43/list4312.cpp b/exploring-cpp-2e/chapter43/list4312.cpp new file mode 100644 index 0000000..012d9a6 --- /dev/null +++ b/exploring-cpp-2e/chapter43/list4312.cpp @@ -0,0 +1,14 @@ +// Listing 43-12. Shuffling Integers into Random Order +#include + +#include "data.hpp" +#include "sequence.hpp" + +int main() +{ + intvector data(100); + std::generate(data.begin(), data.end(), sequence{1, 1}); + write_data(data); + std::random_shuffle(data.begin(), data.end()); + write_data(data); +} diff --git a/exploring-cpp-2e/chapter43/list4313.cpp b/exploring-cpp-2e/chapter43/list4313.cpp new file mode 100644 index 0000000..858b8d0 --- /dev/null +++ b/exploring-cpp-2e/chapter43/list4313.cpp @@ -0,0 +1,17 @@ +// Listing 43-13. Erasing Elements from a Vector +#include +#include "data.hpp" +#include "intrange.hpp" + +int main() +{ + intvector data{}; + read_data(data); + data.erase(std::remove(data.begin(), data.end(), 0), data.end()); + intvector copy{}; + std::remove_copy_if(data.begin(), data.end(), std::back_inserter(copy), + [](int x) { return x< 24 or x > 42; }); + std::sort(copy.begin(), copy.end()); + copy.erase(std::unique(copy.begin(), copy.end()), copy.end()); + write_data(copy); +} diff --git a/exploring-cpp-2e/chapter43/randomint.hpp b/exploring-cpp-2e/chapter43/randomint.hpp new file mode 100644 index 0000000..c303135 --- /dev/null +++ b/exploring-cpp-2e/chapter43/randomint.hpp @@ -0,0 +1,35 @@ +// Listing 43-5. Generating Random Integers +#ifndef RANDOMINT_HPP_ +#define RANDOMINT_HPP_ + +#include +#include + +/// Generate uniformly distributed random integers in a range. +class randomint +{ +public: + typedef std::default_random_engine::result_type result_type; + + /// Construct a random-number generator to produce numbers in the range [low, high]. + /// If @p low > @p high the values are reversed. + randomint(result_type low, result_type high) + // std::random_device uses a system-dependent generation of randomness + // to seed the pseudo-random-number generator. + : prng_{std::random_device{}()}, + distribution_{std::min(low, high), std::max(low, high)} + {} + + /// Generate the next random number generator. + result_type operator()() + { + return distribution_(prng_); + } + +private: + // implementation-defined pseudo-random-number generator + std::default_random_engine prng_; + // Map random numbers to a uniform distribution. + std::uniform_int_distribution distribution_; +}; +#endif diff --git a/exploring-cpp-2e/chapter43/sequence.hpp b/exploring-cpp-2e/chapter43/sequence.hpp new file mode 100644 index 0000000..0f99f1f --- /dev/null +++ b/exploring-cpp-2e/chapter43/sequence.hpp @@ -0,0 +1,28 @@ +// Listing 42-6. The sequence.hpp File +#ifndef SEQUENCE_HPP_ +#define SEQUENCE_HPP_ + +/// Generate a sequence of integers. +class sequence +{ +public: + /// Construct the functor. + /// @param start the first value the generator returns + /// @param step increment the value by this much for each call + sequence(int start, int step ) : value_{start}, step_{step} {} + sequence(int start) : sequence{start, 1} {} + sequence() : sequence{0} {} + + /// Return the current value in the sequence, and increment the value. + int operator()() + { + int result(value_); + value_ = value_ + step_; + return result; + } +private: + int value_; + int const step_; +}; + +#endif diff --git a/exploring-cpp-2e/chapter44/data.hpp b/exploring-cpp-2e/chapter44/data.hpp new file mode 100644 index 0000000..12defa0 --- /dev/null +++ b/exploring-cpp-2e/chapter44/data.hpp @@ -0,0 +1,37 @@ +// Listing 43-2. The data.hpp File to Support Integer Data +#ifndef DATA_HPP_ +#define DATA_HPP_ + +#include +#include +#include +#include + +/// Convenient shorthand for a vector of integers. +typedef std::vector intvector; + +/// Convenient shorthand for an intvector's iterator. +typedef intvector::iterator intvec_iterator; + +/// Read a series of integers from the standard input into @p data, +/// overwriting @p data in the process. +/// @param[in,out] data a vector of integers +inline void read_data(intvector& data) +{ + data.clear(); + data.insert(data.begin(), std::istream_iterator(std::cin), + std::istream_iterator()); +} + +/// Write a vector of integers to the standard output. Write all values on one +/// line, separated by single space characters, and surrounded by curly braces, +/// e.g., { 1 2 3 }. +/// @param data a vector of integers +inline void write_data(intvector const& data) +{ + std::cout << "{ "; + std::copy(data.begin(), data.end(), + std::ostream_iterator(std::cout, " ")); + std::cout << "}\n"; +} +#endif diff --git a/exploring-cpp-2e/chapter44/list4401.cpp b/exploring-cpp-2e/chapter44/list4401.cpp new file mode 100644 index 0000000..7267273 --- /dev/null +++ b/exploring-cpp-2e/chapter44/list4401.cpp @@ -0,0 +1,21 @@ +// Listing 44-1. Comparing Iterators by Using the < Operator +#include +#include +#include +#include + +int main() +{ + std::vector data{}; + int x{}; + while (std::cin >> x) + data.push_back(x); + + for (auto start(data.begin()), end(data.end()); start < end; ++start) + { + --end; // now end points to a real position, possibly start + std::iter_swap(start, end); // swap contents of two iterators + } + + std::copy(data.begin(), data.end(), std::ostream_iterator(std::cout, "\n")); +} diff --git a/exploring-cpp-2e/chapter44/list4402.cpp b/exploring-cpp-2e/chapter44/list4402.cpp new file mode 100644 index 0000000..54a42b0 --- /dev/null +++ b/exploring-cpp-2e/chapter44/list4402.cpp @@ -0,0 +1,21 @@ +// Listing 44-2. Advancing an Iterator +#include +#include +#include +#include + +#include "data.hpp" // see Listing 43-2. + +#include "sequence.hpp" // see Listing 42-6. + + +int main() +{ + intvector data(10); + std::generate(data.begin(), data.end(), sequence{0, 2}); // fill with even numbers + intvec_iterator iter{data.begin()}; + std::advance(iter, 4); + std::cout << *iter << ", "; + iter = std::prev(iter, 2); + std::cout << *iter << '\n'; +} diff --git a/exploring-cpp-2e/chapter44/list4403.cpp b/exploring-cpp-2e/chapter44/list4403.cpp new file mode 100644 index 0000000..82b620d --- /dev/null +++ b/exploring-cpp-2e/chapter44/list4403.cpp @@ -0,0 +1,13 @@ +// Listing 44-3. Printing the Middle Item of a Series of Integers +#include +#include "data.hpp" + +int main() +{ + intvector data{}; + read_data(data); + const intvec_iterator iter{data.begin()}; + std::advance(iter, data.size() / 2); // move to middle of vector + if (not data.empty()) + std::cout << "middle item = " << *iter << '\n'; +} diff --git a/exploring-cpp-2e/chapter44/list4404.cpp b/exploring-cpp-2e/chapter44/list4404.cpp new file mode 100644 index 0000000..225c1e5 --- /dev/null +++ b/exploring-cpp-2e/chapter44/list4404.cpp @@ -0,0 +1,14 @@ +// Listing 44-4. Really Printing the Middle Item of a Series of Integers +#include + +#include "data.hpp" + +int main() +{ + intvector data{}; + read_data(data); + intvector::const_iterator iter{data.begin()}; + std::advance(iter, data.size() / 2); // move to middle of vector + if (not data.empty()) + std::cout << "middle item = " << *iter << '\n'; +} diff --git a/exploring-cpp-2e/chapter44/list4405.cpp b/exploring-cpp-2e/chapter44/list4405.cpp new file mode 100644 index 0000000..80531d3 --- /dev/null +++ b/exploring-cpp-2e/chapter44/list4405.cpp @@ -0,0 +1,15 @@ +// Listing 44-5. Negating the Middle Value in a Series of Integers +#include + +#include "data.hpp" + +int main() +{ + intvector data{}; + read_data(data); + intvector::const_iterator iter{data.begin()}; + std::advance(iter, data.size() / 2); // move to middle of vector + if (not data.empty()) + *iter = -*iter; + write_data(data); +} diff --git a/exploring-cpp-2e/chapter44/list4406.cpp b/exploring-cpp-2e/chapter44/list4406.cpp new file mode 100644 index 0000000..7bc6a82 --- /dev/null +++ b/exploring-cpp-2e/chapter44/list4406.cpp @@ -0,0 +1,26 @@ +// Listing 44-6. Revealing the Implementation of reverse_iterator +#include +#include +#include + +#include "data.hpp" +#include "sequence.hpp" + +int main() +{ + intvector data(10); + std::generate(data.begin(), data.end(), sequence(1)); + write_data(data); // prints { 1 2 3 4 5 6 7 8 9 10 } + intvector::iterator iter{data.begin()}; + iter = iter + 5; // iter is random access + std::cout << *iter << '\n'; // prints 5 + + intvector::reverse_iterator rev{data.rbegin()}; + std::cout << *rev << '\n'; // prints 10 + rev = rev + 4; // rev is also random access + std::cout << *rev << '\n'; // prints 6 + std::cout << *rev.base() << '\n'; // prints 7 + std::cout << *data.rend().base() << '\n'; // prints 0 + assert(data.rbegin().base() == data.end()); + assert(data.rend().base() == data.begin()); +} diff --git a/exploring-cpp-2e/chapter44/sequence.hpp b/exploring-cpp-2e/chapter44/sequence.hpp new file mode 100644 index 0000000..0f99f1f --- /dev/null +++ b/exploring-cpp-2e/chapter44/sequence.hpp @@ -0,0 +1,28 @@ +// Listing 42-6. The sequence.hpp File +#ifndef SEQUENCE_HPP_ +#define SEQUENCE_HPP_ + +/// Generate a sequence of integers. +class sequence +{ +public: + /// Construct the functor. + /// @param start the first value the generator returns + /// @param step increment the value by this much for each call + sequence(int start, int step ) : value_{start}, step_{step} {} + sequence(int start) : sequence{start, 1} {} + sequence() : sequence{0} {} + + /// Return the current value in the sequence, and increment the value. + int operator()() + { + int result(value_); + value_ = value_ + step_; + return result; + } +private: + int value_; + int const step_; +}; + +#endif diff --git a/exploring-cpp-2e/chapter45/list4501.cpp b/exploring-cpp-2e/chapter45/list4501.cpp new file mode 100644 index 0000000..8891957 --- /dev/null +++ b/exploring-cpp-2e/chapter45/list4501.cpp @@ -0,0 +1,10 @@ +// Listing 45-1. Accessing an Element of a Vector +#include +#include + +int main() +{ + std::vector data{ 10, 20 }; + data.at(5) = 0; + std::cout << data.at(5) << '\n'; +} diff --git a/exploring-cpp-2e/chapter45/list4502.cpp b/exploring-cpp-2e/chapter45/list4502.cpp new file mode 100644 index 0000000..62c1e06 --- /dev/null +++ b/exploring-cpp-2e/chapter45/list4502.cpp @@ -0,0 +1,10 @@ +// Listing 45-2. A Bad Way to Access an Element of a Vector +#include +#include + +int main() +{ + std::vector data{ 10, 20 }; + data[5] = 0; + std::cout << data[5] << '\n'; +} diff --git a/exploring-cpp-2e/chapter45/list4503.cpp b/exploring-cpp-2e/chapter45/list4503.cpp new file mode 100644 index 0000000..aa476aa --- /dev/null +++ b/exploring-cpp-2e/chapter45/list4503.cpp @@ -0,0 +1,48 @@ +// Listing 45-3. Forcing a string to Throw Exceptions +#include +#include +#include +#include +#include + +int main() +{ + std::string line{}; + while (std::getline(std::cin, line)) + { + try + { + line.at(10) = ' '; // can throw out_of_range + if (line.size() < 20) + line.append(line.max_size(), '*'); // can throw length_error + for (std::string::size_type size(line.size()); + size < line.max_size(); + size = size * 2) + { + line.resize(size); // can throw bad_alloc + } + line.resize(line.max_size()); // can throw bad_alloc + std::cout << "okay\n"; + } + catch (std::out_of_range const& ex) + { + std::cout << ex.what() << '\n'; + std::cout << "string index (10) out of range.\n"; + } + catch (std::length_error const& ex) + { + std::cout << ex.what() << '\n'; + std::cout << "maximum string length (" << line.max_size() << ") exceeded.\n"; + } + catch (std::exception const& ex) + { + std::cout << "other exception: " << ex.what() << '\n'; + } + catch (...) + { + std::cout << "Unknown exception type. Program terminating.\n"; + std::abort(); + } + } +} + diff --git a/exploring-cpp-2e/chapter45/list4504.cpp b/exploring-cpp-2e/chapter45/list4504.cpp new file mode 100644 index 0000000..c5d9e36 --- /dev/null +++ b/exploring-cpp-2e/chapter45/list4504.cpp @@ -0,0 +1,69 @@ +// Listing 45-4. Visualizing an Exception +#include +#include +#include + +/// Make visual the construction and destruction of objects. +class visual +{ +public: + visual(std::string const& what) + : id_{serial_}, what_{what} + { + ++serial_; + print(""); + } + visual(visual const& ex) + : id_{ex.id_}, what_{ex.what_} + { + print("copy "); + } + ~visual() + { + print("~"); + } + void print(std::string const& label) + const + { + std::cout << label << "visual(" << what_ << ": " << id_ << ")\n"; + } +private: + static int serial_; + int const id_; + std::string const what_; +}; + +int visual::serial_{0}; + +void count_down(int n) +{ + std::cout << "start count_down(" << n << ")\n"; + visual v{"count_down local"}; + try + { + if (n == 3) + throw visual("exception"); + else if (n > 0) + count_down(n - 1); + } + catch (visual ex) + { + ex.print("catch "); + throw; + } + std::cout << "end count_down(" << n << ")\n"; +} + +int main() +{ + try + { + count_down(2); + count_down(4); + } + catch (visual const ex) + { + ex.print("catch "); + } + std::cout << "All done!\n"; +} diff --git a/exploring-cpp-2e/chapter45/list4505.cpp b/exploring-cpp-2e/chapter45/list4505.cpp new file mode 100644 index 0000000..2de8acf --- /dev/null +++ b/exploring-cpp-2e/chapter45/list4505.cpp @@ -0,0 +1,22 @@ +// Listing 45-5. Using an I/O Stream Exception Mask +#include + +int main() +{ + std::cin.exceptions(std::ios_base::badbit); + std::cout.exceptions(std::ios_base::badbit); + + int x{}; + try + { + while (std::cin >> x) + std::cout << x << '\n'; + if (not std::cin.eof()) // failure without eof means invalid input + std::cerr << "Invalid integer input. Program terminated.\n"; + } + catch(std::ios_base::failure const& ex) + { + std::cerr << "Major I/O failure! Program terminated.\n"; + std::terminate(); + } +} diff --git a/exploring-cpp-2e/chapter45/list4506.hpp b/exploring-cpp-2e/chapter45/list4506.hpp new file mode 100644 index 0000000..a8e2234 --- /dev/null +++ b/exploring-cpp-2e/chapter45/list4506.hpp @@ -0,0 +1,90 @@ +// Listing 45-6. Throwing an Exception for a Zero Denominator +#ifndef RATIONAL_HPP_ +#define RATIONAL_HPP_ + +#include +#include +#include +#include +#include +#include + +// Listing 35-4. The Latest Rewrite of the rational Class + +/// Compute the greatest common divisor of two integers, using Euclid’s algorithm. +int gcd(int n, int m) +{ + n = std::abs(n); + while (m != 0) { + int tmp(n % m); + n = m; + m = tmp; + } + return n; +} + + +class rational +{ +public: + class zero_denominator : public std::logic_error + { + public: + zero_denominator(std::string const& what_arg) : logic_error{what_arg} {} + }; + + rational() : rational{0} {} + rational(int num) : numerator_{num}, denominator_{1} {} + rational(int num, int den) : numerator_{num}, denominator_{den} + { + if (denominator_ == 0) + throw zero_denominator{"zero denominator"}; + reduce(); + } + int numerator() const { return numerator_; } + int denominator() const { return denominator_; } + float to_float() + const + { + return static_cast(numerator()) / denominator(); + } + + double to_double() + const + { + return static_cast(numerator()) / denominator(); + } + + long double to_long_double() + const + { + return static_cast(numerator()) / + denominator(); + } + + /// Assign a numerator and a denominator, then reduce to normal form. + void assign(int num, int den) + { + numerator_ = num; + denominator_ = den; + reduce(); + } +private: + /// Reduce the numerator and denominator by their GCD. + void reduce() + { + assert(denominator() != 0); + if (denominator() < 0) + { + denominator_ = -denominator(); + numerator_ = -numerator(); + } + int div{gcd(numerator(), denominator())}; + numerator_ = numerator() / div; + denominator_ = denominator() / div; + } + + int numerator_; + int denominator_; +}; +#endif diff --git a/exploring-cpp-2e/chapter45/list4507.cpp b/exploring-cpp-2e/chapter45/list4507.cpp new file mode 100644 index 0000000..66fa114 --- /dev/null +++ b/exploring-cpp-2e/chapter45/list4507.cpp @@ -0,0 +1,14 @@ +// Listing 45-7. Checking for a Zero Denominator in reduce() +void rational::reduce() +{ + if (denominator_ == 0) + throw zero_denominator{"denominator is zero"}; + if (denominator_ < 0) + { + denominator_ = -denominator_; + numerator_ = -numerator_; + } + int div{gcd(numerator_, denominator_)}; + numerator_ = numerator_ / div; + denominator_ = denominator_ / div; +} diff --git a/exploring-cpp-2e/chapter45/list4508.cpp b/exploring-cpp-2e/chapter45/list4508.cpp new file mode 100644 index 0000000..1d35f75 --- /dev/null +++ b/exploring-cpp-2e/chapter45/list4508.cpp @@ -0,0 +1,18 @@ +// Listing 45-8. Throwing an Exception from a noexcept Function +#include +#include + +void function() noexcept +{ + throw std::exception{}; +} + +int main() +{ + try { + function(); + } catch (std::exception const& ex) { + std::cout << "Gotcha!\n"; + } +} + diff --git a/exploring-cpp-2e/chapter45/rational.hpp b/exploring-cpp-2e/chapter45/rational.hpp new file mode 100644 index 0000000..a8e2234 --- /dev/null +++ b/exploring-cpp-2e/chapter45/rational.hpp @@ -0,0 +1,90 @@ +// Listing 45-6. Throwing an Exception for a Zero Denominator +#ifndef RATIONAL_HPP_ +#define RATIONAL_HPP_ + +#include +#include +#include +#include +#include +#include + +// Listing 35-4. The Latest Rewrite of the rational Class + +/// Compute the greatest common divisor of two integers, using Euclid’s algorithm. +int gcd(int n, int m) +{ + n = std::abs(n); + while (m != 0) { + int tmp(n % m); + n = m; + m = tmp; + } + return n; +} + + +class rational +{ +public: + class zero_denominator : public std::logic_error + { + public: + zero_denominator(std::string const& what_arg) : logic_error{what_arg} {} + }; + + rational() : rational{0} {} + rational(int num) : numerator_{num}, denominator_{1} {} + rational(int num, int den) : numerator_{num}, denominator_{den} + { + if (denominator_ == 0) + throw zero_denominator{"zero denominator"}; + reduce(); + } + int numerator() const { return numerator_; } + int denominator() const { return denominator_; } + float to_float() + const + { + return static_cast(numerator()) / denominator(); + } + + double to_double() + const + { + return static_cast(numerator()) / denominator(); + } + + long double to_long_double() + const + { + return static_cast(numerator()) / + denominator(); + } + + /// Assign a numerator and a denominator, then reduce to normal form. + void assign(int num, int den) + { + numerator_ = num; + denominator_ = den; + reduce(); + } +private: + /// Reduce the numerator and denominator by their GCD. + void reduce() + { + assert(denominator() != 0); + if (denominator() < 0) + { + denominator_ = -denominator(); + numerator_ = -numerator(); + } + int div{gcd(numerator(), denominator())}; + numerator_ = numerator() / div; + denominator_ = denominator() / div; + } + + int numerator_; + int denominator_; +}; +#endif diff --git a/exploring-cpp-2e/chapter46/list4601.cpp b/exploring-cpp-2e/chapter46/list4601.cpp new file mode 100644 index 0000000..f5c09f1 --- /dev/null +++ b/exploring-cpp-2e/chapter46/list4601.cpp @@ -0,0 +1,13 @@ +// Listing 46-1. Using Conditional Expressions in a Constructor’s Initializer +/// Construct a rational object from a numerator and a denominator. +/// If the denominator is zero, throw zero_denominator. If the denominator +/// is negative, normalize the value by negating the numerator and denominator. +/// @post denominator_ > 0 +/// @throws zero_denominator +rational::rational(int num, int den) +: numerator_{den < 0 ? -num : num}, + denominator_{den == 0 ? throw zero_denominator("0 denominator") : + (den < 0 ? -den : den)} +{ + reduce(); +} diff --git a/exploring-cpp-2e/chapter46/list4602.cpp b/exploring-cpp-2e/chapter46/list4602.cpp new file mode 100644 index 0000000..b9f2827 --- /dev/null +++ b/exploring-cpp-2e/chapter46/list4602.cpp @@ -0,0 +1,23 @@ +// Listing 46-2. Using a Function and Conditional Statements Instead of Conditional Expressions +/// Construct a rational object from a numerator and a denominator. +/// If the denominator is zero, throw zero_denominator. If the denominator +/// is negative, normalize the value by negating the numerator and denominator. +/// @post denominator_ > 0 +/// @throws zero_denominator +rational::rational(int num, int den) +: numerator_{den < 0 ? -num : num}, denominator_{init_denominator(den)} +{ + reduce(); +} + +/// Return an initial value for the denominator_ member. This function is used +/// only in a constructor's initializer list. +int rational::init_denominator(int den) +{ + if (den == 0) + throw zero_denominator("0 denominator"); + else if (den < 0) + return -den; + else + return den; +} diff --git a/exploring-cpp-2e/chapter46/list4603.cpp b/exploring-cpp-2e/chapter46/list4603.cpp new file mode 100644 index 0000000..edc7315 --- /dev/null +++ b/exploring-cpp-2e/chapter46/list4603.cpp @@ -0,0 +1,31 @@ +// Listing 46-3. Searching for a Matching Sub-range in a Vector of Integers +#include + +typedef std::vector::iterator viterator; +typedef std::vector::difference_type vdifference; + +viterator search(viterator first1,viterator last1,viterator first2,viterator last2) +{ + // s1 is the size of the untested portion of the first range + // s2 is the size of the second range + // End the search when s2 > s1 because a match is impossible if the remaining + // portion of the search range is smaller than the test range. Each iteration + // of the outer loop shrinks the search range by one, and advances the first1 + // iterator. The inner loop searches for a match starting at first1. + for (vdifference s1(last1-first1), s2(last2-first2); s2 <= s1; --s1, ++first1) + { + // Is there a match starting at first1? + viterator f2(first2); + for (viterator f1(first1); + f1 != last1 and f2 != last2 and *f1 == *f2; + ++f1, ++f2) + { + // The subsequence matches so far, so keep checking. + // All the work is done in the loop header, so the body is empty. + } + if (f2 == last2) + return first1; // match starts at first1 + } + // no match + return last1; +} diff --git a/exploring-cpp-2e/chapter46/list4604.cpp b/exploring-cpp-2e/chapter46/list4604.cpp new file mode 100644 index 0000000..5cd2827 --- /dev/null +++ b/exploring-cpp-2e/chapter46/list4604.cpp @@ -0,0 +1,30 @@ +// Listing 46-4. The search Function Without Using the Comma Operator +#include + +typedef std::vector::iterator viterator; +typedef std::vector::difference_type vdifference; + +viterator search(viterator first1,viterator last1,viterator first2,viterator last2) +{ + // s1 is the size of the untested portion of the first range + // s2 is the size of the second range + // End the search when s2 > s1 because a match is impossible if the remaining + // portion of the search range is smaller than the test range. Each iteration + // of the outer loop shrinks the search range by one, and advances the first1 + // iterator. The inner loop searches for a match starting at first1. + for (vdifference s1(last1-first1), s2(last2-first2); s2 <= s1; --s1) + { + // Is there a match starting at first1? + viterator f2(first2); + for (viterator f1(first1); f1 != last1 and f2 != last2 and *f1 == *f2; ) + { + ++f1; + ++f2; + } + if (f2 == last2) + return first1; // match starts at first1 + ++first1; + } + // no match + return last1; +} diff --git a/exploring-cpp-2e/chapter46/list4605.cpp b/exploring-cpp-2e/chapter46/list4605.cpp new file mode 100644 index 0000000..75fd476 --- /dev/null +++ b/exploring-cpp-2e/chapter46/list4605.cpp @@ -0,0 +1,8 @@ +// Listing 46-5. Implementing the Multiplication Assignment Operator +rational& rational::operator*=(rational const& rhs) +{ + numerator_ *= rhs.numerator(); + denominator_ *= rhs.denominator(); + reduce(); + return *this; +} diff --git a/exploring-cpp-2e/chapter46/list4606.cpp b/exploring-cpp-2e/chapter46/list4606.cpp new file mode 100644 index 0000000..313af40 --- /dev/null +++ b/exploring-cpp-2e/chapter46/list4606.cpp @@ -0,0 +1,7 @@ +// Listing 46-6. Reimplementing Multiplication in Terms of an Assignment Operator +rational operator*(rational const& lhs, rational const& rhs) +{ + rational result{lhs}; + result *= rhs; + return result; +} diff --git a/exploring-cpp-2e/chapter46/list4607.cpp b/exploring-cpp-2e/chapter46/list4607.cpp new file mode 100644 index 0000000..5abef52 --- /dev/null +++ b/exploring-cpp-2e/chapter46/list4607.cpp @@ -0,0 +1,31 @@ +// Listing 46-7. Other Arithmetic Assignment Operators +rational& rational::operator+=(rational const& rhs) +{ + numerator_ = numerator() * rhs.denominator() + rhs.numerator() * denominator(); + denominator_ *= rhs.denominator(); + reduce(); + return *this; +} + +rational& rational::operator-=(rational const& rhs) +{ + numerator_ = numerator() * rhs.denominator() - rhs.numerator() * denominator(); + denominator_ *= rhs.denominator(); + reduce(); + return *this; +} + +rational& rational::operator/=(rational const& rhs) +{ + if (rhs.numerator() == 0) + throw zero_denominator{"divide by zero"}; + numerator_ *= rhs.denominator(); + denominator_ *= rhs.numerator(); + if (denominator_ < 0) + { + denominator_ = -denominator_; + numerator_ = -numerator_; + } + reduce(); + return *this; +} diff --git a/exploring-cpp-2e/chapter46/list4608.cpp b/exploring-cpp-2e/chapter46/list4608.cpp new file mode 100644 index 0000000..d007a0d --- /dev/null +++ b/exploring-cpp-2e/chapter46/list4608.cpp @@ -0,0 +1,6 @@ +// Listing 46-8. The Prefix Increment Operator for rational +rational& rational::operator++() +{ + numerator_ += denominator_; + return *this; +} diff --git a/exploring-cpp-2e/chapter46/list4609.cpp b/exploring-cpp-2e/chapter46/list4609.cpp new file mode 100644 index 0000000..34a9c2e --- /dev/null +++ b/exploring-cpp-2e/chapter46/list4609.cpp @@ -0,0 +1,14 @@ +// Listing 46-9. Postfix Increment and Decrement Operators +rational rational::operator++(int) +{ + rational result{*this}; + numerator_ += denominator_; + return result; +} + +rational rational::operator--(int) +{ + rational result{*this}; + numerator_ -= denominator_; + return result; +} diff --git a/exploring-cpp-2e/chapter46/list4610.hpp b/exploring-cpp-2e/chapter46/list4610.hpp new file mode 100644 index 0000000..a8e76a1 --- /dev/null +++ b/exploring-cpp-2e/chapter46/list4610.hpp @@ -0,0 +1,88 @@ +// Listing 46-10. The rational Class Definition +#ifndef RATIONAL_HPP_ +#define RATIONAL_HPP_ + +#include +#include +#include + +/// Represent a rational number (fraction) as a numerator and denominator. +class rational +{ +public: + class zero_denominator : public std::logic_error + { + public: + zero_denominator(std::string const& what) : logic_error{what} {} + }; + rational(): rational{0} {} + rational(int num): numerator_{num}, denominator_{1} {} + rational(int num, int den); + rational(double r); + + int numerator() const { return numerator_; } + int denominator() const { return denominator_; } + float as_float() const; + double as_double() const; + long double as_long_double() const; + + rational& operator=(int); // optimization to avoid an unneeded call to reduce() + rational& operator+=(rational const& rhs); + rational& operator-=(rational const& rhs); + rational& operator*=(rational const& rhs); + rational& operator/=(rational const& rhs); + rational& operator++(); + rational& operator--(); + rational operator++(int); + rational operator--(int); + +private: + /// Reduce the numerator and denominator by their GCD. + void reduce(); + /// Reduce the numerator and denominator, and normalize the signs of both, + /// that is, ensure denominator is not negative. + void normalize(); + /// Return an initial value for denominator_. Throw a zero_denominator + /// exception if @p den is zero. Always return a positive number. + int init_denominator(int den); + int numerator_; + int denominator_; +}; + +/// Compute the greatest common divisor of two integers, using Euclid's algorithm. +int gcd(int n, int m); + +rational abs(rational const& r); +rational operator-(rational const& r); +rational operator+(rational const& lhs, rational const& rhs); +rational operator-(rational const& lhs, rational const& rhs); +rational operator*(rational const& lhs, rational const& rhs); +rational operator/(rational const& lhs, rational const& rhs); + +bool operator==(rational const& a, rational const& b); +bool operator<(rational const& a, rational const& b); + +inline bool operator!=(rational const& a, rational const& b) +{ + return not (a == b); +} + +inline bool operator<=(rational const& a, rational const& b) +{ + return not (b < a); +} + +inline bool operator>(rational const& a, rational const& b) +{ + return b < a; +} + +inline bool operator>=(rational const& a, rational const& b) +{ + return not (b > a); +} + +std::istream& operator>>(std::istream& in, rational& rat); +std::ostream& operator<<(std::ostream& out, rational const& rat); + +#endif diff --git a/exploring-cpp-2e/chapter46/rational.cpp b/exploring-cpp-2e/chapter46/rational.cpp new file mode 100644 index 0000000..b66777d --- /dev/null +++ b/exploring-cpp-2e/chapter46/rational.cpp @@ -0,0 +1,265 @@ +#include +#include +#include +#include + +#include "rational.hpp" + +/// Compute the greatest common divisor of two integers, using Euclid’s algorithm. +int gcd(int n, int m) +{ + n = std::abs(n); + while (m != 0) { + int tmp(n % m); + n = m; + m = tmp; + } + return n; +} + +// Listing 46-2. Using a Function and Conditional Statements Instead of Conditional Expressions +/// Construct a rational object from a numerator and a denominator. +/// If the denominator is zero, throw zero_denominator. If the denominator +/// is negative, normalize the value by negating the numerator and denominator. +/// @post denominator_ > 0 +/// @throws zero_denominator +rational::rational(int num, int den) +: numerator_{den < 0 ? -num : num}, denominator_{init_denominator(den)} +{ + reduce(); +} + +/// Return an initial value for the denominator_ member. This function is used +/// only in a constructor's initializer list. +int rational::init_denominator(int den) +{ + if (den == 0) + throw zero_denominator("0 denominator"); + else if (den < 0) + return -den; + else + return den; +} + +rational::rational(double r) +: rational{static_cast(r * 10000), 10000} +{ + reduce(); +} + +float rational::to_float() +const +{ + return static_cast(numerator()) / denominator(); +} + +double rational::to_double() +const +{ + return static_cast(numerator()) / denominator(); +} + +long double rational::to_long_double() +const +{ + return static_cast(numerator()) / denominator(); +} + +/// Assign a numerator and a denominator, then reduce to normal form. +void assign(int num, int den) +{ + numerator_ = den < 0 ? -num : num; + denominator_ = init_denominator(den); + reduce(); +} + +void rational::reduce() +{ + int div{gcd(numerator(), denominator())}; + numerator_ = numerator() / div; + denominator_ = denominator() / div; +} + +// Listing 46-5. Implementing the Multiplication Assignment Operator +rational& rational::operator*=(rational const& rhs) +{ + numerator_ *= rhs.numerator(); + denominator_ *= rhs.denominator(); + reduce(); + return *this; +} + +// Listing 46-7. Other Arithmetic Assignment Operators +rational& rational::operator+=(rational const& rhs) +{ + numerator_ = numerator() * rhs.denominator() + rhs.numerator() * denominator(); + denominator_ *= rhs.denominator(); + reduce(); + return *this; +} + +rational& rational::operator-=(rational const& rhs) +{ + numerator_ = numerator() * rhs.denominator() - rhs.numerator() * denominator(); + denominator_ *= rhs.denominator(); + reduce(); + return *this; +} + +rational& rational::operator/=(rational const& rhs) +{ + if (rhs.numerator() == 0) + throw zero_denominator{"divide by zero"}; + numerator_ *= rhs.denominator(); + denominator_ *= rhs.numerator(); + if (denominator_ < 0) + { + denominator_ = -denominator_; + numerator_ = -numerator_; + } + reduce(); + return *this; +} + +// Listing 46-8. The Prefix Increment Operator for rational +rational& rational::operator++() +{ + numerator_ += denominator_; + return *this; +} + +rational& rational::operator--() +{ + numerator_ -= denominator_; + return *this; +} + +// Listing 46-9. Postfix Increment and Decrement Operators +rational rational::operator++(int) +{ + rational result{*this}; + numerator_ += denominator_; + return result; +} + +rational rational::operator--(int) +{ + rational result{*this}; + numerator_ -= denominator_; + return result; +} + +/// Absolute value of a rational number. +rational abs(rational const& r) +{ + return rational{std::abs(r.numerator()), r.denominator()}; +} + +/// Unary negation of a rational number. +rational operator-(rational const& r) +{ + return rational{-r.numerator(), r.denominator()}; +} + +/// Add rational numbers. +rational operator+(rational const& lhs, rational const& rhs) +{ + rational result{lhs}; + result += rhs; + return result; +} + +/// Subtraction of rational numbers. +rational operator-(rational const& lhs, rational const& rhs) +{ + rational result{lhs}; + result -= rhs; + return result; +} + +/// Multiplication of rational numbers. +rational operator*(rational const& lhs, rational const& rhs) +{ + rational result{lhs}; + result *= rhs; + return result; +} + +rational operator/(rational const& lhs, rational const& rhs) +{ + rational result{lhs}; + result /= rhs; + return result; +} + + +/// Compare two rational numbers for equality. +bool operator==(rational const& a, rational const& b) +{ + return a.numerator() == b.numerator() and a.denominator() == b.denominator(); +} + +/// Compare two rational numbers for inequality. +inline bool operator!=(rational const& a, rational const& b) +{ + return not (a == b); +} +/// Compare two rational numbers for less-than. +bool operator<(rational const& a, rational const& b) +{ + return a.numerator() * b.denominator() < b.numerator() * a.denominator(); +} + +/// Compare two rational numbers for less-than-or-equal. +inline bool operator<=(rational const& a, rational const& b) +{ + return not (b < a); +} +/// Compare two rational numbers for greater-than. +inline bool operator>(rational const& a, rational const& b) +{ + return b < a; +} + +/// Compare two rational numbers for greater-than-or-equal. +inline bool operator>=(rational const& a, rational const& b) +{ + return not (b > a); +} + +/// Read a rational number. +/// Format is @em integer @c / @em integer. +std::istream& operator>>(std::istream& in, rational& rat) +{ + int n{}, d{}; + char sep{}; + if (not (in >> n >> sep)) + // Error reading the numerator or the separator character. + in.setstate(in.failbit); + else if (sep != '/') + { + // Push sep back into the input stream, so the next input operation + // will read it. + in.unget(); + rat.assign(n, 1); + } + else if (in >> d) + // Successfully read numerator, separator, and denominator. + rat.assign(n, d); + else + // Error reading denominator. + in.setstate(in.failbit); + + return in; +} + +/// Write a rational numbers. +/// Format is @em numerator @c / @em denominator. +std::ostream& operator<<(std::ostream& out, rational const& rat) +{ + std::ostringstream tmp{}; + tmp << rat.numerator() << '/' << rat.denominator(); + out << tmp.str(); + + return out; +} diff --git a/exploring-cpp-2e/chapter46/rational.hpp b/exploring-cpp-2e/chapter46/rational.hpp new file mode 100644 index 0000000..a8e76a1 --- /dev/null +++ b/exploring-cpp-2e/chapter46/rational.hpp @@ -0,0 +1,88 @@ +// Listing 46-10. The rational Class Definition +#ifndef RATIONAL_HPP_ +#define RATIONAL_HPP_ + +#include +#include +#include + +/// Represent a rational number (fraction) as a numerator and denominator. +class rational +{ +public: + class zero_denominator : public std::logic_error + { + public: + zero_denominator(std::string const& what) : logic_error{what} {} + }; + rational(): rational{0} {} + rational(int num): numerator_{num}, denominator_{1} {} + rational(int num, int den); + rational(double r); + + int numerator() const { return numerator_; } + int denominator() const { return denominator_; } + float as_float() const; + double as_double() const; + long double as_long_double() const; + + rational& operator=(int); // optimization to avoid an unneeded call to reduce() + rational& operator+=(rational const& rhs); + rational& operator-=(rational const& rhs); + rational& operator*=(rational const& rhs); + rational& operator/=(rational const& rhs); + rational& operator++(); + rational& operator--(); + rational operator++(int); + rational operator--(int); + +private: + /// Reduce the numerator and denominator by their GCD. + void reduce(); + /// Reduce the numerator and denominator, and normalize the signs of both, + /// that is, ensure denominator is not negative. + void normalize(); + /// Return an initial value for denominator_. Throw a zero_denominator + /// exception if @p den is zero. Always return a positive number. + int init_denominator(int den); + int numerator_; + int denominator_; +}; + +/// Compute the greatest common divisor of two integers, using Euclid's algorithm. +int gcd(int n, int m); + +rational abs(rational const& r); +rational operator-(rational const& r); +rational operator+(rational const& lhs, rational const& rhs); +rational operator-(rational const& lhs, rational const& rhs); +rational operator*(rational const& lhs, rational const& rhs); +rational operator/(rational const& lhs, rational const& rhs); + +bool operator==(rational const& a, rational const& b); +bool operator<(rational const& a, rational const& b); + +inline bool operator!=(rational const& a, rational const& b) +{ + return not (a == b); +} + +inline bool operator<=(rational const& a, rational const& b) +{ + return not (b < a); +} + +inline bool operator>(rational const& a, rational const& b) +{ + return b < a; +} + +inline bool operator>=(rational const& a, rational const& b) +{ + return not (b > a); +} + +std::istream& operator>>(std::istream& in, rational& rat); +std::ostream& operator<<(std::ostream& out, rational const& rat); + +#endif diff --git a/exploring-cpp-2e/chapter47/Doxyfile b/exploring-cpp-2e/chapter47/Doxyfile new file mode 100644 index 0000000..824fc7c --- /dev/null +++ b/exploring-cpp-2e/chapter47/Doxyfile @@ -0,0 +1,1275 @@ +# Doxyfile 1.5.3 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file that +# follow. The default is UTF-8 which is also the encoding used for all text before +# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into +# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of +# possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = "Project 2 - Fixed-Point Number Class " + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian, +# Italian, Japanese, Japanese-en (Japanese with English messages), Korean, +# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian, +# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = . + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to +# include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be extracted +# and appear in the documentation as a namespace called 'anonymous_namespace{file}', +# where file will be replaced with the base name of the file that contains the anonymous +# namespace. By default anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from the +# version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text " + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = . + +# This tag can be used to specify the character encoding of the source files that +# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default +# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding. +# See http://www.gnu.org/software/libiconv for the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py + +FILE_PATTERNS = *.cpp *.hpp + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the output. +# The symbol name can be a fully qualified name, a word, or if the wildcard * is used, +# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. If you have enabled CALL_GRAPH or CALLER_GRAPH +# then you must also enable this option. If you don't then doxygen will produce +# a warning and turn it on anyway + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentstion. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to +# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to +# specify the directory where the mscgen tool resides. If left empty the tool is assumed to +# be found in the default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will +# generate a caller dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable caller graphs for selected +# functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the number +# of direct children of the root node in a graph is already larger than +# MAX_DOT_GRAPH_NOTES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, which results in a white background. +# Warning: Depending on the platform used, enabling this option may lead to +# badly anti-aliased labels on the edges of a graph (i.e. they become hard to +# read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/exploring-cpp-2e/chapter47/Makefile b/exploring-cpp-2e/chapter47/Makefile new file mode 100644 index 0000000..123bfc0 --- /dev/null +++ b/exploring-cpp-2e/chapter47/Makefile @@ -0,0 +1,23 @@ +DEBUG = -g -pg -fprofile-arcs -ftest-coverage +CXXFLAGS = -ansi -pedantic -Wall -std=c++11 +TEST = test.cpp fixed.cpp +TESTOBJ = $(TEST:.cpp=.o) + +all : runtest + +test : $(TESTOBJ) + $(CXX) $(CXXFLAGS) -o $@ $(TESTOBJ) + +runtest : cleantest test + ./test + +clean : cleantest + $(RM) -r $(TESTOBJ) test html + +cleantest : + $(RM) *.{gcov,gcda} + +test.o : test.cpp fixed.hpp +fixed.o : fixed.cpp fixed.hpp ioflags.hpp + +.PHONY : runtest clean cleantest diff --git a/exploring-cpp-2e/chapter47/fixed.cpp b/exploring-cpp-2e/chapter47/fixed.cpp new file mode 100644 index 0000000..38ab521 --- /dev/null +++ b/exploring-cpp-2e/chapter47/fixed.cpp @@ -0,0 +1,308 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fixed.hpp" +#include "ioflags.hpp" + +// Construct a fixed value from an integer part and a fraction part +fixed::fixed(value_type integer, value_type fraction) +{ + if (fraction < 0) + throw std::invalid_argument("negative fraction not allowed"); + fraction = reduce(fraction); + if (integer < 0) + value_ = integer * places10 - fraction; + else + value_ = integer * places10 + fraction; +} + +// Construct a fixed value from an integer part with no fraction +fixed::fixed(value_type integer) +: value_{integer * places10} +{} + +// Get the fraction part +fixed::value_type fixed::fraction() +const +{ + return std::abs(value()) % places10; +} + +/// Reduce the fractional part to the range [0, places10). +/// Imagine frac has the format F(G(XY*)?)?. +/// The resulting value is FH, where H == 0 if G is absent, +/// or H == G+1 if X==5 and Y* == 0* and G is odd, or +/// H == G+1 if X>5 or X==5 and Y*>0*, else H == G. +/// In other words, check that frac ends with only zero digits, +/// then a 5, then two more digits (searching from least-significant +/// to most-significant). If so, implement banker's rounding. +/// Otherwise, round GXY* to the nearest value (G+1 or G). +fixed::value_type fixed::reduce(value_type frac) +{ + // First scan for zero digits on the right. + value_type f{frac}; + while (f >= places10*10 and f % 10 == 0) + { + f /= 10; + } + + if (f >= places10*10) + { + int x{0}; + // Loop ended because a non-zero digit was seen so Y* > 0. + // Discard the remaining digits, but keep track of the last + // digit to be processed (X). + while (f >= places10) + { + x = f % 10; + f /= 10; + } + // Round up if the last digit (X) is 5 or more + if (x >= 5) + ++f; + return f; + } + // Else all digits so far are zero. Check how many digits there were, + // that is, check whether G, and X at least are present. + else if (f >= places10) + { + // Yes, G and X are present. If X == 5, implement banker's rounding. + // Otherwise, round to nearest. + int x{f % 10}; + f /= 10; + assert(f < places10); + if (x == 5) + { + // Yes, so implement banker's rounding. + if (f % 2 != 0) + ++f; + return f; + } + else if (x < 5) + { + // Round down. + return f; + } + else + { + // Round up. + return f + 1; + } + } + // Not enough digits, so nothing to round. + assert(frac < places10); + return frac; +} + +// Round off to nearest integer. +fixed::value_type fixed::round() +const +{ + const value_type frac{fraction()}; + int adjust{value() < 0 ? -1 : +1}; + if (frac > places10/2) + return integer()+adjust; + else if (frac < places10/2) + return integer(); + else if (integer() % 2 == 0) + return integer(); + else + return integer()+adjust; +} + +// Convert to a string using fixed-point notation. +std::string fixed::as_string() +const +{ + std::ostringstream out{}; + out << integer() << '.' + << std::setfill('0') << std::setw(places) << fraction(); + return out.str(); +} + +fixed& fixed::operator+=(fixed f) +{ + value_ += f.value(); + return *this; +} + +fixed& fixed::operator-=(fixed f) +{ + value_ -= f.value(); + return *this; +} + +fixed& fixed::operator*=(fixed f) +{ + value_ = (value_ * f.value()) / places10; + return *this; +} + +fixed& fixed::operator/=(fixed f) +{ + value_ = (value_ * places10) / f.value(); + return *this; +} + +void fixed::negate() +{ + value_ = -value_; +} + +fixed& fixed::operator++() +{ + value_ += places10; + return *this; +} + +fixed fixed::operator++(int) +{ + fixed result{*this}; + ++*this; + return result; +} + +fixed& fixed::operator--() +{ + value_ -= places10; + return *this; +} + +fixed fixed::operator--(int) +{ + fixed result{*this}; + --*this; + return result; +} + +fixed operator-(fixed a) +{ + a.negate(); + return a; +} + +bool fixed::read(std::istream& strm) +{ + ioflags flags(strm); + + value_type integer{}; + char decimal{}; + if (not (strm >> integer)) + return false; + strm.unsetf(std::ios_base::skipws); + if (not (strm >> decimal) or decimal != '.') + { + // Just an integer is fine. Push back the non-decimal character, + // if there is one, and reset the stream flags to show that + // reading the fixed value succeeded. + strm.unget(); + strm.clear(strm.rdstate() & ~strm.failbit); + value_ = integer * places10; + return true; + } + else + { + value_type fraction{0}; + char c{}; + int p{0}; + // Read one extra place for round-off. + for (; + p != places+1 and strm >> c and std::isdigit(c, strm.getloc()); + ++p) + { + fraction = fraction * 10 + (c - '0'); + } + // Pad out to the requisite number of decimal places. + for (; p < places; ++p) + fraction = fraction * 10; + // If the loop terminated because the maximum number of decimal + // places were read, keep reading the stream to discard excees digits. + while (strm and std::isdigit(c, strm.getloc())) + strm >> c; + // Push back the last, non-digit character read from the stream. + // If the stream reached EOF, unget() is harmless. + strm.unget(); + // Clear failbit because even if reading a character or whatever + // failed, reading the fixed value did not. + strm.clear(strm.rdstate() & ~strm.failbit); + fraction = reduce(fraction); + if (integer < 0) + value_ = integer * places10 - fraction; + else + value_ = integer * places10 + fraction; + } + return true; +} + +std::istream& operator>>(std::istream& strm, fixed& f) +{ + if (not f.read(strm)) + strm.setstate(strm.failbit); + return strm; +} + +std::ostream& operator<<(std::ostream& strm, fixed f) +{ + strm << f.as_string(); + return strm; +} + +fixed operator+(fixed a, fixed b) +{ + a += b; + return a; +} + +fixed operator-(fixed a, fixed b) +{ + a -= b; + return a; +} + +fixed operator*(fixed a, fixed b) +{ + a *= b; + return a; +} + +fixed operator/(fixed a, fixed b) +{ + a /= b; + return a; +} + +bool operator==(fixed a, fixed b) +{ + return a.value() == b.value(); +} + +bool operator!=(fixed a, fixed b) +{ + return not (a == b); +} + +bool operator<(fixed a, fixed b) +{ + return a.value() < b.value(); +} + +bool operator>(fixed a, fixed b) +{ + return b < a; +} + +bool operator<=(fixed a, fixed b) +{ + return not (b < a); +} + +bool operator>=(fixed a, fixed b) +{ + return not (a < b); +} diff --git a/exploring-cpp-2e/chapter47/fixed.hpp b/exploring-cpp-2e/chapter47/fixed.hpp new file mode 100644 index 0000000..4244983 --- /dev/null +++ b/exploring-cpp-2e/chapter47/fixed.hpp @@ -0,0 +1,143 @@ +/** @file + * @brief Fixed-point numbers. + */ +/** @mainpage Project 2 - Fixed-Point Numbers + * This program is Project 2 in Exploring C++, + * by Ray Lischner (Apress). + * + * Your task for Project 2 is to implement a simple fixed-point + * number class. The class represents fixed-point numbers using + * an integer type. The number of places after the decimal point + * is a fixed constant, four. For example, represent the number + * 3.1415 as the integer 31415 and 3.14 as 31400. You must overload + * the arithmetic, comparison, and I/O operators to maintain the + * fixed-point fiction. + * + * Source files: + * - @link fixed.hpp fixed.hpp @endlink + * - @link fixed.cpp fixed.cpp @endlink + * - @link test.cpp test.cpp @endlink: test program + * - @link test.hpp test.hpp @endlink: test header (see Exploration 28) + * - @link ioflags.hpp ioflags.hpp @endlink: save and restore I/O stream flags (Exploration 37) + * + * @author Ray Lischner + */ + +#ifndef FIXED_HPP_ +#define FIXED_HPP_ + +#include +#include +#include + +/** @brief Implement a fixed-point number class. + * Values have @c places places after the decimal point. + * All arithmetic follows the usual rules. + */ +class fixed +{ +public: + typedef int value_type; ///< Type of the actual value + + static int const places = 4; ///< number of decimal places + static value_type const places10 = 10000; ///< 10places + + /// Default constructor initializes to zero. + fixed() : value_{0} {} + + /// Construct from separate integer and fractional parts, + /// e.g., initialize to 123.45 with fixed(123, 45). Initialize + /// to 12.07 with fixed(12, 7). + fixed(value_type integer, value_type fraction); + + /// Construct from an integer, with no fraction. + fixed(value_type integer); + + /// Construct by rounding off a floating point number. + fixed(double value) + : value_(static_cast(value * places10 + (value < 0 ? -0.5 : 0.5))) + {} + + /// Convert to a string. + /// @returns a string representation of the value, e.g., "123.04" + std::string as_string() const; + /// Read from a stream. + /// Overwrite this value with the value read from the stream. + /// @param strm the stream to read + /// @returns true for success or false for failure + bool read(std::istream& strm); + /// Convert to long double. + double as_long_double() const { return static_cast(value()) / places10; } + /// Convert to double. + double as_double() const { return static_cast(value()) / places10; } + /// Convert to float + float as_float() const { return static_cast(value()) / places10; } + /// Return just the integer part, rounded off to the nearest integer. + /// If the value lies equidistant between two integers, round even + /// numbers up and odd numbers down (banker's rounding). + value_type round() const; + + /// Return the integer part (which is the same as trunc()). + value_type integer() const { return value() / places10; } + /// Return the fractional part, e.g., 3 for 12.03 + value_type fraction() const; + + /// Addition assignment operator + fixed& operator+=(fixed f); + /// Subtraction assignment operator + fixed& operator-=(fixed f); + /// Multiplication assignment operator + fixed& operator*=(fixed f); + /// Division assignment operator + fixed& operator/=(fixed f); + + /// Negate this value. + void negate(); + + /// Pre-increment + fixed& operator++(); + /// Post-increment + fixed operator++(int); + /// Pre-decrement + fixed& operator--(); + /// Post-decrement + fixed operator--(int); + + /// Return the internal value. + value_type value() const { return value_; } +private: + /// Reduce frac to the range [0, places10) by discarding digits to the right. + value_type reduce(value_type frac); + value_type value_; +}; + +/// Read a fixed value +std::istream& operator>>(std::istream& strm, fixed& f); +/// Write a fixed value +std::ostream& operator<<(std::ostream& strm, fixed f); + +/// Add fixed values +fixed operator+(fixed a, fixed b); +/// Subtract fixed values +fixed operator-(fixed a, fixed b); +/// Multiply fixed values +fixed operator*(fixed a, fixed b); +/// Divide fixed values +fixed operator/(fixed a, fixed b); +/// Negate a fixed value +fixed operator-(fixed a); + +/// Compare fixed values for equality by comparing the underlying values. +bool operator==(fixed a, fixed b); +/// Compare fixed values for inequality by comparing the underlying values. +bool operator!=(fixed a, fixed b); +/// Compare fixed values for less-than by comparing the underlying values. +bool operator<(fixed a, fixed b); +/// Compare fixed values for greater-than by comparing the underlying values. +bool operator>(fixed a, fixed b); +/// Compare fixed values for less-than-or-equal by comparing the underlying values. +bool operator<=(fixed a, fixed b); +/// Compare fixed values for greater-than-or-equal by comparing the underlying values. +bool operator>=(fixed a, fixed b); + +#endif diff --git a/exploring-cpp-2e/chapter47/html/annotated.html b/exploring-cpp-2e/chapter47/html/annotated.html new file mode 100644 index 0000000..1ff79a6 --- /dev/null +++ b/exploring-cpp-2e/chapter47/html/annotated.html @@ -0,0 +1,62 @@ + + + + + + +Project 2 - Fixed-Point Number Class: Class List + + + + + + +
+
+
+ + + + + +
+
Project 2 - Fixed-Point Number Class +
+
+ + + + + + +
+
+
Class List
+
+
+
Here are the classes, structs, unions and interfaces with brief descriptions:
+ + + +
oCfixedImplement a fixed-point number class. Values have places places after the decimal point. All arithmetic follows the usual rules
\Cioflags
+
+
+ + + + diff --git a/exploring-cpp-2e/chapter47/html/bc_s.png b/exploring-cpp-2e/chapter47/html/bc_s.png new file mode 100644 index 0000000..224b29a Binary files /dev/null and b/exploring-cpp-2e/chapter47/html/bc_s.png differ diff --git a/exploring-cpp-2e/chapter47/html/bdwn.png b/exploring-cpp-2e/chapter47/html/bdwn.png new file mode 100644 index 0000000..940a0b9 Binary files /dev/null and b/exploring-cpp-2e/chapter47/html/bdwn.png differ diff --git a/exploring-cpp-2e/chapter47/html/classes.html b/exploring-cpp-2e/chapter47/html/classes.html new file mode 100644 index 0000000..28bde5d --- /dev/null +++ b/exploring-cpp-2e/chapter47/html/classes.html @@ -0,0 +1,66 @@ + + + + + + +Project 2 - Fixed-Point Number Class: Class Index + + + + + + +
+
+ + + + + + +
+
Project 2 - Fixed-Point Number Class +
+
+
+ + + + +
+
+
+
Class Index
+
+
+
F | I
+ + + + + +
  F  
+
  I  
+
fixed   ioflags   
+
F | I
+
+ + + + diff --git a/exploring-cpp-2e/chapter47/html/classfixed-members.html b/exploring-cpp-2e/chapter47/html/classfixed-members.html new file mode 100644 index 0000000..d4cf385 --- /dev/null +++ b/exploring-cpp-2e/chapter47/html/classfixed-members.html @@ -0,0 +1,84 @@ + + + + + + +Project 2 - Fixed-Point Number Class: Member List + + + + + + +
+
+ + + + + + +
+
Project 2 - Fixed-Point Number Class +
+
+
+ + + + +
+
+
+
fixed Member List
+
+
+ +

This is the complete list of members for fixed, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
as_double() const fixedinline
as_float() const fixedinline
as_long_double() const fixedinline
as_string() const fixed
fixed()fixedinline
fixed(value_type integer, value_type fraction)fixed
fixed(value_type integer)fixed
fixed(double value)fixedinline
fraction() const fixed
integer() const fixedinline
negate()fixed
operator*=(fixed f)fixed
operator++()fixed
operator++(int)fixed
operator+=(fixed f)fixed
operator--()fixed
operator--(int)fixed
operator-=(fixed f)fixed
operator/=(fixed f)fixed
placesfixedstatic
places10fixedstatic
read(std::istream &strm)fixed
round() const fixed
value() const fixedinline
value_type typedeffixed
+ + + + diff --git a/exploring-cpp-2e/chapter47/html/classfixed.html b/exploring-cpp-2e/chapter47/html/classfixed.html new file mode 100644 index 0000000..51e87dd --- /dev/null +++ b/exploring-cpp-2e/chapter47/html/classfixed.html @@ -0,0 +1,282 @@ + + + + + + +Project 2 - Fixed-Point Number Class: fixed Class Reference + + + + + + +
+
+ + + + + + +
+
Project 2 - Fixed-Point Number Class +
+
+
+ + + + +
+ +
+ +

Implement a fixed-point number class. Values have places places after the decimal point. All arithmetic follows the usual rules. + More...

+ +

#include <fixed.hpp>

+ + + + + +

+Public Types

+typedef int value_type
 Type of the actual value.
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

fixed ()
 Default constructor initializes to zero.
 
 fixed (value_type integer, value_type fraction)
 
fixed (value_type integer)
 Construct from an integer, with no fraction.
 
fixed (double value)
 Construct by rounding off a floating point number.
 
std::string as_string () const
 
bool read (std::istream &strm)
 
+double as_long_double () const
 Convert to long double.
 
+double as_double () const
 Convert to double.
 
+float as_float () const
 Convert to float.
 
value_type round () const
 
+value_type integer () const
 Return the integer part (which is the same as trunc()).
 
+value_type fraction () const
 Return the fractional part, e.g., 3 for 12.03.
 
+fixedoperator+= (fixed f)
 Addition assignment operator.
 
+fixedoperator-= (fixed f)
 Subtraction assignment operator.
 
+fixedoperator*= (fixed f)
 Multiplication assignment operator.
 
+fixedoperator/= (fixed f)
 Division assignment operator.
 
+void negate ()
 Negate this value.
 
+fixedoperator++ ()
 Pre-increment.
 
+fixed operator++ (int)
 Post-increment.
 
+fixedoperator-- ()
 Pre-decrement.
 
+fixed operator-- (int)
 Post-decrement.
 
+value_type value () const
 Return the internal value.
 
+ + + + + + + +

+Static Public Attributes

+static int const places = 4
 number of decimal places
 
+static value_type const places10 = 10000
 10places
 
+

Detailed Description

+

Implement a fixed-point number class. Values have places places after the decimal point. All arithmetic follows the usual rules.

+ +

Definition at line 37 of file fixed.hpp.

+

Constructor & Destructor Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + +
fixed::fixed (value_type integer,
value_type fraction 
)
+
+

Construct from separate integer and fractional parts, e.g., initialize to 123.45 with fixed(123, 45). Initialize to 12.07 with fixed(12, 7).

+ +

Definition at line 14 of file fixed.cpp.

+ +

References fraction(), and places10.

+ +
+
+

Member Function Documentation

+ +
+
+ + + + + + + +
std::string fixed::as_string () const
+
+

Convert to a string.

+
Returns
a string representation of the value, e.g., "123.04"
+ +

Definition at line 120 of file fixed.cpp.

+ +

References fraction(), integer(), and places.

+ +

Referenced by operator<<().

+ +
+
+ +
+
+ + + + + + + + +
bool fixed::read (std::istream & strm)
+
+

Read from a stream. Overwrite this value with the value read from the stream.

+
Parameters
+ + +
strmthe stream to read
+
+
+
Returns
true for success or false for failure
+ +

Definition at line 190 of file fixed.cpp.

+ +

References fraction(), integer(), places, and places10.

+ +

Referenced by operator>>().

+ +
+
+ +
+
+ + + + + + + +
fixed::value_type fixed::round () const
+
+

Return just the integer part, rounded off to the nearest integer. If the value lies equidistant between two integers, round even numbers up and odd numbers down (banker's rounding).

+ +

Definition at line 104 of file fixed.cpp.

+ +

References fraction(), integer(), places10, and value().

+ +
+
+
The documentation for this class was generated from the following files: +
+ + + + diff --git a/exploring-cpp-2e/chapter47/html/classioflags-members.html b/exploring-cpp-2e/chapter47/html/classioflags-members.html new file mode 100644 index 0000000..7d15ec4 --- /dev/null +++ b/exploring-cpp-2e/chapter47/html/classioflags-members.html @@ -0,0 +1,63 @@ + + + + + + +Project 2 - Fixed-Point Number Class: Member List + + + + + + +
+
+ + + + + + +
+
Project 2 - Fixed-Point Number Class +
+
+
+ + + + +
+
+
+
ioflags Member List
+
+
+ +

This is the complete list of members for ioflags, including all inherited members.

+ + + + + +
ioflags(std::basic_ios< char > &stream)ioflagsinline
ioflags(ioflags const &)=delete (defined in ioflags)ioflags
operator=(ioflags const &)=delete (defined in ioflags)ioflags
~ioflags()ioflagsinline
+ + + + diff --git a/exploring-cpp-2e/chapter47/html/classioflags.html b/exploring-cpp-2e/chapter47/html/classioflags.html new file mode 100644 index 0000000..5926014 --- /dev/null +++ b/exploring-cpp-2e/chapter47/html/classioflags.html @@ -0,0 +1,118 @@ + + + + + + +Project 2 - Fixed-Point Number Class: ioflags Class Reference + + + + + + +
+
+ + + + + + +
+
Project 2 - Fixed-Point Number Class +
+
+
+ + + + +
+
+ +
+
ioflags Class Reference
+
+
+ +

#include <ioflags.hpp>

+ + + + + + + + + + + +

+Public Member Functions

 ioflags (std::basic_ios< char > &stream)
 
~ioflags ()
 Restore the formatting flags.
 
ioflags (ioflags const &)=delete
 
+ioflagsoperator= (ioflags const &)=delete
 
+

Detailed Description

+

Save and restore I/O stream flags. When a function needs to temporarily alter an I/O stream flags, simply define an object of type ioflags. Set whatever flags you want. When the block exits or function returns, the original flags are restored.

+ +

Definition at line 15 of file ioflags.hpp.

+

Constructor & Destructor Documentation

+ +
+
+ + + + + +
+ + + + + + + + +
ioflags::ioflags (std::basic_ios< char > & stream)
+
+inline
+
+

Save the formatting flags from stream.

+
Parameters
+ + +
streamThe stream that will have its flags modified and restored.
+
+
+ +

Definition at line 20 of file ioflags.hpp.

+ +
+
+
The documentation for this class was generated from the following file: +
+ + + + diff --git a/exploring-cpp-2e/chapter47/html/closed.png b/exploring-cpp-2e/chapter47/html/closed.png new file mode 100644 index 0000000..98cc2c9 Binary files /dev/null and b/exploring-cpp-2e/chapter47/html/closed.png differ diff --git a/exploring-cpp-2e/chapter47/html/doxygen.css b/exploring-cpp-2e/chapter47/html/doxygen.css new file mode 100644 index 0000000..4699e69 --- /dev/null +++ b/exploring-cpp-2e/chapter47/html/doxygen.css @@ -0,0 +1,1357 @@ +/* The standard CSS for doxygen 1.8.5 */ + +body, table, div, p, dl { + font: 400 14px/22px Roboto,sans-serif; +} + +/* @group Heading Levels */ + +h1.groupheader { + font-size: 150%; +} + +.title { + font: 400 14px/28px Roboto,sans-serif; + font-size: 150%; + font-weight: bold; + margin: 10px 2px; +} + +h2.groupheader { + border-bottom: 1px solid #879ECB; + color: #354C7B; + font-size: 150%; + font-weight: normal; + margin-top: 1.75em; + padding-top: 8px; + padding-bottom: 4px; + width: 100%; +} + +h3.groupheader { + font-size: 100%; +} + +h1, h2, h3, h4, h5, h6 { + -webkit-transition: text-shadow 0.5s linear; + -moz-transition: text-shadow 0.5s linear; + -ms-transition: text-shadow 0.5s linear; + -o-transition: text-shadow 0.5s linear; + transition: text-shadow 0.5s linear; + margin-right: 15px; +} + +h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { + text-shadow: 0 0 15px cyan; +} + +dt { + font-weight: bold; +} + +div.multicol { + -moz-column-gap: 1em; + -webkit-column-gap: 1em; + -moz-column-count: 3; + -webkit-column-count: 3; +} + +p.startli, p.startdd, p.starttd { + margin-top: 2px; +} + +p.endli { + margin-bottom: 0px; +} + +p.enddd { + margin-bottom: 4px; +} + +p.endtd { + margin-bottom: 2px; +} + +/* @end */ + +caption { + font-weight: bold; +} + +span.legend { + font-size: 70%; + text-align: center; +} + +h3.version { + font-size: 90%; + text-align: center; +} + +div.qindex, div.navtab{ + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; +} + +div.qindex, div.navpath { + width: 100%; + line-height: 140%; +} + +div.navtab { + margin-right: 15px; +} + +/* @group Link Styling */ + +a { + color: #3D578C; + font-weight: normal; + text-decoration: none; +} + +.contents a:visited { + color: #4665A2; +} + +a:hover { + text-decoration: underline; +} + +a.qindex { + font-weight: bold; +} + +a.qindexHL { + font-weight: bold; + background-color: #9CAFD4; + color: #ffffff; + border: 1px double #869DCA; +} + +.contents a.qindexHL:visited { + color: #ffffff; +} + +a.el { + font-weight: bold; +} + +a.elRef { +} + +a.code, a.code:visited, a.line, a.line:visited { + color: #4665A2; +} + +a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited { + color: #4665A2; +} + +/* @end */ + +dl.el { + margin-left: -1cm; +} + +pre.fragment { + border: 1px solid #C4CFE5; + background-color: #FBFCFD; + padding: 4px 6px; + margin: 4px 8px 4px 2px; + overflow: auto; + word-wrap: break-word; + font-size: 9pt; + line-height: 125%; + font-family: monospace, fixed; + font-size: 105%; +} + +div.fragment { + padding: 0px; + margin: 0px; + background-color: #FBFCFD; + border: 1px solid #C4CFE5; +} + +div.line { + font-family: monospace, fixed; + font-size: 13px; + min-height: 13px; + line-height: 1.0; + text-wrap: unrestricted; + white-space: -moz-pre-wrap; /* Moz */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + white-space: pre-wrap; /* CSS3 */ + word-wrap: break-word; /* IE 5.5+ */ + text-indent: -53px; + padding-left: 53px; + padding-bottom: 0px; + margin: 0px; + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +div.line.glow { + background-color: cyan; + box-shadow: 0 0 10px cyan; +} + + +span.lineno { + padding-right: 4px; + text-align: right; + border-right: 2px solid #0F0; + background-color: #E8E8E8; + white-space: pre; +} +span.lineno a { + background-color: #D8D8D8; +} + +span.lineno a:hover { + background-color: #C8C8C8; +} + +div.ah { + background-color: black; + font-weight: bold; + color: #ffffff; + margin-bottom: 3px; + margin-top: 3px; + padding: 0.2em; + border: solid thin #333; + border-radius: 0.5em; + -webkit-border-radius: .5em; + -moz-border-radius: .5em; + box-shadow: 2px 2px 3px #999; + -webkit-box-shadow: 2px 2px 3px #999; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); + background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000); +} + +div.groupHeader { + margin-left: 16px; + margin-top: 12px; + font-weight: bold; +} + +div.groupText { + margin-left: 16px; + font-style: italic; +} + +body { + background-color: white; + color: black; + margin: 0; +} + +div.contents { + margin-top: 10px; + margin-left: 12px; + margin-right: 8px; +} + +td.indexkey { + background-color: #EBEFF6; + font-weight: bold; + border: 1px solid #C4CFE5; + margin: 2px 0px 2px 0; + padding: 2px 10px; + white-space: nowrap; + vertical-align: top; +} + +td.indexvalue { + background-color: #EBEFF6; + border: 1px solid #C4CFE5; + padding: 2px 10px; + margin: 2px 0px; +} + +tr.memlist { + background-color: #EEF1F7; +} + +p.formulaDsp { + text-align: center; +} + +img.formulaDsp { + +} + +img.formulaInl { + vertical-align: middle; +} + +div.center { + text-align: center; + margin-top: 0px; + margin-bottom: 0px; + padding: 0px; +} + +div.center img { + border: 0px; +} + +address.footer { + text-align: right; + padding-right: 12px; +} + +img.footer { + border: 0px; + vertical-align: middle; +} + +/* @group Code Colorization */ + +span.keyword { + color: #008000 +} + +span.keywordtype { + color: #604020 +} + +span.keywordflow { + color: #e08000 +} + +span.comment { + color: #800000 +} + +span.preprocessor { + color: #806020 +} + +span.stringliteral { + color: #002080 +} + +span.charliteral { + color: #008080 +} + +span.vhdldigit { + color: #ff00ff +} + +span.vhdlchar { + color: #000000 +} + +span.vhdlkeyword { + color: #700070 +} + +span.vhdllogic { + color: #ff0000 +} + +blockquote { + background-color: #F7F8FB; + border-left: 2px solid #9CAFD4; + margin: 0 24px 0 4px; + padding: 0 12px 0 16px; +} + +/* @end */ + +/* +.search { + color: #003399; + font-weight: bold; +} + +form.search { + margin-bottom: 0px; + margin-top: 0px; +} + +input.search { + font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #e8eef2; +} +*/ + +td.tiny { + font-size: 75%; +} + +.dirtab { + padding: 4px; + border-collapse: collapse; + border: 1px solid #A3B4D7; +} + +th.dirtab { + background: #EBEFF6; + font-weight: bold; +} + +hr { + height: 0px; + border: none; + border-top: 1px solid #4A6AAA; +} + +hr.footer { + height: 1px; +} + +/* @group Member Descriptions */ + +table.memberdecls { + border-spacing: 0px; + padding: 0px; +} + +.memberdecls td, .fieldtable tr { + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +.memberdecls td.glow, .fieldtable tr.glow { + background-color: cyan; + box-shadow: 0 0 15px cyan; +} + +.mdescLeft, .mdescRight, +.memItemLeft, .memItemRight, +.memTemplItemLeft, .memTemplItemRight, .memTemplParams { + background-color: #F9FAFC; + border: none; + margin: 4px; + padding: 1px 0 0 8px; +} + +.mdescLeft, .mdescRight { + padding: 0px 8px 4px 8px; + color: #555; +} + +.memSeparator { + border-bottom: 1px solid #DEE4F0; + line-height: 1px; + margin: 0px; + padding: 0px; +} + +.memItemLeft, .memTemplItemLeft { + white-space: nowrap; +} + +.memItemRight { + width: 100%; +} + +.memTemplParams { + color: #4665A2; + white-space: nowrap; + font-size: 80%; +} + +/* @end */ + +/* @group Member Details */ + +/* Styles for detailed member documentation */ + +.memtemplate { + font-size: 80%; + color: #4665A2; + font-weight: normal; + margin-left: 9px; +} + +.memnav { + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} + +.mempage { + width: 100%; +} + +.memitem { + padding: 0; + margin-bottom: 10px; + margin-right: 5px; + -webkit-transition: box-shadow 0.5s linear; + -moz-transition: box-shadow 0.5s linear; + -ms-transition: box-shadow 0.5s linear; + -o-transition: box-shadow 0.5s linear; + transition: box-shadow 0.5s linear; + display: table !important; + width: 100%; +} + +.memitem.glow { + box-shadow: 0 0 15px cyan; +} + +.memname { + font-weight: bold; + margin-left: 6px; +} + +.memname td { + vertical-align: bottom; +} + +.memproto, dl.reflist dt { + border-top: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 0px 6px 0px; + color: #253555; + font-weight: bold; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + /* opera specific markup */ + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + border-top-right-radius: 4px; + border-top-left-radius: 4px; + /* firefox specific markup */ + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + -moz-border-radius-topright: 4px; + -moz-border-radius-topleft: 4px; + /* webkit specific markup */ + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + -webkit-border-top-right-radius: 4px; + -webkit-border-top-left-radius: 4px; + +} + +.memdoc, dl.reflist dd { + border-bottom: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 10px 2px 10px; + background-color: #FBFCFD; + border-top-width: 0; + background-image:url('nav_g.png'); + background-repeat:repeat-x; + background-color: #FFFFFF; + /* opera specific markup */ + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + /* firefox specific markup */ + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-bottomright: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + /* webkit specific markup */ + -webkit-border-bottom-left-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); +} + +dl.reflist dt { + padding: 5px; +} + +dl.reflist dd { + margin: 0px 0px 10px 0px; + padding: 5px; +} + +.paramkey { + text-align: right; +} + +.paramtype { + white-space: nowrap; +} + +.paramname { + color: #602020; + white-space: nowrap; +} +.paramname em { + font-style: normal; +} +.paramname code { + line-height: 14px; +} + +.params, .retval, .exception, .tparams { + margin-left: 0px; + padding-left: 0px; +} + +.params .paramname, .retval .paramname { + font-weight: bold; + vertical-align: top; +} + +.params .paramtype { + font-style: italic; + vertical-align: top; +} + +.params .paramdir { + font-family: "courier new",courier,monospace; + vertical-align: top; +} + +table.mlabels { + border-spacing: 0px; +} + +td.mlabels-left { + width: 100%; + padding: 0px; +} + +td.mlabels-right { + vertical-align: bottom; + padding: 0px; + white-space: nowrap; +} + +span.mlabels { + margin-left: 8px; +} + +span.mlabel { + background-color: #728DC1; + border-top:1px solid #5373B4; + border-left:1px solid #5373B4; + border-right:1px solid #C4CFE5; + border-bottom:1px solid #C4CFE5; + text-shadow: none; + color: white; + margin-right: 4px; + padding: 2px 3px; + border-radius: 3px; + font-size: 7pt; + white-space: nowrap; + vertical-align: middle; +} + + + +/* @end */ + +/* these are for tree view when not used as main index */ + +div.directory { + margin: 10px 0px; + border-top: 1px solid #A8B8D9; + border-bottom: 1px solid #A8B8D9; + width: 100%; +} + +.directory table { + border-collapse:collapse; +} + +.directory td { + margin: 0px; + padding: 0px; + vertical-align: top; +} + +.directory td.entry { + white-space: nowrap; + padding-right: 6px; + padding-top: 3px; +} + +.directory td.entry a { + outline:none; +} + +.directory td.entry a img { + border: none; +} + +.directory td.desc { + width: 100%; + padding-left: 6px; + padding-right: 6px; + padding-top: 3px; + border-left: 1px solid rgba(0,0,0,0.05); +} + +.directory tr.even { + padding-left: 6px; + background-color: #F7F8FB; +} + +.directory img { + vertical-align: -30%; +} + +.directory .levels { + white-space: nowrap; + width: 100%; + text-align: right; + font-size: 9pt; +} + +.directory .levels span { + cursor: pointer; + padding-left: 2px; + padding-right: 2px; + color: #3D578C; +} + +div.dynheader { + margin-top: 8px; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +address { + font-style: normal; + color: #2A3D61; +} + +table.doxtable { + border-collapse:collapse; + margin-top: 4px; + margin-bottom: 4px; +} + +table.doxtable td, table.doxtable th { + border: 1px solid #2D4068; + padding: 3px 7px 2px; +} + +table.doxtable th { + background-color: #374F7F; + color: #FFFFFF; + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; +} + +table.fieldtable { + /*width: 100%;*/ + margin-bottom: 10px; + border: 1px solid #A8B8D9; + border-spacing: 0px; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + border-radius: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); +} + +.fieldtable td, .fieldtable th { + padding: 3px 7px 2px; +} + +.fieldtable td.fieldtype, .fieldtable td.fieldname { + white-space: nowrap; + border-right: 1px solid #A8B8D9; + border-bottom: 1px solid #A8B8D9; + vertical-align: top; +} + +.fieldtable td.fieldname { + padding-top: 3px; +} + +.fieldtable td.fielddoc { + border-bottom: 1px solid #A8B8D9; + /*width: 100%;*/ +} + +.fieldtable td.fielddoc p:first-child { + margin-top: 0px; +} + +.fieldtable td.fielddoc p:last-child { + margin-bottom: 2px; +} + +.fieldtable tr:last-child td { + border-bottom: none; +} + +.fieldtable th { + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + font-size: 90%; + color: #253555; + padding-bottom: 4px; + padding-top: 5px; + text-align:left; + -moz-border-radius-topleft: 4px; + -moz-border-radius-topright: 4px; + -webkit-border-top-left-radius: 4px; + -webkit-border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom: 1px solid #A8B8D9; +} + + +.tabsearch { + top: 0px; + left: 10px; + height: 36px; + background-image: url('tab_b.png'); + z-index: 101; + overflow: hidden; + font-size: 13px; +} + +.navpath ul +{ + font-size: 11px; + background-image:url('tab_b.png'); + background-repeat:repeat-x; + background-position: 0 -5px; + height:30px; + line-height:30px; + color:#8AA0CC; + border:solid 1px #C2CDE4; + overflow:hidden; + margin:0px; + padding:0px; +} + +.navpath li +{ + list-style-type:none; + float:left; + padding-left:10px; + padding-right:15px; + background-image:url('bc_s.png'); + background-repeat:no-repeat; + background-position:right; + color:#364D7C; +} + +.navpath li.navelem a +{ + height:32px; + display:block; + text-decoration: none; + outline: none; + color: #283A5D; + font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + text-decoration: none; +} + +.navpath li.navelem a:hover +{ + color:#6884BD; +} + +.navpath li.footer +{ + list-style-type:none; + float:right; + padding-left:10px; + padding-right:15px; + background-image:none; + background-repeat:no-repeat; + background-position:right; + color:#364D7C; + font-size: 8pt; +} + + +div.summary +{ + float: right; + font-size: 8pt; + padding-right: 5px; + width: 50%; + text-align: right; +} + +div.summary a +{ + white-space: nowrap; +} + +div.ingroups +{ + font-size: 8pt; + width: 50%; + text-align: left; +} + +div.ingroups a +{ + white-space: nowrap; +} + +div.header +{ + background-image:url('nav_h.png'); + background-repeat:repeat-x; + background-color: #F9FAFC; + margin: 0px; + border-bottom: 1px solid #C4CFE5; +} + +div.headertitle +{ + padding: 5px 5px 5px 10px; +} + +dl +{ + padding: 0 0 0 10px; +} + +/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */ +dl.section +{ + margin-left: 0px; + padding-left: 0px; +} + +dl.note +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #D0C000; +} + +dl.warning, dl.attention +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #FF0000; +} + +dl.pre, dl.post, dl.invariant +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #00D000; +} + +dl.deprecated +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #505050; +} + +dl.todo +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #00C0E0; +} + +dl.test +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #3030E0; +} + +dl.bug +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #C08050; +} + +dl.section dd { + margin-bottom: 6px; +} + + +#projectlogo +{ + text-align: center; + vertical-align: bottom; + border-collapse: separate; +} + +#projectlogo img +{ + border: 0px none; +} + +#projectname +{ + font: 300% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 2px 0px; +} + +#projectbrief +{ + font: 120% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#projectnumber +{ + font: 50% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#titlearea +{ + padding: 0px; + margin: 0px; + width: 100%; + border-bottom: 1px solid #5373B4; +} + +.image +{ + text-align: center; +} + +.dotgraph +{ + text-align: center; +} + +.mscgraph +{ + text-align: center; +} + +.caption +{ + font-weight: bold; +} + +div.zoom +{ + border: 1px solid #90A5CE; +} + +dl.citelist { + margin-bottom:50px; +} + +dl.citelist dt { + color:#334975; + float:left; + font-weight:bold; + margin-right:10px; + padding:5px; +} + +dl.citelist dd { + margin:2px 0; + padding:5px 0; +} + +div.toc { + padding: 14px 25px; + background-color: #F4F6FA; + border: 1px solid #D8DFEE; + border-radius: 7px 7px 7px 7px; + float: right; + height: auto; + margin: 0 20px 10px 10px; + width: 200px; +} + +div.toc li { + background: url("bdwn.png") no-repeat scroll 0 5px transparent; + font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif; + margin-top: 5px; + padding-left: 10px; + padding-top: 2px; +} + +div.toc h3 { + font: bold 12px/1.2 Arial,FreeSans,sans-serif; + color: #4665A2; + border-bottom: 0 none; + margin: 0; +} + +div.toc ul { + list-style: none outside none; + border: medium none; + padding: 0px; +} + +div.toc li.level1 { + margin-left: 0px; +} + +div.toc li.level2 { + margin-left: 15px; +} + +div.toc li.level3 { + margin-left: 30px; +} + +div.toc li.level4 { + margin-left: 45px; +} + +.inherit_header { + font-weight: bold; + color: gray; + cursor: pointer; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.inherit_header td { + padding: 6px 0px 2px 5px; +} + +.inherit { + display: none; +} + +tr.heading h2 { + margin-top: 12px; + margin-bottom: 4px; +} + +/* tooltip related style info */ + +.ttc { + position: absolute; + display: none; +} + +#powerTip { + cursor: default; + white-space: nowrap; + background-color: white; + border: 1px solid gray; + border-radius: 4px 4px 4px 4px; + box-shadow: 1px 1px 7px gray; + display: none; + font-size: smaller; + max-width: 80%; + opacity: 0.9; + padding: 1ex 1em 1em; + position: absolute; + z-index: 2147483647; +} + +#powerTip div.ttdoc { + color: grey; + font-style: italic; +} + +#powerTip div.ttname a { + font-weight: bold; +} + +#powerTip div.ttname { + font-weight: bold; +} + +#powerTip div.ttdeci { + color: #006318; +} + +#powerTip div { + margin: 0px; + padding: 0px; + font: 12px/16px Roboto,sans-serif; +} + +#powerTip:before, #powerTip:after { + content: ""; + position: absolute; + margin: 0px; +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.s:after, #powerTip.s:before, +#powerTip.w:after, #powerTip.w:before, +#powerTip.e:after, #powerTip.e:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.nw:after, #powerTip.nw:before, +#powerTip.sw:after, #powerTip.sw:before { + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; +} + +#powerTip.n:after, #powerTip.s:after, +#powerTip.w:after, #powerTip.e:after, +#powerTip.nw:after, #powerTip.ne:after, +#powerTip.sw:after, #powerTip.se:after { + border-color: rgba(255, 255, 255, 0); +} + +#powerTip.n:before, #powerTip.s:before, +#powerTip.w:before, #powerTip.e:before, +#powerTip.nw:before, #powerTip.ne:before, +#powerTip.sw:before, #powerTip.se:before { + border-color: rgba(128, 128, 128, 0); +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.nw:after, #powerTip.nw:before { + top: 100%; +} + +#powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after { + border-top-color: #ffffff; + border-width: 10px; + margin: 0px -10px; +} +#powerTip.n:before { + border-top-color: #808080; + border-width: 11px; + margin: 0px -11px; +} +#powerTip.n:after, #powerTip.n:before { + left: 50%; +} + +#powerTip.nw:after, #powerTip.nw:before { + right: 14px; +} + +#powerTip.ne:after, #powerTip.ne:before { + left: 14px; +} + +#powerTip.s:after, #powerTip.s:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.sw:after, #powerTip.sw:before { + bottom: 100%; +} + +#powerTip.s:after, #powerTip.se:after, #powerTip.sw:after { + border-bottom-color: #ffffff; + border-width: 10px; + margin: 0px -10px; +} + +#powerTip.s:before, #powerTip.se:before, #powerTip.sw:before { + border-bottom-color: #808080; + border-width: 11px; + margin: 0px -11px; +} + +#powerTip.s:after, #powerTip.s:before { + left: 50%; +} + +#powerTip.sw:after, #powerTip.sw:before { + right: 14px; +} + +#powerTip.se:after, #powerTip.se:before { + left: 14px; +} + +#powerTip.e:after, #powerTip.e:before { + left: 100%; +} +#powerTip.e:after { + border-left-color: #ffffff; + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.e:before { + border-left-color: #808080; + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +#powerTip.w:after, #powerTip.w:before { + right: 100%; +} +#powerTip.w:after { + border-right-color: #ffffff; + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.w:before { + border-right-color: #808080; + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +@media print +{ + #top { display: none; } + #side-nav { display: none; } + #nav-path { display: none; } + body { overflow:visible; } + h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } + .summary { display: none; } + .memitem { page-break-inside: avoid; } + #doc-content + { + margin-left:0 !important; + height:auto !important; + width:auto !important; + overflow:inherit; + display:inline; + } +} + diff --git a/exploring-cpp-2e/chapter47/html/doxygen.png b/exploring-cpp-2e/chapter47/html/doxygen.png new file mode 100644 index 0000000..3ff17d8 Binary files /dev/null and b/exploring-cpp-2e/chapter47/html/doxygen.png differ diff --git a/exploring-cpp-2e/chapter47/html/dynsections.js b/exploring-cpp-2e/chapter47/html/dynsections.js new file mode 100644 index 0000000..2f15470 --- /dev/null +++ b/exploring-cpp-2e/chapter47/html/dynsections.js @@ -0,0 +1,104 @@ +function toggleVisibility(linkObj) +{ + var base = $(linkObj).attr('id'); + var summary = $('#'+base+'-summary'); + var content = $('#'+base+'-content'); + var trigger = $('#'+base+'-trigger'); + var src=$(trigger).attr('src'); + if (content.is(':visible')===true) { + content.hide(); + summary.show(); + $(linkObj).addClass('closed').removeClass('opened'); + $(trigger).attr('src',src.substring(0,src.length-8)+'closed.png'); + } else { + content.show(); + summary.hide(); + $(linkObj).removeClass('closed').addClass('opened'); + $(trigger).attr('src',src.substring(0,src.length-10)+'open.png'); + } + return false; +} + +function updateStripes() +{ + $('table.directory tr'). + removeClass('even').filter(':visible:even').addClass('even'); +} +function toggleLevel(level) +{ + $('table.directory tr').each(function(){ + var l = this.id.split('_').length-1; + var i = $('#img'+this.id.substring(3)); + var a = $('#arr'+this.id.substring(3)); + if (l + + + + + +Project 2 - Fixed-Point Number Class: File List + + + + + + +
+
+ + + + + + +
+
Project 2 - Fixed-Point Number Class +
+
+
+ + + + +
+
+
+
File List
+
+
+
Here is a list of all documented files with brief descriptions:
+ + + + + + + +
o*fixed.cpp
o*fixed.hppFixed-point numbers
o*ioflags.hppSave and restore I/O stream flags
o*list4701.cpp
o*test.cpp
\*test.hpp
+
+
+ + + + diff --git a/exploring-cpp-2e/chapter47/html/fixed_8cpp_source.html b/exploring-cpp-2e/chapter47/html/fixed_8cpp_source.html new file mode 100644 index 0000000..4aa0760 --- /dev/null +++ b/exploring-cpp-2e/chapter47/html/fixed_8cpp_source.html @@ -0,0 +1,388 @@ + + + + + + +Project 2 - Fixed-Point Number Class: fixed.cpp Source File + + + + + + +
+
+ + + + + + +
+
Project 2 - Fixed-Point Number Class +
+
+
+ + + + +
+
+
+
fixed.cpp
+
+
+
1 #include <cassert>
+
2 #include <cstdlib>
+
3 #include <iomanip>
+
4 #include <iostream>
+
5 #include <locale>
+
6 #include <sstream>
+
7 #include <stdexcept>
+
8 #include <string>
+
9 
+
10 #include "fixed.hpp"
+
11 #include "ioflags.hpp"
+
12 
+
13 // Construct a fixed value from an integer part and a fraction part
+ +
15 {
+
16  if (fraction < 0)
+
17  throw std::invalid_argument("negative fraction not allowed");
+
18  fraction = reduce(fraction);
+
19  if (integer < 0)
+
20  value_ = integer * places10 - fraction;
+
21  else
+
22  value_ = integer * places10 + fraction;
+
23 }
+
24 
+
25 // Construct a fixed value from an integer part with no fraction
+ +
27 : value_{integer * places10}
+
28 {}
+
29 
+
30 // Get the fraction part
+ +
32 const
+
33 {
+
34  return std::abs(value()) % places10;
+
35 }
+
36 
+
46 fixed::value_type fixed::reduce(value_type frac)
+
47 {
+
48  // First scan for zero digits on the right.
+
49  value_type f{frac};
+
50  while (f >= places10*10 and f % 10 == 0)
+
51  {
+
52  f /= 10;
+
53  }
+
54 
+
55  if (f >= places10*10)
+
56  {
+
57  int x{0};
+
58  // Loop ended because a non-zero digit was seen so Y* > 0.
+
59  // Discard the remaining digits, but keep track of the last
+
60  // digit to be processed (X).
+
61  while (f >= places10)
+
62  {
+
63  x = f % 10;
+
64  f /= 10;
+
65  }
+
66  // Round up if the last digit (X) is 5 or more
+
67  if (x >= 5)
+
68  ++f;
+
69  return f;
+
70  }
+
71  // Else all digits so far are zero. Check how many digits there were,
+
72  // that is, check whether G, and X at least are present.
+
73  else if (f >= places10)
+
74  {
+
75  // Yes, G and X are present. If X == 5, implement banker's rounding.
+
76  // Otherwise, round to nearest.
+
77  int x{f % 10};
+
78  f /= 10;
+
79  assert(f < places10);
+
80  if (x == 5)
+
81  {
+
82  // Yes, so implement banker's rounding.
+
83  if (f % 2 != 0)
+
84  ++f;
+
85  return f;
+
86  }
+
87  else if (x < 5)
+
88  {
+
89  // Round down.
+
90  return f;
+
91  }
+
92  else
+
93  {
+
94  // Round up.
+
95  return f + 1;
+
96  }
+
97  }
+
98  // Not enough digits, so nothing to round.
+
99  assert(frac < places10);
+
100  return frac;
+
101 }
+
102 
+
103 // Round off to nearest integer.
+ +
105 const
+
106 {
+
107  const value_type frac{fraction()};
+
108  int adjust{value() < 0 ? -1 : +1};
+
109  if (frac > places10/2)
+
110  return integer()+adjust;
+
111  else if (frac < places10/2)
+
112  return integer();
+
113  else if (integer() % 2 == 0)
+
114  return integer();
+
115  else
+
116  return integer()+adjust;
+
117 }
+
118 
+
119 // Convert to a string using fixed-point notation.
+
120 std::string fixed::as_string()
+
121 const
+
122 {
+
123  std::ostringstream out{};
+
124  out << integer() << '.'
+
125  << std::setfill('0') << std::setw(places) << fraction();
+
126  return out.str();
+
127 }
+
128 
+ +
130 {
+
131  value_ += f.value();
+
132  return *this;
+
133 }
+
134 
+ +
136 {
+
137  value_ -= f.value();
+
138  return *this;
+
139 }
+
140 
+ +
142 {
+
143  value_ = (value_ * f.value()) / places10;
+
144  return *this;
+
145 }
+
146 
+ +
148 {
+
149  value_ = (value_ * places10) / f.value();
+
150  return *this;
+
151 }
+
152 
+ +
154 {
+
155  value_ = -value_;
+
156 }
+
157 
+ +
159 {
+
160  value_ += places10;
+
161  return *this;
+
162 }
+
163 
+ +
165 {
+
166  fixed result{*this};
+
167  ++*this;
+
168  return result;
+
169 }
+
170 
+ +
172 {
+
173  value_ -= places10;
+
174  return *this;
+
175 }
+
176 
+ +
178 {
+
179  fixed result{*this};
+
180  --*this;
+
181  return result;
+
182 }
+
183 
+ +
185 {
+
186  a.negate();
+
187  return a;
+
188 }
+
189 
+
190 bool fixed::read(std::istream& strm)
+
191 {
+
192  ioflags flags(strm);
+
193 
+ +
195  char decimal{};
+
196  if (not (strm >> integer))
+
197  return false;
+
198  strm.unsetf(std::ios_base::skipws);
+
199  if (not (strm >> decimal) or decimal != '.')
+
200  {
+
201  // Just an integer is fine. Push back the non-decimal character,
+
202  // if there is one, and reset the stream flags to show that
+
203  // reading the fixed value succeeded.
+
204  strm.unget();
+
205  strm.clear(strm.rdstate() & ~strm.failbit);
+
206  value_ = integer * places10;
+
207  return true;
+
208  }
+
209  else
+
210  {
+
211  value_type fraction{0};
+
212  char c{};
+
213  int p{0};
+
214  // Read one extra place for round-off.
+
215  for (;
+
216  p != places+1 and strm >> c and std::isdigit(c, strm.getloc());
+
217  ++p)
+
218  {
+
219  fraction = fraction * 10 + (c - '0');
+
220  }
+
221  // Pad out to the requisite number of decimal places.
+
222  for (; p < places; ++p)
+
223  fraction = fraction * 10;
+
224  // If the loop terminated because the maximum number of decimal
+
225  // places were read, keep reading the stream to discard excees digits.
+
226  while (strm and std::isdigit(c, strm.getloc()))
+
227  strm >> c;
+
228  // Push back the last, non-digit character read from the stream.
+
229  // If the stream reached EOF, unget() is harmless.
+
230  strm.unget();
+
231  // Clear failbit because even if reading a character or whatever
+
232  // failed, reading the fixed value did not.
+
233  strm.clear(strm.rdstate() & ~strm.failbit);
+
234  fraction = reduce(fraction);
+
235  if (integer < 0)
+
236  value_ = integer * places10 - fraction;
+
237  else
+
238  value_ = integer * places10 + fraction;
+
239  }
+
240  return true;
+
241 }
+
242 
+
243 std::istream& operator>>(std::istream& strm, fixed& f)
+
244 {
+
245  if (not f.read(strm))
+
246  strm.setstate(strm.failbit);
+
247  return strm;
+
248 }
+
249 
+
250 std::ostream& operator<<(std::ostream& strm, fixed f)
+
251 {
+
252  strm << f.as_string();
+
253  return strm;
+
254 }
+
255 
+ +
257 {
+
258  a += b;
+
259  return a;
+
260 }
+
261 
+ +
263 {
+
264  a -= b;
+
265  return a;
+
266 }
+
267 
+ +
269 {
+
270  a *= b;
+
271  return a;
+
272 }
+
273 
+ +
275 {
+
276  a /= b;
+
277  return a;
+
278 }
+
279 
+ +
281 {
+
282  return a.value() == b.value();
+
283 }
+
284 
+ +
286 {
+
287  return not (a == b);
+
288 }
+
289 
+ +
291 {
+
292  return a.value() < b.value();
+
293 }
+
294 
+ +
296 {
+
297  return b < a;
+
298 }
+
299 
+ +
301 {
+
302  return not (b < a);
+
303 }
+
304 
+ +
306 {
+
307  return not (a < b);
+
308 }
+
fixed & operator*=(fixed f)
Multiplication assignment operator.
Definition: fixed.cpp:141
+
Implement a fixed-point number class. Values have places places after the decimal point...
Definition: fixed.hpp:37
+
fixed operator*(fixed a, fixed b)
Multiply fixed values.
Definition: fixed.cpp:268
+
std::string as_string() const
Definition: fixed.cpp:120
+
bool operator>=(fixed a, fixed b)
Compare fixed values for greater-than-or-equal by comparing the underlying values.
Definition: fixed.cpp:305
+
bool operator<=(fixed a, fixed b)
Compare fixed values for less-than-or-equal by comparing the underlying values.
Definition: fixed.cpp:300
+
bool operator<(fixed a, fixed b)
Compare fixed values for less-than by comparing the underlying values.
Definition: fixed.cpp:290
+
value_type value() const
Return the internal value.
Definition: fixed.hpp:107
+
value_type integer() const
Return the integer part (which is the same as trunc()).
Definition: fixed.hpp:81
+
Save and restore I/O stream flags.
+
std::ostream & operator<<(std::ostream &strm, fixed f)
Write a fixed value.
Definition: fixed.cpp:250
+
value_type fraction() const
Return the fractional part, e.g., 3 for 12.03.
Definition: fixed.cpp:31
+
bool operator!=(fixed a, fixed b)
Compare fixed values for inequality by comparing the underlying values.
Definition: fixed.cpp:285
+
static int const places
number of decimal places
Definition: fixed.hpp:42
+
bool operator>(fixed a, fixed b)
Compare fixed values for greater-than by comparing the underlying values.
Definition: fixed.cpp:295
+
fixed & operator++()
Pre-increment.
Definition: fixed.cpp:158
+
fixed & operator+=(fixed f)
Addition assignment operator.
Definition: fixed.cpp:129
+
fixed & operator/=(fixed f)
Division assignment operator.
Definition: fixed.cpp:147
+
fixed & operator--()
Pre-decrement.
Definition: fixed.cpp:171
+
fixed operator/(fixed a, fixed b)
Divide fixed values.
Definition: fixed.cpp:274
+
Fixed-point numbers.
+ +
void negate()
Negate this value.
Definition: fixed.cpp:153
+
fixed & operator-=(fixed f)
Subtraction assignment operator.
Definition: fixed.cpp:135
+
std::istream & operator>>(std::istream &strm, fixed &f)
Read a fixed value.
Definition: fixed.cpp:243
+
bool operator==(fixed a, fixed b)
Compare fixed values for equality by comparing the underlying values.
Definition: fixed.cpp:280
+
static value_type const places10
10places
Definition: fixed.hpp:43
+
fixed operator-(fixed a, fixed b)
Subtract fixed values.
Definition: fixed.cpp:262
+
int value_type
Type of the actual value.
Definition: fixed.hpp:40
+
fixed operator+(fixed a, fixed b)
Add fixed values.
Definition: fixed.cpp:256
+
value_type round() const
Definition: fixed.cpp:104
+
fixed()
Default constructor initializes to zero.
Definition: fixed.hpp:46
+
bool read(std::istream &strm)
Definition: fixed.cpp:190
+
+ + + + diff --git a/exploring-cpp-2e/chapter47/html/fixed_8hpp.html b/exploring-cpp-2e/chapter47/html/fixed_8hpp.html new file mode 100644 index 0000000..14589e0 --- /dev/null +++ b/exploring-cpp-2e/chapter47/html/fixed_8hpp.html @@ -0,0 +1,133 @@ + + + + + + +Project 2 - Fixed-Point Number Class: fixed.hpp File Reference + + + + + + +
+
+ + + + + + +
+
Project 2 - Fixed-Point Number Class +
+
+
+ + + + +
+
+ +
+
fixed.hpp File Reference
+
+
+ +

Fixed-point numbers. +More...

+
#include <istream>
+#include <ostream>
+#include <string>
+
+

Go to the source code of this file.

+ + + + + +

+Classes

class  fixed
 Implement a fixed-point number class. Values have places places after the decimal point. All arithmetic follows the usual rules. More...
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Functions

+std::istream & operator>> (std::istream &strm, fixed &f)
 Read a fixed value.
 
+std::ostream & operator<< (std::ostream &strm, fixed f)
 Write a fixed value.
 
+fixed operator+ (fixed a, fixed b)
 Add fixed values.
 
+fixed operator- (fixed a, fixed b)
 Subtract fixed values.
 
+fixed operator* (fixed a, fixed b)
 Multiply fixed values.
 
+fixed operator/ (fixed a, fixed b)
 Divide fixed values.
 
+fixed operator- (fixed a)
 Negate a fixed value.
 
+bool operator== (fixed a, fixed b)
 Compare fixed values for equality by comparing the underlying values.
 
+bool operator!= (fixed a, fixed b)
 Compare fixed values for inequality by comparing the underlying values.
 
+bool operator< (fixed a, fixed b)
 Compare fixed values for less-than by comparing the underlying values.
 
+bool operator> (fixed a, fixed b)
 Compare fixed values for greater-than by comparing the underlying values.
 
+bool operator<= (fixed a, fixed b)
 Compare fixed values for less-than-or-equal by comparing the underlying values.
 
+bool operator>= (fixed a, fixed b)
 Compare fixed values for greater-than-or-equal by comparing the underlying values.
 
+

Detailed Description

+

Fixed-point numbers.

+ +

Definition in file fixed.hpp.

+
+ + + + diff --git a/exploring-cpp-2e/chapter47/html/fixed_8hpp_source.html b/exploring-cpp-2e/chapter47/html/fixed_8hpp_source.html new file mode 100644 index 0000000..b4dc8f0 --- /dev/null +++ b/exploring-cpp-2e/chapter47/html/fixed_8hpp_source.html @@ -0,0 +1,161 @@ + + + + + + +Project 2 - Fixed-Point Number Class: fixed.hpp Source File + + + + + + +
+
+ + + + + + +
+
Project 2 - Fixed-Point Number Class +
+
+
+ + + + +
+
+
+
fixed.hpp
+
+
+Go to the documentation of this file.
1 
+
26 #ifndef FIXED_HPP_
+
27 #define FIXED_HPP_
+
28 
+
29 #include <istream>
+
30 #include <ostream>
+
31 #include <string>
+
32 
+
37 class fixed
+
38 {
+
39 public:
+
40  typedef int value_type;
+
41 
+
42  static int const places = 4;
+
43  static value_type const places10 = 10000;
+
44 
+
46  fixed() : value_{0} {}
+
47 
+ +
52 
+ +
55 
+
57  fixed(double value)
+
58  : value_(static_cast<value_type>(value * places10 + (value < 0 ? -0.5 : 0.5)))
+
59  {}
+
60 
+
63  std::string as_string() const;
+
68  bool read(std::istream& strm);
+
70  double as_long_double() const { return static_cast<long double>(value()) / places10; }
+
72  double as_double() const { return static_cast<double>(value()) / places10; }
+
74  float as_float() const { return static_cast<float>(value()) / places10; }
+
78  value_type round() const;
+
79 
+
81  value_type integer() const { return value() / places10; }
+
83  value_type fraction() const;
+
84 
+ + + + +
93 
+
95  void negate();
+
96 
+
98  fixed& operator++();
+
100  fixed operator++(int);
+
102  fixed& operator--();
+
104  fixed operator--(int);
+
105 
+
107  value_type value() const { return value_; }
+
108 private:
+
110  value_type reduce(value_type frac);
+
111  value_type value_;
+
112 };
+
113 
+
115 std::istream& operator>>(std::istream& strm, fixed& f);
+
117 std::ostream& operator<<(std::ostream& strm, fixed f);
+
118 
+
120 fixed operator+(fixed a, fixed b);
+
122 fixed operator-(fixed a, fixed b);
+
124 fixed operator*(fixed a, fixed b);
+
126 fixed operator/(fixed a, fixed b);
+ +
129 
+
131 bool operator==(fixed a, fixed b);
+
133 bool operator!=(fixed a, fixed b);
+
135 bool operator<(fixed a, fixed b);
+
137 bool operator>(fixed a, fixed b);
+
139 bool operator<=(fixed a, fixed b);
+
141 bool operator>=(fixed a, fixed b);
+
142 
+
143 #endif
+
fixed & operator*=(fixed f)
Multiplication assignment operator.
Definition: fixed.cpp:141
+
Implement a fixed-point number class. Values have places places after the decimal point...
Definition: fixed.hpp:37
+
fixed operator*(fixed a, fixed b)
Multiply fixed values.
Definition: fixed.cpp:268
+
std::string as_string() const
Definition: fixed.cpp:120
+
bool operator>=(fixed a, fixed b)
Compare fixed values for greater-than-or-equal by comparing the underlying values.
Definition: fixed.cpp:305
+
bool operator<=(fixed a, fixed b)
Compare fixed values for less-than-or-equal by comparing the underlying values.
Definition: fixed.cpp:300
+
bool operator<(fixed a, fixed b)
Compare fixed values for less-than by comparing the underlying values.
Definition: fixed.cpp:290
+
value_type value() const
Return the internal value.
Definition: fixed.hpp:107
+
value_type integer() const
Return the integer part (which is the same as trunc()).
Definition: fixed.hpp:81
+
double as_double() const
Convert to double.
Definition: fixed.hpp:72
+
std::ostream & operator<<(std::ostream &strm, fixed f)
Write a fixed value.
Definition: fixed.cpp:250
+
value_type fraction() const
Return the fractional part, e.g., 3 for 12.03.
Definition: fixed.cpp:31
+
bool operator!=(fixed a, fixed b)
Compare fixed values for inequality by comparing the underlying values.
Definition: fixed.cpp:285
+
static int const places
number of decimal places
Definition: fixed.hpp:42
+
bool operator>(fixed a, fixed b)
Compare fixed values for greater-than by comparing the underlying values.
Definition: fixed.cpp:295
+
fixed & operator++()
Pre-increment.
Definition: fixed.cpp:158
+
fixed & operator+=(fixed f)
Addition assignment operator.
Definition: fixed.cpp:129
+
float as_float() const
Convert to float.
Definition: fixed.hpp:74
+
fixed & operator/=(fixed f)
Division assignment operator.
Definition: fixed.cpp:147
+
double as_long_double() const
Convert to long double.
Definition: fixed.hpp:70
+
fixed & operator--()
Pre-decrement.
Definition: fixed.cpp:171
+
fixed operator/(fixed a, fixed b)
Divide fixed values.
Definition: fixed.cpp:274
+
void negate()
Negate this value.
Definition: fixed.cpp:153
+
fixed & operator-=(fixed f)
Subtraction assignment operator.
Definition: fixed.cpp:135
+
std::istream & operator>>(std::istream &strm, fixed &f)
Read a fixed value.
Definition: fixed.cpp:243
+
bool operator==(fixed a, fixed b)
Compare fixed values for equality by comparing the underlying values.
Definition: fixed.cpp:280
+
static value_type const places10
10places
Definition: fixed.hpp:43
+
fixed operator-(fixed a, fixed b)
Subtract fixed values.
Definition: fixed.cpp:262
+
int value_type
Type of the actual value.
Definition: fixed.hpp:40
+
fixed(double value)
Construct by rounding off a floating point number.
Definition: fixed.hpp:57
+
fixed operator+(fixed a, fixed b)
Add fixed values.
Definition: fixed.cpp:256
+
value_type round() const
Definition: fixed.cpp:104
+
fixed()
Default constructor initializes to zero.
Definition: fixed.hpp:46
+
bool read(std::istream &strm)
Definition: fixed.cpp:190
+
+ + + + diff --git a/exploring-cpp-2e/chapter47/html/ftv2blank.png b/exploring-cpp-2e/chapter47/html/ftv2blank.png new file mode 100644 index 0000000..63c605b Binary files /dev/null and b/exploring-cpp-2e/chapter47/html/ftv2blank.png differ diff --git a/exploring-cpp-2e/chapter47/html/ftv2cl.png b/exploring-cpp-2e/chapter47/html/ftv2cl.png new file mode 100644 index 0000000..132f657 Binary files /dev/null and b/exploring-cpp-2e/chapter47/html/ftv2cl.png differ diff --git a/exploring-cpp-2e/chapter47/html/ftv2doc.png b/exploring-cpp-2e/chapter47/html/ftv2doc.png new file mode 100644 index 0000000..17edabf Binary files /dev/null and b/exploring-cpp-2e/chapter47/html/ftv2doc.png differ diff --git a/exploring-cpp-2e/chapter47/html/ftv2folderclosed.png b/exploring-cpp-2e/chapter47/html/ftv2folderclosed.png new file mode 100644 index 0000000..bb8ab35 Binary files /dev/null and b/exploring-cpp-2e/chapter47/html/ftv2folderclosed.png differ diff --git a/exploring-cpp-2e/chapter47/html/ftv2folderopen.png b/exploring-cpp-2e/chapter47/html/ftv2folderopen.png new file mode 100644 index 0000000..d6c7f67 Binary files /dev/null and b/exploring-cpp-2e/chapter47/html/ftv2folderopen.png differ diff --git a/exploring-cpp-2e/chapter47/html/ftv2lastnode.png b/exploring-cpp-2e/chapter47/html/ftv2lastnode.png new file mode 100644 index 0000000..63c605b Binary files /dev/null and b/exploring-cpp-2e/chapter47/html/ftv2lastnode.png differ diff --git a/exploring-cpp-2e/chapter47/html/ftv2link.png b/exploring-cpp-2e/chapter47/html/ftv2link.png new file mode 100644 index 0000000..17edabf Binary files /dev/null and b/exploring-cpp-2e/chapter47/html/ftv2link.png differ diff --git a/exploring-cpp-2e/chapter47/html/ftv2mlastnode.png b/exploring-cpp-2e/chapter47/html/ftv2mlastnode.png new file mode 100644 index 0000000..0b63f6d Binary files /dev/null and b/exploring-cpp-2e/chapter47/html/ftv2mlastnode.png differ diff --git a/exploring-cpp-2e/chapter47/html/ftv2mnode.png b/exploring-cpp-2e/chapter47/html/ftv2mnode.png new file mode 100644 index 0000000..0b63f6d Binary files /dev/null and b/exploring-cpp-2e/chapter47/html/ftv2mnode.png differ diff --git a/exploring-cpp-2e/chapter47/html/ftv2mo.png b/exploring-cpp-2e/chapter47/html/ftv2mo.png new file mode 100644 index 0000000..4bfb80f Binary files /dev/null and b/exploring-cpp-2e/chapter47/html/ftv2mo.png differ diff --git a/exploring-cpp-2e/chapter47/html/ftv2node.png b/exploring-cpp-2e/chapter47/html/ftv2node.png new file mode 100644 index 0000000..63c605b Binary files /dev/null and b/exploring-cpp-2e/chapter47/html/ftv2node.png differ diff --git a/exploring-cpp-2e/chapter47/html/ftv2ns.png b/exploring-cpp-2e/chapter47/html/ftv2ns.png new file mode 100644 index 0000000..72e3d71 Binary files /dev/null and b/exploring-cpp-2e/chapter47/html/ftv2ns.png differ diff --git a/exploring-cpp-2e/chapter47/html/ftv2plastnode.png b/exploring-cpp-2e/chapter47/html/ftv2plastnode.png new file mode 100644 index 0000000..c6ee22f Binary files /dev/null and b/exploring-cpp-2e/chapter47/html/ftv2plastnode.png differ diff --git a/exploring-cpp-2e/chapter47/html/ftv2pnode.png b/exploring-cpp-2e/chapter47/html/ftv2pnode.png new file mode 100644 index 0000000..c6ee22f Binary files /dev/null and b/exploring-cpp-2e/chapter47/html/ftv2pnode.png differ diff --git a/exploring-cpp-2e/chapter47/html/ftv2splitbar.png b/exploring-cpp-2e/chapter47/html/ftv2splitbar.png new file mode 100644 index 0000000..fe895f2 Binary files /dev/null and b/exploring-cpp-2e/chapter47/html/ftv2splitbar.png differ diff --git a/exploring-cpp-2e/chapter47/html/ftv2vertline.png b/exploring-cpp-2e/chapter47/html/ftv2vertline.png new file mode 100644 index 0000000..63c605b Binary files /dev/null and b/exploring-cpp-2e/chapter47/html/ftv2vertline.png differ diff --git a/exploring-cpp-2e/chapter47/html/functions.html b/exploring-cpp-2e/chapter47/html/functions.html new file mode 100644 index 0000000..b7b8d56 --- /dev/null +++ b/exploring-cpp-2e/chapter47/html/functions.html @@ -0,0 +1,128 @@ + + + + + + +Project 2 - Fixed-Point Number Class: Class Members + + + + + + +
+
+ + + + + + +
+
Project 2 - Fixed-Point Number Class +
+
+
+ + + + + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+
+ + + + diff --git a/exploring-cpp-2e/chapter47/html/functions_func.html b/exploring-cpp-2e/chapter47/html/functions_func.html new file mode 100644 index 0000000..4bf1e41 --- /dev/null +++ b/exploring-cpp-2e/chapter47/html/functions_func.html @@ -0,0 +1,119 @@ + + + + + + +Project 2 - Fixed-Point Number Class: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Project 2 - Fixed-Point Number Class +
+
+
+ + + + + +
+
+
+ + + + diff --git a/exploring-cpp-2e/chapter47/html/functions_type.html b/exploring-cpp-2e/chapter47/html/functions_type.html new file mode 100644 index 0000000..557e81c --- /dev/null +++ b/exploring-cpp-2e/chapter47/html/functions_type.html @@ -0,0 +1,65 @@ + + + + + + +Project 2 - Fixed-Point Number Class: Class Members - Typedefs + + + + + + +
+
+ + + + + + +
+
Project 2 - Fixed-Point Number Class +
+
+
+ + + + + +
+
    +
  • value_type +: fixed +
  • +
+
+ + + + diff --git a/exploring-cpp-2e/chapter47/html/functions_vars.html b/exploring-cpp-2e/chapter47/html/functions_vars.html new file mode 100644 index 0000000..261d090 --- /dev/null +++ b/exploring-cpp-2e/chapter47/html/functions_vars.html @@ -0,0 +1,68 @@ + + + + + + +Project 2 - Fixed-Point Number Class: Class Members - Variables + + + + + + +
+
+ + + + + + +
+
Project 2 - Fixed-Point Number Class +
+
+
+ + + + + +
+
+
+ + + + diff --git a/exploring-cpp-2e/chapter47/html/globals.html b/exploring-cpp-2e/chapter47/html/globals.html new file mode 100644 index 0000000..d250c9b --- /dev/null +++ b/exploring-cpp-2e/chapter47/html/globals.html @@ -0,0 +1,99 @@ + + + + + + +Project 2 - Fixed-Point Number Class: File Members + + + + + + +
+
+ + + + + + +
+
Project 2 - Fixed-Point Number Class +
+
+
+ + + + + +
+
+
Here is a list of all documented file members with links to the documentation:
+
+ + + + diff --git a/exploring-cpp-2e/chapter47/html/globals_func.html b/exploring-cpp-2e/chapter47/html/globals_func.html new file mode 100644 index 0000000..826c0b3 --- /dev/null +++ b/exploring-cpp-2e/chapter47/html/globals_func.html @@ -0,0 +1,99 @@ + + + + + + +Project 2 - Fixed-Point Number Class: File Members + + + + + + +
+
+ + + + + + +
+
Project 2 - Fixed-Point Number Class +
+
+
+ + + + + +
+
+
+ + + + diff --git a/exploring-cpp-2e/chapter47/html/index.html b/exploring-cpp-2e/chapter47/html/index.html new file mode 100644 index 0000000..31c7d56 --- /dev/null +++ b/exploring-cpp-2e/chapter47/html/index.html @@ -0,0 +1,61 @@ + + + + + + +Project 2 - Fixed-Point Number Class: Project 2 - Fixed-Point Numbers + + + + + + +
+
+ + + + + + +
+
Project 2 - Fixed-Point Number Class +
+
+
+ + + +
+
+
+
Project 2 - Fixed-Point Numbers
+
+
+

This program is Project 2 in Exploring C++, by Ray Lischner (Apress).

+

Your task for Project 2 is to implement a simple fixed-point number class. The class represents fixed-point numbers using an integer type. The number of places after the decimal point is a fixed constant, four. For example, represent the number 3.1415 as the integer 31415 and 3.14 as 31400. You must overload the arithmetic, comparison, and I/O operators to maintain the fixed-point fiction.

+

Source files:

+ +
Author
Ray Lischner
+
+ + + + diff --git a/exploring-cpp-2e/chapter47/html/ioflags_8hpp.html b/exploring-cpp-2e/chapter47/html/ioflags_8hpp.html new file mode 100644 index 0000000..5feeeab --- /dev/null +++ b/exploring-cpp-2e/chapter47/html/ioflags_8hpp.html @@ -0,0 +1,73 @@ + + + + + + +Project 2 - Fixed-Point Number Class: ioflags.hpp File Reference + + + + + + +
+
+ + + + + + +
+
Project 2 - Fixed-Point Number Class +
+
+
+ + + + +
+
+ +
+
ioflags.hpp File Reference
+
+
+ +

Save and restore I/O stream flags. +More...

+ +

Go to the source code of this file.

+ + + + +

+Classes

class  ioflags
 
+

Detailed Description

+

Save and restore I/O stream flags.

+ +

Definition in file ioflags.hpp.

+
+ + + + diff --git a/exploring-cpp-2e/chapter47/html/ioflags_8hpp_source.html b/exploring-cpp-2e/chapter47/html/ioflags_8hpp_source.html new file mode 100644 index 0000000..ffbab99 --- /dev/null +++ b/exploring-cpp-2e/chapter47/html/ioflags_8hpp_source.html @@ -0,0 +1,77 @@ + + + + + + +Project 2 - Fixed-Point Number Class: ioflags.hpp Source File + + + + + + +
+
+ + + + + + +
+
Project 2 - Fixed-Point Number Class +
+
+
+ + + + +
+
+
+
ioflags.hpp
+
+
+Go to the documentation of this file.
1 #ifndef IOFLAGS_HPP_
+
2 #define IOFLAGS_HPP_
+
3 
+
15 class ioflags
+
16 {
+
17 public:
+
20  ioflags(std::basic_ios<char>& stream) : stream_(stream), flags_{stream.flags()} {}
+
22  ~ioflags() { stream_.flags(flags_); }
+
23 
+
24  ioflags(ioflags const&) = delete;
+
25  ioflags& operator=(ioflags const&) = delete;
+
26 
+
27 private:
+
28  std::basic_ios<char>& stream_;
+
29  std::ios_base::fmtflags flags_;
+
30 };
+
31 
+
32 #endif
+
ioflags(std::basic_ios< char > &stream)
Definition: ioflags.hpp:20
+ +
~ioflags()
Restore the formatting flags.
Definition: ioflags.hpp:22
+
+ + + + diff --git a/exploring-cpp-2e/chapter47/html/jquery.js b/exploring-cpp-2e/chapter47/html/jquery.js new file mode 100644 index 0000000..6aa2e4c --- /dev/null +++ b/exploring-cpp-2e/chapter47/html/jquery.js @@ -0,0 +1,39 @@ +/*! + * jQuery JavaScript Library v1.7.1 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Mon Nov 21 21:11:03 2011 -0500 + */ +(function(bb,L){var av=bb.document,bu=bb.navigator,bl=bb.location;var b=(function(){var bF=function(b0,b1){return new bF.fn.init(b0,b1,bD)},bU=bb.jQuery,bH=bb.$,bD,bY=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,bM=/\S/,bI=/^\s+/,bE=/\s+$/,bA=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,bN=/^[\],:{}\s]*$/,bW=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,bP=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,bJ=/(?:^|:|,)(?:\s*\[)+/g,by=/(webkit)[ \/]([\w.]+)/,bR=/(opera)(?:.*version)?[ \/]([\w.]+)/,bQ=/(msie) ([\w.]+)/,bS=/(mozilla)(?:.*? rv:([\w.]+))?/,bB=/-([a-z]|[0-9])/ig,bZ=/^-ms-/,bT=function(b0,b1){return(b1+"").toUpperCase()},bX=bu.userAgent,bV,bC,e,bL=Object.prototype.toString,bG=Object.prototype.hasOwnProperty,bz=Array.prototype.push,bK=Array.prototype.slice,bO=String.prototype.trim,bv=Array.prototype.indexOf,bx={};bF.fn=bF.prototype={constructor:bF,init:function(b0,b4,b3){var b2,b5,b1,b6;if(!b0){return this}if(b0.nodeType){this.context=this[0]=b0;this.length=1;return this}if(b0==="body"&&!b4&&av.body){this.context=av;this[0]=av.body;this.selector=b0;this.length=1;return this}if(typeof b0==="string"){if(b0.charAt(0)==="<"&&b0.charAt(b0.length-1)===">"&&b0.length>=3){b2=[null,b0,null]}else{b2=bY.exec(b0)}if(b2&&(b2[1]||!b4)){if(b2[1]){b4=b4 instanceof bF?b4[0]:b4;b6=(b4?b4.ownerDocument||b4:av);b1=bA.exec(b0);if(b1){if(bF.isPlainObject(b4)){b0=[av.createElement(b1[1])];bF.fn.attr.call(b0,b4,true)}else{b0=[b6.createElement(b1[1])]}}else{b1=bF.buildFragment([b2[1]],[b6]);b0=(b1.cacheable?bF.clone(b1.fragment):b1.fragment).childNodes}return bF.merge(this,b0)}else{b5=av.getElementById(b2[2]);if(b5&&b5.parentNode){if(b5.id!==b2[2]){return b3.find(b0)}this.length=1;this[0]=b5}this.context=av;this.selector=b0;return this}}else{if(!b4||b4.jquery){return(b4||b3).find(b0)}else{return this.constructor(b4).find(b0)}}}else{if(bF.isFunction(b0)){return b3.ready(b0)}}if(b0.selector!==L){this.selector=b0.selector;this.context=b0.context}return bF.makeArray(b0,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return bK.call(this,0)},get:function(b0){return b0==null?this.toArray():(b0<0?this[this.length+b0]:this[b0])},pushStack:function(b1,b3,b0){var b2=this.constructor();if(bF.isArray(b1)){bz.apply(b2,b1)}else{bF.merge(b2,b1)}b2.prevObject=this;b2.context=this.context;if(b3==="find"){b2.selector=this.selector+(this.selector?" ":"")+b0}else{if(b3){b2.selector=this.selector+"."+b3+"("+b0+")"}}return b2},each:function(b1,b0){return bF.each(this,b1,b0)},ready:function(b0){bF.bindReady();bC.add(b0);return this},eq:function(b0){b0=+b0;return b0===-1?this.slice(b0):this.slice(b0,b0+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(bK.apply(this,arguments),"slice",bK.call(arguments).join(","))},map:function(b0){return this.pushStack(bF.map(this,function(b2,b1){return b0.call(b2,b1,b2)}))},end:function(){return this.prevObject||this.constructor(null)},push:bz,sort:[].sort,splice:[].splice};bF.fn.init.prototype=bF.fn;bF.extend=bF.fn.extend=function(){var b9,b2,b0,b1,b6,b7,b5=arguments[0]||{},b4=1,b3=arguments.length,b8=false;if(typeof b5==="boolean"){b8=b5;b5=arguments[1]||{};b4=2}if(typeof b5!=="object"&&!bF.isFunction(b5)){b5={}}if(b3===b4){b5=this;--b4}for(;b40){return}bC.fireWith(av,[bF]);if(bF.fn.trigger){bF(av).trigger("ready").off("ready")}}},bindReady:function(){if(bC){return}bC=bF.Callbacks("once memory");if(av.readyState==="complete"){return setTimeout(bF.ready,1)}if(av.addEventListener){av.addEventListener("DOMContentLoaded",e,false);bb.addEventListener("load",bF.ready,false)}else{if(av.attachEvent){av.attachEvent("onreadystatechange",e);bb.attachEvent("onload",bF.ready);var b0=false;try{b0=bb.frameElement==null}catch(b1){}if(av.documentElement.doScroll&&b0){bw()}}}},isFunction:function(b0){return bF.type(b0)==="function"},isArray:Array.isArray||function(b0){return bF.type(b0)==="array"},isWindow:function(b0){return b0&&typeof b0==="object"&&"setInterval" in b0},isNumeric:function(b0){return !isNaN(parseFloat(b0))&&isFinite(b0)},type:function(b0){return b0==null?String(b0):bx[bL.call(b0)]||"object"},isPlainObject:function(b2){if(!b2||bF.type(b2)!=="object"||b2.nodeType||bF.isWindow(b2)){return false}try{if(b2.constructor&&!bG.call(b2,"constructor")&&!bG.call(b2.constructor.prototype,"isPrototypeOf")){return false}}catch(b1){return false}var b0;for(b0 in b2){}return b0===L||bG.call(b2,b0)},isEmptyObject:function(b1){for(var b0 in b1){return false}return true},error:function(b0){throw new Error(b0)},parseJSON:function(b0){if(typeof b0!=="string"||!b0){return null}b0=bF.trim(b0);if(bb.JSON&&bb.JSON.parse){return bb.JSON.parse(b0)}if(bN.test(b0.replace(bW,"@").replace(bP,"]").replace(bJ,""))){return(new Function("return "+b0))()}bF.error("Invalid JSON: "+b0)},parseXML:function(b2){var b0,b1;try{if(bb.DOMParser){b1=new DOMParser();b0=b1.parseFromString(b2,"text/xml")}else{b0=new ActiveXObject("Microsoft.XMLDOM");b0.async="false";b0.loadXML(b2)}}catch(b3){b0=L}if(!b0||!b0.documentElement||b0.getElementsByTagName("parsererror").length){bF.error("Invalid XML: "+b2)}return b0},noop:function(){},globalEval:function(b0){if(b0&&bM.test(b0)){(bb.execScript||function(b1){bb["eval"].call(bb,b1)})(b0)}},camelCase:function(b0){return b0.replace(bZ,"ms-").replace(bB,bT)},nodeName:function(b1,b0){return b1.nodeName&&b1.nodeName.toUpperCase()===b0.toUpperCase()},each:function(b3,b6,b2){var b1,b4=0,b5=b3.length,b0=b5===L||bF.isFunction(b3);if(b2){if(b0){for(b1 in b3){if(b6.apply(b3[b1],b2)===false){break}}}else{for(;b40&&b0[0]&&b0[b1-1])||b1===0||bF.isArray(b0));if(b3){for(;b21?aJ.call(arguments,0):bG;if(!(--bw)){bC.resolveWith(bC,bx)}}}function bz(bF){return function(bG){bB[bF]=arguments.length>1?aJ.call(arguments,0):bG;bC.notifyWith(bE,bB)}}if(e>1){for(;bv
a";bI=bv.getElementsByTagName("*");bF=bv.getElementsByTagName("a")[0];if(!bI||!bI.length||!bF){return{}}bG=av.createElement("select");bx=bG.appendChild(av.createElement("option"));bE=bv.getElementsByTagName("input")[0];bJ={leadingWhitespace:(bv.firstChild.nodeType===3),tbody:!bv.getElementsByTagName("tbody").length,htmlSerialize:!!bv.getElementsByTagName("link").length,style:/top/.test(bF.getAttribute("style")),hrefNormalized:(bF.getAttribute("href")==="/a"),opacity:/^0.55/.test(bF.style.opacity),cssFloat:!!bF.style.cssFloat,checkOn:(bE.value==="on"),optSelected:bx.selected,getSetAttribute:bv.className!=="t",enctype:!!av.createElement("form").enctype,html5Clone:av.createElement("nav").cloneNode(true).outerHTML!=="<:nav>",submitBubbles:true,changeBubbles:true,focusinBubbles:false,deleteExpando:true,noCloneEvent:true,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableMarginRight:true};bE.checked=true;bJ.noCloneChecked=bE.cloneNode(true).checked;bG.disabled=true;bJ.optDisabled=!bx.disabled;try{delete bv.test}catch(bC){bJ.deleteExpando=false}if(!bv.addEventListener&&bv.attachEvent&&bv.fireEvent){bv.attachEvent("onclick",function(){bJ.noCloneEvent=false});bv.cloneNode(true).fireEvent("onclick")}bE=av.createElement("input");bE.value="t";bE.setAttribute("type","radio");bJ.radioValue=bE.value==="t";bE.setAttribute("checked","checked");bv.appendChild(bE);bD=av.createDocumentFragment();bD.appendChild(bv.lastChild);bJ.checkClone=bD.cloneNode(true).cloneNode(true).lastChild.checked;bJ.appendChecked=bE.checked;bD.removeChild(bE);bD.appendChild(bv);bv.innerHTML="";if(bb.getComputedStyle){bA=av.createElement("div");bA.style.width="0";bA.style.marginRight="0";bv.style.width="2px";bv.appendChild(bA);bJ.reliableMarginRight=(parseInt((bb.getComputedStyle(bA,null)||{marginRight:0}).marginRight,10)||0)===0}if(bv.attachEvent){for(by in {submit:1,change:1,focusin:1}){bB="on"+by;bw=(bB in bv);if(!bw){bv.setAttribute(bB,"return;");bw=(typeof bv[bB]==="function")}bJ[by+"Bubbles"]=bw}}bD.removeChild(bv);bD=bG=bx=bA=bv=bE=null;b(function(){var bM,bU,bV,bT,bN,bO,bL,bS,bR,e,bP,bQ=av.getElementsByTagName("body")[0];if(!bQ){return}bL=1;bS="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;";bR="visibility:hidden;border:0;";e="style='"+bS+"border:5px solid #000;padding:0;'";bP="
";bM=av.createElement("div");bM.style.cssText=bR+"width:0;height:0;position:static;top:0;margin-top:"+bL+"px";bQ.insertBefore(bM,bQ.firstChild);bv=av.createElement("div");bM.appendChild(bv);bv.innerHTML="
t
";bz=bv.getElementsByTagName("td");bw=(bz[0].offsetHeight===0);bz[0].style.display="";bz[1].style.display="none";bJ.reliableHiddenOffsets=bw&&(bz[0].offsetHeight===0);bv.innerHTML="";bv.style.width=bv.style.paddingLeft="1px";b.boxModel=bJ.boxModel=bv.offsetWidth===2;if(typeof bv.style.zoom!=="undefined"){bv.style.display="inline";bv.style.zoom=1;bJ.inlineBlockNeedsLayout=(bv.offsetWidth===2);bv.style.display="";bv.innerHTML="
";bJ.shrinkWrapBlocks=(bv.offsetWidth!==2)}bv.style.cssText=bS+bR;bv.innerHTML=bP;bU=bv.firstChild;bV=bU.firstChild;bN=bU.nextSibling.firstChild.firstChild;bO={doesNotAddBorder:(bV.offsetTop!==5),doesAddBorderForTableAndCells:(bN.offsetTop===5)};bV.style.position="fixed";bV.style.top="20px";bO.fixedPosition=(bV.offsetTop===20||bV.offsetTop===15);bV.style.position=bV.style.top="";bU.style.overflow="hidden";bU.style.position="relative";bO.subtractsBorderForOverflowNotVisible=(bV.offsetTop===-5);bO.doesNotIncludeMarginInBodyOffset=(bQ.offsetTop!==bL);bQ.removeChild(bM);bv=bM=null;b.extend(bJ,bO)});return bJ})();var aS=/^(?:\{.*\}|\[.*\])$/,aA=/([A-Z])/g;b.extend({cache:{},uuid:0,expando:"jQuery"+(b.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},hasData:function(e){e=e.nodeType?b.cache[e[b.expando]]:e[b.expando];return !!e&&!S(e)},data:function(bx,bv,bz,by){if(!b.acceptData(bx)){return}var bG,bA,bD,bE=b.expando,bC=typeof bv==="string",bF=bx.nodeType,e=bF?b.cache:bx,bw=bF?bx[bE]:bx[bE]&&bE,bB=bv==="events";if((!bw||!e[bw]||(!bB&&!by&&!e[bw].data))&&bC&&bz===L){return}if(!bw){if(bF){bx[bE]=bw=++b.uuid}else{bw=bE}}if(!e[bw]){e[bw]={};if(!bF){e[bw].toJSON=b.noop}}if(typeof bv==="object"||typeof bv==="function"){if(by){e[bw]=b.extend(e[bw],bv)}else{e[bw].data=b.extend(e[bw].data,bv)}}bG=bA=e[bw];if(!by){if(!bA.data){bA.data={}}bA=bA.data}if(bz!==L){bA[b.camelCase(bv)]=bz}if(bB&&!bA[bv]){return bG.events}if(bC){bD=bA[bv];if(bD==null){bD=bA[b.camelCase(bv)]}}else{bD=bA}return bD},removeData:function(bx,bv,by){if(!b.acceptData(bx)){return}var bB,bA,bz,bC=b.expando,bD=bx.nodeType,e=bD?b.cache:bx,bw=bD?bx[bC]:bC;if(!e[bw]){return}if(bv){bB=by?e[bw]:e[bw].data;if(bB){if(!b.isArray(bv)){if(bv in bB){bv=[bv]}else{bv=b.camelCase(bv);if(bv in bB){bv=[bv]}else{bv=bv.split(" ")}}}for(bA=0,bz=bv.length;bA-1){return true}}return false},val:function(bx){var e,bv,by,bw=this[0];if(!arguments.length){if(bw){e=b.valHooks[bw.nodeName.toLowerCase()]||b.valHooks[bw.type];if(e&&"get" in e&&(bv=e.get(bw,"value"))!==L){return bv}bv=bw.value;return typeof bv==="string"?bv.replace(aU,""):bv==null?"":bv}return}by=b.isFunction(bx);return this.each(function(bA){var bz=b(this),bB;if(this.nodeType!==1){return}if(by){bB=bx.call(this,bA,bz.val())}else{bB=bx}if(bB==null){bB=""}else{if(typeof bB==="number"){bB+=""}else{if(b.isArray(bB)){bB=b.map(bB,function(bC){return bC==null?"":bC+""})}}}e=b.valHooks[this.nodeName.toLowerCase()]||b.valHooks[this.type];if(!e||!("set" in e)||e.set(this,bB,"value")===L){this.value=bB}})}});b.extend({valHooks:{option:{get:function(e){var bv=e.attributes.value;return !bv||bv.specified?e.value:e.text}},select:{get:function(e){var bA,bv,bz,bx,by=e.selectedIndex,bB=[],bC=e.options,bw=e.type==="select-one";if(by<0){return null}bv=bw?by:0;bz=bw?by+1:bC.length;for(;bv=0});if(!e.length){bv.selectedIndex=-1}return e}}},attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(bA,bx,bB,bz){var bw,e,by,bv=bA.nodeType; +if(!bA||bv===3||bv===8||bv===2){return}if(bz&&bx in b.attrFn){return b(bA)[bx](bB)}if(typeof bA.getAttribute==="undefined"){return b.prop(bA,bx,bB)}by=bv!==1||!b.isXMLDoc(bA);if(by){bx=bx.toLowerCase();e=b.attrHooks[bx]||(ao.test(bx)?aY:be)}if(bB!==L){if(bB===null){b.removeAttr(bA,bx);return}else{if(e&&"set" in e&&by&&(bw=e.set(bA,bB,bx))!==L){return bw}else{bA.setAttribute(bx,""+bB);return bB}}}else{if(e&&"get" in e&&by&&(bw=e.get(bA,bx))!==null){return bw}else{bw=bA.getAttribute(bx);return bw===null?L:bw}}},removeAttr:function(bx,bz){var by,bA,bv,e,bw=0;if(bz&&bx.nodeType===1){bA=bz.toLowerCase().split(af);e=bA.length;for(;bw=0)}}})});var bd=/^(?:textarea|input|select)$/i,n=/^([^\.]*)?(?:\.(.+))?$/,J=/\bhover(\.\S+)?\b/,aO=/^key/,bf=/^(?:mouse|contextmenu)|click/,T=/^(?:focusinfocus|focusoutblur)$/,U=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,Y=function(e){var bv=U.exec(e);if(bv){bv[1]=(bv[1]||"").toLowerCase();bv[3]=bv[3]&&new RegExp("(?:^|\\s)"+bv[3]+"(?:\\s|$)")}return bv},j=function(bw,e){var bv=bw.attributes||{};return((!e[1]||bw.nodeName.toLowerCase()===e[1])&&(!e[2]||(bv.id||{}).value===e[2])&&(!e[3]||e[3].test((bv["class"]||{}).value)))},bt=function(e){return b.event.special.hover?e:e.replace(J,"mouseenter$1 mouseleave$1")};b.event={add:function(bx,bC,bJ,bA,by){var bD,bB,bK,bI,bH,bF,e,bG,bv,bz,bw,bE;if(bx.nodeType===3||bx.nodeType===8||!bC||!bJ||!(bD=b._data(bx))){return}if(bJ.handler){bv=bJ;bJ=bv.handler}if(!bJ.guid){bJ.guid=b.guid++}bK=bD.events;if(!bK){bD.events=bK={}}bB=bD.handle;if(!bB){bD.handle=bB=function(bL){return typeof b!=="undefined"&&(!bL||b.event.triggered!==bL.type)?b.event.dispatch.apply(bB.elem,arguments):L};bB.elem=bx}bC=b.trim(bt(bC)).split(" ");for(bI=0;bI=0){bG=bG.slice(0,-1);bw=true}if(bG.indexOf(".")>=0){bx=bG.split(".");bG=bx.shift();bx.sort()}if((!bA||b.event.customEvent[bG])&&!b.event.global[bG]){return}bv=typeof bv==="object"?bv[b.expando]?bv:new b.Event(bG,bv):new b.Event(bG);bv.type=bG;bv.isTrigger=true;bv.exclusive=bw;bv.namespace=bx.join(".");bv.namespace_re=bv.namespace?new RegExp("(^|\\.)"+bx.join("\\.(?:.*\\.)?")+"(\\.|$)"):null;by=bG.indexOf(":")<0?"on"+bG:"";if(!bA){e=b.cache;for(bC in e){if(e[bC].events&&e[bC].events[bG]){b.event.trigger(bv,bD,e[bC].handle.elem,true)}}return}bv.result=L;if(!bv.target){bv.target=bA}bD=bD!=null?b.makeArray(bD):[];bD.unshift(bv);bF=b.event.special[bG]||{};if(bF.trigger&&bF.trigger.apply(bA,bD)===false){return}bB=[[bA,bF.bindType||bG]];if(!bJ&&!bF.noBubble&&!b.isWindow(bA)){bI=bF.delegateType||bG;bH=T.test(bI+bG)?bA:bA.parentNode;bz=null;for(;bH;bH=bH.parentNode){bB.push([bH,bI]);bz=bH}if(bz&&bz===bA.ownerDocument){bB.push([bz.defaultView||bz.parentWindow||bb,bI])}}for(bC=0;bCbA){bH.push({elem:this,matches:bz.slice(bA)})}for(bC=0;bC0?this.on(e,null,bx,bw):this.trigger(e)};if(b.attrFn){b.attrFn[e]=true}if(aO.test(e)){b.event.fixHooks[e]=b.event.keyHooks}if(bf.test(e)){b.event.fixHooks[e]=b.event.mouseHooks}}); +/*! + * Sizzle CSS Selector Engine + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){var bH=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,bC="sizcache"+(Math.random()+"").replace(".",""),bI=0,bL=Object.prototype.toString,bB=false,bA=true,bK=/\\/g,bO=/\r\n/g,bQ=/\W/;[0,0].sort(function(){bA=false;return 0});var by=function(bV,e,bY,bZ){bY=bY||[];e=e||av;var b1=e;if(e.nodeType!==1&&e.nodeType!==9){return[]}if(!bV||typeof bV!=="string"){return bY}var bS,b3,b6,bR,b2,b5,b4,bX,bU=true,bT=by.isXML(e),bW=[],b0=bV;do{bH.exec("");bS=bH.exec(b0);if(bS){b0=bS[3];bW.push(bS[1]);if(bS[2]){bR=bS[3];break}}}while(bS);if(bW.length>1&&bD.exec(bV)){if(bW.length===2&&bE.relative[bW[0]]){b3=bM(bW[0]+bW[1],e,bZ)}else{b3=bE.relative[bW[0]]?[e]:by(bW.shift(),e);while(bW.length){bV=bW.shift();if(bE.relative[bV]){bV+=bW.shift()}b3=bM(bV,b3,bZ)}}}else{if(!bZ&&bW.length>1&&e.nodeType===9&&!bT&&bE.match.ID.test(bW[0])&&!bE.match.ID.test(bW[bW.length-1])){b2=by.find(bW.shift(),e,bT);e=b2.expr?by.filter(b2.expr,b2.set)[0]:b2.set[0]}if(e){b2=bZ?{expr:bW.pop(),set:bF(bZ)}:by.find(bW.pop(),bW.length===1&&(bW[0]==="~"||bW[0]==="+")&&e.parentNode?e.parentNode:e,bT);b3=b2.expr?by.filter(b2.expr,b2.set):b2.set;if(bW.length>0){b6=bF(b3)}else{bU=false}while(bW.length){b5=bW.pop();b4=b5;if(!bE.relative[b5]){b5=""}else{b4=bW.pop()}if(b4==null){b4=e}bE.relative[b5](b6,b4,bT)}}else{b6=bW=[]}}if(!b6){b6=b3}if(!b6){by.error(b5||bV)}if(bL.call(b6)==="[object Array]"){if(!bU){bY.push.apply(bY,b6)}else{if(e&&e.nodeType===1){for(bX=0;b6[bX]!=null;bX++){if(b6[bX]&&(b6[bX]===true||b6[bX].nodeType===1&&by.contains(e,b6[bX]))){bY.push(b3[bX])}}}else{for(bX=0;b6[bX]!=null;bX++){if(b6[bX]&&b6[bX].nodeType===1){bY.push(b3[bX])}}}}}else{bF(b6,bY)}if(bR){by(bR,b1,bY,bZ);by.uniqueSort(bY)}return bY};by.uniqueSort=function(bR){if(bJ){bB=bA;bR.sort(bJ);if(bB){for(var e=1;e0};by.find=function(bX,e,bY){var bW,bS,bU,bT,bV,bR;if(!bX){return[]}for(bS=0,bU=bE.order.length;bS":function(bW,bR){var bV,bU=typeof bR==="string",bS=0,e=bW.length;if(bU&&!bQ.test(bR)){bR=bR.toLowerCase();for(;bS=0)){if(!bS){e.push(bV)}}else{if(bS){bR[bU]=false}}}}return false},ID:function(e){return e[1].replace(bK,"")},TAG:function(bR,e){return bR[1].replace(bK,"").toLowerCase()},CHILD:function(e){if(e[1]==="nth"){if(!e[2]){by.error(e[0])}e[2]=e[2].replace(/^\+|\s*/g,"");var bR=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(e[2]==="even"&&"2n"||e[2]==="odd"&&"2n+1"||!/\D/.test(e[2])&&"0n+"+e[2]||e[2]);e[2]=(bR[1]+(bR[2]||1))-0;e[3]=bR[3]-0}else{if(e[2]){by.error(e[0])}}e[0]=bI++;return e},ATTR:function(bU,bR,bS,e,bV,bW){var bT=bU[1]=bU[1].replace(bK,"");if(!bW&&bE.attrMap[bT]){bU[1]=bE.attrMap[bT]}bU[4]=(bU[4]||bU[5]||"").replace(bK,"");if(bU[2]==="~="){bU[4]=" "+bU[4]+" "}return bU},PSEUDO:function(bU,bR,bS,e,bV){if(bU[1]==="not"){if((bH.exec(bU[3])||"").length>1||/^\w/.test(bU[3])){bU[3]=by(bU[3],null,null,bR)}else{var bT=by.filter(bU[3],bR,bS,true^bV);if(!bS){e.push.apply(e,bT)}return false}}else{if(bE.match.POS.test(bU[0])||bE.match.CHILD.test(bU[0])){return true}}return bU},POS:function(e){e.unshift(true);return e}},filters:{enabled:function(e){return e.disabled===false&&e.type!=="hidden"},disabled:function(e){return e.disabled===true},checked:function(e){return e.checked===true},selected:function(e){if(e.parentNode){e.parentNode.selectedIndex}return e.selected===true},parent:function(e){return !!e.firstChild},empty:function(e){return !e.firstChild},has:function(bS,bR,e){return !!by(e[3],bS).length},header:function(e){return(/h\d/i).test(e.nodeName)},text:function(bS){var e=bS.getAttribute("type"),bR=bS.type;return bS.nodeName.toLowerCase()==="input"&&"text"===bR&&(e===bR||e===null)},radio:function(e){return e.nodeName.toLowerCase()==="input"&&"radio"===e.type},checkbox:function(e){return e.nodeName.toLowerCase()==="input"&&"checkbox"===e.type},file:function(e){return e.nodeName.toLowerCase()==="input"&&"file"===e.type},password:function(e){return e.nodeName.toLowerCase()==="input"&&"password"===e.type},submit:function(bR){var e=bR.nodeName.toLowerCase();return(e==="input"||e==="button")&&"submit"===bR.type},image:function(e){return e.nodeName.toLowerCase()==="input"&&"image"===e.type},reset:function(bR){var e=bR.nodeName.toLowerCase();return(e==="input"||e==="button")&&"reset"===bR.type},button:function(bR){var e=bR.nodeName.toLowerCase();return e==="input"&&"button"===bR.type||e==="button"},input:function(e){return(/input|select|textarea|button/i).test(e.nodeName)},focus:function(e){return e===e.ownerDocument.activeElement}},setFilters:{first:function(bR,e){return e===0},last:function(bS,bR,e,bT){return bR===bT.length-1},even:function(bR,e){return e%2===0},odd:function(bR,e){return e%2===1 +},lt:function(bS,bR,e){return bRe[3]-0},nth:function(bS,bR,e){return e[3]-0===bR},eq:function(bS,bR,e){return e[3]-0===bR}},filter:{PSEUDO:function(bS,bX,bW,bY){var e=bX[1],bR=bE.filters[e];if(bR){return bR(bS,bW,bX,bY)}else{if(e==="contains"){return(bS.textContent||bS.innerText||bw([bS])||"").indexOf(bX[3])>=0}else{if(e==="not"){var bT=bX[3];for(var bV=0,bU=bT.length;bV=0)}}},ID:function(bR,e){return bR.nodeType===1&&bR.getAttribute("id")===e},TAG:function(bR,e){return(e==="*"&&bR.nodeType===1)||!!bR.nodeName&&bR.nodeName.toLowerCase()===e},CLASS:function(bR,e){return(" "+(bR.className||bR.getAttribute("class"))+" ").indexOf(e)>-1},ATTR:function(bV,bT){var bS=bT[1],e=by.attr?by.attr(bV,bS):bE.attrHandle[bS]?bE.attrHandle[bS](bV):bV[bS]!=null?bV[bS]:bV.getAttribute(bS),bW=e+"",bU=bT[2],bR=bT[4];return e==null?bU==="!=":!bU&&by.attr?e!=null:bU==="="?bW===bR:bU==="*="?bW.indexOf(bR)>=0:bU==="~="?(" "+bW+" ").indexOf(bR)>=0:!bR?bW&&e!==false:bU==="!="?bW!==bR:bU==="^="?bW.indexOf(bR)===0:bU==="$="?bW.substr(bW.length-bR.length)===bR:bU==="|="?bW===bR||bW.substr(0,bR.length+1)===bR+"-":false},POS:function(bU,bR,bS,bV){var e=bR[2],bT=bE.setFilters[e];if(bT){return bT(bU,bS,bR,bV)}}}};var bD=bE.match.POS,bx=function(bR,e){return"\\"+(e-0+1)};for(var bz in bE.match){bE.match[bz]=new RegExp(bE.match[bz].source+(/(?![^\[]*\])(?![^\(]*\))/.source));bE.leftMatch[bz]=new RegExp(/(^(?:.|\r|\n)*?)/.source+bE.match[bz].source.replace(/\\(\d+)/g,bx))}var bF=function(bR,e){bR=Array.prototype.slice.call(bR,0);if(e){e.push.apply(e,bR);return e}return bR};try{Array.prototype.slice.call(av.documentElement.childNodes,0)[0].nodeType}catch(bP){bF=function(bU,bT){var bS=0,bR=bT||[];if(bL.call(bU)==="[object Array]"){Array.prototype.push.apply(bR,bU)}else{if(typeof bU.length==="number"){for(var e=bU.length;bS";e.insertBefore(bR,e.firstChild);if(av.getElementById(bS)){bE.find.ID=function(bU,bV,bW){if(typeof bV.getElementById!=="undefined"&&!bW){var bT=bV.getElementById(bU[1]);return bT?bT.id===bU[1]||typeof bT.getAttributeNode!=="undefined"&&bT.getAttributeNode("id").nodeValue===bU[1]?[bT]:L:[]}};bE.filter.ID=function(bV,bT){var bU=typeof bV.getAttributeNode!=="undefined"&&bV.getAttributeNode("id");return bV.nodeType===1&&bU&&bU.nodeValue===bT}}e.removeChild(bR);e=bR=null})();(function(){var e=av.createElement("div");e.appendChild(av.createComment(""));if(e.getElementsByTagName("*").length>0){bE.find.TAG=function(bR,bV){var bU=bV.getElementsByTagName(bR[1]);if(bR[1]==="*"){var bT=[];for(var bS=0;bU[bS];bS++){if(bU[bS].nodeType===1){bT.push(bU[bS])}}bU=bT}return bU}}e.innerHTML="";if(e.firstChild&&typeof e.firstChild.getAttribute!=="undefined"&&e.firstChild.getAttribute("href")!=="#"){bE.attrHandle.href=function(bR){return bR.getAttribute("href",2)}}e=null})();if(av.querySelectorAll){(function(){var e=by,bT=av.createElement("div"),bS="__sizzle__";bT.innerHTML="

";if(bT.querySelectorAll&&bT.querySelectorAll(".TEST").length===0){return}by=function(b4,bV,bZ,b3){bV=bV||av;if(!b3&&!by.isXML(bV)){var b2=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b4);if(b2&&(bV.nodeType===1||bV.nodeType===9)){if(b2[1]){return bF(bV.getElementsByTagName(b4),bZ)}else{if(b2[2]&&bE.find.CLASS&&bV.getElementsByClassName){return bF(bV.getElementsByClassName(b2[2]),bZ)}}}if(bV.nodeType===9){if(b4==="body"&&bV.body){return bF([bV.body],bZ)}else{if(b2&&b2[3]){var bY=bV.getElementById(b2[3]);if(bY&&bY.parentNode){if(bY.id===b2[3]){return bF([bY],bZ)}}else{return bF([],bZ)}}}try{return bF(bV.querySelectorAll(b4),bZ)}catch(b0){}}else{if(bV.nodeType===1&&bV.nodeName.toLowerCase()!=="object"){var bW=bV,bX=bV.getAttribute("id"),bU=bX||bS,b6=bV.parentNode,b5=/^\s*[+~]/.test(b4);if(!bX){bV.setAttribute("id",bU)}else{bU=bU.replace(/'/g,"\\$&")}if(b5&&b6){bV=bV.parentNode}try{if(!b5||b6){return bF(bV.querySelectorAll("[id='"+bU+"'] "+b4),bZ)}}catch(b1){}finally{if(!bX){bW.removeAttribute("id")}}}}}return e(b4,bV,bZ,b3)};for(var bR in e){by[bR]=e[bR]}bT=null})()}(function(){var e=av.documentElement,bS=e.matchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.msMatchesSelector;if(bS){var bU=!bS.call(av.createElement("div"),"div"),bR=false;try{bS.call(av.documentElement,"[test!='']:sizzle")}catch(bT){bR=true}by.matchesSelector=function(bW,bY){bY=bY.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!by.isXML(bW)){try{if(bR||!bE.match.PSEUDO.test(bY)&&!/!=/.test(bY)){var bV=bS.call(bW,bY);if(bV||!bU||bW.document&&bW.document.nodeType!==11){return bV}}}catch(bX){}}return by(bY,null,null,[bW]).length>0}}})();(function(){var e=av.createElement("div");e.innerHTML="
";if(!e.getElementsByClassName||e.getElementsByClassName("e").length===0){return}e.lastChild.className="e";if(e.getElementsByClassName("e").length===1){return}bE.order.splice(1,0,"CLASS");bE.find.CLASS=function(bR,bS,bT){if(typeof bS.getElementsByClassName!=="undefined"&&!bT){return bS.getElementsByClassName(bR[1])}};e=null})();function bv(bR,bW,bV,bZ,bX,bY){for(var bT=0,bS=bZ.length;bT0){bU=e;break}}}e=e[bR]}bZ[bT]=bU}}}if(av.documentElement.contains){by.contains=function(bR,e){return bR!==e&&(bR.contains?bR.contains(e):true)}}else{if(av.documentElement.compareDocumentPosition){by.contains=function(bR,e){return !!(bR.compareDocumentPosition(e)&16)}}else{by.contains=function(){return false}}}by.isXML=function(e){var bR=(e?e.ownerDocument||e:0).documentElement;return bR?bR.nodeName!=="HTML":false};var bM=function(bS,e,bW){var bV,bX=[],bU="",bY=e.nodeType?[e]:e;while((bV=bE.match.PSEUDO.exec(bS))){bU+=bV[0];bS=bS.replace(bE.match.PSEUDO,"")}bS=bE.relative[bS]?bS+"*":bS;for(var bT=0,bR=bY.length;bT0){for(bB=bA;bB=0:b.filter(e,this).length>0:this.filter(e).length>0)},closest:function(by,bx){var bv=[],bw,e,bz=this[0];if(b.isArray(by)){var bB=1;while(bz&&bz.ownerDocument&&bz!==bx){for(bw=0;bw-1:b.find.matchesSelector(bz,by)){bv.push(bz);break}else{bz=bz.parentNode;if(!bz||!bz.ownerDocument||bz===bx||bz.nodeType===11){break}}}}bv=bv.length>1?b.unique(bv):bv;return this.pushStack(bv,"closest",by)},index:function(e){if(!e){return(this[0]&&this[0].parentNode)?this.prevAll().length:-1}if(typeof e==="string"){return b.inArray(this[0],b(e))}return b.inArray(e.jquery?e[0]:e,this)},add:function(e,bv){var bx=typeof e==="string"?b(e,bv):b.makeArray(e&&e.nodeType?[e]:e),bw=b.merge(this.get(),bx);return this.pushStack(C(bx[0])||C(bw[0])?bw:b.unique(bw))},andSelf:function(){return this.add(this.prevObject)}});function C(e){return !e||!e.parentNode||e.parentNode.nodeType===11}b.each({parent:function(bv){var e=bv.parentNode;return e&&e.nodeType!==11?e:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(bv,e,bw){return b.dir(bv,"parentNode",bw)},next:function(e){return b.nth(e,2,"nextSibling")},prev:function(e){return b.nth(e,2,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(bv,e,bw){return b.dir(bv,"nextSibling",bw)},prevUntil:function(bv,e,bw){return b.dir(bv,"previousSibling",bw)},siblings:function(e){return b.sibling(e.parentNode.firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:b.makeArray(e.childNodes)}},function(e,bv){b.fn[e]=function(by,bw){var bx=b.map(this,bv,by);if(!ab.test(e)){bw=by}if(bw&&typeof bw==="string"){bx=b.filter(bw,bx)}bx=this.length>1&&!ay[e]?b.unique(bx):bx;if((this.length>1||a9.test(bw))&&aq.test(e)){bx=bx.reverse()}return this.pushStack(bx,e,P.call(arguments).join(","))}});b.extend({filter:function(bw,e,bv){if(bv){bw=":not("+bw+")"}return e.length===1?b.find.matchesSelector(e[0],bw)?[e[0]]:[]:b.find.matches(bw,e)},dir:function(bw,bv,by){var e=[],bx=bw[bv];while(bx&&bx.nodeType!==9&&(by===L||bx.nodeType!==1||!b(bx).is(by))){if(bx.nodeType===1){e.push(bx)}bx=bx[bv]}return e},nth:function(by,e,bw,bx){e=e||1;var bv=0;for(;by;by=by[bw]){if(by.nodeType===1&&++bv===e){break}}return by},sibling:function(bw,bv){var e=[];for(;bw;bw=bw.nextSibling){if(bw.nodeType===1&&bw!==bv){e.push(bw)}}return e}});function aG(bx,bw,e){bw=bw||0;if(b.isFunction(bw)){return b.grep(bx,function(bz,by){var bA=!!bw.call(bz,by,bz);return bA===e})}else{if(bw.nodeType){return b.grep(bx,function(bz,by){return(bz===bw)===e})}else{if(typeof bw==="string"){var bv=b.grep(bx,function(by){return by.nodeType===1});if(bp.test(bw)){return b.filter(bw,bv,!e)}else{bw=b.filter(bw,bv)}}}}return b.grep(bx,function(bz,by){return(b.inArray(bz,bw)>=0)===e})}function a(e){var bw=aR.split("|"),bv=e.createDocumentFragment();if(bv.createElement){while(bw.length){bv.createElement(bw.pop())}}return bv}var aR="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",ag=/ jQuery\d+="(?:\d+|null)"/g,ar=/^\s+/,R=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,d=/<([\w:]+)/,w=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},ac=a(av); +ax.optgroup=ax.option;ax.tbody=ax.tfoot=ax.colgroup=ax.caption=ax.thead;ax.th=ax.td;if(!b.support.htmlSerialize){ax._default=[1,"div
","
"]}b.fn.extend({text:function(e){if(b.isFunction(e)){return this.each(function(bw){var bv=b(this);bv.text(e.call(this,bw,bv.text()))})}if(typeof e!=="object"&&e!==L){return this.empty().append((this[0]&&this[0].ownerDocument||av).createTextNode(e))}return b.text(this)},wrapAll:function(e){if(b.isFunction(e)){return this.each(function(bw){b(this).wrapAll(e.call(this,bw))})}if(this[0]){var bv=b(e,this[0].ownerDocument).eq(0).clone(true);if(this[0].parentNode){bv.insertBefore(this[0])}bv.map(function(){var bw=this;while(bw.firstChild&&bw.firstChild.nodeType===1){bw=bw.firstChild}return bw}).append(this)}return this},wrapInner:function(e){if(b.isFunction(e)){return this.each(function(bv){b(this).wrapInner(e.call(this,bv))})}return this.each(function(){var bv=b(this),bw=bv.contents();if(bw.length){bw.wrapAll(e)}else{bv.append(e)}})},wrap:function(e){var bv=b.isFunction(e);return this.each(function(bw){b(this).wrapAll(bv?e.call(this,bw):e)})},unwrap:function(){return this.parent().each(function(){if(!b.nodeName(this,"body")){b(this).replaceWith(this.childNodes)}}).end()},append:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.appendChild(e)}})},prepend:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.insertBefore(e,this.firstChild)}})},before:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bv){this.parentNode.insertBefore(bv,this)})}else{if(arguments.length){var e=b.clean(arguments);e.push.apply(e,this.toArray());return this.pushStack(e,"before",arguments)}}},after:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bv){this.parentNode.insertBefore(bv,this.nextSibling)})}else{if(arguments.length){var e=this.pushStack(this,"after",arguments);e.push.apply(e,b.clean(arguments));return e}}},remove:function(e,bx){for(var bv=0,bw;(bw=this[bv])!=null;bv++){if(!e||b.filter(e,[bw]).length){if(!bx&&bw.nodeType===1){b.cleanData(bw.getElementsByTagName("*"));b.cleanData([bw])}if(bw.parentNode){bw.parentNode.removeChild(bw)}}}return this},empty:function(){for(var e=0,bv;(bv=this[e])!=null;e++){if(bv.nodeType===1){b.cleanData(bv.getElementsByTagName("*"))}while(bv.firstChild){bv.removeChild(bv.firstChild)}}return this},clone:function(bv,e){bv=bv==null?false:bv;e=e==null?bv:e;return this.map(function(){return b.clone(this,bv,e)})},html:function(bx){if(bx===L){return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(ag,""):null}else{if(typeof bx==="string"&&!ae.test(bx)&&(b.support.leadingWhitespace||!ar.test(bx))&&!ax[(d.exec(bx)||["",""])[1].toLowerCase()]){bx=bx.replace(R,"<$1>");try{for(var bw=0,bv=this.length;bw1&&bw0?this.clone(true):this).get();b(bC[bA])[bv](by);bz=bz.concat(by)}return this.pushStack(bz,e,bC.selector)}}});function bg(e){if(typeof e.getElementsByTagName!=="undefined"){return e.getElementsByTagName("*")}else{if(typeof e.querySelectorAll!=="undefined"){return e.querySelectorAll("*")}else{return[]}}}function az(e){if(e.type==="checkbox"||e.type==="radio"){e.defaultChecked=e.checked}}function E(e){var bv=(e.nodeName||"").toLowerCase();if(bv==="input"){az(e)}else{if(bv!=="script"&&typeof e.getElementsByTagName!=="undefined"){b.grep(e.getElementsByTagName("input"),az)}}}function al(e){var bv=av.createElement("div");ac.appendChild(bv);bv.innerHTML=e.outerHTML;return bv.firstChild}b.extend({clone:function(by,bA,bw){var e,bv,bx,bz=b.support.html5Clone||!ah.test("<"+by.nodeName)?by.cloneNode(true):al(by);if((!b.support.noCloneEvent||!b.support.noCloneChecked)&&(by.nodeType===1||by.nodeType===11)&&!b.isXMLDoc(by)){ai(by,bz);e=bg(by);bv=bg(bz);for(bx=0;e[bx];++bx){if(bv[bx]){ai(e[bx],bv[bx])}}}if(bA){t(by,bz);if(bw){e=bg(by);bv=bg(bz);for(bx=0;e[bx];++bx){t(e[bx],bv[bx])}}}e=bv=null;return bz},clean:function(bw,by,bH,bA){var bF;by=by||av;if(typeof by.createElement==="undefined"){by=by.ownerDocument||by[0]&&by[0].ownerDocument||av}var bI=[],bB;for(var bE=0,bz;(bz=bw[bE])!=null;bE++){if(typeof bz==="number"){bz+=""}if(!bz){continue}if(typeof bz==="string"){if(!W.test(bz)){bz=by.createTextNode(bz)}else{bz=bz.replace(R,"<$1>");var bK=(d.exec(bz)||["",""])[1].toLowerCase(),bx=ax[bK]||ax._default,bD=bx[0],bv=by.createElement("div");if(by===av){ac.appendChild(bv)}else{a(by).appendChild(bv)}bv.innerHTML=bx[1]+bz+bx[2];while(bD--){bv=bv.lastChild}if(!b.support.tbody){var e=w.test(bz),bC=bK==="table"&&!e?bv.firstChild&&bv.firstChild.childNodes:bx[1]===""&&!e?bv.childNodes:[];for(bB=bC.length-1;bB>=0;--bB){if(b.nodeName(bC[bB],"tbody")&&!bC[bB].childNodes.length){bC[bB].parentNode.removeChild(bC[bB])}}}if(!b.support.leadingWhitespace&&ar.test(bz)){bv.insertBefore(by.createTextNode(ar.exec(bz)[0]),bv.firstChild)}bz=bv.childNodes}}var bG;if(!b.support.appendChecked){if(bz[0]&&typeof(bG=bz.length)==="number"){for(bB=0;bB=0){return bx+"px"}}else{return bx}}}});if(!b.support.opacity){b.cssHooks.opacity={get:function(bv,e){return au.test((e&&bv.currentStyle?bv.currentStyle.filter:bv.style.filter)||"")?(parseFloat(RegExp.$1)/100)+"":e?"1":""},set:function(by,bz){var bx=by.style,bv=by.currentStyle,e=b.isNumeric(bz)?"alpha(opacity="+bz*100+")":"",bw=bv&&bv.filter||bx.filter||"";bx.zoom=1;if(bz>=1&&b.trim(bw.replace(ak,""))===""){bx.removeAttribute("filter");if(bv&&!bv.filter){return}}bx.filter=ak.test(bw)?bw.replace(ak,e):bw+" "+e}}}b(function(){if(!b.support.reliableMarginRight){b.cssHooks.marginRight={get:function(bw,bv){var e;b.swap(bw,{display:"inline-block"},function(){if(bv){e=Z(bw,"margin-right","marginRight")}else{e=bw.style.marginRight}});return e}}}});if(av.defaultView&&av.defaultView.getComputedStyle){aI=function(by,bw){var bv,bx,e;bw=bw.replace(z,"-$1").toLowerCase();if((bx=by.ownerDocument.defaultView)&&(e=bx.getComputedStyle(by,null))){bv=e.getPropertyValue(bw);if(bv===""&&!b.contains(by.ownerDocument.documentElement,by)){bv=b.style(by,bw)}}return bv}}if(av.documentElement.currentStyle){aX=function(bz,bw){var bA,e,by,bv=bz.currentStyle&&bz.currentStyle[bw],bx=bz.style;if(bv===null&&bx&&(by=bx[bw])){bv=by}if(!bc.test(bv)&&bn.test(bv)){bA=bx.left;e=bz.runtimeStyle&&bz.runtimeStyle.left;if(e){bz.runtimeStyle.left=bz.currentStyle.left}bx.left=bw==="fontSize"?"1em":(bv||0);bv=bx.pixelLeft+"px";bx.left=bA;if(e){bz.runtimeStyle.left=e}}return bv===""?"auto":bv}}Z=aI||aX;function p(by,bw,bv){var bA=bw==="width"?by.offsetWidth:by.offsetHeight,bz=bw==="width"?an:a1,bx=0,e=bz.length; +if(bA>0){if(bv!=="border"){for(;bx)<[^<]*)*<\/script>/gi,q=/^(?:select|textarea)/i,h=/\s+/,br=/([?&])_=[^&]*/,K=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,A=b.fn.load,aa={},r={},aE,s,aV=["*/"]+["*"];try{aE=bl.href}catch(aw){aE=av.createElement("a");aE.href="";aE=aE.href}s=K.exec(aE.toLowerCase())||[];function f(e){return function(by,bA){if(typeof by!=="string"){bA=by;by="*"}if(b.isFunction(bA)){var bx=by.toLowerCase().split(h),bw=0,bz=bx.length,bv,bB,bC;for(;bw=0){var e=bw.slice(by,bw.length);bw=bw.slice(0,by)}var bx="GET";if(bz){if(b.isFunction(bz)){bA=bz;bz=L}else{if(typeof bz==="object"){bz=b.param(bz,b.ajaxSettings.traditional);bx="POST"}}}var bv=this;b.ajax({url:bw,type:bx,dataType:"html",data:bz,complete:function(bC,bB,bD){bD=bC.responseText;if(bC.isResolved()){bC.done(function(bE){bD=bE});bv.html(e?b("
").append(bD.replace(a6,"")).find(e):bD)}if(bA){bv.each(bA,[bD,bB,bC])}}});return this},serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?b.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||q.test(this.nodeName)||aZ.test(this.type))}).map(function(e,bv){var bw=b(this).val();return bw==null?null:b.isArray(bw)?b.map(bw,function(by,bx){return{name:bv.name,value:by.replace(bs,"\r\n")}}):{name:bv.name,value:bw.replace(bs,"\r\n")}}).get()}});b.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(e,bv){b.fn[bv]=function(bw){return this.on(bv,bw)}});b.each(["get","post"],function(e,bv){b[bv]=function(bw,by,bz,bx){if(b.isFunction(by)){bx=bx||bz;bz=by;by=L}return b.ajax({type:bv,url:bw,data:by,success:bz,dataType:bx})}});b.extend({getScript:function(e,bv){return b.get(e,L,bv,"script")},getJSON:function(e,bv,bw){return b.get(e,bv,bw,"json")},ajaxSetup:function(bv,e){if(e){am(bv,b.ajaxSettings)}else{e=bv;bv=b.ajaxSettings}am(bv,e);return bv},ajaxSettings:{url:aE,isLocal:aM.test(s[1]),global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":aV},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":bb.String,"text html":true,"text json":b.parseJSON,"text xml":b.parseXML},flatOptions:{context:true,url:true}},ajaxPrefilter:f(aa),ajaxTransport:f(r),ajax:function(bz,bx){if(typeof bz==="object"){bx=bz;bz=L}bx=bx||{};var bD=b.ajaxSetup({},bx),bS=bD.context||bD,bG=bS!==bD&&(bS.nodeType||bS instanceof b)?b(bS):b.event,bR=b.Deferred(),bN=b.Callbacks("once memory"),bB=bD.statusCode||{},bC,bH={},bO={},bQ,by,bL,bE,bI,bA=0,bw,bK,bJ={readyState:0,setRequestHeader:function(bT,bU){if(!bA){var e=bT.toLowerCase();bT=bO[e]=bO[e]||bT;bH[bT]=bU}return this},getAllResponseHeaders:function(){return bA===2?bQ:null},getResponseHeader:function(bT){var e;if(bA===2){if(!by){by={};while((e=aD.exec(bQ))){by[e[1].toLowerCase()]=e[2]}}e=by[bT.toLowerCase()]}return e===L?null:e},overrideMimeType:function(e){if(!bA){bD.mimeType=e}return this},abort:function(e){e=e||"abort";if(bL){bL.abort(e)}bF(0,e);return this}};function bF(bZ,bU,b0,bW){if(bA===2){return}bA=2;if(bE){clearTimeout(bE)}bL=L;bQ=bW||"";bJ.readyState=bZ>0?4:0;var bT,b4,b3,bX=bU,bY=b0?bj(bD,bJ,b0):L,bV,b2;if(bZ>=200&&bZ<300||bZ===304){if(bD.ifModified){if((bV=bJ.getResponseHeader("Last-Modified"))){b.lastModified[bC]=bV}if((b2=bJ.getResponseHeader("Etag"))){b.etag[bC]=b2}}if(bZ===304){bX="notmodified";bT=true}else{try{b4=G(bD,bY);bX="success";bT=true}catch(b1){bX="parsererror";b3=b1}}}else{b3=bX;if(!bX||bZ){bX="error";if(bZ<0){bZ=0}}}bJ.status=bZ;bJ.statusText=""+(bU||bX);if(bT){bR.resolveWith(bS,[b4,bX,bJ])}else{bR.rejectWith(bS,[bJ,bX,b3])}bJ.statusCode(bB);bB=L;if(bw){bG.trigger("ajax"+(bT?"Success":"Error"),[bJ,bD,bT?b4:b3])}bN.fireWith(bS,[bJ,bX]);if(bw){bG.trigger("ajaxComplete",[bJ,bD]);if(!(--b.active)){b.event.trigger("ajaxStop")}}}bR.promise(bJ);bJ.success=bJ.done;bJ.error=bJ.fail;bJ.complete=bN.add;bJ.statusCode=function(bT){if(bT){var e;if(bA<2){for(e in bT){bB[e]=[bB[e],bT[e]]}}else{e=bT[bJ.status];bJ.then(e,e)}}return this};bD.url=((bz||bD.url)+"").replace(bq,"").replace(c,s[1]+"//");bD.dataTypes=b.trim(bD.dataType||"*").toLowerCase().split(h);if(bD.crossDomain==null){bI=K.exec(bD.url.toLowerCase());bD.crossDomain=!!(bI&&(bI[1]!=s[1]||bI[2]!=s[2]||(bI[3]||(bI[1]==="http:"?80:443))!=(s[3]||(s[1]==="http:"?80:443))))}if(bD.data&&bD.processData&&typeof bD.data!=="string"){bD.data=b.param(bD.data,bD.traditional)}aW(aa,bD,bx,bJ);if(bA===2){return false}bw=bD.global;bD.type=bD.type.toUpperCase();bD.hasContent=!aQ.test(bD.type);if(bw&&b.active++===0){b.event.trigger("ajaxStart")}if(!bD.hasContent){if(bD.data){bD.url+=(M.test(bD.url)?"&":"?")+bD.data;delete bD.data}bC=bD.url;if(bD.cache===false){var bv=b.now(),bP=bD.url.replace(br,"$1_="+bv);bD.url=bP+((bP===bD.url)?(M.test(bD.url)?"&":"?")+"_="+bv:"")}}if(bD.data&&bD.hasContent&&bD.contentType!==false||bx.contentType){bJ.setRequestHeader("Content-Type",bD.contentType)}if(bD.ifModified){bC=bC||bD.url;if(b.lastModified[bC]){bJ.setRequestHeader("If-Modified-Since",b.lastModified[bC])}if(b.etag[bC]){bJ.setRequestHeader("If-None-Match",b.etag[bC])}}bJ.setRequestHeader("Accept",bD.dataTypes[0]&&bD.accepts[bD.dataTypes[0]]?bD.accepts[bD.dataTypes[0]]+(bD.dataTypes[0]!=="*"?", "+aV+"; q=0.01":""):bD.accepts["*"]);for(bK in bD.headers){bJ.setRequestHeader(bK,bD.headers[bK])}if(bD.beforeSend&&(bD.beforeSend.call(bS,bJ,bD)===false||bA===2)){bJ.abort();return false}for(bK in {success:1,error:1,complete:1}){bJ[bK](bD[bK])}bL=aW(r,bD,bx,bJ);if(!bL){bF(-1,"No Transport")}else{bJ.readyState=1;if(bw){bG.trigger("ajaxSend",[bJ,bD])}if(bD.async&&bD.timeout>0){bE=setTimeout(function(){bJ.abort("timeout")},bD.timeout)}try{bA=1;bL.send(bH,bF)}catch(bM){if(bA<2){bF(-1,bM)}else{throw bM}}}return bJ},param:function(e,bw){var bv=[],by=function(bz,bA){bA=b.isFunction(bA)?bA():bA;bv[bv.length]=encodeURIComponent(bz)+"="+encodeURIComponent(bA)};if(bw===L){bw=b.ajaxSettings.traditional}if(b.isArray(e)||(e.jquery&&!b.isPlainObject(e))){b.each(e,function(){by(this.name,this.value)})}else{for(var bx in e){v(bx,e[bx],bw,by)}}return bv.join("&").replace(k,"+")}});function v(bw,by,bv,bx){if(b.isArray(by)){b.each(by,function(bA,bz){if(bv||ap.test(bw)){bx(bw,bz)}else{v(bw+"["+(typeof bz==="object"||b.isArray(bz)?bA:"")+"]",bz,bv,bx)}})}else{if(!bv&&by!=null&&typeof by==="object"){for(var e in by){v(bw+"["+e+"]",by[e],bv,bx)}}else{bx(bw,by)}}}b.extend({active:0,lastModified:{},etag:{}});function bj(bD,bC,bz){var bv=bD.contents,bB=bD.dataTypes,bw=bD.responseFields,by,bA,bx,e;for(bA in bw){if(bA in bz){bC[bw[bA]]=bz[bA]}}while(bB[0]==="*"){bB.shift();if(by===L){by=bD.mimeType||bC.getResponseHeader("content-type")}}if(by){for(bA in bv){if(bv[bA]&&bv[bA].test(by)){bB.unshift(bA);break}}}if(bB[0] in bz){bx=bB[0]}else{for(bA in bz){if(!bB[0]||bD.converters[bA+" "+bB[0]]){bx=bA;break}if(!e){e=bA}}bx=bx||e}if(bx){if(bx!==bB[0]){bB.unshift(bx)}return bz[bx]}}function G(bH,bz){if(bH.dataFilter){bz=bH.dataFilter(bz,bH.dataType)}var bD=bH.dataTypes,bG={},bA,bE,bw=bD.length,bB,bC=bD[0],bx,by,bF,bv,e;for(bA=1;bA=bw.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();bw.animatedProperties[this.prop]=true;for(bA in bw.animatedProperties){if(bw.animatedProperties[bA]!==true){e=false}}if(e){if(bw.overflow!=null&&!b.support.shrinkWrapBlocks){b.each(["","X","Y"],function(bC,bD){bz.style["overflow"+bD]=bw.overflow[bC]})}if(bw.hide){b(bz).hide()}if(bw.hide||bw.show){for(bA in bw.animatedProperties){b.style(bz,bA,bw.orig[bA]);b.removeData(bz,"fxshow"+bA,true);b.removeData(bz,"toggle"+bA,true)}}bv=bw.complete;if(bv){bw.complete=false;bv.call(bz)}}return false}else{if(bw.duration==Infinity){this.now=bx}else{bB=bx-this.startTime;this.state=bB/bw.duration;this.pos=b.easing[bw.animatedProperties[this.prop]](this.state,bB,0,1,bw.duration);this.now=this.start+((this.end-this.start)*this.pos)}this.update()}return true}};b.extend(b.fx,{tick:function(){var bw,bv=b.timers,e=0;for(;e").appendTo(e),bw=bv.css("display");bv.remove();if(bw==="none"||bw===""){if(!a8){a8=av.createElement("iframe");a8.frameBorder=a8.width=a8.height=0}e.appendChild(a8);if(!m||!a8.createElement){m=(a8.contentWindow||a8.contentDocument).document;m.write((av.compatMode==="CSS1Compat"?"":"")+"");m.close()}bv=m.createElement(bx);m.body.appendChild(bv);bw=b.css(bv,"display");e.removeChild(a8)}Q[bx]=bw}return Q[bx]}var V=/^t(?:able|d|h)$/i,ad=/^(?:body|html)$/i;if("getBoundingClientRect" in av.documentElement){b.fn.offset=function(bI){var by=this[0],bB;if(bI){return this.each(function(e){b.offset.setOffset(this,bI,e)})}if(!by||!by.ownerDocument){return null}if(by===by.ownerDocument.body){return b.offset.bodyOffset(by)}try{bB=by.getBoundingClientRect()}catch(bF){}var bH=by.ownerDocument,bw=bH.documentElement;if(!bB||!b.contains(bw,by)){return bB?{top:bB.top,left:bB.left}:{top:0,left:0}}var bC=bH.body,bD=aK(bH),bA=bw.clientTop||bC.clientTop||0,bE=bw.clientLeft||bC.clientLeft||0,bv=bD.pageYOffset||b.support.boxModel&&bw.scrollTop||bC.scrollTop,bz=bD.pageXOffset||b.support.boxModel&&bw.scrollLeft||bC.scrollLeft,bG=bB.top+bv-bA,bx=bB.left+bz-bE;return{top:bG,left:bx}}}else{b.fn.offset=function(bF){var bz=this[0];if(bF){return this.each(function(bG){b.offset.setOffset(this,bF,bG)})}if(!bz||!bz.ownerDocument){return null}if(bz===bz.ownerDocument.body){return b.offset.bodyOffset(bz)}var bC,bw=bz.offsetParent,bv=bz,bE=bz.ownerDocument,bx=bE.documentElement,bA=bE.body,bB=bE.defaultView,e=bB?bB.getComputedStyle(bz,null):bz.currentStyle,bD=bz.offsetTop,by=bz.offsetLeft;while((bz=bz.parentNode)&&bz!==bA&&bz!==bx){if(b.support.fixedPosition&&e.position==="fixed"){break}bC=bB?bB.getComputedStyle(bz,null):bz.currentStyle;bD-=bz.scrollTop;by-=bz.scrollLeft;if(bz===bw){bD+=bz.offsetTop;by+=bz.offsetLeft;if(b.support.doesNotAddBorder&&!(b.support.doesAddBorderForTableAndCells&&V.test(bz.nodeName))){bD+=parseFloat(bC.borderTopWidth)||0;by+=parseFloat(bC.borderLeftWidth)||0}bv=bw;bw=bz.offsetParent}if(b.support.subtractsBorderForOverflowNotVisible&&bC.overflow!=="visible"){bD+=parseFloat(bC.borderTopWidth)||0;by+=parseFloat(bC.borderLeftWidth)||0}e=bC}if(e.position==="relative"||e.position==="static"){bD+=bA.offsetTop;by+=bA.offsetLeft}if(b.support.fixedPosition&&e.position==="fixed"){bD+=Math.max(bx.scrollTop,bA.scrollTop);by+=Math.max(bx.scrollLeft,bA.scrollLeft)}return{top:bD,left:by}}}b.offset={bodyOffset:function(e){var bw=e.offsetTop,bv=e.offsetLeft;if(b.support.doesNotIncludeMarginInBodyOffset){bw+=parseFloat(b.css(e,"marginTop"))||0;bv+=parseFloat(b.css(e,"marginLeft"))||0}return{top:bw,left:bv}},setOffset:function(bx,bG,bA){var bB=b.css(bx,"position");if(bB==="static"){bx.style.position="relative"}var bz=b(bx),bv=bz.offset(),e=b.css(bx,"top"),bE=b.css(bx,"left"),bF=(bB==="absolute"||bB==="fixed")&&b.inArray("auto",[e,bE])>-1,bD={},bC={},bw,by;if(bF){bC=bz.position();bw=bC.top;by=bC.left}else{bw=parseFloat(e)||0;by=parseFloat(bE)||0}if(b.isFunction(bG)){bG=bG.call(bx,bA,bv)}if(bG.top!=null){bD.top=(bG.top-bv.top)+bw}if(bG.left!=null){bD.left=(bG.left-bv.left)+by}if("using" in bG){bG.using.call(bx,bD)}else{bz.css(bD)}}};b.fn.extend({position:function(){if(!this[0]){return null}var bw=this[0],bv=this.offsetParent(),bx=this.offset(),e=ad.test(bv[0].nodeName)?{top:0,left:0}:bv.offset();bx.top-=parseFloat(b.css(bw,"marginTop"))||0;bx.left-=parseFloat(b.css(bw,"marginLeft"))||0;e.top+=parseFloat(b.css(bv[0],"borderTopWidth"))||0;e.left+=parseFloat(b.css(bv[0],"borderLeftWidth"))||0;return{top:bx.top-e.top,left:bx.left-e.left}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||av.body;while(e&&(!ad.test(e.nodeName)&&b.css(e,"position")==="static")){e=e.offsetParent}return e})}});b.each(["Left","Top"],function(bv,e){var bw="scroll"+e;b.fn[bw]=function(bz){var bx,by;if(bz===L){bx=this[0];if(!bx){return null}by=aK(bx);return by?("pageXOffset" in by)?by[bv?"pageYOffset":"pageXOffset"]:b.support.boxModel&&by.document.documentElement[bw]||by.document.body[bw]:bx[bw]}return this.each(function(){by=aK(this);if(by){by.scrollTo(!bv?bz:b(by).scrollLeft(),bv?bz:b(by).scrollTop())}else{this[bw]=bz}})}});function aK(e){return b.isWindow(e)?e:e.nodeType===9?e.defaultView||e.parentWindow:false}b.each(["Height","Width"],function(bv,e){var bw=e.toLowerCase();b.fn["inner"+e]=function(){var bx=this[0];return bx?bx.style?parseFloat(b.css(bx,bw,"padding")):this[bw]():null};b.fn["outer"+e]=function(by){var bx=this[0];return bx?bx.style?parseFloat(b.css(bx,bw,by?"margin":"border")):this[bw]():null};b.fn[bw]=function(bz){var bA=this[0];if(!bA){return bz==null?null:this}if(b.isFunction(bz)){return this.each(function(bE){var bD=b(this);bD[bw](bz.call(this,bE,bD[bw]()))})}if(b.isWindow(bA)){var bB=bA.document.documentElement["client"+e],bx=bA.document.body;return bA.document.compatMode==="CSS1Compat"&&bB||bx&&bx["client"+e]||bB}else{if(bA.nodeType===9){return Math.max(bA.documentElement["client"+e],bA.body["scroll"+e],bA.documentElement["scroll"+e],bA.body["offset"+e],bA.documentElement["offset"+e])}else{if(bz===L){var bC=b.css(bA,bw),by=parseFloat(bC);return b.isNumeric(by)?by:bC}else{return this.css(bw,typeof bz==="string"?bz:bz+"px")}}}}});bb.jQuery=bb.$=b;if(typeof define==="function"&&define.amd&&define.amd.jQuery){define("jquery",[],function(){return b +})}})(window); +/*! + PowerTip - v1.2.0 - 2013-04-03 + http://stevenbenner.github.com/jquery-powertip/ + Copyright (c) 2013 Steven Benner (http://stevenbenner.com/). + Released under MIT license. + https://raw.github.com/stevenbenner/jquery-powertip/master/LICENSE.txt +*/ +(function(a){if(typeof define==="function"&&define.amd){define(["jquery"],a)}else{a(jQuery)}}(function(k){var A=k(document),s=k(window),w=k("body");var n="displayController",e="hasActiveHover",d="forcedOpen",u="hasMouseMove",f="mouseOnToPopup",g="originalTitle",y="powertip",o="powertipjq",l="powertiptarget",E=180/Math.PI;var c={isTipOpen:false,isFixedTipOpen:false,isClosing:false,tipOpenImminent:false,activeHover:null,currentX:0,currentY:0,previousX:0,previousY:0,desyncTimeout:null,mouseTrackingActive:false,delayInProgress:false,windowWidth:0,windowHeight:0,scrollTop:0,scrollLeft:0};var p={none:0,top:1,bottom:2,left:4,right:8};k.fn.powerTip=function(F,N){if(!this.length){return this}if(k.type(F)==="string"&&k.powerTip[F]){return k.powerTip[F].call(this,this,N)}var O=k.extend({},k.fn.powerTip.defaults,F),G=new x(O);h();this.each(function M(){var R=k(this),Q=R.data(y),P=R.data(o),T=R.data(l),S;if(R.data(n)){k.powerTip.destroy(R)}S=R.attr("title");if(!Q&&!T&&!P&&S){R.data(y,S);R.data(g,S);R.removeAttr("title")}R.data(n,new t(R,O,G))});if(!O.manual){this.on({"mouseenter.powertip":function J(P){k.powerTip.show(this,P)},"mouseleave.powertip":function L(){k.powerTip.hide(this)},"focus.powertip":function K(){k.powerTip.show(this)},"blur.powertip":function H(){k.powerTip.hide(this,true)},"keydown.powertip":function I(P){if(P.keyCode===27){k.powerTip.hide(this,true)}}})}return this};k.fn.powerTip.defaults={fadeInTime:200,fadeOutTime:100,followMouse:false,popupId:"powerTip",intentSensitivity:7,intentPollInterval:100,closeDelay:100,placement:"n",smartPlacement:false,offset:10,mouseOnToPopup:false,manual:false};k.fn.powerTip.smartPlacementLists={n:["n","ne","nw","s"],e:["e","ne","se","w","nw","sw","n","s","e"],s:["s","se","sw","n"],w:["w","nw","sw","e","ne","se","n","s","w"],nw:["nw","w","sw","n","s","se","nw"],ne:["ne","e","se","n","s","sw","ne"],sw:["sw","w","nw","s","n","ne","sw"],se:["se","e","ne","s","n","nw","se"],"nw-alt":["nw-alt","n","ne-alt","sw-alt","s","se-alt","w","e"],"ne-alt":["ne-alt","n","nw-alt","se-alt","s","sw-alt","e","w"],"sw-alt":["sw-alt","s","se-alt","nw-alt","n","ne-alt","w","e"],"se-alt":["se-alt","s","sw-alt","ne-alt","n","nw-alt","e","w"]};k.powerTip={show:function z(F,G){if(G){i(G);c.previousX=G.pageX;c.previousY=G.pageY;k(F).data(n).show()}else{k(F).first().data(n).show(true,true)}return F},reposition:function r(F){k(F).first().data(n).resetPosition();return F},hide:function D(G,F){if(G){k(G).first().data(n).hide(F)}else{if(c.activeHover){c.activeHover.data(n).hide(true)}}return G},destroy:function C(G){k(G).off(".powertip").each(function F(){var I=k(this),H=[g,n,e,d];if(I.data(g)){I.attr("title",I.data(g));H.push(y)}I.removeData(H)});return G}};k.powerTip.showTip=k.powerTip.show;k.powerTip.closeTip=k.powerTip.hide;function b(){var F=this;F.top="auto";F.left="auto";F.right="auto";F.bottom="auto";F.set=function(H,G){if(k.isNumeric(G)){F[H]=Math.round(G)}}}function t(K,N,F){var J=null;function L(P,Q){M();if(!K.data(e)){if(!P){c.tipOpenImminent=true;J=setTimeout(function O(){J=null;I()},N.intentPollInterval)}else{if(Q){K.data(d,true)}F.showTip(K)}}}function G(P){M();c.tipOpenImminent=false;if(K.data(e)){K.data(d,false);if(!P){c.delayInProgress=true;J=setTimeout(function O(){J=null;F.hideTip(K);c.delayInProgress=false},N.closeDelay)}else{F.hideTip(K)}}}function I(){var Q=Math.abs(c.previousX-c.currentX),O=Math.abs(c.previousY-c.currentY),P=Q+O;if(P",{id:Q.popupId});if(w.length===0){w=k("body")}w.append(O)}if(Q.followMouse){if(!O.data(u)){A.on("mousemove",M);s.on("scroll",M);O.data(u,true)}}if(Q.mouseOnToPopup){O.on({mouseenter:function L(){if(O.data(f)){if(c.activeHover){c.activeHover.data(n).cancel()}}},mouseleave:function N(){if(c.activeHover){c.activeHover.data(n).hide()}}})}function I(S){S.data(e,true);O.queue(function R(T){H(S);T()})}function H(S){var U;if(!S.data(e)){return}if(c.isTipOpen){if(!c.isClosing){K(c.activeHover)}O.delay(100).queue(function R(V){H(S);V()});return}S.trigger("powerTipPreRender");U=B(S);if(U){O.empty().append(U)}else{return}S.trigger("powerTipRender");c.activeHover=S;c.isTipOpen=true;O.data(f,Q.mouseOnToPopup);if(!Q.followMouse){G(S);c.isFixedTipOpen=true}else{M()}O.fadeIn(Q.fadeInTime,function T(){if(!c.desyncTimeout){c.desyncTimeout=setInterval(J,500)}S.trigger("powerTipOpen")})}function K(R){c.isClosing=true;c.activeHover=null;c.isTipOpen=false;c.desyncTimeout=clearInterval(c.desyncTimeout);R.data(e,false);R.data(d,false);O.fadeOut(Q.fadeOutTime,function S(){var T=new b();c.isClosing=false;c.isFixedTipOpen=false;O.removeClass();T.set("top",c.currentY+Q.offset);T.set("left",c.currentX+Q.offset);O.css(T);R.trigger("powerTipClose")})}function M(){if(!c.isFixedTipOpen&&(c.isTipOpen||(c.tipOpenImminent&&O.data(u)))){var R=O.outerWidth(),V=O.outerHeight(),U=new b(),S,T;U.set("top",c.currentY+Q.offset);U.set("left",c.currentX+Q.offset);S=m(U,R,V);if(S!==p.none){T=a(S);if(T===1){if(S===p.right){U.set("left",c.windowWidth-R)}else{if(S===p.bottom){U.set("top",c.scrollTop+c.windowHeight-V)}}}else{U.set("left",c.currentX-R-Q.offset);U.set("top",c.currentY-V-Q.offset)}}O.css(U)}}function G(S){var R,T;if(Q.smartPlacement){R=k.fn.powerTip.smartPlacementLists[Q.placement];k.each(R,function(U,W){var V=m(F(S,W),O.outerWidth(),O.outerHeight());T=W;if(V===p.none){return false}})}else{F(S,Q.placement);T=Q.placement}O.addClass(T)}function F(U,T){var R=0,S,W,V=new b();V.set("top",0);V.set("left",0);O.css(V);do{S=O.outerWidth();W=O.outerHeight();V=P.compute(U,T,S,W,Q.offset);O.css(V)}while(++R<=5&&(S!==O.outerWidth()||W!==O.outerHeight()));return V}function J(){var R=false;if(c.isTipOpen&&!c.isClosing&&!c.delayInProgress){if(c.activeHover.data(e)===false||c.activeHover.is(":disabled")){R=true}else{if(!v(c.activeHover)&&!c.activeHover.is(":focus")&&!c.activeHover.data(d)){if(O.data(f)){if(!v(O)){R=true}}else{R=true}}}if(R){K(c.activeHover)}}}this.showTip=I;this.hideTip=K;this.resetPosition=G}function q(F){return window.SVGElement&&F[0] instanceof SVGElement}function h(){if(!c.mouseTrackingActive){c.mouseTrackingActive=true;k(function H(){c.scrollLeft=s.scrollLeft();c.scrollTop=s.scrollTop();c.windowWidth=s.width();c.windowHeight=s.height()});A.on("mousemove",i);s.on({resize:function G(){c.windowWidth=s.width();c.windowHeight=s.height()},scroll:function F(){var I=s.scrollLeft(),J=s.scrollTop();if(I!==c.scrollLeft){c.currentX+=I-c.scrollLeft;c.scrollLeft=I}if(J!==c.scrollTop){c.currentY+=J-c.scrollTop;c.scrollTop=J}}})}}function i(F){c.currentX=F.pageX;c.currentY=F.pageY}function v(F){var H=F.offset(),J=F[0].getBoundingClientRect(),I=J.right-J.left,G=J.bottom-J.top;return c.currentX>=H.left&&c.currentX<=H.left+I&&c.currentY>=H.top&&c.currentY<=H.top+G}function B(I){var G=I.data(y),F=I.data(o),K=I.data(l),H,J;if(G){if(k.isFunction(G)){G=G.call(I[0])}J=G}else{if(F){if(k.isFunction(F)){F=F.call(I[0])}if(F.length>0){J=F.clone(true,true)}}else{if(K){H=k("#"+K);if(H.length>0){J=H.html()}}}}return J}function m(M,L,K){var G=c.scrollTop,J=c.scrollLeft,I=G+c.windowHeight,F=J+c.windowWidth,H=p.none;if(M.topI||Math.abs(M.bottom-c.windowHeight)>I){H|=p.bottom}if(M.leftF){H|=p.left}if(M.left+L>F||M.right + + + + + +Project 2 - Fixed-Point Number Class: list4701.cpp Source File + + + + + + +
+
+
+ + + + + +
+
Project 2 - Fixed-Point Number Class +
+
+ + + + + + +
+
+
list4701.cpp
+
+
+
1 // Listing 47-1. Testing the fixed Class
+
2 #include <iostream>
+
3 #include <sstream>
+
4 #include <stdexcept>
+
5 
+
6 #include "test.hpp"
+
7 #include "fixed.hpp"
+
8 
+
9 int main()
+
10 {
+
11  fixed f1{};
+
12  test_equal(f1.value(), 0);
+
13  fixed f2{1};
+
14  test_equal(f2.value(), 10000);
+
15  fixed f3{3, 14162};
+
16  test_equal(f3.value(), 31416);
+
17  fixed f4{2, 14159265};
+
18  test_equal(f4.value(), 21416);
+
19  test_equal(f2 + f4, f1 + f3);
+
20  test(f2 + f4 <= f1 + f3);
+
21  test(f2 + f4 >= f1 + f3);
+
22  test(f1 < f2);
+
23  test(f1 <= f2);
+
24  test(f1 != f2);
+
25  test(f2 > f1);
+
26  test(f2 >= f1);
+
27  test(f2 != f1);
+
28 
+
29  test_equal(f2 + f4, f3 - f1);
+
30  test_equal(f2 * f3, f3);
+
31  test_equal(f3 / f2, f3);
+
32  f4 += f2;
+
33  test_equal(f3, f4);
+
34  f4 -= f1;
+
35  test_equal(f3, f4);
+
36  f4 *= f2;
+
37  test_equal(f3, f4);
+
38  f4 /= f2;
+
39  test_equal(f3, f4);
+
40 
+
41  test_equal(-f4, f1 - f4);
+
42  test_equal(-(-f4), f4);
+
43  --f4;
+
44  test_equal(f4 + 1, f3);
+
45  f4--;
+
46  test_equal(f4 + 2, f3);
+
47  ++f4;
+
48  test_equal(f4 + 1, f3);
+
49  f4++;
+
50  test_equal(f4, f3);
+
51  ++f3;
+
52  test_equal(++f4, f3);
+
53  test_equal(f4--, f3);
+
54  test_equal(f4++, --f3);
+
55  test_equal(--f4, f3);
+
56 
+
57  test_equal(f4 / f3, f2);
+
58  test_equal(f4 - f3, f1);
+
59 
+
60  test_equal(f4.to_string(), "3.1416");
+
61  test_equal(f4.integer(), 3);
+
62  f4 += fixed{0,4584};
+
63  test_equal(f4, 3.6);
+
64  test_equal(f4.integer(), 3);
+
65  test_equal(f4.round(), 4);
+
66 
+
67  test_equal(f3.integer(), 3);
+
68  test_equal((-f3).integer(), -3);
+
69  test_equal(f3.fraction(), 1416);
+
70  test_equal((-f3).fraction(), 1416);
+
71 
+
72  test_equal(fixed{7,4999}.round(), 7);
+
73  test_equal(fixed{7,5000}.round(), 8);
+
74  test_equal(fixed{7,5001}.round(), 8);
+
75  test_equal(fixed{7,4999}.round(), 7);
+
76  test_equal(fixed{8,5000}.round(), 8);
+
77  test_equal(fixed{8,5001}.round(), 9);
+
78 
+
79  test_equal(fixed{123,2345500}, fixed(123,2346));
+
80  test_equal(fixed{123,2345501}, fixed(123,2346));
+
81  test_equal(fixed{123,2345499}, fixed(123,2345));
+
82  test_equal(fixed{123,2346500}, fixed(123,2346));
+
83  test_equal(fixed{123,2346501}, fixed(123,2347));
+
84  test_equal(fixed{123,2346499}, fixed(123,2346));
+
85  test_equal(fixed{123,2346400}, fixed(123,2346));
+
86  test_equal(fixed{123,2346600}, fixed(123,2347));
+
87 
+
88  test_equal(fixed{-7,4999}.round(), -7);
+
89  test_equal(fixed{-7,5000}.round(), -8);
+
90  test_equal(fixed{-7,5001}.round(), -8);
+
91  test_equal(fixed{-7,4999}.round(), -7);
+
92  test_equal(fixed{-8,5000}.round(), -8);
+
93  test_equal(fixed{-8,5001}.round(), -9);
+
94 
+
95  test_equal(fixed{-3.14159265}.value(), -31416);
+
96  test_equal(fixed{123,456789}.value(), 1234568);
+
97  test_equal(fixed{123,4}.value(), 1230004);
+
98  test_equal(fixed{-10,1111}.value(), -101111);
+
99 
+
100  std::ostringstream out{};
+
101  out << f3 << " 3.14159265 " << fixed(-10,12) << " 3 421.4 end";
+
102  fixed f5{};
+
103  std::istringstream in{out.str()};
+
104  test(in >> f5);
+
105  test_equal(f5, f3);
+
106  test(in >> f5);
+
107  test_equal(f5, f3);
+
108  test(in >> f5);
+
109  test_equal(f5.value(), -100012);
+
110  test(in >> f5);
+
111  test_equal(f5.value(), 30000);
+
112  test(in >> f5);
+
113  test_equal(f5.value(), 4214000);
+
114  test(not (in >> f5));
+
115 
+
116  test_equal(fixed{31.4159265}, fixed{31, 4159});
+
117  test_equal(fixed{31.41595}, fixed{31, 4160});
+
118 
+
119  bool okay{false};
+
120  try {
+
121  fixed f6{1, -1};
+
122  } catch (std::invalid_argument const& ex) {
+
123  okay = true;
+
124  } catch (...) {
+
125  }
+
126  test(okay);
+
127 }
+
Implement a fixed-point number class. Values have places places after the decimal point...
Definition: fixed.hpp:37
+
value_type value() const
Return the internal value.
Definition: fixed.hpp:107
+
int main()
Definition: test.cpp:12
+
Fixed-point numbers.
+
value_type round() const
Definition: fixed.cpp:104
+
+ + + + diff --git a/exploring-cpp-2e/chapter47/html/nav_f.png b/exploring-cpp-2e/chapter47/html/nav_f.png new file mode 100644 index 0000000..72a58a5 Binary files /dev/null and b/exploring-cpp-2e/chapter47/html/nav_f.png differ diff --git a/exploring-cpp-2e/chapter47/html/nav_g.png b/exploring-cpp-2e/chapter47/html/nav_g.png new file mode 100644 index 0000000..2093a23 Binary files /dev/null and b/exploring-cpp-2e/chapter47/html/nav_g.png differ diff --git a/exploring-cpp-2e/chapter47/html/nav_h.png b/exploring-cpp-2e/chapter47/html/nav_h.png new file mode 100644 index 0000000..33389b1 Binary files /dev/null and b/exploring-cpp-2e/chapter47/html/nav_h.png differ diff --git a/exploring-cpp-2e/chapter47/html/open.png b/exploring-cpp-2e/chapter47/html/open.png new file mode 100644 index 0000000..30f75c7 Binary files /dev/null and b/exploring-cpp-2e/chapter47/html/open.png differ diff --git a/exploring-cpp-2e/chapter47/html/sync_off.png b/exploring-cpp-2e/chapter47/html/sync_off.png new file mode 100644 index 0000000..3b443fc Binary files /dev/null and b/exploring-cpp-2e/chapter47/html/sync_off.png differ diff --git a/exploring-cpp-2e/chapter47/html/sync_on.png b/exploring-cpp-2e/chapter47/html/sync_on.png new file mode 100644 index 0000000..e08320f Binary files /dev/null and b/exploring-cpp-2e/chapter47/html/sync_on.png differ diff --git a/exploring-cpp-2e/chapter47/html/tab_a.png b/exploring-cpp-2e/chapter47/html/tab_a.png new file mode 100644 index 0000000..3b725c4 Binary files /dev/null and b/exploring-cpp-2e/chapter47/html/tab_a.png differ diff --git a/exploring-cpp-2e/chapter47/html/tab_b.png b/exploring-cpp-2e/chapter47/html/tab_b.png new file mode 100644 index 0000000..e2b4a86 Binary files /dev/null and b/exploring-cpp-2e/chapter47/html/tab_b.png differ diff --git a/exploring-cpp-2e/chapter47/html/tab_h.png b/exploring-cpp-2e/chapter47/html/tab_h.png new file mode 100644 index 0000000..fd5cb70 Binary files /dev/null and b/exploring-cpp-2e/chapter47/html/tab_h.png differ diff --git a/exploring-cpp-2e/chapter47/html/tab_s.png b/exploring-cpp-2e/chapter47/html/tab_s.png new file mode 100644 index 0000000..ab478c9 Binary files /dev/null and b/exploring-cpp-2e/chapter47/html/tab_s.png differ diff --git a/exploring-cpp-2e/chapter47/html/tabs.css b/exploring-cpp-2e/chapter47/html/tabs.css new file mode 100644 index 0000000..9cf578f --- /dev/null +++ b/exploring-cpp-2e/chapter47/html/tabs.css @@ -0,0 +1,60 @@ +.tabs, .tabs2, .tabs3 { + background-image: url('tab_b.png'); + width: 100%; + z-index: 101; + font-size: 13px; + font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; +} + +.tabs2 { + font-size: 10px; +} +.tabs3 { + font-size: 9px; +} + +.tablist { + margin: 0; + padding: 0; + display: table; +} + +.tablist li { + float: left; + display: table-cell; + background-image: url('tab_b.png'); + line-height: 36px; + list-style: none; +} + +.tablist a { + display: block; + padding: 0 20px; + font-weight: bold; + background-image:url('tab_s.png'); + background-repeat:no-repeat; + background-position:right; + color: #283A5D; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + text-decoration: none; + outline: none; +} + +.tabs3 .tablist a { + padding: 0 10px; +} + +.tablist a:hover { + background-image: url('tab_h.png'); + background-repeat:repeat-x; + color: #fff; + text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); + text-decoration: none; +} + +.tablist li.current a { + background-image: url('tab_a.png'); + background-repeat:repeat-x; + color: #fff; + text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); +} diff --git a/exploring-cpp-2e/chapter47/html/test_8cpp.html b/exploring-cpp-2e/chapter47/html/test_8cpp.html new file mode 100644 index 0000000..35bf261 --- /dev/null +++ b/exploring-cpp-2e/chapter47/html/test_8cpp.html @@ -0,0 +1,94 @@ + + + + + + +Project 2 - Fixed-Point Number Class: test.cpp File Reference + + + + + + +
+
+ + + + + + +
+
Project 2 - Fixed-Point Number Class +
+
+
+ + + + +
+
+ +
+
test.cpp File Reference
+
+
+
#include <iostream>
+#include <istream>
+#include <ostream>
+#include <sstream>
+#include <stdexcept>
+#include "test.hpp"
+#include "fixed.hpp"
+
+

Go to the source code of this file.

+ + + + +

+Functions

int main ()
 
+

Function Documentation

+ +
+
+ + + + + + + +
int main ()
+
+

Listing 45-1. Testing the fixed Class

+ +

Definition at line 12 of file test.cpp.

+ +

References fixed::value().

+ +
+
+
+ + + + diff --git a/exploring-cpp-2e/chapter47/html/test_8cpp_source.html b/exploring-cpp-2e/chapter47/html/test_8cpp_source.html new file mode 100644 index 0000000..ce693e7 --- /dev/null +++ b/exploring-cpp-2e/chapter47/html/test_8cpp_source.html @@ -0,0 +1,189 @@ + + + + + + +Project 2 - Fixed-Point Number Class: test.cpp Source File + + + + + + +
+
+ + + + + + +
+
Project 2 - Fixed-Point Number Class +
+
+
+ + + + +
+
+
+
test.cpp
+
+
+Go to the documentation of this file.
1 
+
3 #include <iostream>
+
4 #include <istream>
+
5 #include <ostream>
+
6 #include <sstream>
+
7 #include <stdexcept>
+
8 
+
9 #include "test.hpp"
+
10 #include "fixed.hpp"
+
11 
+
12 int main()
+
13 {
+
14  fixed f1;
+
15  TEST(f1.value() == 0);
+
16  fixed f2(1);
+
17  TEST(f2.value() == 10000);
+
18  fixed f3(3, 14162);
+
19  TEST(f3.value() == 31416);
+
20  fixed f4(2, 14159265);
+
21  TEST(f4.value() == 21416);
+
22  TEST(f2 + f4 == f1 + f3);
+
23  TEST(f2 + f4 <= f1 + f3);
+
24  TEST(f2 + f4 >= f1 + f3);
+
25  TEST(f1 < f2);
+
26  TEST(f1 <= f2);
+
27  TEST(f1 != f2);
+
28  TEST(f2 > f1);
+
29  TEST(f2 >= f1);
+
30  TEST(f2 != f1);
+
31 
+
32  TEST(f2 + f4 == f3 - f1);
+
33  TEST(f2 * f3 == f3);
+
34  TEST(f3 / f2 == f3);
+
35  f4 += f2;
+
36  TEST(f3 == f4);
+
37  f4 -= f1;
+
38  TEST(f3 == f4);
+
39  f4 *= f2;
+
40  TEST(f3 == f4);
+
41  f4 /= f2;
+
42  TEST(f3 == f4);
+
43 
+
44  TEST(-f4 == f1 - f4);
+
45  TEST(-(-f4) == f4);
+
46  --f4;
+
47  TEST(f4 + 1 == f3);
+
48  f4--;
+
49  TEST(f4 + 2 == f3);
+
50  ++f4;
+
51  TEST(f4 + 1 == f3);
+
52  f4++;
+
53  TEST(f4 == f3);
+
54  ++f3;
+
55  TEST(++f4 == f3);
+
56  TEST(f4-- == f3);
+
57  TEST(f4++ == --f3);
+
58  TEST(--f4 == f3);
+
59 
+
60  TEST(f4 / f3 == f2);
+
61  TEST(f4 - f3 == f1);
+
62 
+
63  TEST(f4.as_string() == "3.1416");
+
64  TEST(f4.integer() == 3);
+
65  f4 += fixed(0,4584);
+
66  TEST(f4 == 3.6);
+
67  TEST(f4.integer() == 3);
+
68  TEST(f4.round() == 4);
+
69 
+
70  TEST(f3.integer() == 3);
+
71  TEST((-f3).integer() == -3);
+
72  TEST(f3.fraction() == 1416);
+
73  TEST((-f3).fraction() == 1416);
+
74 
+
75  TEST(fixed(7,4999).round() == 7);
+
76  TEST(fixed(7,5000).round() == 8);
+
77  TEST(fixed(7,5001).round() == 8);
+
78  TEST(fixed(7,4999).round() == 7);
+
79  TEST(fixed(8,5000).round() == 8);
+
80  TEST(fixed(8,5001).round() == 9);
+
81 
+
82  TEST(fixed(123,2345500) == fixed(123,2346));
+
83  TEST(fixed(123,2345501) == fixed(123,2346));
+
84  TEST(fixed(123,2345499) == fixed(123,2345));
+
85  TEST(fixed(123,2346500) == fixed(123,2346));
+
86  TEST(fixed(123,2346501) == fixed(123,2347));
+
87  TEST(fixed(123,2346499) == fixed(123,2346));
+
88  TEST(fixed(123,2346400) == fixed(123,2346));
+
89  TEST(fixed(123,2346600) == fixed(123,2347));
+
90 
+
91  TEST(fixed(-7,4999).round() == -7);
+
92  TEST(fixed(-7,5000).round() == -8);
+
93  TEST(fixed(-7,5001).round() == -8);
+
94  TEST(fixed(-7,4999).round() == -7);
+
95  TEST(fixed(-8,5000).round() == -8);
+
96  TEST(fixed(-8,5001).round() == -9);
+
97 
+
98  TEST(fixed(-3.14159265).value() == -31416);
+
99  TEST(fixed(123,456789).value() == 1234568);
+
100  TEST(fixed(123,4).value() == 1230004);
+
101  TEST(fixed(-10,1111).value() == -101111);
+
102 
+
103  std::ostringstream out;
+
104  out << f3 << " 3.14159265 " << fixed(-10,12) << " 3 421.4 end";
+
105  fixed f5;
+
106  std::istringstream in(out.str());
+
107  TEST(in >> f5);
+
108  TEST(f5 == f3);
+
109  TEST(in >> f5);
+
110  TEST(f5 == f3);
+
111  TEST(in >> f5);
+
112  TEST(f5.value() == -100012);
+
113  TEST(in >> f5);
+
114  TEST(f5.value() == 30000);
+
115  TEST(in >> f5);
+
116  TEST(f5.value() == 4214000);
+
117  TEST(not (in >> f5));
+
118 
+
119  TEST(fixed(31.4159265) == fixed(31, 4159));
+
120  TEST(fixed(31.41595) == fixed(31, 4160));
+
121 
+
122  bool okay(false);
+
123  try {
+
124  fixed f6(1, -1);
+
125  } catch (std::invalid_argument const& ex) {
+
126  okay = true;
+
127  } catch (...) {
+
128  }
+
129  TEST(okay);
+
130 }
+
Implement a fixed-point number class. Values have places places after the decimal point...
Definition: fixed.hpp:37
+
value_type value() const
Return the internal value.
Definition: fixed.hpp:107
+
int main()
Definition: test.cpp:12
+
Fixed-point numbers.
+
+ + + + diff --git a/exploring-cpp-2e/chapter47/html/test_8hpp_source.html b/exploring-cpp-2e/chapter47/html/test_8hpp_source.html new file mode 100644 index 0000000..5718a46 --- /dev/null +++ b/exploring-cpp-2e/chapter47/html/test_8hpp_source.html @@ -0,0 +1,102 @@ + + + + + + +Project 2 - Fixed-Point Number Class: test.hpp Source File + + + + + + +
+
+ + + + + + +
+
Project 2 - Fixed-Point Number Class +
+
+
+ + + + +
+
+
+
test.hpp
+
+
+
1 #ifndef TEST_HPP_
+
2 #define TEST_HPP_
+
3 
+
4 #include <exception>
+
5 #include <iostream>
+
6 #include <ostream>
+
7 
+
8 // For internal use by the test() macro.
+
9 // Turn the macro argument into a character string literal
+
10 #define TEST_STRINGIFY(x) #x
+
11 
+
12 // For internal use by the test() macro.
+
13 // Report a test failure.
+
14 inline void test_failed(char const* expr, char const* file, int line)
+
15 {
+
16  std::cerr << file << ", line " << line << ": test failed: " << expr << '\n';
+
17 }
+
18 
+
19 // For internal use by the test() macro
+
20 // Run a test. Report a failure if the condition is false or
+
21 inline void test_run(bool condition, char const* expr, char const* file, int line)
+
22 {
+
23  if (not condition)
+
24  test_failed(expr, file, line);
+
25 }
+
26 
+
27 // For internal use by the test() macro.
+
28 // Report an exception.
+
29 inline void test_exception(std::exception const& ex, char const* expr, char const* file, int line)
+
30 {
+
31  std::string msg{ expr };
+
32  msg += " threw an exception: ";
+
33  msg += ex.what();
+
34  test_failed(msg.c_str(), file, line);
+
35 }
+
36 
+
45 #define TEST(x) \
+
46 try {\
+
47  test_run(x, TEST_STRINGIFY(x), __FILE__, __LINE__);\
+
48 }\
+
49 catch(std::exception const& ex)\
+
50 {\
+
51  test_exception(ex, TEST_STRINGIFY(x), __FILE__, __LINE__);\
+
52 }
+
53 
+
54 #endif
+
+ + + + diff --git a/exploring-cpp-2e/chapter47/ioflags.hpp b/exploring-cpp-2e/chapter47/ioflags.hpp new file mode 100644 index 0000000..45e28e2 --- /dev/null +++ b/exploring-cpp-2e/chapter47/ioflags.hpp @@ -0,0 +1,32 @@ +#ifndef IOFLAGS_HPP_ +#define IOFLAGS_HPP_ + +/** @file + * @brief Save and restore I/O stream flags. + */ + +/** Save and restore I/O stream flags. + * When a function needs to temporarily alter an I/O stream flags, + * simply define an object of type @c ioflags. Set whatever flags + * you want. When the block exits or function returns, the + * original flags are restored. + */ + +class ioflags +{ +public: + /// Save the formatting flags from @p stream. + /// @param stream The stream that will have its flags modified and restored. + ioflags(std::basic_ios& stream) : stream_(stream), flags_{stream.flags()} {} + /// Restore the formatting flags. + ~ioflags() { stream_.flags(flags_); } + + ioflags(ioflags const&) = delete; + ioflags& operator=(ioflags const&) = delete; + +private: + std::basic_ios& stream_; + std::ios_base::fmtflags flags_; +}; + +#endif diff --git a/exploring-cpp-2e/chapter47/list4701.cpp b/exploring-cpp-2e/chapter47/list4701.cpp new file mode 100644 index 0000000..bc00b53 --- /dev/null +++ b/exploring-cpp-2e/chapter47/list4701.cpp @@ -0,0 +1,127 @@ +// Listing 47-1. Testing the fixed Class +#include +#include +#include + +#include "test.hpp" +#include "fixed.hpp" + +int main() +{ + fixed f1{}; + test_equal(f1.value(), 0); + fixed f2{1}; + test_equal(f2.value(), 10000); + fixed f3{3, 14162}; + test_equal(f3.value(), 31416); + fixed f4{2, 14159265}; + test_equal(f4.value(), 21416); + test_equal(f2 + f4, f1 + f3); + test(f2 + f4 <= f1 + f3); + test(f2 + f4 >= f1 + f3); + test(f1 < f2); + test(f1 <= f2); + test(f1 != f2); + test(f2 > f1); + test(f2 >= f1); + test(f2 != f1); + + test_equal(f2 + f4, f3 - f1); + test_equal(f2 * f3, f3); + test_equal(f3 / f2, f3); + f4 += f2; + test_equal(f3, f4); + f4 -= f1; + test_equal(f3, f4); + f4 *= f2; + test_equal(f3, f4); + f4 /= f2; + test_equal(f3, f4); + + test_equal(-f4, f1 - f4); + test_equal(-(-f4), f4); + --f4; + test_equal(f4 + 1, f3); + f4--; + test_equal(f4 + 2, f3); + ++f4; + test_equal(f4 + 1, f3); + f4++; + test_equal(f4, f3); + ++f3; + test_equal(++f4, f3); + test_equal(f4--, f3); + test_equal(f4++, --f3); + test_equal(--f4, f3); + + test_equal(f4 / f3, f2); + test_equal(f4 - f3, f1); + + test_equal(f4.to_string(), "3.1416"); + test_equal(f4.integer(), 3); + f4 += fixed{0,4584}; + test_equal(f4, 3.6); + test_equal(f4.integer(), 3); + test_equal(f4.round(), 4); + + test_equal(f3.integer(), 3); + test_equal((-f3).integer(), -3); + test_equal(f3.fraction(), 1416); + test_equal((-f3).fraction(), 1416); + + test_equal(fixed{7,4999}.round(), 7); + test_equal(fixed{7,5000}.round(), 8); + test_equal(fixed{7,5001}.round(), 8); + test_equal(fixed{7,4999}.round(), 7); + test_equal(fixed{8,5000}.round(), 8); + test_equal(fixed{8,5001}.round(), 9); + + test_equal(fixed{123,2345500}, fixed(123,2346)); + test_equal(fixed{123,2345501}, fixed(123,2346)); + test_equal(fixed{123,2345499}, fixed(123,2345)); + test_equal(fixed{123,2346500}, fixed(123,2346)); + test_equal(fixed{123,2346501}, fixed(123,2347)); + test_equal(fixed{123,2346499}, fixed(123,2346)); + test_equal(fixed{123,2346400}, fixed(123,2346)); + test_equal(fixed{123,2346600}, fixed(123,2347)); + + test_equal(fixed{-7,4999}.round(), -7); + test_equal(fixed{-7,5000}.round(), -8); + test_equal(fixed{-7,5001}.round(), -8); + test_equal(fixed{-7,4999}.round(), -7); + test_equal(fixed{-8,5000}.round(), -8); + test_equal(fixed{-8,5001}.round(), -9); + + test_equal(fixed{-3.14159265}.value(), -31416); + test_equal(fixed{123,456789}.value(), 1234568); + test_equal(fixed{123,4}.value(), 1230004); + test_equal(fixed{-10,1111}.value(), -101111); + + std::ostringstream out{}; + out << f3 << " 3.14159265 " << fixed(-10,12) << " 3 421.4 end"; + fixed f5{}; + std::istringstream in{out.str()}; + test(in >> f5); + test_equal(f5, f3); + test(in >> f5); + test_equal(f5, f3); + test(in >> f5); + test_equal(f5.value(), -100012); + test(in >> f5); + test_equal(f5.value(), 30000); + test(in >> f5); + test_equal(f5.value(), 4214000); + test(not (in >> f5)); + + test_equal(fixed{31.4159265}, fixed{31, 4159}); + test_equal(fixed{31.41595}, fixed{31, 4160}); + + bool okay{false}; + try { + fixed f6{1, -1}; + } catch (std::invalid_argument const& ex) { + okay = true; + } catch (...) { + } + test(okay); +} diff --git a/exploring-cpp-2e/chapter47/test.cpp b/exploring-cpp-2e/chapter47/test.cpp new file mode 100644 index 0000000..d843ad7 --- /dev/null +++ b/exploring-cpp-2e/chapter47/test.cpp @@ -0,0 +1,130 @@ +/** @file test.cpp */ +/** Listing 45-1. Testing the fixed Class */ +#include +#include +#include +#include +#include + +#include "test.hpp" +#include "fixed.hpp" + +int main() +{ + fixed f1; + TEST(f1.value() == 0); + fixed f2(1); + TEST(f2.value() == 10000); + fixed f3(3, 14162); + TEST(f3.value() == 31416); + fixed f4(2, 14159265); + TEST(f4.value() == 21416); + TEST(f2 + f4 == f1 + f3); + TEST(f2 + f4 <= f1 + f3); + TEST(f2 + f4 >= f1 + f3); + TEST(f1 < f2); + TEST(f1 <= f2); + TEST(f1 != f2); + TEST(f2 > f1); + TEST(f2 >= f1); + TEST(f2 != f1); + + TEST(f2 + f4 == f3 - f1); + TEST(f2 * f3 == f3); + TEST(f3 / f2 == f3); + f4 += f2; + TEST(f3 == f4); + f4 -= f1; + TEST(f3 == f4); + f4 *= f2; + TEST(f3 == f4); + f4 /= f2; + TEST(f3 == f4); + + TEST(-f4 == f1 - f4); + TEST(-(-f4) == f4); + --f4; + TEST(f4 + 1 == f3); + f4--; + TEST(f4 + 2 == f3); + ++f4; + TEST(f4 + 1 == f3); + f4++; + TEST(f4 == f3); + ++f3; + TEST(++f4 == f3); + TEST(f4-- == f3); + TEST(f4++ == --f3); + TEST(--f4 == f3); + + TEST(f4 / f3 == f2); + TEST(f4 - f3 == f1); + + TEST(f4.as_string() == "3.1416"); + TEST(f4.integer() == 3); + f4 += fixed(0,4584); + TEST(f4 == 3.6); + TEST(f4.integer() == 3); + TEST(f4.round() == 4); + + TEST(f3.integer() == 3); + TEST((-f3).integer() == -3); + TEST(f3.fraction() == 1416); + TEST((-f3).fraction() == 1416); + + TEST(fixed(7,4999).round() == 7); + TEST(fixed(7,5000).round() == 8); + TEST(fixed(7,5001).round() == 8); + TEST(fixed(7,4999).round() == 7); + TEST(fixed(8,5000).round() == 8); + TEST(fixed(8,5001).round() == 9); + + TEST(fixed(123,2345500) == fixed(123,2346)); + TEST(fixed(123,2345501) == fixed(123,2346)); + TEST(fixed(123,2345499) == fixed(123,2345)); + TEST(fixed(123,2346500) == fixed(123,2346)); + TEST(fixed(123,2346501) == fixed(123,2347)); + TEST(fixed(123,2346499) == fixed(123,2346)); + TEST(fixed(123,2346400) == fixed(123,2346)); + TEST(fixed(123,2346600) == fixed(123,2347)); + + TEST(fixed(-7,4999).round() == -7); + TEST(fixed(-7,5000).round() == -8); + TEST(fixed(-7,5001).round() == -8); + TEST(fixed(-7,4999).round() == -7); + TEST(fixed(-8,5000).round() == -8); + TEST(fixed(-8,5001).round() == -9); + + TEST(fixed(-3.14159265).value() == -31416); + TEST(fixed(123,456789).value() == 1234568); + TEST(fixed(123,4).value() == 1230004); + TEST(fixed(-10,1111).value() == -101111); + + std::ostringstream out; + out << f3 << " 3.14159265 " << fixed(-10,12) << " 3 421.4 end"; + fixed f5; + std::istringstream in(out.str()); + TEST(in >> f5); + TEST(f5 == f3); + TEST(in >> f5); + TEST(f5 == f3); + TEST(in >> f5); + TEST(f5.value() == -100012); + TEST(in >> f5); + TEST(f5.value() == 30000); + TEST(in >> f5); + TEST(f5.value() == 4214000); + TEST(not (in >> f5)); + + TEST(fixed(31.4159265) == fixed(31, 4159)); + TEST(fixed(31.41595) == fixed(31, 4160)); + + bool okay(false); + try { + fixed f6(1, -1); + } catch (std::invalid_argument const& ex) { + okay = true; + } catch (...) { + } + TEST(okay); +} diff --git a/exploring-cpp-2e/chapter47/test.hpp b/exploring-cpp-2e/chapter47/test.hpp new file mode 100644 index 0000000..5e7776f --- /dev/null +++ b/exploring-cpp-2e/chapter47/test.hpp @@ -0,0 +1,54 @@ +#ifndef TEST_HPP_ +#define TEST_HPP_ + +#include +#include +#include + +// For internal use by the test() macro. +// Turn the macro argument into a character string literal +#define TEST_STRINGIFY(x) #x + +// For internal use by the test() macro. +// Report a test failure. +inline void test_failed(char const* expr, char const* file, int line) +{ + std::cerr << file << ", line " << line << ": test failed: " << expr << '\n'; +} + +// For internal use by the test() macro +// Run a test. Report a failure if the condition is false or +inline void test_run(bool condition, char const* expr, char const* file, int line) +{ + if (not condition) + test_failed(expr, file, line); +} + +// For internal use by the test() macro. +// Report an exception. +inline void test_exception(std::exception const& ex, char const* expr, char const* file, int line) +{ + std::string msg{ expr }; + msg += " threw an exception: "; + msg += ex.what(); + test_failed(msg.c_str(), file, line); +} + +/// Test a condition, @p x. +/// If @p x evaluates to @c true the test passes. +/// If not, the test fails, and a message is printed to @c cerr. +/// The text of @p x, plus the file name and line number are printed. +/// +/// See Boost.Test for a real test framework +/// +/// @param x A condition to test; the condition must be able to be converted implicitly to @c bool. +#define TEST(x) \ +try {\ + test_run(x, TEST_STRINGIFY(x), __FILE__, __LINE__);\ +}\ +catch(std::exception const& ex)\ +{\ + test_exception(ex, TEST_STRINGIFY(x), __FILE__, __LINE__);\ +} + +#endif diff --git a/exploring-cpp-2e/chapter48/gcd.hpp b/exploring-cpp-2e/chapter48/gcd.hpp new file mode 100644 index 0000000..4221c28 --- /dev/null +++ b/exploring-cpp-2e/chapter48/gcd.hpp @@ -0,0 +1,19 @@ +// Listing 48-9. The gcd Function Template +#ifndef GCD_HPP_ +#define GCD_HPP_ + +#include // for std::abs + +template +/// Compute the greatest common divisor of two integers, using Euclid's algorithm. +T gcd(T n, T m) +{ + n = std::abs(n); + while (m != 0) { + T tmp{n % m}; + n = m; + m = tmp; + } + return n; +} +#endif diff --git a/exploring-cpp-2e/chapter48/list4801.cpp b/exploring-cpp-2e/chapter48/list4801.cpp new file mode 100644 index 0000000..2a59549 --- /dev/null +++ b/exploring-cpp-2e/chapter48/list4801.cpp @@ -0,0 +1,8 @@ +// Listing 48-1. Writing an Absolute Value Function +T absval(T x) +{ + if (x < 0) + return -x; + else + return x; +} diff --git a/exploring-cpp-2e/chapter48/list4802.cpp b/exploring-cpp-2e/chapter48/list4802.cpp new file mode 100644 index 0000000..a4af938 --- /dev/null +++ b/exploring-cpp-2e/chapter48/list4802.cpp @@ -0,0 +1,9 @@ +// Listing 48-2. Writing a Function Template +template +T absval(T x) +{ + if (x < 0) + return -x; + else + return x; +} diff --git a/exploring-cpp-2e/chapter48/list4803.cpp b/exploring-cpp-2e/chapter48/list4803.cpp new file mode 100644 index 0000000..19f3d83 --- /dev/null +++ b/exploring-cpp-2e/chapter48/list4803.cpp @@ -0,0 +1,25 @@ +// Listing 48-3. Testing the absval Function Template +#include +#include "rational.hpp" // Listing 46-10 + + +template +T absval(T x) +{ + if (x < 0) + return -x; + else + return x; +} + +int main() +{ + std::cout << absval(-42) << '\n'; + std::cout << absval(-4.2) << '\n'; + std::cout << absval(42) << '\n'; + std::cout << absval(4.2) << '\n'; + std::cout << absval(-42L) << '\n'; + std::cout << absval(rational{42, 5}) << '\n'; + std::cout << absval(rational{-42, 5}) << '\n'; + std::cout << absval(rational{42, -5}) << '\n'; +} diff --git a/exploring-cpp-2e/chapter48/list4804.cpp b/exploring-cpp-2e/chapter48/list4804.cpp new file mode 100644 index 0000000..3dc2eea --- /dev/null +++ b/exploring-cpp-2e/chapter48/list4804.cpp @@ -0,0 +1,10 @@ +// Listing 48-4. Mystery Function Template +template +T add(T lhs, T rhs) +{ + return lhs(rhs); +} + +int main() +{ +} diff --git a/exploring-cpp-2e/chapter48/list4805.cpp b/exploring-cpp-2e/chapter48/list4805.cpp new file mode 100644 index 0000000..a54d25e --- /dev/null +++ b/exploring-cpp-2e/chapter48/list4805.cpp @@ -0,0 +1,8 @@ +// Listing 48-5. One Way to Implement the copy Algorithm +template +OutputIterator copy(InputIterator start, InputIterator end, OutputIterator result) +{ + for ( ; start != end; ++start, ++result) + *result = *start; + return result; +} diff --git a/exploring-cpp-2e/chapter48/list4806.cpp b/exploring-cpp-2e/chapter48/list4806.cpp new file mode 100644 index 0000000..477f94c --- /dev/null +++ b/exploring-cpp-2e/chapter48/list4806.cpp @@ -0,0 +1,9 @@ +// Listing 48-6. Implementing the find Algorithm +template +InputIterator find(InputIterator start, InputIterator end, T value) +{ + for ( ; start != end; ++start) + if (*start == value) + return start; + return end; +} diff --git a/exploring-cpp-2e/chapter48/list4807.cpp b/exploring-cpp-2e/chapter48/list4807.cpp new file mode 100644 index 0000000..97c5ac4 --- /dev/null +++ b/exploring-cpp-2e/chapter48/list4807.cpp @@ -0,0 +1,11 @@ +// Listing 48-7. The std::min Algorithm +template +T min(T a, T b) +{ + if (a < b) + return a; + else if (b < a) + return b; + else + return a; // a and b are equivalent, so return a +} diff --git a/exploring-cpp-2e/chapter48/list4808.cpp b/exploring-cpp-2e/chapter48/list4808.cpp new file mode 100644 index 0000000..0f4a1b2 --- /dev/null +++ b/exploring-cpp-2e/chapter48/list4808.cpp @@ -0,0 +1,18 @@ +// Listing 48-8. Multiple Template Arguments +#include + +template +U input_sum(std::istream& in) +{ + T x{}; + U sum{0}; + while (in >> x) + sum += x; + return sum; +} + +int main() +{ + long sum{input_sum(std::cin)}; + std::cout << sum << '\n'; +} diff --git a/exploring-cpp-2e/chapter48/list4809.hpp b/exploring-cpp-2e/chapter48/list4809.hpp new file mode 100644 index 0000000..4221c28 --- /dev/null +++ b/exploring-cpp-2e/chapter48/list4809.hpp @@ -0,0 +1,19 @@ +// Listing 48-9. The gcd Function Template +#ifndef GCD_HPP_ +#define GCD_HPP_ + +#include // for std::abs + +template +/// Compute the greatest common divisor of two integers, using Euclid's algorithm. +T gcd(T n, T m) +{ + n = std::abs(n); + while (m != 0) { + T tmp{n % m}; + n = m; + m = tmp; + } + return n; +} +#endif diff --git a/exploring-cpp-2e/chapter48/list4810.cpp b/exploring-cpp-2e/chapter48/list4810.cpp new file mode 100644 index 0000000..e10dbfc --- /dev/null +++ b/exploring-cpp-2e/chapter48/list4810.cpp @@ -0,0 +1,42 @@ +// Listing 48-10. Implementing a Member Function Template +class rational +{ +public: + rational() : rational{0} {} + rational(int num) : numerator_{num}, denominator_{1} {} + rational(int num, int den); + rational(double r); + + int numerator() const { return numerator_; } + int denominator() const { return denominator_; } + + template + T convert() + const + { + return static_cast(numerator()) / static_cast(denominator()); + } + + rational& operator=(int); // optimization to avoid an unneeded call to reduce() + rational& operator+=(rational const& rhs); + rational& operator-=(rational const& rhs); + rational& operator*=(rational const& rhs); + rational& operator/=(rational const& rhs); + rational& operator++(); + rational& operator--(); + rational operator++(int); + rational operator--(int); + +private: + /// Reduce the numerator and denominator by their GCD. + void reduce(); + /// Reduce the numerator and denominator, and normalize the signs of both, + /// that is, ensure denominator is not negative. + void normalize(); + /// Return an initial value for denominator_. Throw a zero_denominator + /// exception if @p den is zero. Always return a positive number. + int init_denominator(int den); + + int numerator_; + int denominator_; +}; diff --git a/exploring-cpp-2e/chapter48/rational.cpp b/exploring-cpp-2e/chapter48/rational.cpp new file mode 100644 index 0000000..b66777d --- /dev/null +++ b/exploring-cpp-2e/chapter48/rational.cpp @@ -0,0 +1,265 @@ +#include +#include +#include +#include + +#include "rational.hpp" + +/// Compute the greatest common divisor of two integers, using Euclid’s algorithm. +int gcd(int n, int m) +{ + n = std::abs(n); + while (m != 0) { + int tmp(n % m); + n = m; + m = tmp; + } + return n; +} + +// Listing 46-2. Using a Function and Conditional Statements Instead of Conditional Expressions +/// Construct a rational object from a numerator and a denominator. +/// If the denominator is zero, throw zero_denominator. If the denominator +/// is negative, normalize the value by negating the numerator and denominator. +/// @post denominator_ > 0 +/// @throws zero_denominator +rational::rational(int num, int den) +: numerator_{den < 0 ? -num : num}, denominator_{init_denominator(den)} +{ + reduce(); +} + +/// Return an initial value for the denominator_ member. This function is used +/// only in a constructor's initializer list. +int rational::init_denominator(int den) +{ + if (den == 0) + throw zero_denominator("0 denominator"); + else if (den < 0) + return -den; + else + return den; +} + +rational::rational(double r) +: rational{static_cast(r * 10000), 10000} +{ + reduce(); +} + +float rational::to_float() +const +{ + return static_cast(numerator()) / denominator(); +} + +double rational::to_double() +const +{ + return static_cast(numerator()) / denominator(); +} + +long double rational::to_long_double() +const +{ + return static_cast(numerator()) / denominator(); +} + +/// Assign a numerator and a denominator, then reduce to normal form. +void assign(int num, int den) +{ + numerator_ = den < 0 ? -num : num; + denominator_ = init_denominator(den); + reduce(); +} + +void rational::reduce() +{ + int div{gcd(numerator(), denominator())}; + numerator_ = numerator() / div; + denominator_ = denominator() / div; +} + +// Listing 46-5. Implementing the Multiplication Assignment Operator +rational& rational::operator*=(rational const& rhs) +{ + numerator_ *= rhs.numerator(); + denominator_ *= rhs.denominator(); + reduce(); + return *this; +} + +// Listing 46-7. Other Arithmetic Assignment Operators +rational& rational::operator+=(rational const& rhs) +{ + numerator_ = numerator() * rhs.denominator() + rhs.numerator() * denominator(); + denominator_ *= rhs.denominator(); + reduce(); + return *this; +} + +rational& rational::operator-=(rational const& rhs) +{ + numerator_ = numerator() * rhs.denominator() - rhs.numerator() * denominator(); + denominator_ *= rhs.denominator(); + reduce(); + return *this; +} + +rational& rational::operator/=(rational const& rhs) +{ + if (rhs.numerator() == 0) + throw zero_denominator{"divide by zero"}; + numerator_ *= rhs.denominator(); + denominator_ *= rhs.numerator(); + if (denominator_ < 0) + { + denominator_ = -denominator_; + numerator_ = -numerator_; + } + reduce(); + return *this; +} + +// Listing 46-8. The Prefix Increment Operator for rational +rational& rational::operator++() +{ + numerator_ += denominator_; + return *this; +} + +rational& rational::operator--() +{ + numerator_ -= denominator_; + return *this; +} + +// Listing 46-9. Postfix Increment and Decrement Operators +rational rational::operator++(int) +{ + rational result{*this}; + numerator_ += denominator_; + return result; +} + +rational rational::operator--(int) +{ + rational result{*this}; + numerator_ -= denominator_; + return result; +} + +/// Absolute value of a rational number. +rational abs(rational const& r) +{ + return rational{std::abs(r.numerator()), r.denominator()}; +} + +/// Unary negation of a rational number. +rational operator-(rational const& r) +{ + return rational{-r.numerator(), r.denominator()}; +} + +/// Add rational numbers. +rational operator+(rational const& lhs, rational const& rhs) +{ + rational result{lhs}; + result += rhs; + return result; +} + +/// Subtraction of rational numbers. +rational operator-(rational const& lhs, rational const& rhs) +{ + rational result{lhs}; + result -= rhs; + return result; +} + +/// Multiplication of rational numbers. +rational operator*(rational const& lhs, rational const& rhs) +{ + rational result{lhs}; + result *= rhs; + return result; +} + +rational operator/(rational const& lhs, rational const& rhs) +{ + rational result{lhs}; + result /= rhs; + return result; +} + + +/// Compare two rational numbers for equality. +bool operator==(rational const& a, rational const& b) +{ + return a.numerator() == b.numerator() and a.denominator() == b.denominator(); +} + +/// Compare two rational numbers for inequality. +inline bool operator!=(rational const& a, rational const& b) +{ + return not (a == b); +} +/// Compare two rational numbers for less-than. +bool operator<(rational const& a, rational const& b) +{ + return a.numerator() * b.denominator() < b.numerator() * a.denominator(); +} + +/// Compare two rational numbers for less-than-or-equal. +inline bool operator<=(rational const& a, rational const& b) +{ + return not (b < a); +} +/// Compare two rational numbers for greater-than. +inline bool operator>(rational const& a, rational const& b) +{ + return b < a; +} + +/// Compare two rational numbers for greater-than-or-equal. +inline bool operator>=(rational const& a, rational const& b) +{ + return not (b > a); +} + +/// Read a rational number. +/// Format is @em integer @c / @em integer. +std::istream& operator>>(std::istream& in, rational& rat) +{ + int n{}, d{}; + char sep{}; + if (not (in >> n >> sep)) + // Error reading the numerator or the separator character. + in.setstate(in.failbit); + else if (sep != '/') + { + // Push sep back into the input stream, so the next input operation + // will read it. + in.unget(); + rat.assign(n, 1); + } + else if (in >> d) + // Successfully read numerator, separator, and denominator. + rat.assign(n, d); + else + // Error reading denominator. + in.setstate(in.failbit); + + return in; +} + +/// Write a rational numbers. +/// Format is @em numerator @c / @em denominator. +std::ostream& operator<<(std::ostream& out, rational const& rat) +{ + std::ostringstream tmp{}; + tmp << rat.numerator() << '/' << rat.denominator(); + out << tmp.str(); + + return out; +} diff --git a/exploring-cpp-2e/chapter48/rational.hpp b/exploring-cpp-2e/chapter48/rational.hpp new file mode 100644 index 0000000..a8e76a1 --- /dev/null +++ b/exploring-cpp-2e/chapter48/rational.hpp @@ -0,0 +1,88 @@ +// Listing 46-10. The rational Class Definition +#ifndef RATIONAL_HPP_ +#define RATIONAL_HPP_ + +#include +#include +#include + +/// Represent a rational number (fraction) as a numerator and denominator. +class rational +{ +public: + class zero_denominator : public std::logic_error + { + public: + zero_denominator(std::string const& what) : logic_error{what} {} + }; + rational(): rational{0} {} + rational(int num): numerator_{num}, denominator_{1} {} + rational(int num, int den); + rational(double r); + + int numerator() const { return numerator_; } + int denominator() const { return denominator_; } + float as_float() const; + double as_double() const; + long double as_long_double() const; + + rational& operator=(int); // optimization to avoid an unneeded call to reduce() + rational& operator+=(rational const& rhs); + rational& operator-=(rational const& rhs); + rational& operator*=(rational const& rhs); + rational& operator/=(rational const& rhs); + rational& operator++(); + rational& operator--(); + rational operator++(int); + rational operator--(int); + +private: + /// Reduce the numerator and denominator by their GCD. + void reduce(); + /// Reduce the numerator and denominator, and normalize the signs of both, + /// that is, ensure denominator is not negative. + void normalize(); + /// Return an initial value for denominator_. Throw a zero_denominator + /// exception if @p den is zero. Always return a positive number. + int init_denominator(int den); + int numerator_; + int denominator_; +}; + +/// Compute the greatest common divisor of two integers, using Euclid's algorithm. +int gcd(int n, int m); + +rational abs(rational const& r); +rational operator-(rational const& r); +rational operator+(rational const& lhs, rational const& rhs); +rational operator-(rational const& lhs, rational const& rhs); +rational operator*(rational const& lhs, rational const& rhs); +rational operator/(rational const& lhs, rational const& rhs); + +bool operator==(rational const& a, rational const& b); +bool operator<(rational const& a, rational const& b); + +inline bool operator!=(rational const& a, rational const& b) +{ + return not (a == b); +} + +inline bool operator<=(rational const& a, rational const& b) +{ + return not (b < a); +} + +inline bool operator>(rational const& a, rational const& b) +{ + return b < a; +} + +inline bool operator>=(rational const& a, rational const& b) +{ + return not (b > a); +} + +std::istream& operator>>(std::istream& in, rational& rat); +std::ostream& operator<<(std::ostream& out, rational const& rat); + +#endif diff --git a/exploring-cpp-2e/chapter49/list4901.cpp b/exploring-cpp-2e/chapter49/list4901.cpp new file mode 100644 index 0000000..baf0a39 --- /dev/null +++ b/exploring-cpp-2e/chapter49/list4901.cpp @@ -0,0 +1,19 @@ +// Listing 49-1. The point Class Template +template +class point { +public: + point(T x, T y) : x_{x}, y_{y} {} + T x() const { return x_; } + T y() const { return y_; } + void move_to(T x, T y); ///< Move to absolute coordinates (x, y) + void move_by(T x, T y); ///< Add (x, y) to current position +private: + T x_, y_; +}; + +template +void point::move_to(T x, T y) +{ + x_ = x; + y_ = y; +} diff --git a/exploring-cpp-2e/chapter49/list4902.cpp b/exploring-cpp-2e/chapter49/list4902.cpp new file mode 100644 index 0000000..a1c6302 --- /dev/null +++ b/exploring-cpp-2e/chapter49/list4902.cpp @@ -0,0 +1,7 @@ +// Listing 49-2. The move_by Member Function +template +void point::move_by(T x, T y) +{ + x_ += x; + y_ += y; +} diff --git a/exploring-cpp-2e/chapter49/list4903.hpp b/exploring-cpp-2e/chapter49/list4903.hpp new file mode 100644 index 0000000..a4bd1a9 --- /dev/null +++ b/exploring-cpp-2e/chapter49/list4903.hpp @@ -0,0 +1,58 @@ +// Listing 49-3. The rational Class Template +#ifndef RATIONAL_HPP_ +#define RATIONAL_HPP_ +template +class rational +{ +public: + typedef T value_type; + rational() : rational{0} {} + rational(T num) : numerator_{num}, denominator_{1} {} + rational(T num, T den); + + void assign(T num, T den); + + template + U convert() + const + { + return static_cast(numerator()) / static_cast(denominator()); + } + + T numerator() const { return numerator_; } + T denominator() const { return denominator_; } +private: + void reduce(); + T numerator_; + T denominator_; +}; + +template +rational::rational(T num, T den) +: numerator_{num}, denominator_{den} +{ + reduce(); +} + +template +void rational::assign(T num, T den) +{ + numerator_ = num; + denominator_ = den; + reduce(); +} + +template +bool operator==(rational const& a, rational const& b) +{ + return a.numerator() == b.numerator() and + a.denominator() == b.denominator(); +} + +template +inline bool operator!=(rational const& a, rational const& b) +{ + return not (a == b); +} + +#endif diff --git a/exploring-cpp-2e/chapter49/list4904.cpp b/exploring-cpp-2e/chapter49/list4904.cpp new file mode 100644 index 0000000..7e26255 --- /dev/null +++ b/exploring-cpp-2e/chapter49/list4904.cpp @@ -0,0 +1,36 @@ +// Listing 49-4. Simple I/O Test of the rational Class Template +#include +#include "rational.hpp" + +template +std::istream& operator>>(std::istream& in, rational& rat) +{ + T n{}, d{}; + char sep{}; + if (not (in >> n >> sep)) + // Error reading the numerator or the separator character. + in.setstate(in.failbit); + else if (sep != '/') + { + // Push sep back into the input stream, so the next input operation + // will read it. + in.unget(); + rat.assign(n, 1); + } + else if (in >> d) + // Successfully read numerator, separator, and denominator. + rat.assign(n, d); + else + // Error reading denominator. + in.setstate(in.failbit); + + return in; +} + +int main() +{ + rational r{}; + while (std::cin >> r) + std::cout << r << '\n'; +} + diff --git a/exploring-cpp-2e/chapter49/list4905.cpp b/exploring-cpp-2e/chapter49/list4905.cpp new file mode 100644 index 0000000..9d462dc --- /dev/null +++ b/exploring-cpp-2e/chapter49/list4905.cpp @@ -0,0 +1,11 @@ +// Listing 49-5. Testing rational Comparison Operator +#include +#include "rational.hpp" + +int main() +{ + rational r{}; + while (std::cin >> r) + if (r != 0) + std::cout << r << '\n'; +} diff --git a/exploring-cpp-2e/chapter49/list4906.cpp b/exploring-cpp-2e/chapter49/list4906.cpp new file mode 100644 index 0000000..7878398 --- /dev/null +++ b/exploring-cpp-2e/chapter49/list4906.cpp @@ -0,0 +1,16 @@ +// Listing 49-6. Invoking a Default Constructor of a Template Parameter +template +rational& rational::operator/=(rational const& rhs) +{ + if (rhs.numerator() == T{}) + throw zero_denominator("divide by zero"); + numerator_ *= rhs.denominator(); + denominator_ *= rhs.numerator(); + if (denominator_ < T{}) + { + denominator_ = -denominator_; + numerator_ = -numerator_; + } + reduce(); + return *this; +} diff --git a/exploring-cpp-2e/chapter49/list4907.cpp b/exploring-cpp-2e/chapter49/list4907.cpp new file mode 100644 index 0000000..060d818 --- /dev/null +++ b/exploring-cpp-2e/chapter49/list4907.cpp @@ -0,0 +1,9 @@ +// Listing 49-7. Trying to Mix rational Base Types +#include "rational.hpp" + +int main() +{ + rational little{}; + rational big{}; + big = little; +} diff --git a/exploring-cpp-2e/chapter49/list4908.cpp b/exploring-cpp-2e/chapter49/list4908.cpp new file mode 100644 index 0000000..41c7cf0 --- /dev/null +++ b/exploring-cpp-2e/chapter49/list4908.cpp @@ -0,0 +1,8 @@ +// Listing 49-8. Defining the Assignment Operator Function Template +template +template +rational& rational::operator=(rational const& rhs) +{ + assign(rhs.numerator(), rhs.denominator()); + return *this; +} diff --git a/exploring-cpp-2e/chapter49/list4909.cpp b/exploring-cpp-2e/chapter49/list4909.cpp new file mode 100644 index 0000000..93ffa8f --- /dev/null +++ b/exploring-cpp-2e/chapter49/list4909.cpp @@ -0,0 +1,6 @@ +// Listing 49-9. Defining a Member Constructor Template +template +template +rational::rational(rational const& copy) +: numerator_{copy.numerator()}, denominator_{copy.denominator()} +{} diff --git a/exploring-cpp-2e/chapter49/rational.hpp b/exploring-cpp-2e/chapter49/rational.hpp new file mode 100644 index 0000000..483e30e --- /dev/null +++ b/exploring-cpp-2e/chapter49/rational.hpp @@ -0,0 +1,100 @@ +// Listing 49-3. The rational Class Template +#ifndef RATIONAL_HPP_ +#define RATIONAL_HPP_ + +#include +#include +#include + +/// Compute the greatest common divisor of two integers, using Euclid’s algorithm. +int gcd(int n, int m) +{ + n = std::abs(n); + while (m != 0) { + int tmp(n % m); + n = m; + m = tmp; + } + return n; +} + + +template +class rational +{ +public: + typedef T value_type; + rational() : rational{0} {} + rational(T num) : numerator_{num}, denominator_{1} {} + rational(T num, T den); + + void assign(T num, T den); + + template + U convert() + const + { + return static_cast(numerator()) / static_cast(denominator()); + } + + T numerator() const { return numerator_; } + T denominator() const { return denominator_; } +private: + void reduce(); + T numerator_; + T denominator_; +}; + +template +rational::rational(T num, T den) +: numerator_{num}, denominator_{den} +{ + reduce(); +} + +template +void rational::assign(T num, T den) +{ + numerator_ = num; + denominator_ = den; + reduce(); +} + +template +void rational::reduce() +{ + assert(denominator() != 0); + if (denominator() < 0) + { + denominator_ = -denominator(); + numerator_ = -numerator(); + } + int div{gcd(numerator(), denominator())}; + numerator_ = numerator() / div; + denominator_ = denominator() / div; +} + +template +bool operator==(rational const& a, rational const& b) +{ + return a.numerator() == b.numerator() and + a.denominator() == b.denominator(); +} + +template +inline bool operator!=(rational const& a, rational const& b) +{ + return not (a == b); +} + +template +std::istream& operator>>(std::istream& in, rational& rat); + +template +std::ostream& operator<<(std::ostream& in, rational& rat) +{ + in << rat.numerator() << '/' << rat.denominator(); + return in; +} + +#endif diff --git a/exploring-cpp-2e/chapter50/list5001.cpp b/exploring-cpp-2e/chapter50/list5001.cpp new file mode 100644 index 0000000..8c5e9e0 --- /dev/null +++ b/exploring-cpp-2e/chapter50/list5001.cpp @@ -0,0 +1,22 @@ +// Listing 50-1. The point Class Template +template +class point +{ +public: + typedef T value_type; + point(T const& x, T const& y) : x_{x}, y_{y} {} + point() : point{T{}, T{}} {} + T const& x() const { return x_; } + T const& y() const { return y_; } + void move_absolute(T const& x, T const& y) { + x_ = x; + y_ = y; + } + void move_relative(T const& dx, T const& dy) { + x_ += dx; + y_ += dy; + } +private: + T x_; + T y_; +}; diff --git a/exploring-cpp-2e/chapter50/list5002.cpp b/exploring-cpp-2e/chapter50/list5002.cpp new file mode 100644 index 0000000..ebaff36 --- /dev/null +++ b/exploring-cpp-2e/chapter50/list5002.cpp @@ -0,0 +1,22 @@ +// Listing 50-2. The point Specialization +template<> +class point +{ +public: + typedef int value_type; + point(int x, int y) : x_{x}, y_{y} {} + point() : point{0, 0} {} + int x() const { return x_; } + int y() const { return y_; } + void move_absolute(int x, int y) { + x_ = x; + y_ = y; + } + void move_relative(int dx, int dy) { + x_ += dx; + y_ += dy; + } +private: + int x_; + int y_; +}; diff --git a/exploring-cpp-2e/chapter50/list5003.cpp b/exploring-cpp-2e/chapter50/list5003.cpp new file mode 100644 index 0000000..9ffaf0b --- /dev/null +++ b/exploring-cpp-2e/chapter50/list5003.cpp @@ -0,0 +1,54 @@ +// Listing 50-3. Specializing point and Testing the Code +#include + +template +class point +{ +public: + typedef T value_type; + point(T const& x, T const& y) : x_{x}, y_{y} {} + point() : point{T{}, T{}} { std::cout << "point<>()\n"; } + T const& x() const { return x_; } + T const& y() const { return y_; } + void move_absolute(T const& x, T const& y) { + x_ = x; + y_ = y; + } + void move_relative(T const& dx, T const& dy) { + x_ += dx; + y_ += dy; + } +private: + T x_; + T y_; +}; + +template<> +class point +{ +public: + typedef double value_type; + point(double x, double y) : x_(x), y_(y) {} + point() : point{0.0, 0.0} { std::cout << "point specialization\n"; } + double x() const { return x_; } + double y() const { return y_; } + void move_absolute(double x, double y) { + x_ = x; + y_ = y; + } + void move_relative(double dx, double dy) { + x_ += dx; + y_ += dy; + } +private: + double x_; + double y_; +}; + +int main() +{ + point s; + point d; + s.move_absolute(10, 20); + d.move_absolute(1.23, 4.56); +} diff --git a/exploring-cpp-2e/chapter50/list5004.cpp b/exploring-cpp-2e/chapter50/list5004.cpp new file mode 100644 index 0000000..21ee485 --- /dev/null +++ b/exploring-cpp-2e/chapter50/list5004.cpp @@ -0,0 +1,37 @@ +// Listing 50-4. Specializing std::less to Compare person Objects by Name +#include +#include +#include +#include + +class person { +public: + person() : name_{}, address_{}, phone_{} {} + person(std::string const& name, + std::string const& address, + std::string const& phone) + : name_{name}, address_{address}, phone_{phone} + {} + std::string const& name() const { return name_; } + std::string const& address() const { return address_; } + std::string const& phone() const { return phone_; } +private: + std::string name_, address_, phone_; +}; + +namespace std { + template<> + struct less { + bool operator()(person const& a, person const& b) const { + return a.name() < b.name(); + } + }; +} + +int main() +{ + std::map people; + people[person{"Ray", "123 Erewhon", "555-5555"}] = 42; + people[person{"Arthur", "456 Utopia", "123-4567"}]= 10; + std::cout << people.begin()->first.name() << '\n'; +} diff --git a/exploring-cpp-2e/chapter50/list5005.cpp b/exploring-cpp-2e/chapter50/list5005.cpp new file mode 100644 index 0000000..04d0d16 --- /dev/null +++ b/exploring-cpp-2e/chapter50/list5005.cpp @@ -0,0 +1,6 @@ +// Listing 50-5. The Primary std::less Class Template +template +struct less +{ + bool operator()(T const& a, T const& b) const { return a < b; } +}; diff --git a/exploring-cpp-2e/chapter50/list5006.cpp b/exploring-cpp-2e/chapter50/list5006.cpp new file mode 100644 index 0000000..f4eef04 --- /dev/null +++ b/exploring-cpp-2e/chapter50/list5006.cpp @@ -0,0 +1,49 @@ +// Listing 50-6. Specializing numeric_limits for the rational Class +namespace std { +template<> +class numeric_limits +{ +public: + static constexpr bool is_specialized{true}; + static constexpr rational min() noexcept { return rational(numeric_limits::min()); } + static constexpr rational max() noexcept { return rational(numeric_limits::max()); } + static rational lowest() noexcept { return -max(); } + static constexpr int digits{ 2 * numeric_limits::digits }; + static constexpr int digits10{ numeric_limits::digits10 }; + static constexpr int max_digits10{ numeric_limits::max_digits10 }; + static constexpr bool is_signed{ true }; + static constexpr bool is_integer{ false }; + static constexpr bool is_exact{ true }; + static constexpr int radix{ 2 }; + static constexpr bool is_bounded{ true }; + static constexpr bool is_modulo{ false }; + static constexpr bool traps{ std::numeric_limits::traps }; + + static rational epsilon() noexcept + { return rational(1, numeric_limits::max()-1); } + static rational round_error() noexcept + { return rational(1, numeric_limits::max()); } + + // The following are meaningful only for floating-point types. + static constexpr int min_exponent{ 0 }; + static constexpr int min_exponent10{ 0 }; + static constexpr int max_exponent{ 0 }; + static constexpr int max_exponent10{ 0 }; + static constexpr bool has_infinity{ false }; + static constexpr bool has_quiet_NaN{ false }; + static constexpr bool has_signaling_NaN{ false }; + static constexpr float_denorm_style has_denorm {denorm_absent}; + static constexpr bool has_denorm_loss {false}; + // The following are meant only for floating-point types, but you have + // to define them, anyway, even for nonfloating-point types. The values + // they return do not have to be meaningful. + static constexpr rational infinity() noexcept { return max(); } + static constexpr rational quiet_NaN() noexcept { return rational(); } + static constexpr rational signaling_NaN() noexcept { return rational(); } + static constexpr rational denorm_min() noexcept { return rational(); } + static constexpr bool is_iec559{ false }; + static constexpr bool tinyness_before{ false }; + static constexpr float_round_style round_style{ round_toward_zero }; +}; + +} // namespace std diff --git a/exploring-cpp-2e/chapter51/list5101.cpp b/exploring-cpp-2e/chapter51/list5101.cpp new file mode 100644 index 0000000..edf463b --- /dev/null +++ b/exploring-cpp-2e/chapter51/list5101.cpp @@ -0,0 +1,13 @@ +// Listing 51-1. The std::pair Class Template +template +struct pair +{ + typedef T first_type; + typedef U second_type; + T first; + U second; + pair(); + pair(T const& first, U const& second); + template + pair(pair const& other); +}; diff --git a/exploring-cpp-2e/chapter51/list5102.cpp b/exploring-cpp-2e/chapter51/list5102.cpp new file mode 100644 index 0000000..75bb8f3 --- /dev/null +++ b/exploring-cpp-2e/chapter51/list5102.cpp @@ -0,0 +1,10 @@ +// Listing 51-2. Specializing pair<> for Two void Arguments +template<> +struct pair +{ + typedef void first_type; + typedef void second_type; + pair(pair const&) = default; + pair() = default; + pair& operator=(pair const&) = default; +}; diff --git a/exploring-cpp-2e/chapter51/list5103.cpp b/exploring-cpp-2e/chapter51/list5103.cpp new file mode 100644 index 0000000..139ecde --- /dev/null +++ b/exploring-cpp-2e/chapter51/list5103.cpp @@ -0,0 +1,13 @@ +// Listing 51-3. Specializing pair for One void Argument +template +struct pair +{ + typedef void first_type; + typedef U second_type; + U second; + pair() = default; + pair(pair const&) = default; + pair(U const& second); + template + pair(pair const& other); +}; diff --git a/exploring-cpp-2e/chapter51/list5104.cpp b/exploring-cpp-2e/chapter51/list5104.cpp new file mode 100644 index 0000000..0e4a7b3 --- /dev/null +++ b/exploring-cpp-2e/chapter51/list5104.cpp @@ -0,0 +1,13 @@ +// Listing 51-4. Specializing pair for the Other void Argument +template +struct pair +{ + typedef T first_type; + typedef void second_type; + T first; + pair() = default; + pair(pair const&) = default; + pair(T const& first); + template + pair(pair const& other); +}; diff --git a/exploring-cpp-2e/chapter51/list5105.cpp b/exploring-cpp-2e/chapter51/list5105.cpp new file mode 100644 index 0000000..c5372c6 --- /dev/null +++ b/exploring-cpp-2e/chapter51/list5105.cpp @@ -0,0 +1,25 @@ +// Listing 51-5. Changing fixed from a Class to a Class Template +template +class fixed +{ +public: + typedef T value_type; + static constexpr int places{N}; + static constexpr int places10{power10(N)}; + fixed(); + fixed(T const& integer, T const& fraction); + fixed& operator=(fixed const& rhs); + fixed& operator+=(fixed const& rhs); + fixed& operator*=(fixed const& rhs); + // and so on... +private: + T value_; // scaled to N decimal places +}; + +template +bool operator==(fixed const& a, fixed const& b); +template +fixed operator+(fixed const& a, fixed const& b); +template +fixed operator*(fixed const& a, fixed const& b); +// ... and so on... diff --git a/exploring-cpp-2e/chapter51/list5106.cpp b/exploring-cpp-2e/chapter51/list5106.cpp new file mode 100644 index 0000000..13c2220 --- /dev/null +++ b/exploring-cpp-2e/chapter51/list5106.cpp @@ -0,0 +1,12 @@ +// Listing 51-6. Computing a Power of 10 at Compile Time +/// Called from power10 to compute 10@p n, storing the result so far in @p result. +int constexpr power10_helper(int n, int result) +{ + return n == 0 ? result : power10_helper(n - 1, 10 * result); +} + +/// Compute a power of 10 at compile time. The type T must support subtraction and multiplication. +int constexpr power10(int n) +{ + return power10_helper(n, 1); +} diff --git a/exploring-cpp-2e/chapter51/list5107.cpp b/exploring-cpp-2e/chapter51/list5107.cpp new file mode 100644 index 0000000..ad7da20 --- /dev/null +++ b/exploring-cpp-2e/chapter51/list5107.cpp @@ -0,0 +1,17 @@ +// Listing 51-7. Specializing fixed for N == 0 +template +class fixed +{ +public: + typedef T value_type; + static constexpr T places{0}; + static constexpr T places10{1}; + fixed() : value_{} {} + fixed(T const& integer, T const&) : value_{integer} {} + fixed& operator=(fixed const& rhs) { value_ = rhs; } + fixed& operator+=(fixed const& rhs) { value_ += rhs; } + fixed& operator*=(fixed const& rhs) { value_ *= rhs; } + ... and so on... +private: + T value_; // no need for scaling +}; diff --git a/exploring-cpp-2e/chapter52/list5201.cpp b/exploring-cpp-2e/chapter52/list5201.cpp new file mode 100644 index 0000000..f2081c7 --- /dev/null +++ b/exploring-cpp-2e/chapter52/list5201.cpp @@ -0,0 +1,19 @@ +// Listing 52-1. Defining the rational Class Template in the numeric Namespace +#ifndef RATIONAL_HPP_ +#define RATIONAL_HPP_ + +namespace numeric +{ + template + class rational + { + ... you know what goes here... + }; + template + bool operator==(rational const& a, rational const& b); + template + rational operator+(rational const& a, rational const& b); + ... and so on... +} // namespace numeric + +#endif diff --git a/exploring-cpp-2e/chapter52/list5202.cpp b/exploring-cpp-2e/chapter52/list5202.cpp new file mode 100644 index 0000000..672cfd5 --- /dev/null +++ b/exploring-cpp-2e/chapter52/list5202.cpp @@ -0,0 +1,19 @@ +// Listing 52-2. Defining the fixed Class Template in the numeric Namespace +#ifndef FIXED_HPP_ +#define FIXED_HPP_ + +namespace numeric +{ + template + class fixed + { + ... copied from Exploration 51... + }; + template + bool operator==(fixed const& a, fixed const& b); + template + fixed operator+(fixed const& a, fixed const& b); + // and so on... +} // namespace numeric + +#endif diff --git a/exploring-cpp-2e/chapter52/list5203.cpp b/exploring-cpp-2e/chapter52/list5203.cpp new file mode 100644 index 0000000..2f300ea --- /dev/null +++ b/exploring-cpp-2e/chapter52/list5203.cpp @@ -0,0 +1,19 @@ +// Listing 52-3. Defining Entities in a Namespace +namespace numeric +{ + template + rational operator+(rational const& a, rational const& b) + { + rational result{a}; + result += b; + return result; + } +} + +template +numeric::fixed numeric::operator+(fixed const& a, fixed const& b) +{ + fixed result{a}; + result += b; + return result; +} diff --git a/exploring-cpp-2e/chapter52/list5204.cpp b/exploring-cpp-2e/chapter52/list5204.cpp new file mode 100644 index 0000000..f5e2667 --- /dev/null +++ b/exploring-cpp-2e/chapter52/list5204.cpp @@ -0,0 +1,8 @@ +// Listing 52-4. Alternative Style of Function Declaration in a Namespace +template +auto numeric::operator+(fixed const& a, fixed const& b) -> fixed +{ + fixed result{a}; + result += b; + return result; +} diff --git a/exploring-cpp-2e/chapter52/list5205.cpp b/exploring-cpp-2e/chapter52/list5205.cpp new file mode 100644 index 0000000..c17b84b --- /dev/null +++ b/exploring-cpp-2e/chapter52/list5205.cpp @@ -0,0 +1,39 @@ +// Listing 52-5. Coping with Conflicting Names + 1 #include + 2 #include + 3 #include + 4 + 5 namespace stats { + 6 // Really bad name for a functor to compute sum of squares, + 7 // for use in determining standard deviation. + 8 class std + 9 { +10 public: +11 std(double mean) : mean_{mean} {} +12 double operator()(double acc, double x) +13 const +14 { +15 return acc + square(x - mean_); +16 } +17 double square(double x) const { return x * x; } +18 private: +19 double mean_; +20 }; +21 +22 // Really bad name for a function in the stats namespace. +23 // It computes standard deviation. +24 double stats(::std::vector const& data) +25 { +26 double std{0.0}; // Really, really bad name for a local variable +27 if (not data.empty()) +28 { +29 double sum{::std::accumulate(data.begin(), data.end(), 0.0)}; +30 double mean{sum / data.size()}; +31 double sumsq{::std::accumulate(data.begin(), data.end(), 0.0, +32 stats::std(mean))}; +33 double variance{sumsq / data.size() - mean * mean}; +34 std = ::std::sqrt(variance); +35 } +36 return std; +37 } +38 } diff --git a/exploring-cpp-2e/chapter52/list5206.cpp b/exploring-cpp-2e/chapter52/list5206.cpp new file mode 100644 index 0000000..fbe73c6 --- /dev/null +++ b/exploring-cpp-2e/chapter52/list5206.cpp @@ -0,0 +1,47 @@ +// Listing 52-6. Examples of using Directives + 1 #include + 2 + 3 void print(int i) + 4 { + 5 std::cout << "int: " << i << '\n'; + 6 } + 7 + 8 namespace labeled + 9 { +10 void print(double d) +11 { +12 std::cout << "double: " << d << '\n'; +13 } +14 } +15 +16 namespace simple +17 { +18 void print(int i) +19 { +20 std::cout << i << '\n'; +21 } +22 void print(double d) +23 { +24 std::cout << d << '\n'; +25 } +26 } +27 +28 void test_simple() +29 { +30 using namespace simple; +31 print(42); // ??? +32 print(3.14159); // finds simple::print(double) +33 } +34 +35 void test_labeled() +36 { +37 using namespace labeled; +38 print(42); // find ::print(int) +39 print(3.14159); // finds labeled::print(double) +40 } +41 +42 int main() +43 { +44 test_simple(); +45 test_labeled(); +46 } diff --git a/exploring-cpp-2e/chapter52/list5207.cpp b/exploring-cpp-2e/chapter52/list5207.cpp new file mode 100644 index 0000000..6e219a1 --- /dev/null +++ b/exploring-cpp-2e/chapter52/list5207.cpp @@ -0,0 +1,47 @@ +// Listing 52-7. Examples of using Declarations with Namespaces + 1 #include + 2 + 3 void print(int i) + 4 { + 5 std::cout << "int: " << i << '\n'; + 6 } + 7 + 8 namespace labeled + 9 { +10 void print(double d) +11 { +12 std::cout << "double: " << d << '\n'; +13 } +14 } +15 +16 namespace simple +17 { +18 void print(int i) +19 { +20 std::cout << i << '\n'; +21 } +22 void print(double d) +23 { +24 std::cout << d << '\n'; +25 } +26 } +27 +28 void test_simple() +29 { +30 using simple::print; +31 print(42); +32 print(3.14159); +33 } +34 +35 void test_labeled() +36 { +37 using labeled::print; +38 print(42); +39 print(3.14159); +40 } +41 +42 int main() +43 { +44 test_simple(); +45 test_labeled(); +46 } diff --git a/exploring-cpp-2e/chapter52/list5208.cpp b/exploring-cpp-2e/chapter52/list5208.cpp new file mode 100644 index 0000000..b1f6494 --- /dev/null +++ b/exploring-cpp-2e/chapter52/list5208.cpp @@ -0,0 +1,18 @@ +// Listing 52-8. Comparing a using Directive with a using Declaration +#include + +void demonstrate_using_directive() +{ + using namespace std; + typedef int ostream; + ostream x{0}; + std::cout << x << '\n'; +} + +void demonstrate_using_declaration() +{ + using std::ostream; + typedef int ostream; + ostream x{0}; + std::cout << x << '\n'; +} diff --git a/exploring-cpp-2e/chapter52/list5209.cpp b/exploring-cpp-2e/chapter52/list5209.cpp new file mode 100644 index 0000000..cc62094 --- /dev/null +++ b/exploring-cpp-2e/chapter52/list5209.cpp @@ -0,0 +1,30 @@ +// Listing 52-9. Examples of using Declarations with Classes +#include + +class base +{ +public: + void print(int i) { std::cout << "base: " << i << '\n'; } +}; + +class derived1 : public base +{ +public: + void print(double d) { std::cout << "derived: " << d << '\n'; } +}; + +class derived2 : public base +{ +public: + using base::print; + void print(double d) { std::cout << "derived: " << d << '\n'; } +}; + +int main() +{ + derived1 d1{}; + derived2 d2{}; + + d1.print(42); + d2.print(42); +} diff --git a/exploring-cpp-2e/chapter52/list5210.cpp b/exploring-cpp-2e/chapter52/list5210.cpp new file mode 100644 index 0000000..eca6645 --- /dev/null +++ b/exploring-cpp-2e/chapter52/list5210.cpp @@ -0,0 +1,45 @@ +// Listing 52-10. Reading and Writing Tokens +#include +#include +#include +#include +#include + +namespace parser +{ + class token + { + public: + token() : text_{} {} + token(std::string& s) : text_{s} {} + token& operator=(std::string const& s) { text_ = s; return *this; } + std::string text() const { return text_; } + private: + std::string text_; + }; +} + +std::istream& operator>>(std::istream& in, parser::token& tok) +{ + std::string str{}; + if (in >> str) + tok = str; + return in; +} + +std::ostream& operator<<(std::ostream& out, parser::token const& tok) +{ + out << tok.text(); + return out; +} + +int main() +{ + using namespace parser; + using namespace std; + + vector tokens{}; + copy(istream_iterator(std::cin), istream_iterator(), + back_inserter(tokens)); + copy(tokens.begin(), tokens.end(), ostream_iterator(cout, "\n")); +} diff --git a/exploring-cpp-2e/chapter52/list5211.cpp b/exploring-cpp-2e/chapter52/list5211.cpp new file mode 100644 index 0000000..2af2be2 --- /dev/null +++ b/exploring-cpp-2e/chapter52/list5211.cpp @@ -0,0 +1,45 @@ +// Listing 52-11. Move the I/O Operators into the parser Namespace +#include +#include +#include +#include +#include + +namespace parser +{ + class token + { + public: + token() : text_{} {} + token(std::string& s) : text_{s} {} + token& operator=(std::string const& s) { text_ = s; return *this; } + std::string text() const { return text_; } + private: + std::string text_; + }; + + std::istream& operator>>(std::istream& in, parser::token& tok) + { + std::string str{}; + if (in >> str) + tok = str; + return in; + } + + std::ostream& operator<<(std::ostream& out, parser::token const& tok) + { + out << tok.text(); + return out; + } +} + +int main() +{ + using namespace parser; + using namespace std; + + vector tokens{}; + copy(istream_iterator(std::cin), istream_iterator(), + back_inserter(tokens)); + copy(tokens.begin(), tokens.end(), ostream_iterator(cout, "\n")); +} diff --git a/exploring-cpp-2e/chapter52/list5212.cpp b/exploring-cpp-2e/chapter52/list5212.cpp new file mode 100644 index 0000000..7c84bcd --- /dev/null +++ b/exploring-cpp-2e/chapter52/list5212.cpp @@ -0,0 +1,60 @@ +// Listing 52-12. Counting Occurrences of Tokens +#include +#include +#include +#include +#include + +namespace parser +{ + class token + { + public: + token() : text_{} {} + token(std::string& s) : text_{s} {} + token& operator=(std::string const& s) { text_ = s; return *this; } + std::string text() const { return text_; } + private: + std::string text_; + }; + + // To store tokens in a map. + bool operator<(token const& a, token const& b) + { + return a.text() < b.text(); + } + + std::istream& operator>>(std::istream& in, parser::token& tok) + { + std::string str{}; + if (in >> str) + tok = str; + return in; + } + + std::ostream& operator<<(std::ostream& out, parser::token const& tok) + { + out << tok.text(); + return out; + } + + std::ostream& operator<<(std::ostream& out, + std::pair const& count) + { + out << count.first.text() << '\t' << count.second << '\n'; + return out; + } +} + +int main() +{ + using namespace parser; + using namespace std; + + map tokens{}; + token tok{}; + while (std::cin >> tok) + ++tokens[tok]; + copy(tokens.begin(), tokens.end(), + ostream_iterator >(cout)); +} diff --git a/exploring-cpp-2e/chapter53/card.hpp b/exploring-cpp-2e/chapter53/card.hpp new file mode 100644 index 0000000..8f36844 --- /dev/null +++ b/exploring-cpp-2e/chapter53/card.hpp @@ -0,0 +1,56 @@ +// Listing 53-5. The card Class, to Represent a Playing Card +#ifndef CARD_HPP_ +#define CARD_HPP_ + +#include + +/// Represent a standard western playing card. +class card +{ +public: + typedef char suit; + static suit const spades {4}; + static suit const hearts {3}; + static suit const clubs {2}; + static suit const diamonds {1}; + + typedef char rank; + static rank const ace {14}; + static rank const king {13}; + static rank const queen {12}; + static rank const jack {11}; + + card() : rank_{0}, suit_{0} {} + card(rank r, suit s) : rank_{r}, suit_{s} {} + + void assign(rank r, suit s); + suit get_suit() const { return suit_; } + rank get_rank() const { return rank_; } +private: + rank rank_; + suit suit_; +}; + +bool operator==(card a, card b); +bool operator!=(card a, card b); +std::ostream& operator<<(std::ostream& out, card c); +std::istream& operator>>(std::istream& in, card& c); + +/// In some games, Aces are high. In other Aces are low. Use different +/// comparison functors depending on the game. +bool acehigh_compare(card a, card b); +bool acelow_compare(card a, card b); + +/// Generate successive playing cards, in a well-defined order, +/// namely, 2-10, J, Q, K, A. Diamonds first, then Clubs, Hearts, and Spades. +/// Roll-over and start at the beginning again after generating 52 cards. +class card_generator +{ +public: + card_generator(); + card operator()(); +private: + card card_; +}; + +#endif diff --git a/exploring-cpp-2e/chapter53/erase_less.hpp b/exploring-cpp-2e/chapter53/erase_less.hpp new file mode 100644 index 0000000..2b9929e --- /dev/null +++ b/exploring-cpp-2e/chapter53/erase_less.hpp @@ -0,0 +1,22 @@ +#ifndef ERASE_LESS_HPP_ +#define ERASE_LESS_HPP_ + +// Listing 53-3. Erasing Elements from a Sequence Container +template +void erase_less(Container& cont) +{ + typename Container::iterator prev{cont.end()}; + typename Container::iterator iter{cont.begin()}; + while (iter != cont.end()) + { + if (prev != cont.end() and not (*prev < *iter)) + iter = cont.erase(iter); + else + { + prev = iter; + ++iter; + } + } +} + +#endif diff --git a/exploring-cpp-2e/chapter53/list5301.cpp b/exploring-cpp-2e/chapter53/list5301.cpp new file mode 100644 index 0000000..4c4ebf6 --- /dev/null +++ b/exploring-cpp-2e/chapter53/list5301.cpp @@ -0,0 +1,18 @@ +// Listing 53-1. Specializing the hash Template for the rational Type +#include +#include "rational.hpp" +namespace std { + +template +class hash> +{ +public: + std::size_t operator()(rational const& r) + const + { + return hasher_(r.numerator()) + hasher_(r.denominator()); + } +private: + std::hash hasher_; +}; +} // end of std diff --git a/exploring-cpp-2e/chapter53/list5302.cpp b/exploring-cpp-2e/chapter53/list5302.cpp new file mode 100644 index 0000000..5a58f03 --- /dev/null +++ b/exploring-cpp-2e/chapter53/list5302.cpp @@ -0,0 +1,14 @@ +// Listing 53-2. Using a Hint Position When Inserting into a Set +#include +#include +#include + +int main() +{ + std::set words{}; + + std::set::iterator hint{words.begin()}; + std::string word{}; + while(std::cin >> word) + hint = words.emplace_hint(hint, std::move(word)); +} diff --git a/exploring-cpp-2e/chapter53/list5303.hpp b/exploring-cpp-2e/chapter53/list5303.hpp new file mode 100644 index 0000000..2b9929e --- /dev/null +++ b/exploring-cpp-2e/chapter53/list5303.hpp @@ -0,0 +1,22 @@ +#ifndef ERASE_LESS_HPP_ +#define ERASE_LESS_HPP_ + +// Listing 53-3. Erasing Elements from a Sequence Container +template +void erase_less(Container& cont) +{ + typename Container::iterator prev{cont.end()}; + typename Container::iterator iter{cont.begin()}; + while (iter != cont.end()) + { + if (prev != cont.end() and not (*prev < *iter)) + iter = cont.erase(iter); + else + { + prev = iter; + ++iter; + } + } +} + +#endif diff --git a/exploring-cpp-2e/chapter53/list5304.cpp b/exploring-cpp-2e/chapter53/list5304.cpp new file mode 100644 index 0000000..3ed9945 --- /dev/null +++ b/exploring-cpp-2e/chapter53/list5304.cpp @@ -0,0 +1,59 @@ +// Listing 53-4. Testing the erase_less Function Template +#include +#include +#include +#include +#include +#include +#include + +#include "erase_less.hpp" //Listing 53-3 + + +/// Extract items from a string and store them in a container. +template +void read(std::string const& str, Container& cont) +{ + std::istringstream in(str); + cont.insert(cont.begin(), + std::istream_iterator(in), + std::istream_iterator()); +} + +/// Print items from a container to the standard output. +template +void print(std::string const& label, Container const& cont) +{ + std::cout << label; + std::copy(cont.begin(), cont.end(), + std::ostream_iterator(std::cout, " ")); + std::cout << '\n'; +} + +/// Test erase_less by extracting integers from a string into a container +/// and calling erase_less. Print the container before and after. +/// Double-check that the same results obtain with a list and a vector. +void test(std::string const& str) +{ + std::list list{}; + read(str, list); + print("before: ", list); + erase_less(list); + print("after: ", list); + + std::vector vector{}; + read(str, vector); + erase_less(vector); + + assert(list.size() == vector.size()); + assert(std::equal(list.begin(), list.end(), vector.begin())); +} + +int main() +{ + test("2 3 7 11 13 17 23 29 31 37"); + test("37 31 29 23 17 13 11 7 3 2"); + test(""); + test("42"); + test("10 30 20 40 0 50"); +} diff --git a/exploring-cpp-2e/chapter53/list5305.hpp b/exploring-cpp-2e/chapter53/list5305.hpp new file mode 100644 index 0000000..8f36844 --- /dev/null +++ b/exploring-cpp-2e/chapter53/list5305.hpp @@ -0,0 +1,56 @@ +// Listing 53-5. The card Class, to Represent a Playing Card +#ifndef CARD_HPP_ +#define CARD_HPP_ + +#include + +/// Represent a standard western playing card. +class card +{ +public: + typedef char suit; + static suit const spades {4}; + static suit const hearts {3}; + static suit const clubs {2}; + static suit const diamonds {1}; + + typedef char rank; + static rank const ace {14}; + static rank const king {13}; + static rank const queen {12}; + static rank const jack {11}; + + card() : rank_{0}, suit_{0} {} + card(rank r, suit s) : rank_{r}, suit_{s} {} + + void assign(rank r, suit s); + suit get_suit() const { return suit_; } + rank get_rank() const { return rank_; } +private: + rank rank_; + suit suit_; +}; + +bool operator==(card a, card b); +bool operator!=(card a, card b); +std::ostream& operator<<(std::ostream& out, card c); +std::istream& operator>>(std::istream& in, card& c); + +/// In some games, Aces are high. In other Aces are low. Use different +/// comparison functors depending on the game. +bool acehigh_compare(card a, card b); +bool acelow_compare(card a, card b); + +/// Generate successive playing cards, in a well-defined order, +/// namely, 2-10, J, Q, K, A. Diamonds first, then Clubs, Hearts, and Spades. +/// Roll-over and start at the beginning again after generating 52 cards. +class card_generator +{ +public: + card_generator(); + card operator()(); +private: + card card_; +}; + +#endif diff --git a/exploring-cpp-2e/chapter53/list5306.cpp b/exploring-cpp-2e/chapter53/list5306.cpp new file mode 100644 index 0000000..70a403e --- /dev/null +++ b/exploring-cpp-2e/chapter53/list5306.cpp @@ -0,0 +1,28 @@ +// Listing 53-6. Playing High-Card with array +#include +#include + +#include "card.hpp" +#include "randomint.hpp" // Listing 43-5 + + +int main() +{ + std::array deck; + std::generate(deck.begin(), deck.end(), card_generator{}); + + randomint picker{0, deck.size() - 1}; + for (int i{0}; i != 10; ++i) + { + card const& computer_card{deck.at(picker())}; + std::cout << "I picked " << computer_card << '\n'; + + card const& user_card{deck.at(picker())}; + std::cout << "You picked " << user_card << '\n'; + + if (acehigh_compare(computer_card, user_card)) + std::cout << "You win.\n"; + else + std::cout << "I win.\n"; + } +} diff --git a/exploring-cpp-2e/chapter53/list5307.cpp b/exploring-cpp-2e/chapter53/list5307.cpp new file mode 100644 index 0000000..d56f1f8 --- /dev/null +++ b/exploring-cpp-2e/chapter53/list5307.cpp @@ -0,0 +1,32 @@ +// Listing 53-7. Playing High-Card with a deque +#include +#include + +#include "card.hpp" +#include "randomint.hpp" + +int main() +{ + std::deque deck(52); + std::generate(deck.begin(), deck.end(), card_generator{}); + + + for (int i{0}; i != 10; ++i) + { + std::deque::iterator pick{deck.begin() + randomint{0, deck.size()-1}()}; + card computer_card{*pick}; + deck.erase(pick); + std::cout << "I picked " << computer_card << '\n'; + + pick = deck.begin() + randomint{0, deck.size() - 1}(); + card user_card{*pick}; + deck.erase(pick); + std::cout << "You picked " << user_card << '\n'; + + if (acehigh_compare(computer_card, user_card)) + std::cout << "You win.\n"; + else + std::cout << "I win.\n"; + + } +} diff --git a/exploring-cpp-2e/chapter53/list5308.cpp b/exploring-cpp-2e/chapter53/list5308.cpp new file mode 100644 index 0000000..1f5e5d2 --- /dev/null +++ b/exploring-cpp-2e/chapter53/list5308.cpp @@ -0,0 +1,33 @@ +// Listing 53-8. Playing High-Card with a list +#include +#include + +#include "card.hpp" +#include "randomint.hpp" + +int main() +{ + std::list deck(52); + std::generate(deck.begin(), deck.end(), card_generator{}); + + + for (int i{0}; i != 10; ++i) + { + std::list::iterator pick{deck.begin()}; + std::advance(pick, randomint{0, deck.size() - 1}()); + card computer_card{*pick}; + deck.erase(pick); + std::cout << "I picked " << computer_card << '\n'; + + pick = std::next(deck.begin(), randomint{0, deck.size() - 1}()); + card user_card{*pick}; + deck.erase(pick); + std::cout << "You picked " << user_card << '\n'; + + if (acehigh_compare(computer_card, user_card)) + std::cout << "You win.\n"; + else + std::cout << "I win.\n"; + + } +} diff --git a/exploring-cpp-2e/chapter53/list5309.cpp b/exploring-cpp-2e/chapter53/list5309.cpp new file mode 100644 index 0000000..a797a1f --- /dev/null +++ b/exploring-cpp-2e/chapter53/list5309.cpp @@ -0,0 +1,32 @@ +// Listing 53-9. Playing High-Card with vector +#include +#include + +#include "card.hpp" +#include "randomint.hpp" + +int main() +{ + std::vector deck(52); + std::generate(deck.begin(), deck.end(), card_generator{}); + + + for (int i{0}; i != 10; ++i) + { + std::vector::iterator pick{deck.begin() + randomint{0, deck.size()-1}()}; + card computer_card{*pick}; + deck.erase(pick); + std::cout << "I picked " << computer_card << '\n'; + + pick = deck.begin() + randomint{0, deck.size() - 1}(); + card user_card{*pick}; + deck.erase(pick); + std::cout << "You picked " << user_card << '\n'; + + if (acehigh_compare(computer_card, user_card)) + std::cout << "You win.\n"; + else + std::cout << "I win.\n"; + + } +} diff --git a/exploring-cpp-2e/chapter53/list5310.cpp b/exploring-cpp-2e/chapter53/list5310.cpp new file mode 100644 index 0000000..724ffca --- /dev/null +++ b/exploring-cpp-2e/chapter53/list5310.cpp @@ -0,0 +1,37 @@ +// Listing 53-10. Playing High-Card with set +#include +#include +#include +#include + +#include "card.hpp" +#include "randomint.hpp" + +int main() +{ + typedef std::set> cardset; + cardset deck(acehigh_compare); + std::generate_n(std::inserter(deck, deck.begin()), 52, card_generator{}); + + + for (int i{0}; i != 10; ++i) + { + cardset::iterator pick{deck.begin()}; + std::advance(pick, randomint{0, deck.size() - 1}()); + card computer_card{*pick}; + deck.erase(pick); + std::cout << "I picked " << computer_card << '\n'; + + pick = deck.begin(); + std::advance(pick, randomint{0, deck.size() - 1}()); + card user_card{*pick}; + deck.erase(pick); + std::cout << "You picked " << user_card << '\n'; + + if (acehigh_compare(computer_card, user_card)) + std::cout << "You win.\n"; + else + std::cout << "I win.\n"; + + } +} diff --git a/exploring-cpp-2e/chapter53/list5311.cpp b/exploring-cpp-2e/chapter53/list5311.cpp new file mode 100644 index 0000000..0c6f6b9 --- /dev/null +++ b/exploring-cpp-2e/chapter53/list5311.cpp @@ -0,0 +1,50 @@ +// Listing 53-11. Playing High-Card Using an Explicit Specialization of std::less +#include +#include +#include +#include + +#include "card.hpp" +#include "randomint.hpp" + +namespace std +{ + template<> + class less + { + public: + typedef card first_argument_type; + typedef card second_argument_type; + typedef bool result_type; + bool operator()(card a, card b) const { return acehigh_compare(a, b); } + }; +} + +int main() +{ + typedef std::set cardset; + cardset deck{}; + std::generate_n(std::inserter(deck, deck.begin()), 52, card_generator{}); + + + for (int i{0}; i != 10; ++i) + { + cardset::iterator pick{deck.begin()}; + std::advance(pick, randomint{0, deck.size() - 1}()); + card computer_card{*pick}; + deck.erase(pick); + std::cout << "I picked " << computer_card << '\n'; + + pick = deck.begin(); + std::advance(pick, randomint{0, deck.size() - 1}()); + card user_card{*pick}; + deck.erase(pick); + std::cout << "You picked " << user_card << '\n'; + + if (acehigh_compare(computer_card, user_card)) + std::cout << "You win.\n"; + else + std::cout << "I win.\n"; + + } +} diff --git a/exploring-cpp-2e/chapter53/list5312.cpp b/exploring-cpp-2e/chapter53/list5312.cpp new file mode 100644 index 0000000..5f02cab --- /dev/null +++ b/exploring-cpp-2e/chapter53/list5312.cpp @@ -0,0 +1,51 @@ +// Listing 53-12. Playing High-Card with unordered_set +#include +#include +#include +#include + +#include "card.hpp" +#include "randomint.hpp" + +namespace std +{ + template<> + class hash + { + public: + std::size_t operator()(card a) + const + { + return hash{}(a.get_suit()) * hash{}(a.get_rank()); + } + }; +} // namespace std + +int main() +{ + typedef std::unordered_set cardset; + cardset deck{}; + std::generate_n(std::inserter(deck, deck.begin()), 52, card_generator{}); + + + for (int i(0); i != 10; ++i) + { + cardset::iterator pick{deck.begin()}; + std::advance(pick, randomint{0, deck.size() - 1}()); + card computer_card{*pick}; + deck.erase(pick); + std::cout << "I picked " << computer_card << '\n'; + + pick = deck.begin(); + std::advance(pick, randomint{0, deck.size() - 1}()); + card user_card{*pick}; + deck.erase(pick); + std::cout << "You picked " << user_card << '\n'; + + if (acehigh_compare(computer_card, user_card)) + std::cout << "You win.\n"; + else + std::cout << "I win.\n"; + + } +} diff --git a/exploring-cpp-2e/chapter53/randomint.hpp b/exploring-cpp-2e/chapter53/randomint.hpp new file mode 100644 index 0000000..c303135 --- /dev/null +++ b/exploring-cpp-2e/chapter53/randomint.hpp @@ -0,0 +1,35 @@ +// Listing 43-5. Generating Random Integers +#ifndef RANDOMINT_HPP_ +#define RANDOMINT_HPP_ + +#include +#include + +/// Generate uniformly distributed random integers in a range. +class randomint +{ +public: + typedef std::default_random_engine::result_type result_type; + + /// Construct a random-number generator to produce numbers in the range [low, high]. + /// If @p low > @p high the values are reversed. + randomint(result_type low, result_type high) + // std::random_device uses a system-dependent generation of randomness + // to seed the pseudo-random-number generator. + : prng_{std::random_device{}()}, + distribution_{std::min(low, high), std::max(low, high)} + {} + + /// Generate the next random number generator. + result_type operator()() + { + return distribution_(prng_); + } + +private: + // implementation-defined pseudo-random-number generator + std::default_random_engine prng_; + // Map random numbers to a uniform distribution. + std::uniform_int_distribution distribution_; +}; +#endif diff --git a/exploring-cpp-2e/chapter54/ioflags.hpp b/exploring-cpp-2e/chapter54/ioflags.hpp new file mode 100644 index 0000000..c7d24e6 --- /dev/null +++ b/exploring-cpp-2e/chapter54/ioflags.hpp @@ -0,0 +1,20 @@ +#ifndef IOFLAGS_HPP_ +#define IOFLAGS_HPP_ + +/// Save current I/O stream flags to restore when exiting the block. +/// from Listing 39-4 +class ioflags +{ +public: + /// Save the formatting flags from @p stream. + ioflags(std::basic_ios& stream) : stream_(stream), flags_{stream.flags()} {} + ioflags(ioflags const&) = delete; + /// Restore the formatting flags. + ~ioflags() { stream_.flags(flags_); } +private: + std::basic_ios& stream_; + std::ios_base::fmtflags flags_; +}; + +#endif + diff --git a/exploring-cpp-2e/chapter54/list5401.cpp b/exploring-cpp-2e/chapter54/list5401.cpp new file mode 100644 index 0000000..d2ad0f5 --- /dev/null +++ b/exploring-cpp-2e/chapter54/list5401.cpp @@ -0,0 +1,24 @@ +// Listing 54-1. Reading and Writing Currency Using the Money I/O Manipulators +#include +#include +#include +#include +#include + +int main() +{ + std::locale native{""}; + std::cin.imbue(native); + std::cout.imbue(native); + + std::cin >> std::noshowbase; // currency symbol is optional for input + std::cout << std::showbase; // always write the currency symbol for output + + std::string digits; + while (std::cin >> std::get_money(digits)) + { + std::cout << std::put_money(digits) << '\n'; + } + if (not std::cin.eof()) + std::cout << "Invalid input.\n"; +} diff --git a/exploring-cpp-2e/chapter54/list5402.cpp b/exploring-cpp-2e/chapter54/list5402.cpp new file mode 100644 index 0000000..202d73b --- /dev/null +++ b/exploring-cpp-2e/chapter54/list5402.cpp @@ -0,0 +1,58 @@ +// Listing 54-2. Exploring Character Sets and Locales +#include +#include +#include +#include + +#include "ioflags.hpp" // from Listing 39-4 + + +/// Print a character's categorization in a locale. +void print(int c, std::string const& name, std::locale loc) +{ + // Don't concern yourself with the & operator. I'll cover that later + // in the book, in Exploration 63. Its purpose is just to ensure + // the character's escape code is printed correctly. + std::cout << "\\x" << std::setw(2) << (c & 0xff) << + " is " << name << " in " << loc.name() << '\n'; +} + +/// Test a character's categorization in the locale, @p loc. +void test(char c, std::locale loc) +{ + ioflags save{std::cout}; + std::cout << std::hex << std::setfill('0'); + if (std::isalnum(c, loc)) + print(c, "alphanumeric", loc); + else if (std::iscntrl(c, loc)) + print(c, "control", loc); + else if (std::ispunct(c, loc)) + print(c, "punctuation", loc); + else + print(c, "none of the above", loc); +} + +int main() +{ + // Test the same code point in different locales and character sets. + char c{'\xd7'}; + + // ISO 8859-1 is also called Latin-1 and is widely used in Western Europe + // and the Americas. It is often the default character set in these regions. + // The country and language are unimportant for this test. + // Choose any that support the ISO 8859-1 character set. + test(c, std::locale{"en_US.iso88591"}); + + // ISO 8859-5 is Cyrillic. It is often the default character set in Russia + // and some Eastern European countries. Choose any language and region that + // support the ISO 8859-5 character set. + test(c, std::locale{"ru_RU.iso88595"}); + + // ISO 8859-7 is Greek. Choose any language and region that + // support the ISO 8859-7 character set. + test(c, std::locale{"el_GR.iso88597"}); + + // ISO 8859-8 contains some Hebrew. The character set is no longer widely used. + // Choose any language and region that support the ISO 8859-8 character set. + test(c, std::locale{"he_IL.iso88598"}); +} diff --git a/exploring-cpp-2e/chapter54/list5403.cpp b/exploring-cpp-2e/chapter54/list5403.cpp new file mode 100644 index 0000000..9cf0739 --- /dev/null +++ b/exploring-cpp-2e/chapter54/list5403.cpp @@ -0,0 +1,5 @@ +// Listing 54-3. Result of Running the Program in Listing 54-2 +\xd7 is punctuation in en_US.iso88591 +\xd7 is alphanumeric in ru_RU.iso88595 +\xd7 is alphanumeric in el_GR.iso88597 +\xd7 is none of the above in he_IL.iso88598 diff --git a/exploring-cpp-2e/chapter54/list5404.cpp b/exploring-cpp-2e/chapter54/list5404.cpp new file mode 100644 index 0000000..3738681 --- /dev/null +++ b/exploring-cpp-2e/chapter54/list5404.cpp @@ -0,0 +1,59 @@ +// Listing 54-4. Caching the ctype Facet +#include +#include +#include + +#include "ioflags.hpp" // from Listing 39-4 + + +void print(int c, std::string const& name, std::locale loc) +{ + // Don't concern yourself with the & operator. I'll cover that later + // in the book. Its purpose is just to ensure the character's escape + // code is printed correctly. + std::cout << "\\x" << std::setw(2) << (c & 0xff) << + " is " << name << " in " << loc.name() << '\n'; +} + +/// Test a character's categorization in the locale, @p loc. +void test(char c, std::locale loc) +{ + ioflags save{std::cout}; + + std::ctype const& ctype{std::use_facet>(loc)}; + + std::cout << std::hex << std::setfill('0'); + if (ctype.is(std::ctype_base::alnum, c)) + print(c, "alphanumeric", loc); + else if (ctype.is(std::ctype_base::cntrl, c)) + print(c, "control", loc); + else if (ctype.is(std::ctype_base::punct, c)) + print(c, "punctuation", loc); + else + print(c, "none of the above", loc); +} + +int main() +{ + // Test the same code point in different locales and character sets. + char c{'\xd7'}; + + // ISO 8859-1 is also called Latin-1 and is widely used in Western Europe + // and the Americas. It is often the default character set in these regions. + // The country and language are unimportant for this test. + // Choose any that support the ISO 8859-1 character set. + test(c, std::locale{"en_US.iso88591"}); + + // ISO 8859-5 is Cyrillic. It is often the default character set in Russia + // and some Eastern European countries. Choose any language and region that + // support the ISO 8859-5 character set. + test(c, std::locale{"ru_RU.iso88595"}); + + // ISO 8859-7 is Greek. Choose any language and region that + // support the ISO 8859-7 character set. + test(c, std::locale{"el_GR.iso88597"}); + + // ISO 8859-8 contains some Hebrew. It is no longer widely used. + // Choose any language and region that support the ISO 8859-8 character set. + test(c, std::locale{"he_IL.iso88598"}); +} diff --git a/exploring-cpp-2e/chapter54/list5405.cpp b/exploring-cpp-2e/chapter54/list5405.cpp new file mode 100644 index 0000000..d057ea4 --- /dev/null +++ b/exploring-cpp-2e/chapter54/list5405.cpp @@ -0,0 +1,121 @@ +// Listing 54-5. Counting Words Again, This Time with Cached Facets + +// Copy the initial portion of Listing 22-2 here, including print_counts, +// but stopping just before sanitize. +// Listing 22-2. New main Function That Sets the Global Locale +#include +#include +#include +#include +#include + +typedef std::map count_map; ///< Map words to counts +typedef count_map::value_type count_pair; ///< pair of a word and a count +typedef std::string::size_type str_size; ///< String size type + +/** Initialize the I/O streams by imbuing them with + * the global locale. Use this function to imbue the streams + * with the native locale. C++ initially imbues streams with + * the classic locale. + */ +void initialize_streams() +{ + std::cin.imbue(std::locale{}); + std::cout.imbue(std::locale{}); +} + +/** Find the longest key in a map. + * @param map the map to search + * @returns the size of the longest key in @p map + */ +str_size get_longest_key(count_map const& map) +{ + str_size result{0}; + for (auto pair : map) + if (pair.first.size() > result) + result = pair.first.size(); + return result; +} + +/** Print the word, count, newline. Keep the columns neatly aligned. + * Rather than the tedious operation of measuring the magnitude of all + * the counts and then determining the necessary number of columns, just + * use a sufficiently large value for the counts column. + * @param pair a word/count pair + * @param longest the size of the longest key; pad all keys to this size + */ +void print_pair(count_pair const& pair, str_size longest) +{ + int const count_size{10}; // Number of places for printing the count + std::cout << std::setw(longest) << std::left << pair.first << + std::setw(count_size) << std::right << pair.second << '\n'; +} + +/** Print the results in neat columns. + * @param counts the map of all the counts + */ +void print_counts(count_map counts) +{ + str_size longest{get_longest_key(counts)}; + + // For each word/count pair... + for (count_pair pair: counts) + print_pair(pair, longest); +} + +/** Base class to hold a ctype facet. */ +class function +{ +public: + function(std::locale loc) : ctype_{std::use_facet>(loc)} {} + bool isalnum(char ch) const { return ctype_.is(std::ctype_base::alnum, ch); } + char tolower(char ch) const { return ctype_.tolower(ch); } +private: + std::ctype const& ctype_; +}; + +/** Sanitize a string by keeping only alphabetic characters. + * @param str the original string + * @return a santized copy of the string + */ +class sanitizer : public function +{ +public: + typedef std::string argument_type; + typedef std::string result_type; + sanitizer(std::locale loc) : function{loc} {} + std::string operator()(std::string const& str) + { + std::string result{}; + for (char c : str) + if (isalnum(c)) + result.push_back(tolower(c)); + return result; + } +}; + +/** Main program to count unique words in the standard input. */ +int main() +{ + // Set the global locale to the native locale. + std::locale::global(std::locale{""}); + initialize_streams(); + + count_map counts{}; + + // Read words from the standard input and count the number of times + // each word occurs. + std::string word{}; + sanitizer sanitize{std::locale{}}; + while (std::cin >> word) + { + std::string copy{sanitize(word)}; + + // The "word" might be all punctuation, so the copy would be empty. + // Don't count empty strings. + if (not copy.empty()) + ++counts[copy]; + } + + print_counts(counts); +} diff --git a/exploring-cpp-2e/chapter54/list5406.cpp b/exploring-cpp-2e/chapter54/list5406.cpp new file mode 100644 index 0000000..04a0109 --- /dev/null +++ b/exploring-cpp-2e/chapter54/list5406.cpp @@ -0,0 +1,34 @@ +// Listing 54-6. Demonstrating How Collation Order Depends on Locale +#include +#include +#include +#include +#include +#include + +void sort_words(std::vector words, std::locale loc) +{ + std::sort(words.begin(), words.end(), loc); + std::cout << loc.name() << ":\n"; + std::copy(words.begin(), words.end(), + std::ostream_iterator(std::cout, "\n")); +} + +int main() +{ + using namespace std; + vector words{ + "circus", + "\u00e5ngstrom", // ångstrom + "\u00e7irc\u00ea", // çircê + "angle", + "essen", + "ether", + "\u00e6ther", // æther + "aether", + "e\u00dfen" // eßen + }; + sort_words(words, locale::classic()); + sort_words(words, locale{"en_GB.utf8"}); // Great Britain + sort_words(words, locale{"no_NO.utf8"}); // Norway +} diff --git a/exploring-cpp-2e/chapter55/list5501.cpp b/exploring-cpp-2e/chapter55/list5501.cpp new file mode 100644 index 0000000..fe95030 --- /dev/null +++ b/exploring-cpp-2e/chapter55/list5501.cpp @@ -0,0 +1,35 @@ +// Listing 55-1. Supporting Cast for the is_palindrome Function Template +#include +#include +#include +#include +#include + +/** Test for non-letter. + * @param ch the character to test + * @return true if @p ch is not a letter + */ +template +bool non_letter(Char ch) +{ + return not std::isalpha(ch, std::locale{}); +} + +/** Convert to lowercase. + * Use a canonical form by converting to uppercase first, + * and then to lowercase. + * @param ch the character to test + * @return the character converted to lowercase + */ +template +Char lowercase(Char ch) +{ + return std::tolower(ch, std::locale{}); +} + +/** Compare two characters without regard to case. */ +template +bool same_char(Char a, Char b) +{ + return lowercase(a) == lowercase(b); +} diff --git a/exploring-cpp-2e/chapter55/list5502.cpp b/exploring-cpp-2e/chapter55/list5502.cpp new file mode 100644 index 0000000..a2f2e84 --- /dev/null +++ b/exploring-cpp-2e/chapter55/list5502.cpp @@ -0,0 +1,18 @@ +// Listing 55-2. Changing is_palindrome to a Function Template +/** Determine whether @p str is a palindrome. + * Only letter characters are tested. Spaces and punctuation don't count. + * Empty strings are not palindromes because that's just too easy. + * @param str the string to test + * @return true if @p str is the same forward and backward + */ +template +bool is_palindrome(std::basic_string str) +{ + typedef typename std::basic_string string; + typename string::iterator end{ + std::remove_if(str.begin(), str.end(), non_letter)}; + string rev{str.begin(), end}; + std::reverse(rev.begin(), rev.end()); + return not rev.empty() and + std::equal(str.begin(), end, rev.begin(), same_char); +} diff --git a/exploring-cpp-2e/chapter55/list5503.cpp b/exploring-cpp-2e/chapter55/list5503.cpp new file mode 100644 index 0000000..7ead7e8 --- /dev/null +++ b/exploring-cpp-2e/chapter55/list5503.cpp @@ -0,0 +1,12 @@ +// Listing 55-3. The main Program for Testing is_palindrome +int main() +{ + std::locale::global(std::locale{""}); + std::wcin.imbue(std::locale{}); + std::wcout.imbue(std::locale{}); + + std::wstring line{}; + while (std::getline(std::wcin, line)) + if (is_palindrome(line)) + std::wcout << line << L'\n'; +} diff --git a/exploring-cpp-2e/chapter55/palindrome.cpp b/exploring-cpp-2e/chapter55/palindrome.cpp new file mode 100644 index 0000000..e6935cd --- /dev/null +++ b/exploring-cpp-2e/chapter55/palindrome.cpp @@ -0,0 +1,68 @@ +// Listing 55-1. Supporting Cast for the is_palindrome Function Template +#include +#include +#include +#include +#include + +/** Test for non-letter. + * @param ch the character to test + * @return true if @p ch is not a letter + */ +template +bool non_letter(Char ch) +{ + return not std::isalpha(ch, std::locale{}); +} + +/** Convert to lowercase. + * Use a canonical form by converting to uppercase first, + * and then to lowercase. + * @param ch the character to test + * @return the character converted to lowercase + */ +template +Char lowercase(Char ch) +{ + return std::tolower(ch, std::locale{}); +} + +/** Compare two characters without regard to case. */ +template +bool same_char(Char a, Char b) +{ + return lowercase(a) == lowercase(b); +} + +// Listing 55-2. Changing is_palindrome to a Function Template +/** Determine whether @p str is a palindrome. + * Only letter characters are tested. Spaces and punctuation don't count. + * Empty strings are not palindromes because that's just too easy. + * @param str the string to test + * @return true if @p str is the same forward and backward + */ +template +bool is_palindrome(std::basic_string str) +{ + typedef typename std::basic_string string; + typename string::iterator end{ + std::remove_if(str.begin(), str.end(), non_letter)}; + string rev{str.begin(), end}; + std::reverse(rev.begin(), rev.end()); + return not rev.empty() and + std::equal(str.begin(), end, rev.begin(), same_char); +} + +// Listing 55-3. The main Program for Testing is_palindrome +int main() +{ + std::locale::global(std::locale{""}); + std::wcin.imbue(std::locale{}); + std::wcout.imbue(std::locale{}); + + std::wstring line{}; + while (std::getline(std::wcin, line)) + if (is_palindrome(line)) + std::wcout << line << L'\n'; +} + diff --git a/exploring-cpp-2e/chapter56/debug.hpp b/exploring-cpp-2e/chapter56/debug.hpp new file mode 100644 index 0000000..66bd768 --- /dev/null +++ b/exploring-cpp-2e/chapter56/debug.hpp @@ -0,0 +1,12 @@ +// Listing 56-1. Header That Declares a Trivial Debugging Function +#ifndef DEBUG_HPP_ +#define DEBUG_HPP_ + +#include + +/** @brief Write a debug message to the file @c "debug.txt" + * @param msg The message to write + */ +void debug(std::string const& msg); + +#endif diff --git a/exploring-cpp-2e/chapter56/list5601.hpp b/exploring-cpp-2e/chapter56/list5601.hpp new file mode 100644 index 0000000..66bd768 --- /dev/null +++ b/exploring-cpp-2e/chapter56/list5601.hpp @@ -0,0 +1,12 @@ +// Listing 56-1. Header That Declares a Trivial Debugging Function +#ifndef DEBUG_HPP_ +#define DEBUG_HPP_ + +#include + +/** @brief Write a debug message to the file @c "debug.txt" + * @param msg The message to write + */ +void debug(std::string const& msg); + +#endif diff --git a/exploring-cpp-2e/chapter56/list5602.cpp b/exploring-cpp-2e/chapter56/list5602.cpp new file mode 100644 index 0000000..9335c92 --- /dev/null +++ b/exploring-cpp-2e/chapter56/list5602.cpp @@ -0,0 +1,18 @@ +// Listing 56-2. Implementing the Debug Function +#include +#include +#include + +#include +#include "debug.hpp" + +void debug(std::string const& str) +{ + std::ofstream stream{"debug.txt", std::ios_base::out | std::ios_base::app}; + if (not stream) + throw std::runtime_error("cannot open debug.txt"); + stream.exceptions(std::ios_base::failbit); + stream << str << '\n'; + stream.close(); +} + diff --git a/exploring-cpp-2e/chapter56/list5603.cpp b/exploring-cpp-2e/chapter56/list5603.cpp new file mode 100644 index 0000000..1763c35 --- /dev/null +++ b/exploring-cpp-2e/chapter56/list5603.cpp @@ -0,0 +1,23 @@ +// Listing 56-3. Computing Miles per Gallon +#include + +int main() +{ + double total_fuel{0.0}; + double total_distance{0.0}; + double prev_odometer{0.0}; + double fuel{}, odometer{}; + while (std::cin >> odometer >> fuel) + { + if (fuel != 0) + { + double distance{odometer - prev_odometer}; + std::cout << distance / fuel << '\n'; + total_fuel += fuel; + total_distance += distance; + prev_odometer = odometer; + } + } + if (total_fuel != 0) + std::cout << "Net MPG=" << total_distance / total_fuel << '\n'; +} diff --git a/exploring-cpp-2e/chapter56/list5604.cpp b/exploring-cpp-2e/chapter56/list5604.cpp new file mode 100644 index 0000000..9bffa39 --- /dev/null +++ b/exploring-cpp-2e/chapter56/list5604.cpp @@ -0,0 +1,23 @@ +// Listing 56-4. Computing Liters per Kilometer +#include + +int main() +{ + double total_fuel{0.0}; + double total_distance{0.0}; + double prev_odometer{0.0}; + double fuel{}, odometer{}; + while (std::cin >> odometer >> fuel) + { + double distance{odometer - prev_odometer}; + if (distance != 0) + { + std::cout << fuel / distance << '\n'; + total_fuel += fuel; + total_distance += distance; + prev_odometer = odometer; + } + } + if (total_distance != 0) + std::cout << "Net LPK=" << total_fuel / total_distance << '\n'; +} diff --git a/exploring-cpp-2e/chapter56/list5605.cpp b/exploring-cpp-2e/chapter56/list5605.cpp new file mode 100644 index 0000000..d982855 --- /dev/null +++ b/exploring-cpp-2e/chapter56/list5605.cpp @@ -0,0 +1,44 @@ +// Listing 56-5. Rewriting the Miles-per-Gallon Program to Parse a String Stream +#include +#include +#include + +int main() +{ + double prev_odometer{0.0}; + double total_fuel{0.0}; + double total_distance{0.0}; + std::string line{}; + int linenum{0}; + bool error{false}; + while (std::getline(std::cin, line)) + { + ++linenum; + std::istringstream input{line}; + double odometer{}; + if (input >> odometer) + { + double fuel{}; + if (not (input >> fuel)) + { + std::cerr << "Missing fuel consumption on line " << linenum << '\n'; + error = true; + } + else if (fuel != 0) + { + double distance{odometer - prev_odometer}; + std::cout << distance / fuel << '\n'; + total_fuel += fuel; + total_distance += distance; + prev_odometer = odometer; + } + } + } + if (total_fuel != 0) + { + std::cout << "Net MPG=" << total_distance / total_fuel; + if (error) + std::cout << " (estimated, due to input error)"; + std::cout << '\n'; + } +} diff --git a/exploring-cpp-2e/chapter56/list5606.cpp b/exploring-cpp-2e/chapter56/list5606.cpp new file mode 100644 index 0000000..dd0cc33 --- /dev/null +++ b/exploring-cpp-2e/chapter56/list5606.cpp @@ -0,0 +1,49 @@ +// Listing 56-6. Parsing Comments in the Miles-per-Gallon Data File +#include +#include +#include + +int main() +{ + double total_fuel{0.0}; + double total_distance{0.0}; + double prev_odometer{0.0}; + std::string line{}; + int linenum{0}; + bool error{false}; + while (std::getline(std::cin, line)) + { + ++linenum; + std::istringstream input{line}; + char comment{}; + if (input >> comment and comment != '#') + { + input.unget(); + double odometer{}; + if (input >> odometer) + { + double fuel{}; + if (not (input >> fuel)) + { + std::cerr << "Missing fuel consumption on line " << linenum << '\n'; + error = true; + } + else if (fuel != 0) + { + double distance{odometer - prev_odometer}; + std::cout << distance / fuel << '\n'; + total_fuel += fuel; + total_distance += distance; + prev_odometer = odometer; + } + } + } + } + if (total_fuel != 0) + { + std::cout << "Net MPG=" << total_distance / total_fuel; + if (error) + std::cout << " (estimated, due to input error)"; + std::cout << '\n'; + } +} diff --git a/exploring-cpp-2e/chapter56/list5607.cpp b/exploring-cpp-2e/chapter56/list5607.cpp new file mode 100644 index 0000000..88e0eba --- /dev/null +++ b/exploring-cpp-2e/chapter56/list5607.cpp @@ -0,0 +1,47 @@ +// Listing 56-7. Allowing Comments Anywhere in the Miles-per-Gallon Data File +#include +#include +#include + +int main() +{ + double total_fuel{0.0}; + double total_distance{0.0}; + double prev_odometer{0.0}; + std::string line{}; + int linenum{0}; + bool error{false}; + while (std::getline(std::cin, line)) + { + ++linenum; + std::string::size_type comment{line.find('#')}; + if (comment != std::string::npos) + line.erase(comment); + std::istringstream input{line}; + double odometer{}; + if (input >> odometer) + { + double fuel{}; + if (not (input >> fuel)) + { + std::cerr << "Missing fuel consumption on line " << linenum << '\n'; + error = true; + } + else if (fuel != 0) + { + double distance{odometer - prev_odometer}; + std::cout << distance / fuel << '\n'; + total_fuel += fuel; + total_distance += distance; + prev_odometer = odometer; + } + } + } + if (total_fuel != 0) + { + std::cout << "Net MPG=" << total_distance / total_fuel; + if (error) + std::cout << " (estimated, due to input error)"; + std::cout << '\n'; + } +} diff --git a/exploring-cpp-2e/chapter56/list5608.cpp b/exploring-cpp-2e/chapter56/list5608.cpp new file mode 100644 index 0000000..8fb0755 --- /dev/null +++ b/exploring-cpp-2e/chapter56/list5608.cpp @@ -0,0 +1,53 @@ +// Listing 56-8. Adding Error-Checking for Each Line of Input +#include +#include +#include + +int main() +{ + double total_fuel{0.0}; + double total_distance{0.0}; + double prev_odometer{0.0}; + std::string line{}; + int linenum{0}; + bool error{false}; + while (std::getline(std::cin, line)) + { + ++linenum; + std::string::size_type comment{line.find('#')}; + if (comment != std::string::npos) + line.erase(comment); + std::istringstream input{line}; + double odometer{}; + if (input >> odometer) + { + double fuel{}; + char check{}; + if (not (input >> fuel)) + { + std::cerr << "Missing fuel consumption on line " << linenum << '\n'; + error = true; + } + else if (input >> check) + { + std::cerr << "Extra text on line " << linenum << '\n'; + error = true; + } + else if (fuel != 0) + { + double distance{odometer - prev_odometer}; + std::cout << distance / fuel << '\n'; + total_fuel += fuel; + total_distance += distance; + prev_odometer = odometer; + } + } + } + if (total_fuel != 0) + { + std::cout << "Net MPG=" << total_distance / total_fuel; + if (error) + std::cout << " (estimated, due to input error)"; + std::cout << '\n'; + } +} diff --git a/exploring-cpp-2e/chapter56/list5609.hpp b/exploring-cpp-2e/chapter56/list5609.hpp new file mode 100644 index 0000000..4f97971 --- /dev/null +++ b/exploring-cpp-2e/chapter56/list5609.hpp @@ -0,0 +1,17 @@ +// Listing 56-9. The from_string Function Extracts a Value from a String +#include // for the >> operator +#include // for istringstream +#include // for string +#include "conversion_error.hpp" + +template +T from_string(std::string const& str) +{ + std::istringstream in{str}; + T result{}; + if (in >> result) + return result; + else + throw conversion_error{str}; +} + diff --git a/exploring-cpp-2e/chapter56/list5610.hpp b/exploring-cpp-2e/chapter56/list5610.hpp new file mode 100644 index 0000000..70f8a85 --- /dev/null +++ b/exploring-cpp-2e/chapter56/list5610.hpp @@ -0,0 +1,22 @@ +// Listing 56-10. Enhancing the from_string Function +#include // for std::noskipws +#include // for the >> operator +#include // for istringstream +#include // for string +#include "conversion_error.hpp" + +template +T from_string(std::string const& str, bool skipws = true) +{ + std::istringstream in{str}; + if (not skipws) + in >> std::noskipws; + T result{}; + char extra; + if (not (in >> result)) + throw conversion_error{str}; + else if (in >> extra) + throw conversion_error{str}; + else + return result; +} diff --git a/exploring-cpp-2e/chapter56/list5611.hpp b/exploring-cpp-2e/chapter56/list5611.hpp new file mode 100644 index 0000000..f1abc19 --- /dev/null +++ b/exploring-cpp-2e/chapter56/list5611.hpp @@ -0,0 +1,18 @@ +#ifndef TO_STRING_HPP_ +#define TO_STRING_HPP_ + +// Listing 56-11. The to_string Function Converts a Value to a String +#include // for the << operator +#include // for ostringstream +#include // for string + +template +std::string to_string(T const& obj) +{ + std::ostringstream out{}; + out << obj; + return out.str(); +} + +#endif + diff --git a/exploring-cpp-2e/chapter56/list5612.hpp b/exploring-cpp-2e/chapter56/list5612.hpp new file mode 100644 index 0000000..cd0622c --- /dev/null +++ b/exploring-cpp-2e/chapter56/list5612.hpp @@ -0,0 +1,12 @@ +// Listing 56-12. Rewriting to_string As a Template Function +#include // for the << operator +#include // for ostringstream +#include // for basic_string + +template +std::basic_string to_string(T const& obj) +{ + std::basic_ostringstream out{}; + out << obj; + return out.str(); +} diff --git a/exploring-cpp-2e/chapter56/list5613.cpp b/exploring-cpp-2e/chapter56/list5613.cpp new file mode 100644 index 0000000..3c32450 --- /dev/null +++ b/exploring-cpp-2e/chapter56/list5613.cpp @@ -0,0 +1,12 @@ +// Listing 56-13. Demonstrating the Use of to_string +#include +#include "to_string.hpp" +#include "from_string.hpp" + +int main() +{ + std::string str{ + to_string, std::allocator>(42) + }; + int value{from_string(str)}; +} diff --git a/exploring-cpp-2e/chapter56/list5614.hpp b/exploring-cpp-2e/chapter56/list5614.hpp new file mode 100644 index 0000000..6b99008 --- /dev/null +++ b/exploring-cpp-2e/chapter56/list5614.hpp @@ -0,0 +1,20 @@ +// Listing 56-14. Passing the Destination String As an Argument to to_string +#include // for the << operator +#include // for ostringstream +#include // for string +#include "from_string.hpp" + +template +void to_string(T const& obj, std::basic_string& result) +{ + std::basic_ostringstream out{}; + out << obj; + result = out.str(); +} + +int main() +{ + std::string str{}; + to_string(42, str); + int value(from_string(str)); +} diff --git a/exploring-cpp-2e/chapter56/list5615.hpp b/exploring-cpp-2e/chapter56/list5615.hpp new file mode 100644 index 0000000..7510ad2 --- /dev/null +++ b/exploring-cpp-2e/chapter56/list5615.hpp @@ -0,0 +1,12 @@ +// Listing 56-15. Improving the Calling Interface of to_string +#include // for the << operator +#include // for ostringstream + +template +String to_string(T const& obj) +{ + std::basic_ostringstream out{}; + out << obj; + return out.str(); +} diff --git a/exploring-cpp-2e/chapter56/list5616.hpp b/exploring-cpp-2e/chapter56/list5616.hpp new file mode 100644 index 0000000..2e93e61 --- /dev/null +++ b/exploring-cpp-2e/chapter56/list5616.hpp @@ -0,0 +1,19 @@ +// Listing 56-16. Making to_string Too Complicated +#include +#include // for the << operator +#include // for ostringstream + +template +String to_string(T const& obj, + std::ios_base::fmtflags flags = std::ios_base::fmtflags{}, + int width = 0, + char fill = ' ') +{ + std::basic_ostringstream out{}; + out.flags(flags); + out.width(width); + out.fill(fill); + out << obj; + return out.str(); +} diff --git a/exploring-cpp-2e/chapter56/list5617.cpp b/exploring-cpp-2e/chapter56/list5617.cpp new file mode 100644 index 0000000..4132d42 --- /dev/null +++ b/exploring-cpp-2e/chapter56/list5617.cpp @@ -0,0 +1,10 @@ +// Listing 56-17. Calling to_string +#include +#include "to_string.hpp" + +int main() +{ + std::cout << to_string(42, std::ios_base::hex) << '\n'; + std::cout << to_string(42.0, std::ios_base::scientific, 10) << '\n'; + std::cout << to_string(true, std::ios_base::boolalpha) << '\n'; +} diff --git a/exploring-cpp-2e/chapter57/Doxyfile b/exploring-cpp-2e/chapter57/Doxyfile new file mode 100644 index 0000000..2641f2b --- /dev/null +++ b/exploring-cpp-2e/chapter57/Doxyfile @@ -0,0 +1,1275 @@ +# Doxyfile 1.5.3 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file that +# follow. The default is UTF-8 which is also the encoding used for all text before +# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into +# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of +# possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = "Project 3 - Currency Type " + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian, +# Italian, Japanese, Japanese-en (Japanese with English messages), Korean, +# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian, +# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = . + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to +# include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be extracted +# and appear in the documentation as a namespace called 'anonymous_namespace{file}', +# where file will be replaced with the base name of the file that contains the anonymous +# namespace. By default anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from the +# version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text " + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = . + +# This tag can be used to specify the character encoding of the source files that +# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default +# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding. +# See http://www.gnu.org/software/libiconv for the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py + +FILE_PATTERNS = *.cpp *.hpp + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the output. +# The symbol name can be a fully qualified name, a word, or if the wildcard * is used, +# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. If you have enabled CALL_GRAPH or CALLER_GRAPH +# then you must also enable this option. If you don't then doxygen will produce +# a warning and turn it on anyway + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentstion. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to +# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to +# specify the directory where the mscgen tool resides. If left empty the tool is assumed to +# be found in the default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will +# generate a caller dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable caller graphs for selected +# functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the number +# of direct children of the root node in a graph is already larger than +# MAX_DOT_GRAPH_NOTES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, which results in a white background. +# Warning: Depending on the platform used, enabling this option may lead to +# badly anti-aliased labels on the edges of a graph (i.e. they become hard to +# read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/exploring-cpp-2e/chapter57/Makefile b/exploring-cpp-2e/chapter57/Makefile new file mode 100644 index 0000000..65cb8fe --- /dev/null +++ b/exploring-cpp-2e/chapter57/Makefile @@ -0,0 +1,20 @@ +DEBUG = -g3 -O0 -MMD +CXXFLAGS = -ansi -pedantic -Wall -std=c++11 $(DEBUG) +TEST = test.cpp +TESTOBJ = $(TEST:.cpp=.o) + +all : runtest + +test : $(TESTOBJ) + $(CXX) $(CXXFLAGS) -o $@ $(TESTOBJ) + +runtest : cleantest test + ./test + +clean : cleantest + $(RM) -r $(TESTOBJ) test html *.d + +cleantest : + $(RM) *.{gcov,gcda} + +.PHONY : runtest clean cleantest diff --git a/exploring-cpp-2e/chapter57/currency.hpp b/exploring-cpp-2e/chapter57/currency.hpp new file mode 100644 index 0000000..7f2b8b8 --- /dev/null +++ b/exploring-cpp-2e/chapter57/currency.hpp @@ -0,0 +1,512 @@ +/** @file currency.hpp + * Implement a currency type. + */ + +/** @mainpage Project 3: Currency Type + * It’s time for another project. You’re going to continue building on the + * @c fixed type from Project 2 and incorporate what you’ve learned about + * locales and I/O. Your task this time is to write a @c currency type. + * + * The value is stored as a fixed-point value. + * I/O is formatted using the @c get_money and @c put_money manipulators. + * + * Make sure you can add two currency amounts to get a currency value, + * subtract two currency amounts to get currency, + * multiply and divide currency by an integer or rational value + * to get a currency result, and divide two currency values + * to get a rational result. + * + * As with any project, start small and add functionality as you go. + * For example, start with the basic data representation, + * then add I/O operators. Add arithmetic operators one at a time. + * Write each test function before you implement the feature. +*/ + +#ifndef CURRENCY_HPP_ +#define CURRENCY_HPP_ + +#include +#include +#include +#include +#include +#include +#include + +#include "ioflags.hpp" +#include "fixed.hpp" +#include "rational.hpp" + +/** Class to represent a currency value in the global locale. */ +template +class currency +{ +public: + typedef T int_type; ///< Storage type + typedef fixed value_type; ///< Type of the actual value + + /// Default constructor initializes the value to zero. + constexpr currency() : value_() {} + /// Initialize the value to @p integer + /// @param integer The integer initial value; the fractional part is zero. + constexpr currency(T integer) : value_(integer) {} + /// Initialize the value. + /// The interpretation of the fractional part depends on @p N. + /// For example, if @p N is 2, a @p fraction of 9 represents 0.09, + /// buf if @p N is 5, @p fraction of 9 means 0.0009. + /// @param integer The integer part of the initial value + /// @param fraction The fractional part of the initial value + currency(T integer, T fraction) : value_(integer, fraction) {} + /// Initialize from a floating point number. + /// @param value the initial value + currency(double value) : value_(value) {} + + /// Copy a value that uses a different precision. + template + currency(currency const& rhs): value_(rhs.value()) {} + + /// Assign a value that uses a different precision. + template + currency& operator=(currency rhs) + { + value_ = rhs.value(); + return *this; + } + + /// Convert to a string. + /// @returns a string representation of the value, e.g., "$123.04" + std::string as_string() const; + /// Overwrite this value with the value read from the stream. + /// The value in the stream must have the correct number of digits. + /// If the showbase flag is set, the currency symbol must be present. + /// @param strm Input stream + /// @return true if the read is success and @c *this has been modified, + /// or false if the read fails. Check @p strm for details. + template + bool read(std::basic_istream& strm); + + /// Convert the value to a different numeric type. + /// Typically, the other type is a floating-point type. + template + /// Convert to some other type, especially floating point. + U convert() const { return value().template convert(); } + + /// Round off to the nearest integer, using banker's rounding. + int_type round() const { return value().round(); } + + /// Return the integer part (which is the same as trunc()). + int_type integer() const { return value().integer(); } + /// Return the fractional part, to @p M places. + template + int_type fraction() const { return value().template fraction(); } + /// Return the fractional part. + int_type fraction() const { return value().fraction(); } + + /// Addition operator. + /// @param c the value to add + /// @return @c *this + currency& operator+=(currency c); + /// Subtraction operator. + /// @param c the value to subtract + /// @return @c *this + currency& operator-=(currency c); + /// Multiplication operator. + /// @param m the value to multiply + /// @return @c *this + currency& operator*=(value_type m); + /// Multiplication operator. + /// @param m the value to multiply + /// @return @c *this + currency& operator*=(int_type m); + /// Division operator. + /// @param m the divisor + /// @return @c *this + currency& operator/=(value_type m); + /// Division operator. + /// @param m the divisor + /// @return @c *this + currency& operator/=(int_type m); + + /// Negate this value. + void negate(); + + /// Pre-increment operator. + currency& operator++(); + /// Post-increment operator. + currency operator++(int); + /// Pre-decrement operator. + currency& operator--(); + /// Post-decrement operator. + currency operator--(int); + + /// Return the internal value. + value_type value() const { return value_; } + +private: + value_type value_; +}; + +template +std::string currency::as_string() +const +{ + std::ostringstream digits; + digits.imbue(std::locale::classic()); + digits << integer() << std::setw(value_type::places) << std::setfill('0') << fraction(); + + std::ostringstream out; + std::money_put const& put(std::use_facet >(std::locale())); + put.put(std::ostreambuf_iterator(out), false, out, '0', digits.str()); + return out.str(); +} + +template +currency& currency::operator+=(currency f) +{ + value_ += f.value(); + return *this; +} + +template +currency& currency::operator-=(currency f) +{ + value_ -= f.value(); + return *this; +} + +template +currency& currency::operator*=(value_type i) +{ + value_ *= i; + return *this; +} +template +currency& currency::operator*=(int_type i) +{ + value_ *= i; + return *this; +} + +template +currency& currency::operator/=(value_type i) +{ + value_ /= i; + return *this; +} +template +currency& currency::operator/=(int_type i) +{ + value_ /= i; + return *this; +} + +template +void currency::negate() +{ + value_ = -value_; +} + +template +currency& currency::operator++() +{ + ++value_; + return *this; +} + +template +currency currency::operator++(int) +{ + currency result(*this); + ++value_; + return result; +} + +template +currency& currency::operator--() +{ + --value_; + return *this; +} + +template +currency currency::operator--(int) +{ + currency result(*this); + --value_; + return result; +} + +template +template +bool currency::read(std::basic_istream& strm) +{ + ioflags flags(strm); + typename std::basic_istream::sentry sentry(strm, false); + if (not sentry) + return false; + + std::ios_base::iostate error(std::ios_base::goodbit); + std::string digits; + std::money_get const& get( + std::use_facet >(strm.getloc())); + get.get(std::istreambuf_iterator(strm), std::istreambuf_iterator(), + false, strm, error, digits); + + if ((error & std::ios_base::failbit) != 0) + return false; + + std::moneypunct const& punct( + std::use_facet >(strm.getloc())); + + // Set fraction to the rightmost frac_digits() characters of digits. + std::string fraction(digits.substr(digits.size() - punct.frac_digits(), punct.frac_digits())); + // Set integer to the remainder of digits. + std::string integer(digits.substr(0, digits.size() - punct.frac_digits())); + + std::istringstream fixed_stream(integer + "." + fraction); + return value_.read(fixed_stream); +} + +/// Read a currency value +/// @param strm The input stream +/// @param[out] c Store the value here +template +std::basic_istream& operator>>(std::basic_istream& strm, currency& c) +{ + if (not c.read(strm)) + strm.setstate(strm.failbit); + return strm; +} + +/// Write a currency value +/// @param strm The output stream +/// @param c The value to write +template +std::basic_ostream& operator<<(std::basic_ostream& strm, currency c) +{ + typename std::basic_ostream::sentry sentry(strm); + strm << c.as_string(); + return strm; +} + +/// Negate a currency value +template +currency operator-(currency a) +{ + a.negate(); + return a; +} + +/// Add currency values +/// @param a The left-hand operand +/// @param b The right-hand operand +template +currency operator+(currency a, currency b) +{ + a += b; + return a; +} + +/// Subtract currency values +/// @param a The left-hand operand +/// @param b The right-hand operand +template +currency operator-(currency a, currency b) +{ + a -= b; + return a; +} + +/// Multiply currency value and an integer +/// @param a The left-hand operand +/// @param b The right-hand operand +template +currency operator*(currency a, T b) +{ + a *= b; + return a; +} + +/// Multiply currency value and an integer +/// @param a The left-hand operand +/// @param b The right-hand operand +template +currency operator*(T a, currency b) +{ + b *= a; + return b; +} + +/// Divide currency value by an integer +/// @param a The left-hand operand +/// @param b The right-hand operand +template +currency operator/(currency a, T b) +{ + a /= b; + return a; +} + +/// Divide currency values to yield a rational result. +/// @param n the numerator +/// @param d the denominator +template +rational operator/(currency n, currency d) +{ + // Extract the underlying value of the fixed values. No adjustment + // to scaling is needed because the numerator and denominator are + // both scaled to the same amount. + return rational(n.value().value(), d.value().value()); +} + +/// Compare currency values for equality by comparing the underlying values. +/// @param a The left-hand operand +/// @param b The right-hand operand +template +bool operator==(currency a, currency b) +{ + return a.value() == b.value(); +} +/// Compare currency value and an integer for equality +/// @param a The left-hand operand +/// @param b The right-hand operand +template +bool operator==(currency a, T b) +{ + return a.value() == b; +} +/// Compare currency value and an integer for equality +/// @param a The left-hand operand +/// @param b The right-hand operand +template +bool operator==(T a, currency b) +{ + return a == b.value(); +} + +/// Compare currency values for inequality. +/// @param a The left-hand operand +/// @param b The right-hand operand +template +inline bool operator!=(currency a, currency b) +{ + return not (a == b); +} +/// Compare currency value and an integer for inequality +/// @param a The left-hand operand +/// @param b The right-hand operand +template +inline bool operator!=(currency a, T b) +{ + return not (a == b); +} +/// Compare currency value and an integer for inequality +/// @param a The left-hand operand +/// @param b The right-hand operand +template +inline bool operator!=(T a, currency b) +{ + return not (a == b); +} + +/// Compare currency values for less-than by comparing the underlying values. +/// @param a The left-hand operand +/// @param b The right-hand operand +template +bool operator<(currency a, currency b) +{ + return a.value() < b.value(); +} +/// Compare a currency value and an integer for less-than. +/// @param a The left-hand operand +/// @param b The right-hand operand +template +bool operator<(currency a, T b) +{ + return a.value() < b; +} +/// Compare a currency value and an integer for less-than. +/// @param a The left-hand operand +/// @param b The right-hand operand +template +bool operator<(T a, currency b) +{ + return a < b.value(); +} + +/// Compare currency values for greater-than. +/// @param a The left-hand operand +/// @param b The right-hand operand +template +inline bool operator>(currency a, currency b) +{ + return b < a; +} +/// Compare a currency value and an integer for greater-than. +/// @param a The left-hand operand +/// @param b The right-hand operand +template +inline bool operator>(currency a, T b) +{ + return b < a; +} +/// Compare a currency value and an integer for greater-than. +/// @param a The left-hand operand +/// @param b The right-hand operand +template +inline bool operator>(T a, currency b) +{ + return b < a; +} + +/// Compare currency values for less-than-or-equal. +/// @param a The left-hand operand +/// @param b The right-hand operand +template +inline bool operator<=(currency a, currency b) +{ + return not (b < a); +} +/// Compare a currency value and an integer for less-than-or-equal. +/// @param a The left-hand operand +/// @param b The right-hand operand +template +inline bool operator<=(currency a, T b) +{ + return not (b < a); +} +/// Compare a currency value and an integer for less-than-or-equal. +/// @param a The left-hand operand +/// @param b The right-hand operand +template +inline bool operator<=(T a, currency b) +{ + return not (b < a); +} + +/// Compare currency values for greater-than-or-equal. +/// @param a The left-hand operand +/// @param b The right-hand operand +template +inline bool operator>=(currency a, currency b) +{ + return not (a < b); +} +/// Compare a currency value and an integer for greater-than-or-equal. +/// @param a The left-hand operand +/// @param b The right-hand operand +template +inline bool operator>=(currency a, T b) +{ + return not (a < b); +} +/// Compare a currency value and an integer for greater-than-or-equal. +/// @param a The left-hand operand +/// @param b The right-hand operand +template +inline bool operator>=(T a, currency b) +{ + return not (a < b); +} + +#endif diff --git a/exploring-cpp-2e/chapter57/fixed.hpp b/exploring-cpp-2e/chapter57/fixed.hpp new file mode 100644 index 0000000..11b1acf --- /dev/null +++ b/exploring-cpp-2e/chapter57/fixed.hpp @@ -0,0 +1,520 @@ +/** @file fixed.hpp */ +/** Listing 49-5. Changing fixed from a Class to a Class Template */ + +#ifndef FIXED_HPP_ +#define FIXED_HPP_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ioflags.hpp" +#include "power10.hpp" + +/** @brief Implement a fixed-point number class template. + * Values have @c N places after the decimal point. + * All arithmetic follows the usual rules. + */ +template +class fixed +{ +public: + typedef T value_type; ///< Type of the actual value + + static value_type constexpr places{N}; ///< number of decimal places + static value_type constexpr places10{power10(N)}; ///< 10places + + /// Default constructor initializes to zero. + constexpr fixed() : value_() {} + + /// Construct from separate integer and fractional parts, + /// e.g., initialize to 123.45 with fixed(123, 45). Initialize + /// to 12.07 with fixed(12, 7). + fixed(value_type integer, value_type fraction); + + /// Construct from an integer with no fractional part. + constexpr fixed(value_type integer); + + /// Construct by rounding off a floating point number. + fixed(double value) + : value_(static_cast(value * places10 + (value < 0 ? -0.5 : 0.5))) + {} + + /// Convert to a string. + /// @returns a string representation of the value, e.g., "123.04" + std::string as_string() const; + /// Read from a stream. + /// Overwrite this value with the value read from the stream. + /// @param strm the stream to read + /// @returns true for success or false for failure + template + bool read(std::basic_istream& strm); + /// Convert to long double. + double as_long_double() const { return static_cast(value()) / places10; } + /// Convert to double. + double as_double() const { return static_cast(value()) / places10; } + /// Convert to float + float as_float() const { return static_cast(value()) / places10; } + /// Return just the integer part, rounded off to the nearest integer. + /// If the value lies equidistant between two integers, round even + /// numbers up and odd numbers down (banker's rounding). + value_type round() const; + + /// Return the integer part (which is the same as trunc()). + value_type integer() const { return value() / places10; } + /// Return the fractional part, e.g., 3 for 12.03 + value_type fraction() const; + + /// Addition assignment operator + fixed& operator+=(fixed f); + /// Subtraction assignment operator + fixed& operator-=(fixed f); + /// Multiplication assignment operator + fixed& operator*=(fixed f); + /// Division assignment operator + fixed& operator/=(fixed f); + + /// Negate this value. + void negate(); + + /// Pre-increment + fixed& operator++(); + /// Post-increment + fixed operator++(int); + /// Pre-decrement + fixed& operator--(); + /// Post-decrement + fixed operator--(int); + + /// Return the internal value. + value_type value() const { return value_; } +private: + /// Reduce frac to the range [0, places10) by discarding digits to the right. + value_type reduce(value_type frac); + value_type value_; +}; + +template +typename fixed::value_type constexpr fixed::places10; + +// Construct a fixed value from an integer part and a fraction part +template +fixed::fixed(value_type integer, value_type fraction) +{ + if (fraction < T()) + throw std::invalid_argument("negative fraction not allowed"); + fraction = reduce(fraction); + if (integer < T()) + value_ = integer * places10 - fraction; + else + value_ = integer * places10 + fraction; +} + +// Construct a fixed value from an integer part with no fraction +template +constexpr +fixed::fixed(value_type integer) +: value_(integer * places10) +{} + +// Get the fraction part +template +typename fixed::value_type fixed::fraction() +const +{ + return std::abs(value()) % places10; +} + +/// Reduce the fractional part to the range [0, places10). +/// Imagine frac has the format F(G(XY*)?)?. +/// The resulting value is FH, where H == 0 if G is absent, +/// or H == G+1 if X==5 and Y* == 0* and G is odd, or +/// H == G+1 if X>5 or X==5 and Y*>0*, else H == G. +/// In other words, check that frac ends with only zero digits, +/// then a 5, then two more digits (searching from least-significant +/// to most-significant). If so, implement banker's rounding. +/// Otherwise, round GXY* to the nearest value (G+1 or G). +template +typename fixed::value_type fixed::reduce(value_type frac) +{ + // First scan for zero digits on the right. + value_type f(frac); + while (f >= places10*10 and f % 10 == 0) + { + f /= 10; + } + + if (f >= places10*10) + { + int x(0); + // Loop ended because a non-zero digit was seen so Y* > 0. + // Discard the remaining digits, but keep track of the last + // digit to be processed (X). + while (f >= places10) + { + x = f % 10; + f /= 10; + } + // Round up if the last digit (X) is 5 or more + if (x >= 5) + ++f; + return f; + } + // Else all digits so far are zero. Check how many digits there were, + // that is, check whether G, and X at least are present. + else if (f >= places10) + { + // Yes, G and X are present. If X == 5, implement banker's rounding. + // Otherwise, round to nearest. + int x(f % 10); + f /= 10; + assert(f < places10); + if (x == 5) + { + // Yes, so implement banker's rounding. + if (f % 2 != 0) + ++f; + return f; + } + else if (x < 5) + { + // Round down. + return f; + } + else + { + // Round up. + return f + 1; + } + } + // Not enough digits, so nothing to round. + assert(frac < places10); + return frac; +} + +// Round off to nearest integer. +template +typename fixed::value_type fixed::round() +const +{ + const value_type frac(fraction()); + int adjust(value() < 0 ? -1 : +1); + if (frac > places10/2) + return integer()+adjust; + else if (frac < places10/2) + return integer(); + else if (integer() % 2 == 0) + return integer(); + else + return integer()+adjust; +} + +// Convert to a string using fixed-point notation. +template +std::string fixed::as_string() +const +{ + std::ostringstream out; + out << integer() << '.' + << std::setfill('0') << std::setw(places) << fraction(); + return out.str(); +} + +template +fixed& fixed::operator+=(fixed f) +{ + value_ += f.value(); + return *this; +} + +template +fixed& fixed::operator-=(fixed f) +{ + value_ -= f.value(); + return *this; +} + +template +fixed& fixed::operator*=(fixed f) +{ + value_ = (value_ * f.value()) / places10; + return *this; +} + +template +fixed& fixed::operator/=(fixed f) +{ + value_ = (value_ * places10) / f.value(); + return *this; +} + +template +void fixed::negate() +{ + value_ = -value_; +} + +template +fixed& fixed::operator++() +{ + value_ += places10; + return *this; +} + +template +fixed fixed::operator++(int) +{ + fixed result(*this); + ++*this; + return result; +} + +template +fixed& fixed::operator--() +{ + value_ -= places10; + return *this; +} + +template +fixed fixed::operator--(int) +{ + fixed result(*this); + --*this; + return result; +} + +template +template +bool fixed::read(std::basic_istream& strm) +{ + ioflags flags(strm); + + value_type integer; + char decimal; + if (not (strm >> integer)) + return false; + strm.unsetf(std::ios_base::skipws); + if (not (strm >> decimal) or decimal != '.') + { + // Just an integer is fine. Push back the non-decimal character, + // if there is one, and reset the stream flags to show that + // reading the fixed value succeeded. + strm.unget(); + strm.clear(strm.rdstate() & ~strm.failbit); + value_ = integer * places10; + return true; + } + else + { + value_type fraction(0); + char c; + int p(0); + // Read one extra place for round-off. + for (; + p != places+1 and strm >> c and std::isdigit(c, strm.getloc()); + ++p) + { + fraction = fraction * 10 + (c - '0'); + } + // Pad out to the requisite number of decimal places. + for (; p < places; ++p) + fraction = fraction * 10; + // If the loop terminated because the maximum number of decimal + // places were read, keep reading the stream to discard excees digits. + while (strm and std::isdigit(c, strm.getloc())) + strm >> c; + // Push back the last, non-digit character read from the stream. + // If the stream reached EOF, unget() is harmless. + strm.unget(); + // Clear failbit because even if reading a character or whatever + // failed, reading the fixed value did not. + strm.clear(strm.rdstate() & ~strm.failbit); + fraction = reduce(fraction); + if (integer < 0) + value_ = integer * places10 - fraction; + else + value_ = integer * places10 + fraction; + } + return true; +} + +/// Read a fixed value +template +std::basic_istream& operator>>(std::basic_istream& strm, fixed& f) +{ + if (not f.read(strm)) + strm.setstate(strm.failbit); + return strm; +} + +/// Write a fixed value +template +std::basic_ostream& operator<<(std::basic_ostream& strm, fixed f) +{ + strm << f.as_string(); + return strm; +} + +/// Add fixed values +template +fixed operator+(fixed a, fixed b) +{ + a += b; + return a; +} + +/// Subtract fixed values +template +fixed operator-(fixed a, fixed b) +{ + a -= b; + return a; +} + +/// Multiply fixed values +template +fixed operator*(fixed a, fixed b) +{ + a *= b; + return a; +} + +/// Divide fixed values +template +fixed operator/(fixed a, fixed b) +{ + a /= b; + return a; +} + +/// Negate a fixed value +template +fixed operator-(fixed a) +{ + a.negate(); + return a; +} + +/// Compare fixed values for equality by comparing the underlying values. +template +bool operator==(fixed a, fixed b) +{ + return a.value() == b.value(); +} +/// Compare fixed values for equality by comparing the value wih an integer. +template +bool operator==(T a, fixed b) +{ + return a == b.value(); +} +/// Compare fixed values for equality by comparing the value wih an integer. +template +bool operator==(fixed a, T b) +{ + return a.value() == b; +} + +/// Compare fixed values for inequality by comparing the underlying values. +template +bool operator!=(fixed a, fixed b) +{ + return not (a == b); +} +/// Compare fixed values for inequality by comparing the value wih an integer. +template +bool operator!=(T a, fixed b) +{ + return not (a == b); +} +/// Compare fixed values for inequality by comparing the value wih an integer. +template +bool operator!=(fixed a, T b) +{ + return not (a == b); +} + +/// Compare fixed values for less-than by comparing the underlying values. +template +bool operator<(fixed a, fixed b) +{ + return a.value() < b.value(); +} +/// Compare fixed values for less-than by comparing the value wih an integer. +template +bool operator<(T a, fixed b) +{ + return a < b.value(); +} +/// Compare fixed values for less-than by comparing the value wih an integer. +template +bool operator<(fixed a, T b) +{ + return a.value() < b; +} + +/// Compare fixed values for greater-than by comparing the underlying values. +template +bool operator>(fixed a, fixed b) +{ + return b < a; +} +/// Compare fixed values for greater-than by comparing the value wih an integer. +template +bool operator>(T a, fixed b) +{ + return b < a; +} +/// Compare fixed values for greater-than by comparing the value wih an integer. +template +bool operator>(fixed a, T b) +{ + return b < a; +} + +/// Compare fixed values for less-than-or-equal by comparing the underlying values. +template +bool operator<=(fixed a, fixed b) +{ + return not (b < a); +} +/// Compare fixed values for less-than-or-equal by comparing the value wih an integer. +template +bool operator<=(T a, fixed b) +{ + return not (b < a); +} +/// Compare fixed values for less-than-or-equal by comparing the value wih an integer. +template +bool operator<=(fixed a, T b) +{ + return not (b < a); +} + +/// Compare fixed values for greater-than-or-equal by comparing the underlying values. +template +bool operator>=(fixed a, fixed b) +{ + return not (a < b); +} +/// Compare fixed values for greater-than-or-equal by comparing the value wih an integer. +template +bool operator>=(T a, fixed b) +{ + return not (a < b); +} +/// Compare fixed values for greater-than-or-equal by comparing the value wih an integer. +template +bool operator>=(fixed a, T b) +{ + return not (a < b); +} + +#endif diff --git a/exploring-cpp-2e/chapter57/gcd.cpp b/exploring-cpp-2e/chapter57/gcd.cpp new file mode 100644 index 0000000..7068860 --- /dev/null +++ b/exploring-cpp-2e/chapter57/gcd.cpp @@ -0,0 +1,13 @@ +#include "gcd.hpp" + +int gcd(int n, int m) +{ + if (n < 0) + n = -n; + while (m != 0) { + int tmp{n % m}; + n = m; + m = tmp; + } + return n; +} diff --git a/exploring-cpp-2e/chapter57/gcd.hpp b/exploring-cpp-2e/chapter57/gcd.hpp new file mode 100644 index 0000000..5a4d407 --- /dev/null +++ b/exploring-cpp-2e/chapter57/gcd.hpp @@ -0,0 +1,21 @@ +#ifndef GCD_HPP_ +#define GCD_HPP_ + +/// Compute greatest-common-denominator. +/// @param n +/// @param m +template +T gcd(T n, T m) +{ + static const T zero{}; + if (n < zero) + n = -n; + while (m != zero) { + T tmp{n % m}; + n = m; + m = tmp; + } + return n; +} + +#endif diff --git a/exploring-cpp-2e/chapter57/html/annotated.html b/exploring-cpp-2e/chapter57/html/annotated.html new file mode 100644 index 0000000..44702a3 --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/annotated.html @@ -0,0 +1,66 @@ + + + + + + +Project 3 - Currency Type: Class List + + + + + + +
+
+ + + + + + +
+
Project 3 - Currency Type +
+
+
+ + + + +
+
+
+
Class List
+
+
+
Here are the classes, structs, unions and interfaces with brief descriptions:
+
[detail level 12]
+ + + + + +
oCcurrency
oCfixedImplement a fixed-point number class template. Values have N places after the decimal point. All arithmetic follows the usual rules
oCioflags
\CrationalRepresent a rational number (fraction) as a numerator and denominator
 \Czero_denominatorException class if the denominator is ever zero
+
+
+ + + + diff --git a/exploring-cpp-2e/chapter57/html/bc_s.png b/exploring-cpp-2e/chapter57/html/bc_s.png new file mode 100644 index 0000000..224b29a Binary files /dev/null and b/exploring-cpp-2e/chapter57/html/bc_s.png differ diff --git a/exploring-cpp-2e/chapter57/html/bdwn.png b/exploring-cpp-2e/chapter57/html/bdwn.png new file mode 100644 index 0000000..940a0b9 Binary files /dev/null and b/exploring-cpp-2e/chapter57/html/bdwn.png differ diff --git a/exploring-cpp-2e/chapter57/html/classcurrency-members.html b/exploring-cpp-2e/chapter57/html/classcurrency-members.html new file mode 100644 index 0000000..f78968c --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/classcurrency-members.html @@ -0,0 +1,88 @@ + + + + + + +Project 3 - Currency Type: Member List + + + + + + +
+
+ + + + + + +
+
Project 3 - Currency Type +
+
+
+ + + + +
+
+
+
currency< T, N > Member List
+
+
+ +

This is the complete list of members for currency< T, N >, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
as_string() const currency< T, N >
convert() const currency< T, N >inline
currency()currency< T, N >inline
currency(T integer)currency< T, N >inline
currency(T integer, T fraction)currency< T, N >inline
currency(double value)currency< T, N >inline
currency(currency< U, M > const &rhs)currency< T, N >inline
fraction() const currency< T, N >inline
fraction() const currency< T, N >inline
int_type typedefcurrency< T, N >
integer() const currency< T, N >inline
negate()currency< T, N >
operator*=(value_type m)currency< T, N >
operator*=(int_type m)currency< T, N >
operator++()currency< T, N >
operator++(int)currency< T, N >
operator+=(currency c)currency< T, N >
operator--()currency< T, N >
operator--(int)currency< T, N >
operator-=(currency c)currency< T, N >
operator/=(value_type m)currency< T, N >
operator/=(int_type m)currency< T, N >
operator=(currency< U, M > rhs)currency< T, N >inline
read(std::basic_istream< Char, Traits > &strm)currency< T, N >
read(std::basic_istream< CharT, Traits > &strm) (defined in currency< T, N >)currency< T, N >
round() const currency< T, N >inline
value() const currency< T, N >inline
value_type typedefcurrency< T, N >
+ + + + diff --git a/exploring-cpp-2e/chapter57/html/classcurrency.html b/exploring-cpp-2e/chapter57/html/classcurrency.html new file mode 100644 index 0000000..f5efc13 --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/classcurrency.html @@ -0,0 +1,549 @@ + + + + + + +Project 3 - Currency Type: currency< T, N > Class Template Reference + + + + + + +
+
+ + + + + + +
+
Project 3 - Currency Type +
+
+
+ + + + +
+
+ +
+
currency< T, N > Class Template Reference
+
+
+ +

#include <currency.hpp>

+ + + + + + + + +

+Public Types

+typedef T int_type
 Storage type.
 
+typedef fixed< T, N > value_type
 Type of the actual value.
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

+constexpr currency ()
 Default constructor initializes the value to zero.
 
constexpr currency (T integer)
 
 currency (T integer, T fraction)
 
 currency (double value)
 
+template<class U , int M>
 currency (currency< U, M > const &rhs)
 Copy a value that uses a different precision.
 
+template<class U , int M>
currencyoperator= (currency< U, M > rhs)
 Assign a value that uses a different precision.
 
std::string as_string () const
 
template<class Char , class Traits >
bool read (std::basic_istream< Char, Traits > &strm)
 
template<class U >
convert () const
 Convert to some other type, especially floating point. More...
 
+int_type round () const
 Round off to the nearest integer, using banker's rounding.
 
+int_type integer () const
 Return the integer part (which is the same as trunc()).
 
+template<int M>
int_type fraction () const
 Return the fractional part, to M places.
 
+int_type fraction () const
 Return the fractional part.
 
currencyoperator+= (currency c)
 
currencyoperator-= (currency c)
 
currencyoperator*= (value_type m)
 
currencyoperator*= (int_type m)
 
currencyoperator/= (value_type m)
 
currencyoperator/= (int_type m)
 
+void negate ()
 Negate this value.
 
+currencyoperator++ ()
 Pre-increment operator.
 
+currency operator++ (int)
 Post-increment operator.
 
+currencyoperator-- ()
 Pre-decrement operator.
 
+currency operator-- (int)
 Post-decrement operator.
 
+value_type value () const
 Return the internal value.
 
+template<class CharT , class Traits >
bool read (std::basic_istream< CharT, Traits > &strm)
 
+

Detailed Description

+

template<class T = long, int N = 2>
+class currency< T, N >

+ +

Class to represent a currency value in the global locale.

+ +

Definition at line 42 of file currency.hpp.

+

Constructor & Destructor Documentation

+ +
+
+
+template<class T = long, int N = 2>
+ + + + + +
+ + + + + + + + +
constexpr currency< T, N >::currency (integer)
+
+inline
+
+

Initialize the value to integer

+
Parameters
+ + +
integerThe integer initial value; the fractional part is zero.
+
+
+ +

Definition at line 52 of file currency.hpp.

+ +
+
+ +
+
+
+template<class T = long, int N = 2>
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
currency< T, N >::currency (integer,
fraction 
)
+
+inline
+
+

Initialize the value. The interpretation of the fractional part depends on N. For example, if N is 2, a fraction of 9 represents 0.09, buf if N is 5, fraction of 9 means 0.0009.

+
Parameters
+ + + +
integerThe integer part of the initial value
fractionThe fractional part of the initial value
+
+
+ +

Definition at line 59 of file currency.hpp.

+ +
+
+ +
+
+
+template<class T = long, int N = 2>
+ + + + + +
+ + + + + + + + +
currency< T, N >::currency (double value)
+
+inline
+
+

Initialize from a floating point number.

+
Parameters
+ + +
valuethe initial value
+
+
+ +

Definition at line 62 of file currency.hpp.

+ +
+
+

Member Function Documentation

+ +
+
+
+template<class T , int N>
+ + + + + + + +
std::string currency< T, N >::as_string () const
+
+

Convert to a string.

+
Returns
a string representation of the value, e.g., "$123.04"
+ +

Definition at line 150 of file currency.hpp.

+ +
+
+ +
+
+
+template<class T = long, int N = 2>
+
+template<class U >
+ + + + + +
+ + + + + + + +
U currency< T, N >::convert () const
+
+inline
+
+ +

Convert to some other type, especially floating point.

+

Convert the value to a different numeric type. Typically, the other type is a floating-point type.

+ +

Definition at line 92 of file currency.hpp.

+ +

References currency< T, N >::value().

+ +
+
+ +
+
+
+template<class T , int N>
+ + + + + + + + +
currency< T, N > & currency< T, N >::operator*= (value_type m)
+
+

Multiplication operator.

+
Parameters
+ + +
mthe value to multiply
+
+
+
Returns
*this
+ +

Definition at line 178 of file currency.hpp.

+ +
+
+ +
+
+
+template<class T , int N>
+ + + + + + + + +
currency< T, N > & currency< T, N >::operator*= (int_type m)
+
+

Multiplication operator.

+
Parameters
+ + +
mthe value to multiply
+
+
+
Returns
*this
+ +

Definition at line 184 of file currency.hpp.

+ +
+
+ +
+
+
+template<class T , int N>
+ + + + + + + + +
currency< T, N > & currency< T, N >::operator+= (currency< T, N > c)
+
+

Addition operator.

+
Parameters
+ + +
cthe value to add
+
+
+
Returns
*this
+ +

Definition at line 164 of file currency.hpp.

+ +

References currency< T, N >::value().

+ +
+
+ +
+
+
+template<class T , int N>
+ + + + + + + + +
currency< T, N > & currency< T, N >::operator-= (currency< T, N > c)
+
+

Subtraction operator.

+
Parameters
+ + +
cthe value to subtract
+
+
+
Returns
*this
+ +

Definition at line 171 of file currency.hpp.

+ +

References currency< T, N >::value().

+ +
+
+ +
+
+
+template<class T , int N>
+ + + + + + + + +
currency< T, N > & currency< T, N >::operator/= (value_type m)
+
+

Division operator.

+
Parameters
+ + +
mthe divisor
+
+
+
Returns
*this
+ +

Definition at line 191 of file currency.hpp.

+ +
+
+ +
+
+
+template<class T , int N>
+ + + + + + + + +
currency< T, N > & currency< T, N >::operator/= (int_type m)
+
+

Division operator.

+
Parameters
+ + +
mthe divisor
+
+
+
Returns
*this
+ +

Definition at line 197 of file currency.hpp.

+ +
+
+ +
+
+
+template<class T = long, int N = 2>
+
+template<class Char , class Traits >
+ + + + + + + + +
bool currency< T, N >::read (std::basic_istream< Char, Traits > & strm)
+
+

Overwrite this value with the value read from the stream. The value in the stream must have the correct number of digits. If the showbase flag is set, the currency symbol must be present.

+
Parameters
+ + +
strmInput stream
+
+
+
Returns
true if the read is success and *this has been modified, or false if the read fails. Check strm for details.
+ +

Referenced by operator>>().

+ +
+
+
The documentation for this class was generated from the following file: +
+ + + + diff --git a/exploring-cpp-2e/chapter57/html/classes.html b/exploring-cpp-2e/chapter57/html/classes.html new file mode 100644 index 0000000..23fe9a5 --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/classes.html @@ -0,0 +1,70 @@ + + + + + + +Project 3 - Currency Type: Class Index + + + + + + +
+
+ + + + + + +
+
Project 3 - Currency Type +
+
+
+ + + + +
+
+
+
Class Index
+
+
+
C | F | I | R | Z
+ + + + + +
  C  
+
  F  
+
  I  
+
  R  
+
  Z  
+
currency   fixed   ioflags   rational   rational::zero_denominator   
+
C | F | I | R | Z
+
+ + + + diff --git a/exploring-cpp-2e/chapter57/html/classfixed-members.html b/exploring-cpp-2e/chapter57/html/classfixed-members.html new file mode 100644 index 0000000..f7ed58c --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/classfixed-members.html @@ -0,0 +1,85 @@ + + + + + + +Project 3 - Currency Type: Member List + + + + + + +
+
+ + + + + + +
+
Project 3 - Currency Type +
+
+
+ + + + +
+
+
+
fixed< T, N > Member List
+
+
+ +

This is the complete list of members for fixed< T, N >, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
as_double() const fixed< T, N >inline
as_float() const fixed< T, N >inline
as_long_double() const fixed< T, N >inline
as_string() const fixed< T, N >
fixed()fixed< T, N >inline
fixed(value_type integer, value_type fraction)fixed< T, N >
fixed(value_type integer)fixed< T, N >
fixed(double value)fixed< T, N >inline
fraction() const fixed< T, N >
integer() const fixed< T, N >inline
negate()fixed< T, N >
operator*=(fixed f)fixed< T, N >
operator++()fixed< T, N >
operator++(int)fixed< T, N >
operator+=(fixed f)fixed< T, N >
operator--()fixed< T, N >
operator--(int)fixed< T, N >
operator-=(fixed f)fixed< T, N >
operator/=(fixed f)fixed< T, N >
placesfixed< T, N >static
places10fixed< T, N >static
read(std::basic_istream< Char, Traits > &strm)fixed< T, N >
round() const fixed< T, N >
value() const fixed< T, N >inline
value_type typedeffixed< T, N >
+ + + + diff --git a/exploring-cpp-2e/chapter57/html/classfixed.html b/exploring-cpp-2e/chapter57/html/classfixed.html new file mode 100644 index 0000000..ef25174 --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/classfixed.html @@ -0,0 +1,291 @@ + + + + + + +Project 3 - Currency Type: fixed< T, N > Class Template Reference + + + + + + +
+
+ + + + + + +
+
Project 3 - Currency Type +
+
+
+ + + + +
+
+ +
+
fixed< T, N > Class Template Reference
+
+
+ +

Implement a fixed-point number class template. Values have N places after the decimal point. All arithmetic follows the usual rules. + More...

+ +

#include <fixed.hpp>

+ + + + + +

+Public Types

+typedef T value_type
 Type of the actual value.
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

+constexpr fixed ()
 Default constructor initializes to zero.
 
 fixed (value_type integer, value_type fraction)
 
+constexpr fixed (value_type integer)
 Construct from an integer with no fractional part.
 
fixed (double value)
 Construct by rounding off a floating point number.
 
std::string as_string () const
 
template<class Char , class Traits >
bool read (std::basic_istream< Char, Traits > &strm)
 
+double as_long_double () const
 Convert to long double.
 
+double as_double () const
 Convert to double.
 
+float as_float () const
 Convert to float.
 
value_type round () const
 
+value_type integer () const
 Return the integer part (which is the same as trunc()).
 
+value_type fraction () const
 Return the fractional part, e.g., 3 for 12.03.
 
+fixedoperator+= (fixed f)
 Addition assignment operator.
 
+fixedoperator-= (fixed f)
 Subtraction assignment operator.
 
+fixedoperator*= (fixed f)
 Multiplication assignment operator.
 
+fixedoperator/= (fixed f)
 Division assignment operator.
 
+void negate ()
 Negate this value.
 
+fixedoperator++ ()
 Pre-increment.
 
+fixed operator++ (int)
 Post-increment.
 
+fixedoperator-- ()
 Pre-decrement.
 
+fixed operator-- (int)
 Post-decrement.
 
+value_type value () const
 Return the internal value.
 
+ + + + + + + +

+Static Public Attributes

+static value_type constexpr places {N}
 number of decimal places
 
+static value_type constexpr places10 {power10(N)}
 10places
 
+

Detailed Description

+

template<class T, int N>
+class fixed< T, N >

+ +

Implement a fixed-point number class template. Values have N places after the decimal point. All arithmetic follows the usual rules.

+

Listing 49-5. Changing fixed from a Class to a Class Template

+ +

Definition at line 26 of file fixed.hpp.

+

Constructor & Destructor Documentation

+ +
+
+
+template<class T , int N>
+ + + + + + + + + + + + + + + + + + +
fixed< T, N >::fixed (value_type integer,
value_type fraction 
)
+
+

Construct from separate integer and fractional parts, e.g., initialize to 123.45 with fixed(123, 45). Initialize to 12.07 with fixed(12, 7).

+ +

Definition at line 109 of file fixed.hpp.

+ +
+
+

Member Function Documentation

+ +
+
+
+template<class T , int N>
+ + + + + + + +
std::string fixed< T, N >::as_string () const
+
+

Convert to a string.

+
Returns
a string representation of the value, e.g., "123.04"
+ +

Definition at line 221 of file fixed.hpp.

+ +

Referenced by operator<<().

+ +
+
+ +
+
+
+template<class T , int N>
+
+template<class Char , class Traits >
+ + + + + + + + +
bool fixed< T, N >::read (std::basic_istream< Char, Traits > & strm)
+
+

Read from a stream. Overwrite this value with the value read from the stream.

+
Parameters
+ + +
strmthe stream to read
+
+
+
Returns
true for success or false for failure
+ +

Definition at line 296 of file fixed.hpp.

+ +

Referenced by operator>>().

+ +
+
+ +
+
+
+template<class T , int N>
+ + + + + + + +
fixed< T, N >::value_type fixed< T, N >::round () const
+
+

Return just the integer part, rounded off to the nearest integer. If the value lies equidistant between two integers, round even numbers up and odd numbers down (banker's rounding).

+ +

Definition at line 204 of file fixed.hpp.

+ +

Referenced by currency< T, N >::round().

+ +
+
+
The documentation for this class was generated from the following file: +
+ + + + diff --git a/exploring-cpp-2e/chapter57/html/classioflags-members.html b/exploring-cpp-2e/chapter57/html/classioflags-members.html new file mode 100644 index 0000000..79a59cf --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/classioflags-members.html @@ -0,0 +1,64 @@ + + + + + + +Project 3 - Currency Type: Member List + + + + + + +
+
+ + + + + + +
+
Project 3 - Currency Type +
+
+
+ + + + +
+
+
+
ioflags Member List
+
+
+ +

This is the complete list of members for ioflags, including all inherited members.

+ + + + + +
ioflags(std::basic_ios< char > &stream)ioflagsinline
ioflags(ioflags const &)=delete (defined in ioflags)ioflags
operator=(ioflags const &)=delete (defined in ioflags)ioflags
~ioflags()ioflagsinline
+ + + + diff --git a/exploring-cpp-2e/chapter57/html/classioflags.html b/exploring-cpp-2e/chapter57/html/classioflags.html new file mode 100644 index 0000000..f66efd9 --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/classioflags.html @@ -0,0 +1,119 @@ + + + + + + +Project 3 - Currency Type: ioflags Class Reference + + + + + + +
+
+ + + + + + +
+
Project 3 - Currency Type +
+
+
+ + + + +
+
+ +
+
ioflags Class Reference
+
+
+ +

#include <ioflags.hpp>

+ + + + + + + + + + + +

+Public Member Functions

 ioflags (std::basic_ios< char > &stream)
 
~ioflags ()
 Restore the formatting flags.
 
ioflags (ioflags const &)=delete
 
+ioflagsoperator= (ioflags const &)=delete
 
+

Detailed Description

+

Save and restore I/O stream flags. When a function needs to temporarily alter an I/O stream flags, simply define an object of type ioflags. Set whatever flags you want. When the block exits or function returns, the original flags are restored.

+ +

Definition at line 15 of file ioflags.hpp.

+

Constructor & Destructor Documentation

+ +
+
+ + + + + +
+ + + + + + + + +
ioflags::ioflags (std::basic_ios< char > & stream)
+
+inline
+
+

Save the formatting flags from stream.

+
Parameters
+ + +
streamThe stream that will have its flags modified and restored.
+
+
+ +

Definition at line 20 of file ioflags.hpp.

+ +
+
+
The documentation for this class was generated from the following file: +
+ + + + diff --git a/exploring-cpp-2e/chapter57/html/classrational-members.html b/exploring-cpp-2e/chapter57/html/classrational-members.html new file mode 100644 index 0000000..a78ef42 --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/classrational-members.html @@ -0,0 +1,84 @@ + + + + + + +Project 3 - Currency Type: Member List + + + + + + +
+
+ + + + + + +
+
Project 3 - Currency Type +
+
+
+ + + + +
+
+
+
rational< T > Member List
+
+
+ +

This is the complete list of members for rational< T >, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + +
as() const rational< T >inline
denominator() const rational< T >inline
numerator() const rational< T >inline
operator*=(rational const &rhs)rational< T >
operator*=(value_type const &rhs)rational< T >
operator++()rational< T >
operator++(int)rational< T >
operator+=(rational const &rhs)rational< T >
operator+=(value_type const &rhs)rational< T >
operator--()rational< T >
operator--(int)rational< T >
operator-=(rational const &rhs)rational< T >
operator-=(value_type const &rhs)rational< T >
operator/=(rational const &rhs)rational< T >
operator/=(value_type const &rhs)rational< T >
operator=(value_type)rational< T >
operator=(rational< U > const &rhs)rational< T >
operator=(rational< U > const &rhs) (defined in rational< T >)rational< T >
rational(value_type num=0)rational< T >inline
rational(value_type num, value_type den)rational< T >
rational(double r)rational< T >
rational(rational< U > const &that)rational< T >
scale(U value) (defined in rational< T >)rational< T >
value_type typedefrational< T >
+ + + + diff --git a/exploring-cpp-2e/chapter57/html/classrational.html b/exploring-cpp-2e/chapter57/html/classrational.html new file mode 100644 index 0000000..8d9dc75 --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/classrational.html @@ -0,0 +1,290 @@ + + + + + + +Project 3 - Currency Type: rational< T > Class Template Reference + + + + + + +
+
+ + + + + + +
+
Project 3 - Currency Type +
+
+
+ + + + +
+
+ +
+
rational< T > Class Template Reference
+
+
+ +

Represent a rational number (fraction) as a numerator and denominator. + More...

+ +

#include <rational.hpp>

+ + + + + +

+Classes

class  zero_denominator
 Exception class if the denominator is ever zero. More...
 
+ + + + +

+Public Types

+typedef T value_type
 Convenience typedef for the integral type of the numerator and denominator.
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 rational (value_type num=0)
 
 rational (value_type num, value_type den)
 
 rational (double r)
 
+template<class U >
 rational (rational< U > const &that)
 Copy from a different type of rational.
 
+value_type numerator () const
 Return the numerator.
 
+value_type denominator () const
 Return the denominator.
 
+template<class U >
as () const
 Convert the rational number to another type, especially floating-point.
 
+rationaloperator= (value_type)
 Assignment of an integer.
 
+template<class U >
rationaloperator= (rational< U > const &rhs)
 Assignment of a rational with a different size.
 
+rationaloperator+= (rational const &rhs)
 Addition assignment operator.
 
+rationaloperator+= (value_type const &rhs)
 Addition assignment operator.
 
+rationaloperator-= (rational const &rhs)
 Subtraction assignment operator.
 
+rationaloperator-= (value_type const &rhs)
 Subtraction assignment operator.
 
+rationaloperator*= (rational const &rhs)
 Multiplication assignment operator.
 
+rationaloperator*= (value_type const &rhs)
 Multiplication assignment operator.
 
+rationaloperator/= (rational const &rhs)
 Division assignment operator.
 
+rationaloperator/= (value_type const &rhs)
 Division assignment operator.
 
+rationaloperator++ ()
 Pre-increment.
 
+rationaloperator-- ()
 Pre-decrement.
 
+rational operator++ (int)
 Post-increment.
 
+rational operator-- (int)
 Post-decrement.
 
+template<class U >
scale (U value)
 
+template<class U >
rational< T > & operator= (rational< U > const &rhs)
 
+

Detailed Description

+

template<class T>
+class rational< T >

+ +

Represent a rational number (fraction) as a numerator and denominator.

+ +

Definition at line 16 of file rational.hpp.

+

Constructor & Destructor Documentation

+ +
+
+
+template<class T>
+ + + + + +
+ + + + + + + + +
rational< T >::rational (value_type num = 0)
+
+inline
+
+

Default constructor and constructor from a single value. As a default constructor, initializes to zero. Otherwise, initializes to the integer num.

+
Parameters
+ + +
numThe integer value to use as the initial value
+
+
+ +

Definition at line 33 of file rational.hpp.

+ +
+
+ +
+
+
+template<class T >
+ + + + + + + + + + + + + + + + + + +
rational< T >::rational (value_type num,
value_type den 
)
+
+

Construct a rational number

+
Parameters
+ + + +
numnumerator
dendenominator
+
+
+
Exceptions
+ + +
zero_denominatorif den == 0
+
+
+ +

Definition at line 106 of file rational.hpp.

+ +
+
+ +
+
+
+template<class T >
+ + + + + + + + +
rational< T >::rational (double r)
+
+

Initialize the rational number with an approximation of r

+
Parameters
+ + +
rthe initial value
+
+
+ +

Definition at line 114 of file rational.hpp.

+ +
+
+
The documentation for this class was generated from the following file: +
+ + + + diff --git a/exploring-cpp-2e/chapter57/html/classrational_1_1zero__denominator-members.html b/exploring-cpp-2e/chapter57/html/classrational_1_1zero__denominator-members.html new file mode 100644 index 0000000..11fc3d6 --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/classrational_1_1zero__denominator-members.html @@ -0,0 +1,65 @@ + + + + + + +Project 3 - Currency Type: Member List + + + + + + +
+
+ + + + + + +
+
Project 3 - Currency Type +
+
+
+ + + + + +
+
+
+
rational< T >::zero_denominator Member List
+
+
+ +

This is the complete list of members for rational< T >::zero_denominator, including all inherited members.

+ + +
zero_denominator(std::string const &what)rational< T >::zero_denominatorinline
+ + + + diff --git a/exploring-cpp-2e/chapter57/html/classrational_1_1zero__denominator.html b/exploring-cpp-2e/chapter57/html/classrational_1_1zero__denominator.html new file mode 100644 index 0000000..8a75191 --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/classrational_1_1zero__denominator.html @@ -0,0 +1,95 @@ + + + + + + +Project 3 - Currency Type: rational< T >::zero_denominator Class Reference + + + + + + +
+
+ + + + + + +
+
Project 3 - Currency Type +
+
+
+ + + + + +
+
+ +
+
rational< T >::zero_denominator Class Reference
+
+
+ +

Exception class if the denominator is ever zero. + More...

+ +

#include <rational.hpp>

+
+Inheritance diagram for rational< T >::zero_denominator:
+
+
+ + + +
+ + + + + +

+Public Member Functions

zero_denominator (std::string const &what)
 Construct the exception object.
 
+

Detailed Description

+

template<class T>
+class rational< T >::zero_denominator

+ +

Exception class if the denominator is ever zero.

+ +

Definition at line 22 of file rational.hpp.

+

The documentation for this class was generated from the following file: +
+ + + + diff --git a/exploring-cpp-2e/chapter57/html/classrational_1_1zero__denominator.png b/exploring-cpp-2e/chapter57/html/classrational_1_1zero__denominator.png new file mode 100644 index 0000000..949006e Binary files /dev/null and b/exploring-cpp-2e/chapter57/html/classrational_1_1zero__denominator.png differ diff --git a/exploring-cpp-2e/chapter57/html/closed.png b/exploring-cpp-2e/chapter57/html/closed.png new file mode 100644 index 0000000..98cc2c9 Binary files /dev/null and b/exploring-cpp-2e/chapter57/html/closed.png differ diff --git a/exploring-cpp-2e/chapter57/html/currency_8hpp.html b/exploring-cpp-2e/chapter57/html/currency_8hpp.html new file mode 100644 index 0000000..86abeed --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/currency_8hpp.html @@ -0,0 +1,1266 @@ + + + + + + +Project 3 - Currency Type: currency.hpp File Reference + + + + + + +
+
+ + + + + + +
+
Project 3 - Currency Type +
+
+
+ + + + +
+
+ +
+
currency.hpp File Reference
+
+
+
#include <iomanip>
+#include <istream>
+#include <locale>
+#include <ostream>
+#include <sstream>
+#include <string>
+#include <stdexcept>
+#include "ioflags.hpp"
+#include "fixed.hpp"
+#include "rational.hpp"
+
+

Go to the source code of this file.

+ + + + +

+Classes

class  currency< T, N >
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Functions

template<class T , int N, class Char , class Traits >
std::basic_istream< Char,
+Traits > & 
operator>> (std::basic_istream< Char, Traits > &strm, currency< T, N > &c)
 
template<class T , int N, class Char , class Traits >
std::basic_ostream< Char,
+Traits > & 
operator<< (std::basic_ostream< Char, Traits > &strm, currency< T, N > c)
 
+template<class T , int N>
currency< T, N > operator- (currency< T, N > a)
 Negate a currency value.
 
template<class T , int N>
currency< T, N > operator+ (currency< T, N > a, currency< T, N > b)
 
template<class T , int N>
currency< T, N > operator- (currency< T, N > a, currency< T, N > b)
 
template<class T , int N>
currency< T, N > operator* (currency< T, N > a, T b)
 
template<class T , int N>
currency< T, N > operator* (T a, currency< T, N > b)
 
template<class T , int N>
currency< T, N > operator/ (currency< T, N > a, T b)
 
template<class T , int N>
rational< T > operator/ (currency< T, N > n, currency< T, N > d)
 
template<class T , int N>
bool operator== (currency< T, N > a, currency< T, N > b)
 
template<class T , int N>
bool operator== (currency< T, N > a, T b)
 
template<class T , int N>
bool operator== (T a, currency< T, N > b)
 
template<class T , int N>
bool operator!= (currency< T, N > a, currency< T, N > b)
 
template<class T , int N>
bool operator!= (currency< T, N > a, T b)
 
template<class T , int N>
bool operator!= (T a, currency< T, N > b)
 
template<class T , int N>
bool operator< (currency< T, N > a, currency< T, N > b)
 
template<class T , int N>
bool operator< (currency< T, N > a, T b)
 
template<class T , int N>
bool operator< (T a, currency< T, N > b)
 
template<class T , int N>
bool operator> (currency< T, N > a, currency< T, N > b)
 
template<class T , int N>
bool operator> (currency< T, N > a, T b)
 
template<class T , int N>
bool operator> (T a, currency< T, N > b)
 
template<class T , int N>
bool operator<= (currency< T, N > a, currency< T, N > b)
 
template<class T , int N>
bool operator<= (currency< T, N > a, T b)
 
template<class T , int N>
bool operator<= (T a, currency< T, N > b)
 
template<class T , int N>
bool operator>= (currency< T, N > a, currency< T, N > b)
 
template<class T , int N>
bool operator>= (currency< T, N > a, T b)
 
template<class T , int N>
bool operator>= (T a, currency< T, N > b)
 
+

Detailed Description

+

Implement a currency type.

+ +

Definition in file currency.hpp.

+

Function Documentation

+ +
+
+
+template<class T , int N>
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
bool operator!= (currency< T, N > a,
currency< T, N > b 
)
+
+inline
+
+

Compare currency values for inequality.

+
Parameters
+ + + +
aThe left-hand operand
bThe right-hand operand
+
+
+ +

Definition at line 391 of file currency.hpp.

+ +
+
+ +
+
+
+template<class T , int N>
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
bool operator!= (currency< T, N > a,
b 
)
+
+inline
+
+

Compare currency value and an integer for inequality

+
Parameters
+ + + +
aThe left-hand operand
bThe right-hand operand
+
+
+ +

Definition at line 399 of file currency.hpp.

+ +
+
+ +
+
+
+template<class T , int N>
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
bool operator!= (a,
currency< T, N > b 
)
+
+inline
+
+

Compare currency value and an integer for inequality

+
Parameters
+ + + +
aThe left-hand operand
bThe right-hand operand
+
+
+ +

Definition at line 407 of file currency.hpp.

+ +
+
+ +
+
+
+template<class T , int N>
+ + + + + + + + + + + + + + + + + + +
currency<T,N> operator* (currency< T, N > a,
b 
)
+
+

Multiply currency value and an integer

+
Parameters
+ + + +
aThe left-hand operand
bThe right-hand operand
+
+
+ +

Definition at line 324 of file currency.hpp.

+ +
+
+ +
+
+
+template<class T , int N>
+ + + + + + + + + + + + + + + + + + +
currency<T,N> operator* (a,
currency< T, N > b 
)
+
+

Multiply currency value and an integer

+
Parameters
+ + + +
aThe left-hand operand
bThe right-hand operand
+
+
+ +

Definition at line 334 of file currency.hpp.

+ +
+
+ +
+
+
+template<class T , int N>
+ + + + + + + + + + + + + + + + + + +
currency<T,N> operator+ (currency< T, N > a,
currency< T, N > b 
)
+
+

Add currency values

+
Parameters
+ + + +
aThe left-hand operand
bThe right-hand operand
+
+
+ +

Definition at line 304 of file currency.hpp.

+ +
+
+ +
+
+
+template<class T , int N>
+ + + + + + + + + + + + + + + + + + +
currency<T,N> operator- (currency< T, N > a,
currency< T, N > b 
)
+
+

Subtract currency values

+
Parameters
+ + + +
aThe left-hand operand
bThe right-hand operand
+
+
+ +

Definition at line 314 of file currency.hpp.

+ +
+
+ +
+
+
+template<class T , int N>
+ + + + + + + + + + + + + + + + + + +
currency<T,N> operator/ (currency< T, N > a,
b 
)
+
+

Divide currency value by an integer

+
Parameters
+ + + +
aThe left-hand operand
bThe right-hand operand
+
+
+ +

Definition at line 344 of file currency.hpp.

+ +
+
+ +
+
+
+template<class T , int N>
+ + + + + + + + + + + + + + + + + + +
rational<T> operator/ (currency< T, N > n,
currency< T, N > d 
)
+
+

Divide currency values to yield a rational result.

+
Parameters
+ + + +
nthe numerator
dthe denominator
+
+
+ +

Definition at line 354 of file currency.hpp.

+ +

References fixed< T, N >::value(), and currency< T, N >::value().

+ +
+
+ +
+
+
+template<class T , int N>
+ + + + + + + + + + + + + + + + + + +
bool operator< (currency< T, N > a,
currency< T, N > b 
)
+
+

Compare currency values for less-than by comparing the underlying values.

+
Parameters
+ + + +
aThe left-hand operand
bThe right-hand operand
+
+
+ +

Definition at line 416 of file currency.hpp.

+ +

References fixed< T, N >::value(), and currency< T, N >::value().

+ +
+
+ +
+
+
+template<class T , int N>
+ + + + + + + + + + + + + + + + + + +
bool operator< (currency< T, N > a,
b 
)
+
+

Compare a currency value and an integer for less-than.

+
Parameters
+ + + +
aThe left-hand operand
bThe right-hand operand
+
+
+ +

Definition at line 424 of file currency.hpp.

+ +
+
+ +
+
+
+template<class T , int N>
+ + + + + + + + + + + + + + + + + + +
bool operator< (a,
currency< T, N > b 
)
+
+

Compare a currency value and an integer for less-than.

+
Parameters
+ + + +
aThe left-hand operand
bThe right-hand operand
+
+
+ +

Definition at line 432 of file currency.hpp.

+ +
+
+ +
+
+
+template<class T , int N, class Char , class Traits >
+ + + + + + + + + + + + + + + + + + +
std::basic_ostream<Char, Traits>& operator<< (std::basic_ostream< Char, Traits > & strm,
currency< T, N > c 
)
+
+

Write a currency value

+
Parameters
+ + + +
strmThe output stream
cThe value to write
+
+
+ +

Definition at line 285 of file currency.hpp.

+ +
+
+ +
+
+
+template<class T , int N>
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
bool operator<= (currency< T, N > a,
currency< T, N > b 
)
+
+inline
+
+

Compare currency values for less-than-or-equal.

+
Parameters
+ + + +
aThe left-hand operand
bThe right-hand operand
+
+
+ +

Definition at line 466 of file currency.hpp.

+ +
+
+ +
+
+
+template<class T , int N>
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
bool operator<= (currency< T, N > a,
b 
)
+
+inline
+
+

Compare a currency value and an integer for less-than-or-equal.

+
Parameters
+ + + +
aThe left-hand operand
bThe right-hand operand
+
+
+ +

Definition at line 474 of file currency.hpp.

+ +
+
+ +
+
+
+template<class T , int N>
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
bool operator<= (a,
currency< T, N > b 
)
+
+inline
+
+

Compare a currency value and an integer for less-than-or-equal.

+
Parameters
+ + + +
aThe left-hand operand
bThe right-hand operand
+
+
+ +

Definition at line 482 of file currency.hpp.

+ +
+
+ +
+
+
+template<class T , int N>
+ + + + + + + + + + + + + + + + + + +
bool operator== (currency< T, N > a,
currency< T, N > b 
)
+
+

Compare currency values for equality by comparing the underlying values.

+
Parameters
+ + + +
aThe left-hand operand
bThe right-hand operand
+
+
+ +

Definition at line 366 of file currency.hpp.

+ +

References currency< T, N >::value().

+ +
+
+ +
+
+
+template<class T , int N>
+ + + + + + + + + + + + + + + + + + +
bool operator== (currency< T, N > a,
b 
)
+
+

Compare currency value and an integer for equality

+
Parameters
+ + + +
aThe left-hand operand
bThe right-hand operand
+
+
+ +

Definition at line 374 of file currency.hpp.

+ +

References currency< T, N >::value().

+ +
+
+ +
+
+
+template<class T , int N>
+ + + + + + + + + + + + + + + + + + +
bool operator== (a,
currency< T, N > b 
)
+
+

Compare currency value and an integer for equality

+
Parameters
+ + + +
aThe left-hand operand
bThe right-hand operand
+
+
+ +

Definition at line 382 of file currency.hpp.

+ +

References currency< T, N >::value().

+ +
+
+ +
+
+
+template<class T , int N>
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
bool operator> (currency< T, N > a,
currency< T, N > b 
)
+
+inline
+
+

Compare currency values for greater-than.

+
Parameters
+ + + +
aThe left-hand operand
bThe right-hand operand
+
+
+ +

Definition at line 441 of file currency.hpp.

+ +
+
+ +
+
+
+template<class T , int N>
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
bool operator> (currency< T, N > a,
b 
)
+
+inline
+
+

Compare a currency value and an integer for greater-than.

+
Parameters
+ + + +
aThe left-hand operand
bThe right-hand operand
+
+
+ +

Definition at line 449 of file currency.hpp.

+ +
+
+ +
+
+
+template<class T , int N>
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
bool operator> (a,
currency< T, N > b 
)
+
+inline
+
+

Compare a currency value and an integer for greater-than.

+
Parameters
+ + + +
aThe left-hand operand
bThe right-hand operand
+
+
+ +

Definition at line 457 of file currency.hpp.

+ +
+
+ +
+
+
+template<class T , int N>
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
bool operator>= (currency< T, N > a,
currency< T, N > b 
)
+
+inline
+
+

Compare currency values for greater-than-or-equal.

+
Parameters
+ + + +
aThe left-hand operand
bThe right-hand operand
+
+
+ +

Definition at line 491 of file currency.hpp.

+ +
+
+ +
+
+
+template<class T , int N>
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
bool operator>= (currency< T, N > a,
b 
)
+
+inline
+
+

Compare a currency value and an integer for greater-than-or-equal.

+
Parameters
+ + + +
aThe left-hand operand
bThe right-hand operand
+
+
+ +

Definition at line 499 of file currency.hpp.

+ +
+
+ +
+
+
+template<class T , int N>
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
bool operator>= (a,
currency< T, N > b 
)
+
+inline
+
+

Compare a currency value and an integer for greater-than-or-equal.

+
Parameters
+ + + +
aThe left-hand operand
bThe right-hand operand
+
+
+ +

Definition at line 507 of file currency.hpp.

+ +
+
+ +
+
+
+template<class T , int N, class Char , class Traits >
+ + + + + + + + + + + + + + + + + + +
std::basic_istream<Char, Traits>& operator>> (std::basic_istream< Char, Traits > & strm,
currency< T, N > & c 
)
+
+

Read a currency value

+
Parameters
+ + + +
strmThe input stream
[out]cStore the value here
+
+
+ +

Definition at line 274 of file currency.hpp.

+ +

References currency< T, N >::read().

+ +
+
+
+ + + + diff --git a/exploring-cpp-2e/chapter57/html/currency_8hpp_source.html b/exploring-cpp-2e/chapter57/html/currency_8hpp_source.html new file mode 100644 index 0000000..73b230a --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/currency_8hpp_source.html @@ -0,0 +1,455 @@ + + + + + + +Project 3 - Currency Type: currency.hpp Source File + + + + + + +
+
+ + + + + + +
+
Project 3 - Currency Type +
+
+
+ + + + +
+
+
+
currency.hpp
+
+
+Go to the documentation of this file.
1 
+
25 #ifndef CURRENCY_HPP_
+
26 #define CURRENCY_HPP_
+
27 
+
28 #include <iomanip>
+
29 #include <istream>
+
30 #include <locale>
+
31 #include <ostream>
+
32 #include <sstream>
+
33 #include <string>
+
34 #include <stdexcept>
+
35 
+
36 #include "ioflags.hpp"
+
37 #include "fixed.hpp"
+
38 #include "rational.hpp"
+
39 
+
41 template<class T=long, int N=2>
+
42 class currency
+
43 {
+
44 public:
+
45  typedef T int_type;
+ +
47 
+
49  constexpr currency() : value_() {}
+
52  constexpr currency(T integer) : value_(integer) {}
+
59  currency(T integer, T fraction) : value_(integer, fraction) {}
+
62  currency(double value) : value_(value) {}
+
63 
+
65  template<class U, int M>
+
66  currency(currency<U, M> const& rhs): value_(rhs.value()) {}
+
67 
+
69  template<class U, int M>
+ +
71  {
+
72  value_ = rhs.value();
+
73  return *this;
+
74  }
+
75 
+
78  std::string as_string() const;
+
85  template<class Char, class Traits>
+
86  bool read(std::basic_istream<Char, Traits>& strm);
+
87 
+
90  template<class U>
+
92  U convert() const { return value().template convert<U>(); }
+
93 
+
95  int_type round() const { return value().round(); }
+
96 
+
98  int_type integer() const { return value().integer(); }
+
100  template<int M>
+
101  int_type fraction() const { return value().template fraction<M>(); }
+
103  int_type fraction() const { return value().fraction(); }
+
104 
+ + + + + + +
129 
+
131  void negate();
+
132 
+
134  currency& operator++();
+
136  currency operator++(int);
+
138  currency& operator--();
+
140  currency operator--(int);
+
141 
+
143  value_type value() const { return value_; }
+
144 
+
145 private:
+
146  value_type value_;
+
147 };
+
148 
+
149 template<class T, int N>
+ +
151 const
+
152 {
+
153  std::ostringstream digits;
+
154  digits.imbue(std::locale::classic());
+
155  digits << integer() << std::setw(value_type::places) << std::setfill('0') << fraction();
+
156 
+
157  std::ostringstream out;
+
158  std::money_put<char> const& put(std::use_facet<std::money_put<char> >(std::locale()));
+
159  put.put(std::ostreambuf_iterator<char>(out), false, out, '0', digits.str());
+
160  return out.str();
+
161 }
+
162 
+
163 template<class T, int N>
+ +
165 {
+
166  value_ += f.value();
+
167  return *this;
+
168 }
+
169 
+
170 template<class T, int N>
+ +
172 {
+
173  value_ -= f.value();
+
174  return *this;
+
175 }
+
176 
+
177 template<class T, int N>
+ +
179 {
+
180  value_ *= i;
+
181  return *this;
+
182 }
+
183 template<class T, int N>
+ +
185 {
+
186  value_ *= i;
+
187  return *this;
+
188 }
+
189 
+
190 template<class T, int N>
+ +
192 {
+
193  value_ /= i;
+
194  return *this;
+
195 }
+
196 template<class T, int N>
+ +
198 {
+
199  value_ /= i;
+
200  return *this;
+
201 }
+
202 
+
203 template<class T, int N>
+ +
205 {
+
206  value_ = -value_;
+
207 }
+
208 
+
209 template<class T, int N>
+ +
211 {
+
212  ++value_;
+
213  return *this;
+
214 }
+
215 
+
216 template<class T, int N>
+ +
218 {
+
219  currency result(*this);
+
220  ++value_;
+
221  return result;
+
222 }
+
223 
+
224 template<class T, int N>
+ +
226 {
+
227  --value_;
+
228  return *this;
+
229 }
+
230 
+
231 template<class T, int N>
+ +
233 {
+
234  currency result(*this);
+
235  --value_;
+
236  return result;
+
237 }
+
238 
+
239 template<class T, int N>
+
240 template<class CharT, class Traits>
+
241 bool currency<T,N>::read(std::basic_istream<CharT,Traits>& strm)
+
242 {
+
243  ioflags flags(strm);
+
244  typename std::basic_istream<CharT, Traits>::sentry sentry(strm, false);
+
245  if (not sentry)
+
246  return false;
+
247 
+
248  std::ios_base::iostate error(std::ios_base::goodbit);
+
249  std::string digits;
+
250  std::money_get<CharT> const& get(
+
251  std::use_facet<std::money_get<CharT> >(strm.getloc()));
+
252  get.get(std::istreambuf_iterator<CharT>(strm), std::istreambuf_iterator<CharT>(),
+
253  false, strm, error, digits);
+
254 
+
255  if ((error & std::ios_base::failbit) != 0)
+
256  return false;
+
257 
+
258  std::moneypunct<CharT> const& punct(
+
259  std::use_facet<std::moneypunct<CharT> >(strm.getloc()));
+
260 
+
261  // Set fraction to the rightmost frac_digits() characters of digits.
+
262  std::string fraction(digits.substr(digits.size() - punct.frac_digits(), punct.frac_digits()));
+
263  // Set integer to the remainder of digits.
+
264  std::string integer(digits.substr(0, digits.size() - punct.frac_digits()));
+
265 
+
266  std::istringstream fixed_stream(integer + "." + fraction);
+
267  return value_.read(fixed_stream);
+
268 }
+
269 
+
273 template<class T, int N, class Char, class Traits>
+
274 std::basic_istream<Char, Traits>& operator>>(std::basic_istream<Char, Traits>& strm, currency<T,N>& c)
+
275 {
+
276  if (not c.read(strm))
+
277  strm.setstate(strm.failbit);
+
278  return strm;
+
279 }
+
280 
+
284 template<class T, int N, class Char, class Traits>
+
285 std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& strm, currency<T,N> c)
+
286 {
+
287  typename std::basic_ostream<Char, Traits>::sentry sentry(strm);
+
288  strm << c.as_string();
+
289  return strm;
+
290 }
+
291 
+
293 template<class T, int N>
+ +
295 {
+
296  a.negate();
+
297  return a;
+
298 }
+
299 
+
303 template<class T, int N>
+ +
305 {
+
306  a += b;
+
307  return a;
+
308 }
+
309 
+
313 template<class T, int N>
+ +
315 {
+
316  a -= b;
+
317  return a;
+
318 }
+
319 
+
323 template<class T, int N>
+ +
325 {
+
326  a *= b;
+
327  return a;
+
328 }
+
329 
+
333 template<class T, int N>
+ +
335 {
+
336  b *= a;
+
337  return b;
+
338 }
+
339 
+
343 template<class T, int N>
+ +
345 {
+
346  a /= b;
+
347  return a;
+
348 }
+
349 
+
353 template<class T, int N>
+ +
355 {
+
356  // Extract the underlying value of the fixed values. No adjustment
+
357  // to scaling is needed because the numerator and denominator are
+
358  // both scaled to the same amount.
+
359  return rational<T>(n.value().value(), d.value().value());
+
360 }
+
361 
+
365 template<class T, int N>
+ +
367 {
+
368  return a.value() == b.value();
+
369 }
+
373 template<class T, int N>
+ +
375 {
+
376  return a.value() == b;
+
377 }
+
381 template<class T, int N>
+ +
383 {
+
384  return a == b.value();
+
385 }
+
386 
+
390 template<class T, int N>
+ +
392 {
+
393  return not (a == b);
+
394 }
+
398 template<class T, int N>
+
399 inline bool operator!=(currency<T,N> a, T b)
+
400 {
+
401  return not (a == b);
+
402 }
+
406 template<class T, int N>
+
407 inline bool operator!=(T a, currency<T,N> b)
+
408 {
+
409  return not (a == b);
+
410 }
+
411 
+
415 template<class T, int N>
+
416 bool operator<(currency<T,N> a, currency<T,N> b)
+
417 {
+
418  return a.value() < b.value();
+
419 }
+
423 template<class T, int N>
+
424 bool operator<(currency<T,N> a, T b)
+
425 {
+
426  return a.value() < b;
+
427 }
+
431 template<class T, int N>
+
432 bool operator<(T a, currency<T,N> b)
+
433 {
+
434  return a < b.value();
+
435 }
+
436 
+
440 template<class T, int N>
+ +
442 {
+
443  return b < a;
+
444 }
+
448 template<class T, int N>
+
449 inline bool operator>(currency<T,N> a, T b)
+
450 {
+
451  return b < a;
+
452 }
+
456 template<class T, int N>
+
457 inline bool operator>(T a, currency<T,N> b)
+
458 {
+
459  return b < a;
+
460 }
+
461 
+
465 template<class T, int N>
+
466 inline bool operator<=(currency<T,N> a, currency<T,N> b)
+
467 {
+
468  return not (b < a);
+
469 }
+
473 template<class T, int N>
+
474 inline bool operator<=(currency<T,N> a, T b)
+
475 {
+
476  return not (b < a);
+
477 }
+
481 template<class T, int N>
+
482 inline bool operator<=(T a, currency<T,N> b)
+
483 {
+
484  return not (b < a);
+
485 }
+
486 
+
490 template<class T, int N>
+ +
492 {
+
493  return not (a < b);
+
494 }
+
498 template<class T, int N>
+
499 inline bool operator>=(currency<T,N> a, T b)
+
500 {
+
501  return not (a < b);
+
502 }
+
506 template<class T, int N>
+
507 inline bool operator>=(T a, currency<T,N> b)
+
508 {
+
509  return not (a < b);
+
510 }
+
511 
+
512 #endif
+
currency< T, N > operator+(currency< T, N > a, currency< T, N > b)
Definition: currency.hpp:304
+
currency & operator+=(currency c)
Definition: currency.hpp:164
+
currency & operator--()
Pre-decrement operator.
Definition: currency.hpp:225
+
bool read(std::basic_istream< Char, Traits > &strm)
+
Implement a fixed-point number class template. Values have N places after the decimal point...
Definition: fixed.hpp:26
+
bool operator==(currency< T, N > a, currency< T, N > b)
Definition: currency.hpp:366
+
currency< T, N > operator*(currency< T, N > a, T b)
Definition: currency.hpp:324
+
constexpr currency()
Default constructor initializes the value to zero.
Definition: currency.hpp:49
+
fixed< T, N > value_type
Type of the actual value.
Definition: currency.hpp:46
+
value_type value() const
Return the internal value.
Definition: currency.hpp:143
+
currency< T, N > operator/(currency< T, N > a, T b)
Definition: currency.hpp:344
+
std::string as_string() const
Definition: currency.hpp:150
+
Save and restore I/O stream flags.
+
bool operator!=(currency< T, N > a, currency< T, N > b)
Definition: currency.hpp:391
+ +
value_type fraction() const
Return the fractional part, e.g., 3 for 12.03.
Definition: fixed.hpp:129
+
value_type round() const
Definition: fixed.hpp:204
+
int_type round() const
Round off to the nearest integer, using banker&#39;s rounding.
Definition: currency.hpp:95
+
constexpr currency(T integer)
Definition: currency.hpp:52
+
Represent a rational number (fraction) as a numerator and denominator.
Definition: rational.hpp:16
+
void negate()
Negate this value.
Definition: currency.hpp:204
+
currency(currency< U, M > const &rhs)
Copy a value that uses a different precision.
Definition: currency.hpp:66
+
currency & operator=(currency< U, M > rhs)
Assign a value that uses a different precision.
Definition: currency.hpp:70
+
currency & operator*=(value_type m)
Definition: currency.hpp:178
+
bool operator>=(currency< T, N > a, currency< T, N > b)
Definition: currency.hpp:491
+
currency & operator-=(currency c)
Definition: currency.hpp:171
+
currency(double value)
Definition: currency.hpp:62
+
currency(T integer, T fraction)
Definition: currency.hpp:59
+
int_type integer() const
Return the integer part (which is the same as trunc()).
Definition: currency.hpp:98
+ +
int_type fraction() const
Return the fractional part, to M places.
Definition: currency.hpp:101
+
currency & operator++()
Pre-increment operator.
Definition: currency.hpp:210
+ +
value_type integer() const
Return the integer part (which is the same as trunc()).
Definition: fixed.hpp:71
+
value_type value() const
Return the internal value.
Definition: fixed.hpp:97
+
bool operator>(currency< T, N > a, currency< T, N > b)
Definition: currency.hpp:441
+
int_type fraction() const
Return the fractional part.
Definition: currency.hpp:103
+
U convert() const
Convert to some other type, especially floating point.
Definition: currency.hpp:92
+
std::basic_istream< Char, Traits > & operator>>(std::basic_istream< Char, Traits > &strm, currency< T, N > &c)
Definition: currency.hpp:274
+
currency & operator/=(value_type m)
Definition: currency.hpp:191
+
T int_type
Storage type.
Definition: currency.hpp:45
+
currency< T, N > operator-(currency< T, N > a)
Negate a currency value.
Definition: currency.hpp:294
+
+ + + + diff --git a/exploring-cpp-2e/chapter57/html/doxygen.css b/exploring-cpp-2e/chapter57/html/doxygen.css new file mode 100644 index 0000000..4699e69 --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/doxygen.css @@ -0,0 +1,1357 @@ +/* The standard CSS for doxygen 1.8.5 */ + +body, table, div, p, dl { + font: 400 14px/22px Roboto,sans-serif; +} + +/* @group Heading Levels */ + +h1.groupheader { + font-size: 150%; +} + +.title { + font: 400 14px/28px Roboto,sans-serif; + font-size: 150%; + font-weight: bold; + margin: 10px 2px; +} + +h2.groupheader { + border-bottom: 1px solid #879ECB; + color: #354C7B; + font-size: 150%; + font-weight: normal; + margin-top: 1.75em; + padding-top: 8px; + padding-bottom: 4px; + width: 100%; +} + +h3.groupheader { + font-size: 100%; +} + +h1, h2, h3, h4, h5, h6 { + -webkit-transition: text-shadow 0.5s linear; + -moz-transition: text-shadow 0.5s linear; + -ms-transition: text-shadow 0.5s linear; + -o-transition: text-shadow 0.5s linear; + transition: text-shadow 0.5s linear; + margin-right: 15px; +} + +h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { + text-shadow: 0 0 15px cyan; +} + +dt { + font-weight: bold; +} + +div.multicol { + -moz-column-gap: 1em; + -webkit-column-gap: 1em; + -moz-column-count: 3; + -webkit-column-count: 3; +} + +p.startli, p.startdd, p.starttd { + margin-top: 2px; +} + +p.endli { + margin-bottom: 0px; +} + +p.enddd { + margin-bottom: 4px; +} + +p.endtd { + margin-bottom: 2px; +} + +/* @end */ + +caption { + font-weight: bold; +} + +span.legend { + font-size: 70%; + text-align: center; +} + +h3.version { + font-size: 90%; + text-align: center; +} + +div.qindex, div.navtab{ + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; +} + +div.qindex, div.navpath { + width: 100%; + line-height: 140%; +} + +div.navtab { + margin-right: 15px; +} + +/* @group Link Styling */ + +a { + color: #3D578C; + font-weight: normal; + text-decoration: none; +} + +.contents a:visited { + color: #4665A2; +} + +a:hover { + text-decoration: underline; +} + +a.qindex { + font-weight: bold; +} + +a.qindexHL { + font-weight: bold; + background-color: #9CAFD4; + color: #ffffff; + border: 1px double #869DCA; +} + +.contents a.qindexHL:visited { + color: #ffffff; +} + +a.el { + font-weight: bold; +} + +a.elRef { +} + +a.code, a.code:visited, a.line, a.line:visited { + color: #4665A2; +} + +a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited { + color: #4665A2; +} + +/* @end */ + +dl.el { + margin-left: -1cm; +} + +pre.fragment { + border: 1px solid #C4CFE5; + background-color: #FBFCFD; + padding: 4px 6px; + margin: 4px 8px 4px 2px; + overflow: auto; + word-wrap: break-word; + font-size: 9pt; + line-height: 125%; + font-family: monospace, fixed; + font-size: 105%; +} + +div.fragment { + padding: 0px; + margin: 0px; + background-color: #FBFCFD; + border: 1px solid #C4CFE5; +} + +div.line { + font-family: monospace, fixed; + font-size: 13px; + min-height: 13px; + line-height: 1.0; + text-wrap: unrestricted; + white-space: -moz-pre-wrap; /* Moz */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + white-space: pre-wrap; /* CSS3 */ + word-wrap: break-word; /* IE 5.5+ */ + text-indent: -53px; + padding-left: 53px; + padding-bottom: 0px; + margin: 0px; + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +div.line.glow { + background-color: cyan; + box-shadow: 0 0 10px cyan; +} + + +span.lineno { + padding-right: 4px; + text-align: right; + border-right: 2px solid #0F0; + background-color: #E8E8E8; + white-space: pre; +} +span.lineno a { + background-color: #D8D8D8; +} + +span.lineno a:hover { + background-color: #C8C8C8; +} + +div.ah { + background-color: black; + font-weight: bold; + color: #ffffff; + margin-bottom: 3px; + margin-top: 3px; + padding: 0.2em; + border: solid thin #333; + border-radius: 0.5em; + -webkit-border-radius: .5em; + -moz-border-radius: .5em; + box-shadow: 2px 2px 3px #999; + -webkit-box-shadow: 2px 2px 3px #999; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); + background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000); +} + +div.groupHeader { + margin-left: 16px; + margin-top: 12px; + font-weight: bold; +} + +div.groupText { + margin-left: 16px; + font-style: italic; +} + +body { + background-color: white; + color: black; + margin: 0; +} + +div.contents { + margin-top: 10px; + margin-left: 12px; + margin-right: 8px; +} + +td.indexkey { + background-color: #EBEFF6; + font-weight: bold; + border: 1px solid #C4CFE5; + margin: 2px 0px 2px 0; + padding: 2px 10px; + white-space: nowrap; + vertical-align: top; +} + +td.indexvalue { + background-color: #EBEFF6; + border: 1px solid #C4CFE5; + padding: 2px 10px; + margin: 2px 0px; +} + +tr.memlist { + background-color: #EEF1F7; +} + +p.formulaDsp { + text-align: center; +} + +img.formulaDsp { + +} + +img.formulaInl { + vertical-align: middle; +} + +div.center { + text-align: center; + margin-top: 0px; + margin-bottom: 0px; + padding: 0px; +} + +div.center img { + border: 0px; +} + +address.footer { + text-align: right; + padding-right: 12px; +} + +img.footer { + border: 0px; + vertical-align: middle; +} + +/* @group Code Colorization */ + +span.keyword { + color: #008000 +} + +span.keywordtype { + color: #604020 +} + +span.keywordflow { + color: #e08000 +} + +span.comment { + color: #800000 +} + +span.preprocessor { + color: #806020 +} + +span.stringliteral { + color: #002080 +} + +span.charliteral { + color: #008080 +} + +span.vhdldigit { + color: #ff00ff +} + +span.vhdlchar { + color: #000000 +} + +span.vhdlkeyword { + color: #700070 +} + +span.vhdllogic { + color: #ff0000 +} + +blockquote { + background-color: #F7F8FB; + border-left: 2px solid #9CAFD4; + margin: 0 24px 0 4px; + padding: 0 12px 0 16px; +} + +/* @end */ + +/* +.search { + color: #003399; + font-weight: bold; +} + +form.search { + margin-bottom: 0px; + margin-top: 0px; +} + +input.search { + font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #e8eef2; +} +*/ + +td.tiny { + font-size: 75%; +} + +.dirtab { + padding: 4px; + border-collapse: collapse; + border: 1px solid #A3B4D7; +} + +th.dirtab { + background: #EBEFF6; + font-weight: bold; +} + +hr { + height: 0px; + border: none; + border-top: 1px solid #4A6AAA; +} + +hr.footer { + height: 1px; +} + +/* @group Member Descriptions */ + +table.memberdecls { + border-spacing: 0px; + padding: 0px; +} + +.memberdecls td, .fieldtable tr { + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +.memberdecls td.glow, .fieldtable tr.glow { + background-color: cyan; + box-shadow: 0 0 15px cyan; +} + +.mdescLeft, .mdescRight, +.memItemLeft, .memItemRight, +.memTemplItemLeft, .memTemplItemRight, .memTemplParams { + background-color: #F9FAFC; + border: none; + margin: 4px; + padding: 1px 0 0 8px; +} + +.mdescLeft, .mdescRight { + padding: 0px 8px 4px 8px; + color: #555; +} + +.memSeparator { + border-bottom: 1px solid #DEE4F0; + line-height: 1px; + margin: 0px; + padding: 0px; +} + +.memItemLeft, .memTemplItemLeft { + white-space: nowrap; +} + +.memItemRight { + width: 100%; +} + +.memTemplParams { + color: #4665A2; + white-space: nowrap; + font-size: 80%; +} + +/* @end */ + +/* @group Member Details */ + +/* Styles for detailed member documentation */ + +.memtemplate { + font-size: 80%; + color: #4665A2; + font-weight: normal; + margin-left: 9px; +} + +.memnav { + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} + +.mempage { + width: 100%; +} + +.memitem { + padding: 0; + margin-bottom: 10px; + margin-right: 5px; + -webkit-transition: box-shadow 0.5s linear; + -moz-transition: box-shadow 0.5s linear; + -ms-transition: box-shadow 0.5s linear; + -o-transition: box-shadow 0.5s linear; + transition: box-shadow 0.5s linear; + display: table !important; + width: 100%; +} + +.memitem.glow { + box-shadow: 0 0 15px cyan; +} + +.memname { + font-weight: bold; + margin-left: 6px; +} + +.memname td { + vertical-align: bottom; +} + +.memproto, dl.reflist dt { + border-top: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 0px 6px 0px; + color: #253555; + font-weight: bold; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + /* opera specific markup */ + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + border-top-right-radius: 4px; + border-top-left-radius: 4px; + /* firefox specific markup */ + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + -moz-border-radius-topright: 4px; + -moz-border-radius-topleft: 4px; + /* webkit specific markup */ + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + -webkit-border-top-right-radius: 4px; + -webkit-border-top-left-radius: 4px; + +} + +.memdoc, dl.reflist dd { + border-bottom: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 10px 2px 10px; + background-color: #FBFCFD; + border-top-width: 0; + background-image:url('nav_g.png'); + background-repeat:repeat-x; + background-color: #FFFFFF; + /* opera specific markup */ + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + /* firefox specific markup */ + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-bottomright: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + /* webkit specific markup */ + -webkit-border-bottom-left-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); +} + +dl.reflist dt { + padding: 5px; +} + +dl.reflist dd { + margin: 0px 0px 10px 0px; + padding: 5px; +} + +.paramkey { + text-align: right; +} + +.paramtype { + white-space: nowrap; +} + +.paramname { + color: #602020; + white-space: nowrap; +} +.paramname em { + font-style: normal; +} +.paramname code { + line-height: 14px; +} + +.params, .retval, .exception, .tparams { + margin-left: 0px; + padding-left: 0px; +} + +.params .paramname, .retval .paramname { + font-weight: bold; + vertical-align: top; +} + +.params .paramtype { + font-style: italic; + vertical-align: top; +} + +.params .paramdir { + font-family: "courier new",courier,monospace; + vertical-align: top; +} + +table.mlabels { + border-spacing: 0px; +} + +td.mlabels-left { + width: 100%; + padding: 0px; +} + +td.mlabels-right { + vertical-align: bottom; + padding: 0px; + white-space: nowrap; +} + +span.mlabels { + margin-left: 8px; +} + +span.mlabel { + background-color: #728DC1; + border-top:1px solid #5373B4; + border-left:1px solid #5373B4; + border-right:1px solid #C4CFE5; + border-bottom:1px solid #C4CFE5; + text-shadow: none; + color: white; + margin-right: 4px; + padding: 2px 3px; + border-radius: 3px; + font-size: 7pt; + white-space: nowrap; + vertical-align: middle; +} + + + +/* @end */ + +/* these are for tree view when not used as main index */ + +div.directory { + margin: 10px 0px; + border-top: 1px solid #A8B8D9; + border-bottom: 1px solid #A8B8D9; + width: 100%; +} + +.directory table { + border-collapse:collapse; +} + +.directory td { + margin: 0px; + padding: 0px; + vertical-align: top; +} + +.directory td.entry { + white-space: nowrap; + padding-right: 6px; + padding-top: 3px; +} + +.directory td.entry a { + outline:none; +} + +.directory td.entry a img { + border: none; +} + +.directory td.desc { + width: 100%; + padding-left: 6px; + padding-right: 6px; + padding-top: 3px; + border-left: 1px solid rgba(0,0,0,0.05); +} + +.directory tr.even { + padding-left: 6px; + background-color: #F7F8FB; +} + +.directory img { + vertical-align: -30%; +} + +.directory .levels { + white-space: nowrap; + width: 100%; + text-align: right; + font-size: 9pt; +} + +.directory .levels span { + cursor: pointer; + padding-left: 2px; + padding-right: 2px; + color: #3D578C; +} + +div.dynheader { + margin-top: 8px; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +address { + font-style: normal; + color: #2A3D61; +} + +table.doxtable { + border-collapse:collapse; + margin-top: 4px; + margin-bottom: 4px; +} + +table.doxtable td, table.doxtable th { + border: 1px solid #2D4068; + padding: 3px 7px 2px; +} + +table.doxtable th { + background-color: #374F7F; + color: #FFFFFF; + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; +} + +table.fieldtable { + /*width: 100%;*/ + margin-bottom: 10px; + border: 1px solid #A8B8D9; + border-spacing: 0px; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + border-radius: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); +} + +.fieldtable td, .fieldtable th { + padding: 3px 7px 2px; +} + +.fieldtable td.fieldtype, .fieldtable td.fieldname { + white-space: nowrap; + border-right: 1px solid #A8B8D9; + border-bottom: 1px solid #A8B8D9; + vertical-align: top; +} + +.fieldtable td.fieldname { + padding-top: 3px; +} + +.fieldtable td.fielddoc { + border-bottom: 1px solid #A8B8D9; + /*width: 100%;*/ +} + +.fieldtable td.fielddoc p:first-child { + margin-top: 0px; +} + +.fieldtable td.fielddoc p:last-child { + margin-bottom: 2px; +} + +.fieldtable tr:last-child td { + border-bottom: none; +} + +.fieldtable th { + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + font-size: 90%; + color: #253555; + padding-bottom: 4px; + padding-top: 5px; + text-align:left; + -moz-border-radius-topleft: 4px; + -moz-border-radius-topright: 4px; + -webkit-border-top-left-radius: 4px; + -webkit-border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom: 1px solid #A8B8D9; +} + + +.tabsearch { + top: 0px; + left: 10px; + height: 36px; + background-image: url('tab_b.png'); + z-index: 101; + overflow: hidden; + font-size: 13px; +} + +.navpath ul +{ + font-size: 11px; + background-image:url('tab_b.png'); + background-repeat:repeat-x; + background-position: 0 -5px; + height:30px; + line-height:30px; + color:#8AA0CC; + border:solid 1px #C2CDE4; + overflow:hidden; + margin:0px; + padding:0px; +} + +.navpath li +{ + list-style-type:none; + float:left; + padding-left:10px; + padding-right:15px; + background-image:url('bc_s.png'); + background-repeat:no-repeat; + background-position:right; + color:#364D7C; +} + +.navpath li.navelem a +{ + height:32px; + display:block; + text-decoration: none; + outline: none; + color: #283A5D; + font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + text-decoration: none; +} + +.navpath li.navelem a:hover +{ + color:#6884BD; +} + +.navpath li.footer +{ + list-style-type:none; + float:right; + padding-left:10px; + padding-right:15px; + background-image:none; + background-repeat:no-repeat; + background-position:right; + color:#364D7C; + font-size: 8pt; +} + + +div.summary +{ + float: right; + font-size: 8pt; + padding-right: 5px; + width: 50%; + text-align: right; +} + +div.summary a +{ + white-space: nowrap; +} + +div.ingroups +{ + font-size: 8pt; + width: 50%; + text-align: left; +} + +div.ingroups a +{ + white-space: nowrap; +} + +div.header +{ + background-image:url('nav_h.png'); + background-repeat:repeat-x; + background-color: #F9FAFC; + margin: 0px; + border-bottom: 1px solid #C4CFE5; +} + +div.headertitle +{ + padding: 5px 5px 5px 10px; +} + +dl +{ + padding: 0 0 0 10px; +} + +/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */ +dl.section +{ + margin-left: 0px; + padding-left: 0px; +} + +dl.note +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #D0C000; +} + +dl.warning, dl.attention +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #FF0000; +} + +dl.pre, dl.post, dl.invariant +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #00D000; +} + +dl.deprecated +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #505050; +} + +dl.todo +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #00C0E0; +} + +dl.test +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #3030E0; +} + +dl.bug +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #C08050; +} + +dl.section dd { + margin-bottom: 6px; +} + + +#projectlogo +{ + text-align: center; + vertical-align: bottom; + border-collapse: separate; +} + +#projectlogo img +{ + border: 0px none; +} + +#projectname +{ + font: 300% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 2px 0px; +} + +#projectbrief +{ + font: 120% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#projectnumber +{ + font: 50% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#titlearea +{ + padding: 0px; + margin: 0px; + width: 100%; + border-bottom: 1px solid #5373B4; +} + +.image +{ + text-align: center; +} + +.dotgraph +{ + text-align: center; +} + +.mscgraph +{ + text-align: center; +} + +.caption +{ + font-weight: bold; +} + +div.zoom +{ + border: 1px solid #90A5CE; +} + +dl.citelist { + margin-bottom:50px; +} + +dl.citelist dt { + color:#334975; + float:left; + font-weight:bold; + margin-right:10px; + padding:5px; +} + +dl.citelist dd { + margin:2px 0; + padding:5px 0; +} + +div.toc { + padding: 14px 25px; + background-color: #F4F6FA; + border: 1px solid #D8DFEE; + border-radius: 7px 7px 7px 7px; + float: right; + height: auto; + margin: 0 20px 10px 10px; + width: 200px; +} + +div.toc li { + background: url("bdwn.png") no-repeat scroll 0 5px transparent; + font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif; + margin-top: 5px; + padding-left: 10px; + padding-top: 2px; +} + +div.toc h3 { + font: bold 12px/1.2 Arial,FreeSans,sans-serif; + color: #4665A2; + border-bottom: 0 none; + margin: 0; +} + +div.toc ul { + list-style: none outside none; + border: medium none; + padding: 0px; +} + +div.toc li.level1 { + margin-left: 0px; +} + +div.toc li.level2 { + margin-left: 15px; +} + +div.toc li.level3 { + margin-left: 30px; +} + +div.toc li.level4 { + margin-left: 45px; +} + +.inherit_header { + font-weight: bold; + color: gray; + cursor: pointer; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.inherit_header td { + padding: 6px 0px 2px 5px; +} + +.inherit { + display: none; +} + +tr.heading h2 { + margin-top: 12px; + margin-bottom: 4px; +} + +/* tooltip related style info */ + +.ttc { + position: absolute; + display: none; +} + +#powerTip { + cursor: default; + white-space: nowrap; + background-color: white; + border: 1px solid gray; + border-radius: 4px 4px 4px 4px; + box-shadow: 1px 1px 7px gray; + display: none; + font-size: smaller; + max-width: 80%; + opacity: 0.9; + padding: 1ex 1em 1em; + position: absolute; + z-index: 2147483647; +} + +#powerTip div.ttdoc { + color: grey; + font-style: italic; +} + +#powerTip div.ttname a { + font-weight: bold; +} + +#powerTip div.ttname { + font-weight: bold; +} + +#powerTip div.ttdeci { + color: #006318; +} + +#powerTip div { + margin: 0px; + padding: 0px; + font: 12px/16px Roboto,sans-serif; +} + +#powerTip:before, #powerTip:after { + content: ""; + position: absolute; + margin: 0px; +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.s:after, #powerTip.s:before, +#powerTip.w:after, #powerTip.w:before, +#powerTip.e:after, #powerTip.e:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.nw:after, #powerTip.nw:before, +#powerTip.sw:after, #powerTip.sw:before { + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; +} + +#powerTip.n:after, #powerTip.s:after, +#powerTip.w:after, #powerTip.e:after, +#powerTip.nw:after, #powerTip.ne:after, +#powerTip.sw:after, #powerTip.se:after { + border-color: rgba(255, 255, 255, 0); +} + +#powerTip.n:before, #powerTip.s:before, +#powerTip.w:before, #powerTip.e:before, +#powerTip.nw:before, #powerTip.ne:before, +#powerTip.sw:before, #powerTip.se:before { + border-color: rgba(128, 128, 128, 0); +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.nw:after, #powerTip.nw:before { + top: 100%; +} + +#powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after { + border-top-color: #ffffff; + border-width: 10px; + margin: 0px -10px; +} +#powerTip.n:before { + border-top-color: #808080; + border-width: 11px; + margin: 0px -11px; +} +#powerTip.n:after, #powerTip.n:before { + left: 50%; +} + +#powerTip.nw:after, #powerTip.nw:before { + right: 14px; +} + +#powerTip.ne:after, #powerTip.ne:before { + left: 14px; +} + +#powerTip.s:after, #powerTip.s:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.sw:after, #powerTip.sw:before { + bottom: 100%; +} + +#powerTip.s:after, #powerTip.se:after, #powerTip.sw:after { + border-bottom-color: #ffffff; + border-width: 10px; + margin: 0px -10px; +} + +#powerTip.s:before, #powerTip.se:before, #powerTip.sw:before { + border-bottom-color: #808080; + border-width: 11px; + margin: 0px -11px; +} + +#powerTip.s:after, #powerTip.s:before { + left: 50%; +} + +#powerTip.sw:after, #powerTip.sw:before { + right: 14px; +} + +#powerTip.se:after, #powerTip.se:before { + left: 14px; +} + +#powerTip.e:after, #powerTip.e:before { + left: 100%; +} +#powerTip.e:after { + border-left-color: #ffffff; + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.e:before { + border-left-color: #808080; + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +#powerTip.w:after, #powerTip.w:before { + right: 100%; +} +#powerTip.w:after { + border-right-color: #ffffff; + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.w:before { + border-right-color: #808080; + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +@media print +{ + #top { display: none; } + #side-nav { display: none; } + #nav-path { display: none; } + body { overflow:visible; } + h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } + .summary { display: none; } + .memitem { page-break-inside: avoid; } + #doc-content + { + margin-left:0 !important; + height:auto !important; + width:auto !important; + overflow:inherit; + display:inline; + } +} + diff --git a/exploring-cpp-2e/chapter57/html/doxygen.png b/exploring-cpp-2e/chapter57/html/doxygen.png new file mode 100644 index 0000000..3ff17d8 Binary files /dev/null and b/exploring-cpp-2e/chapter57/html/doxygen.png differ diff --git a/exploring-cpp-2e/chapter57/html/dynsections.js b/exploring-cpp-2e/chapter57/html/dynsections.js new file mode 100644 index 0000000..2f15470 --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/dynsections.js @@ -0,0 +1,104 @@ +function toggleVisibility(linkObj) +{ + var base = $(linkObj).attr('id'); + var summary = $('#'+base+'-summary'); + var content = $('#'+base+'-content'); + var trigger = $('#'+base+'-trigger'); + var src=$(trigger).attr('src'); + if (content.is(':visible')===true) { + content.hide(); + summary.show(); + $(linkObj).addClass('closed').removeClass('opened'); + $(trigger).attr('src',src.substring(0,src.length-8)+'closed.png'); + } else { + content.show(); + summary.hide(); + $(linkObj).removeClass('closed').addClass('opened'); + $(trigger).attr('src',src.substring(0,src.length-10)+'open.png'); + } + return false; +} + +function updateStripes() +{ + $('table.directory tr'). + removeClass('even').filter(':visible:even').addClass('even'); +} +function toggleLevel(level) +{ + $('table.directory tr').each(function(){ + var l = this.id.split('_').length-1; + var i = $('#img'+this.id.substring(3)); + var a = $('#arr'+this.id.substring(3)); + if (l + + + + + +Project 3 - Currency Type: File List + + + + + + +
+
+ + + + + + +
+
Project 3 - Currency Type +
+
+
+ + + + +
+
+
+
File List
+
+
+
Here is a list of all documented files with brief descriptions:
+ + + + + + + + + + +
o*currency.hpp
o*fixed.hpp
o*gcd.cpp
o*gcd.hpp
o*ioflags.hppSave and restore I/O stream flags
o*power10.hpp
o*rational.hpp
o*test.cpp
\*test.hpp
+
+
+ + + + diff --git a/exploring-cpp-2e/chapter57/html/fixed_8hpp.html b/exploring-cpp-2e/chapter57/html/fixed_8hpp.html new file mode 100644 index 0000000..c4e7c7f --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/fixed_8hpp.html @@ -0,0 +1,210 @@ + + + + + + +Project 3 - Currency Type: fixed.hpp File Reference + + + + + + +
+
+ + + + + + +
+
Project 3 - Currency Type +
+
+
+ + + + +
+
+ +
+
fixed.hpp File Reference
+
+
+
#include <cassert>
+#include <cmath>
+#include <iomanip>
+#include <ios>
+#include <istream>
+#include <locale>
+#include <ostream>
+#include <sstream>
+#include <stdexcept>
+#include <string>
+#include "ioflags.hpp"
+#include "power10.hpp"
+
+

Go to the source code of this file.

+ + + + + +

+Classes

class  fixed< T, N >
 Implement a fixed-point number class template. Values have N places after the decimal point. All arithmetic follows the usual rules. More...
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Functions

+template<class T , int N, class Char , class Traits >
std::basic_istream< Char,
+Traits > & 
operator>> (std::basic_istream< Char, Traits > &strm, fixed< T, N > &f)
 Read a fixed value.
 
+template<class T , int N, class Char , class Traits >
std::basic_ostream< Char,
+Traits > & 
operator<< (std::basic_ostream< Char, Traits > &strm, fixed< T, N > f)
 Write a fixed value.
 
+template<class T , int N>
fixed< T, N > operator+ (fixed< T, N > a, fixed< T, N > b)
 Add fixed values.
 
+template<class T , int N>
fixed< T, N > operator- (fixed< T, N > a, fixed< T, N > b)
 Subtract fixed values.
 
+template<class T , int N>
fixed< T, N > operator* (fixed< T, N > a, fixed< T, N > b)
 Multiply fixed values.
 
+template<class T , int N>
fixed< T, N > operator/ (fixed< T, N > a, fixed< T, N > b)
 Divide fixed values.
 
+template<class T , int N>
fixed< T, N > operator- (fixed< T, N > a)
 Negate a fixed value.
 
+template<class T , int N>
bool operator== (fixed< T, N > a, fixed< T, N > b)
 Compare fixed values for equality by comparing the underlying values.
 
+template<class T , int N>
bool operator== (T a, fixed< T, N > b)
 Compare fixed values for equality by comparing the value wih an integer.
 
+template<class T , int N>
bool operator== (fixed< T, N > a, T b)
 Compare fixed values for equality by comparing the value wih an integer.
 
+template<class T , int N>
bool operator!= (fixed< T, N > a, fixed< T, N > b)
 Compare fixed values for inequality by comparing the underlying values.
 
+template<class T , int N>
bool operator!= (T a, fixed< T, N > b)
 Compare fixed values for inequality by comparing the value wih an integer.
 
+template<class T , int N>
bool operator!= (fixed< T, N > a, T b)
 Compare fixed values for inequality by comparing the value wih an integer.
 
+template<class T , int N>
bool operator< (fixed< T, N > a, fixed< T, N > b)
 Compare fixed values for less-than by comparing the underlying values.
 
+template<class T , int N>
bool operator< (T a, fixed< T, N > b)
 Compare fixed values for less-than by comparing the value wih an integer.
 
+template<class T , int N>
bool operator< (fixed< T, N > a, T b)
 Compare fixed values for less-than by comparing the value wih an integer.
 
+template<class T , int N>
bool operator> (fixed< T, N > a, fixed< T, N > b)
 Compare fixed values for greater-than by comparing the underlying values.
 
+template<class T , int N>
bool operator> (T a, fixed< T, N > b)
 Compare fixed values for greater-than by comparing the value wih an integer.
 
+template<class T , int N>
bool operator> (fixed< T, N > a, T b)
 Compare fixed values for greater-than by comparing the value wih an integer.
 
+template<class T , int N>
bool operator<= (fixed< T, N > a, fixed< T, N > b)
 Compare fixed values for less-than-or-equal by comparing the underlying values.
 
+template<class T , int N>
bool operator<= (T a, fixed< T, N > b)
 Compare fixed values for less-than-or-equal by comparing the value wih an integer.
 
+template<class T , int N>
bool operator<= (fixed< T, N > a, T b)
 Compare fixed values for less-than-or-equal by comparing the value wih an integer.
 
+template<class T , int N>
bool operator>= (fixed< T, N > a, fixed< T, N > b)
 Compare fixed values for greater-than-or-equal by comparing the underlying values.
 
+template<class T , int N>
bool operator>= (T a, fixed< T, N > b)
 Compare fixed values for greater-than-or-equal by comparing the value wih an integer.
 
+template<class T , int N>
bool operator>= (fixed< T, N > a, T b)
 Compare fixed values for greater-than-or-equal by comparing the value wih an integer.
 
+
+ + + + diff --git a/exploring-cpp-2e/chapter57/html/fixed_8hpp_source.html b/exploring-cpp-2e/chapter57/html/fixed_8hpp_source.html new file mode 100644 index 0000000..e4dc2e2 --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/fixed_8hpp_source.html @@ -0,0 +1,538 @@ + + + + + + +Project 3 - Currency Type: fixed.hpp Source File + + + + + + +
+
+ + + + + + +
+
Project 3 - Currency Type +
+
+
+ + + + +
+
+
+
fixed.hpp
+
+
+Go to the documentation of this file.
1 
+
4 #ifndef FIXED_HPP_
+
5 #define FIXED_HPP_
+
6 
+
7 #include <cassert>
+
8 #include <cmath>
+
9 #include <iomanip>
+
10 #include <ios>
+
11 #include <istream>
+
12 #include <locale>
+
13 #include <ostream>
+
14 #include <sstream>
+
15 #include <stdexcept>
+
16 #include <string>
+
17 
+
18 #include "ioflags.hpp"
+
19 #include "power10.hpp"
+
20 
+
25 template<class T, int N>
+
26 class fixed
+
27 {
+
28 public:
+
29  typedef T value_type;
+
30 
+
31  static value_type constexpr places{N};
+
32  static value_type constexpr places10{power10(N)};
+
33 
+
35  constexpr fixed() : value_() {}
+
36 
+ +
41 
+
43  constexpr fixed(value_type integer);
+
44 
+
46  fixed(double value)
+
47  : value_(static_cast<value_type>(value * places10 + (value < 0 ? -0.5 : 0.5)))
+
48  {}
+
49 
+
52  std::string as_string() const;
+
57  template<class Char, class Traits>
+
58  bool read(std::basic_istream<Char, Traits>& strm);
+
60  double as_long_double() const { return static_cast<long double>(value()) / places10; }
+
62  double as_double() const { return static_cast<double>(value()) / places10; }
+
64  float as_float() const { return static_cast<float>(value()) / places10; }
+
68  value_type round() const;
+
69 
+
71  value_type integer() const { return value() / places10; }
+
73  value_type fraction() const;
+
74 
+ + + + +
83 
+
85  void negate();
+
86 
+
88  fixed& operator++();
+
90  fixed operator++(int);
+
92  fixed& operator--();
+
94  fixed operator--(int);
+
95 
+
97  value_type value() const { return value_; }
+
98 private:
+
100  value_type reduce(value_type frac);
+
101  value_type value_;
+
102 };
+
103 
+
104 template<class T, int N>
+ +
106 
+
107 // Construct a fixed value from an integer part and a fraction part
+
108 template<class T, int N>
+ +
110 {
+
111  if (fraction < T())
+
112  throw std::invalid_argument("negative fraction not allowed");
+
113  fraction = reduce(fraction);
+
114  if (integer < T())
+
115  value_ = integer * places10 - fraction;
+
116  else
+
117  value_ = integer * places10 + fraction;
+
118 }
+
119 
+
120 // Construct a fixed value from an integer part with no fraction
+
121 template<class T, int N>
+
122 constexpr
+ +
124 : value_(integer * places10)
+
125 {}
+
126 
+
127 // Get the fraction part
+
128 template<class T, int N>
+ +
130 const
+
131 {
+
132  return std::abs(value()) % places10;
+
133 }
+
134 
+
144 template<class T, int N>
+
145 typename fixed<T,N>::value_type fixed<T,N>::reduce(value_type frac)
+
146 {
+
147  // First scan for zero digits on the right.
+
148  value_type f(frac);
+
149  while (f >= places10*10 and f % 10 == 0)
+
150  {
+
151  f /= 10;
+
152  }
+
153 
+
154  if (f >= places10*10)
+
155  {
+
156  int x(0);
+
157  // Loop ended because a non-zero digit was seen so Y* > 0.
+
158  // Discard the remaining digits, but keep track of the last
+
159  // digit to be processed (X).
+
160  while (f >= places10)
+
161  {
+
162  x = f % 10;
+
163  f /= 10;
+
164  }
+
165  // Round up if the last digit (X) is 5 or more
+
166  if (x >= 5)
+
167  ++f;
+
168  return f;
+
169  }
+
170  // Else all digits so far are zero. Check how many digits there were,
+
171  // that is, check whether G, and X at least are present.
+
172  else if (f >= places10)
+
173  {
+
174  // Yes, G and X are present. If X == 5, implement banker's rounding.
+
175  // Otherwise, round to nearest.
+
176  int x(f % 10);
+
177  f /= 10;
+
178  assert(f < places10);
+
179  if (x == 5)
+
180  {
+
181  // Yes, so implement banker's rounding.
+
182  if (f % 2 != 0)
+
183  ++f;
+
184  return f;
+
185  }
+
186  else if (x < 5)
+
187  {
+
188  // Round down.
+
189  return f;
+
190  }
+
191  else
+
192  {
+
193  // Round up.
+
194  return f + 1;
+
195  }
+
196  }
+
197  // Not enough digits, so nothing to round.
+
198  assert(frac < places10);
+
199  return frac;
+
200 }
+
201 
+
202 // Round off to nearest integer.
+
203 template<class T, int N>
+ +
205 const
+
206 {
+
207  const value_type frac(fraction());
+
208  int adjust(value() < 0 ? -1 : +1);
+
209  if (frac > places10/2)
+
210  return integer()+adjust;
+
211  else if (frac < places10/2)
+
212  return integer();
+
213  else if (integer() % 2 == 0)
+
214  return integer();
+
215  else
+
216  return integer()+adjust;
+
217 }
+
218 
+
219 // Convert to a string using fixed-point notation.
+
220 template<class T, int N>
+ +
222 const
+
223 {
+
224  std::ostringstream out;
+
225  out << integer() << '.'
+
226  << std::setfill('0') << std::setw(places) << fraction();
+
227  return out.str();
+
228 }
+
229 
+
230 template<class T, int N>
+ +
232 {
+
233  value_ += f.value();
+
234  return *this;
+
235 }
+
236 
+
237 template<class T, int N>
+ +
239 {
+
240  value_ -= f.value();
+
241  return *this;
+
242 }
+
243 
+
244 template<class T, int N>
+ +
246 {
+
247  value_ = (value_ * f.value()) / places10;
+
248  return *this;
+
249 }
+
250 
+
251 template<class T, int N>
+ +
253 {
+
254  value_ = (value_ * places10) / f.value();
+
255  return *this;
+
256 }
+
257 
+
258 template<class T, int N>
+ +
260 {
+
261  value_ = -value_;
+
262 }
+
263 
+
264 template<class T, int N>
+ +
266 {
+
267  value_ += places10;
+
268  return *this;
+
269 }
+
270 
+
271 template<class T, int N>
+ +
273 {
+
274  fixed result(*this);
+
275  ++*this;
+
276  return result;
+
277 }
+
278 
+
279 template<class T, int N>
+ +
281 {
+
282  value_ -= places10;
+
283  return *this;
+
284 }
+
285 
+
286 template<class T, int N>
+ +
288 {
+
289  fixed result(*this);
+
290  --*this;
+
291  return result;
+
292 }
+
293 
+
294 template<class T, int N>
+
295 template<class Char, class Traits>
+
296 bool fixed<T,N>::read(std::basic_istream<Char, Traits>& strm)
+
297 {
+
298  ioflags flags(strm);
+
299 
+
300  value_type integer;
+
301  char decimal;
+
302  if (not (strm >> integer))
+
303  return false;
+
304  strm.unsetf(std::ios_base::skipws);
+
305  if (not (strm >> decimal) or decimal != '.')
+
306  {
+
307  // Just an integer is fine. Push back the non-decimal character,
+
308  // if there is one, and reset the stream flags to show that
+
309  // reading the fixed value succeeded.
+
310  strm.unget();
+
311  strm.clear(strm.rdstate() & ~strm.failbit);
+
312  value_ = integer * places10;
+
313  return true;
+
314  }
+
315  else
+
316  {
+
317  value_type fraction(0);
+
318  char c;
+
319  int p(0);
+
320  // Read one extra place for round-off.
+
321  for (;
+
322  p != places+1 and strm >> c and std::isdigit(c, strm.getloc());
+
323  ++p)
+
324  {
+
325  fraction = fraction * 10 + (c - '0');
+
326  }
+
327  // Pad out to the requisite number of decimal places.
+
328  for (; p < places; ++p)
+
329  fraction = fraction * 10;
+
330  // If the loop terminated because the maximum number of decimal
+
331  // places were read, keep reading the stream to discard excees digits.
+
332  while (strm and std::isdigit(c, strm.getloc()))
+
333  strm >> c;
+
334  // Push back the last, non-digit character read from the stream.
+
335  // If the stream reached EOF, unget() is harmless.
+
336  strm.unget();
+
337  // Clear failbit because even if reading a character or whatever
+
338  // failed, reading the fixed value did not.
+
339  strm.clear(strm.rdstate() & ~strm.failbit);
+
340  fraction = reduce(fraction);
+
341  if (integer < 0)
+
342  value_ = integer * places10 - fraction;
+
343  else
+
344  value_ = integer * places10 + fraction;
+
345  }
+
346  return true;
+
347 }
+
348 
+
350 template<class T, int N, class Char, class Traits>
+
351 std::basic_istream<Char, Traits>& operator>>(std::basic_istream<Char, Traits>& strm, fixed<T,N>& f)
+
352 {
+
353  if (not f.read(strm))
+
354  strm.setstate(strm.failbit);
+
355  return strm;
+
356 }
+
357 
+
359 template<class T, int N, class Char, class Traits>
+
360 std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& strm, fixed<T,N> f)
+
361 {
+
362  strm << f.as_string();
+
363  return strm;
+
364 }
+
365 
+
367 template<class T, int N>
+ +
369 {
+
370  a += b;
+
371  return a;
+
372 }
+
373 
+
375 template<class T, int N>
+ +
377 {
+
378  a -= b;
+
379  return a;
+
380 }
+
381 
+
383 template<class T, int N>
+ +
385 {
+
386  a *= b;
+
387  return a;
+
388 }
+
389 
+
391 template<class T, int N>
+ +
393 {
+
394  a /= b;
+
395  return a;
+
396 }
+
397 
+
399 template<class T, int N>
+ +
401 {
+
402  a.negate();
+
403  return a;
+
404 }
+
405 
+
407 template<class T, int N>
+ +
409 {
+
410  return a.value() == b.value();
+
411 }
+
413 template<class T, int N>
+
414 bool operator==(T a, fixed<T,N> b)
+
415 {
+
416  return a == b.value();
+
417 }
+
419 template<class T, int N>
+
420 bool operator==(fixed<T,N> a, T b)
+
421 {
+
422  return a.value() == b;
+
423 }
+
424 
+
426 template<class T, int N>
+ +
428 {
+
429  return not (a == b);
+
430 }
+
432 template<class T, int N>
+
433 bool operator!=(T a, fixed<T,N> b)
+
434 {
+
435  return not (a == b);
+
436 }
+
438 template<class T, int N>
+
439 bool operator!=(fixed<T,N> a, T b)
+
440 {
+
441  return not (a == b);
+
442 }
+
443 
+
445 template<class T, int N>
+
446 bool operator<(fixed<T,N> a, fixed<T,N> b)
+
447 {
+
448  return a.value() < b.value();
+
449 }
+
451 template<class T, int N>
+
452 bool operator<(T a, fixed<T,N> b)
+
453 {
+
454  return a < b.value();
+
455 }
+
457 template<class T, int N>
+
458 bool operator<(fixed<T,N> a, T b)
+
459 {
+
460  return a.value() < b;
+
461 }
+
462 
+
464 template<class T, int N>
+ +
466 {
+
467  return b < a;
+
468 }
+
470 template<class T, int N>
+
471 bool operator>(T a, fixed<T,N> b)
+
472 {
+
473  return b < a;
+
474 }
+
476 template<class T, int N>
+
477 bool operator>(fixed<T,N> a, T b)
+
478 {
+
479  return b < a;
+
480 }
+
481 
+
483 template<class T, int N>
+
484 bool operator<=(fixed<T,N> a, fixed<T,N> b)
+
485 {
+
486  return not (b < a);
+
487 }
+
489 template<class T, int N>
+
490 bool operator<=(T a, fixed<T,N> b)
+
491 {
+
492  return not (b < a);
+
493 }
+
495 template<class T, int N>
+
496 bool operator<=(fixed<T,N> a, T b)
+
497 {
+
498  return not (b < a);
+
499 }
+
500 
+
502 template<class T, int N>
+ +
504 {
+
505  return not (a < b);
+
506 }
+
508 template<class T, int N>
+
509 bool operator>=(T a, fixed<T,N> b)
+
510 {
+
511  return not (a < b);
+
512 }
+
514 template<class T, int N>
+
515 bool operator>=(fixed<T,N> a, T b)
+
516 {
+
517  return not (a < b);
+
518 }
+
519 
+
520 #endif
+
double as_long_double() const
Convert to long double.
Definition: fixed.hpp:60
+
currency< T, N > operator+(currency< T, N > a, currency< T, N > b)
Definition: currency.hpp:304
+
Implement a fixed-point number class template. Values have N places after the decimal point...
Definition: fixed.hpp:26
+
bool operator==(currency< T, N > a, currency< T, N > b)
Definition: currency.hpp:366
+
currency< T, N > operator*(currency< T, N > a, T b)
Definition: currency.hpp:324
+
std::string as_string() const
Definition: fixed.hpp:221
+
fixed & operator++()
Pre-increment.
Definition: fixed.hpp:265
+
currency< T, N > operator/(currency< T, N > a, T b)
Definition: currency.hpp:344
+
float as_float() const
Convert to float.
Definition: fixed.hpp:64
+
constexpr fixed()
Default constructor initializes to zero.
Definition: fixed.hpp:35
+
Save and restore I/O stream flags.
+
T value_type
Type of the actual value.
Definition: fixed.hpp:29
+
fixed & operator--()
Pre-decrement.
Definition: fixed.hpp:280
+
static value_type constexpr places10
10places
Definition: fixed.hpp:32
+
bool operator!=(currency< T, N > a, currency< T, N > b)
Definition: currency.hpp:391
+
double as_double() const
Convert to double.
Definition: fixed.hpp:62
+
value_type fraction() const
Return the fractional part, e.g., 3 for 12.03.
Definition: fixed.hpp:129
+
value_type round() const
Definition: fixed.hpp:204
+
fixed & operator*=(fixed f)
Multiplication assignment operator.
Definition: fixed.hpp:245
+
fixed(double value)
Construct by rounding off a floating point number.
Definition: fixed.hpp:46
+
bool operator>=(currency< T, N > a, currency< T, N > b)
Definition: currency.hpp:491
+
fixed & operator-=(fixed f)
Subtraction assignment operator.
Definition: fixed.hpp:238
+ +
fixed & operator/=(fixed f)
Division assignment operator.
Definition: fixed.hpp:252
+
value_type integer() const
Return the integer part (which is the same as trunc()).
Definition: fixed.hpp:71
+
bool read(std::basic_istream< Char, Traits > &strm)
Definition: fixed.hpp:296
+
value_type value() const
Return the internal value.
Definition: fixed.hpp:97
+
bool operator>(currency< T, N > a, currency< T, N > b)
Definition: currency.hpp:441
+
void negate()
Negate this value.
Definition: fixed.hpp:259
+
std::basic_istream< Char, Traits > & operator>>(std::basic_istream< Char, Traits > &strm, currency< T, N > &c)
Definition: currency.hpp:274
+
static value_type constexpr places
number of decimal places
Definition: fixed.hpp:31
+
fixed & operator+=(fixed f)
Addition assignment operator.
Definition: fixed.hpp:231
+
currency< T, N > operator-(currency< T, N > a)
Negate a currency value.
Definition: currency.hpp:294
+
+ + + + diff --git a/exploring-cpp-2e/chapter57/html/ftv2blank.png b/exploring-cpp-2e/chapter57/html/ftv2blank.png new file mode 100644 index 0000000..63c605b Binary files /dev/null and b/exploring-cpp-2e/chapter57/html/ftv2blank.png differ diff --git a/exploring-cpp-2e/chapter57/html/ftv2cl.png b/exploring-cpp-2e/chapter57/html/ftv2cl.png new file mode 100644 index 0000000..132f657 Binary files /dev/null and b/exploring-cpp-2e/chapter57/html/ftv2cl.png differ diff --git a/exploring-cpp-2e/chapter57/html/ftv2doc.png b/exploring-cpp-2e/chapter57/html/ftv2doc.png new file mode 100644 index 0000000..17edabf Binary files /dev/null and b/exploring-cpp-2e/chapter57/html/ftv2doc.png differ diff --git a/exploring-cpp-2e/chapter57/html/ftv2folderclosed.png b/exploring-cpp-2e/chapter57/html/ftv2folderclosed.png new file mode 100644 index 0000000..bb8ab35 Binary files /dev/null and b/exploring-cpp-2e/chapter57/html/ftv2folderclosed.png differ diff --git a/exploring-cpp-2e/chapter57/html/ftv2folderopen.png b/exploring-cpp-2e/chapter57/html/ftv2folderopen.png new file mode 100644 index 0000000..d6c7f67 Binary files /dev/null and b/exploring-cpp-2e/chapter57/html/ftv2folderopen.png differ diff --git a/exploring-cpp-2e/chapter57/html/ftv2lastnode.png b/exploring-cpp-2e/chapter57/html/ftv2lastnode.png new file mode 100644 index 0000000..63c605b Binary files /dev/null and b/exploring-cpp-2e/chapter57/html/ftv2lastnode.png differ diff --git a/exploring-cpp-2e/chapter57/html/ftv2link.png b/exploring-cpp-2e/chapter57/html/ftv2link.png new file mode 100644 index 0000000..17edabf Binary files /dev/null and b/exploring-cpp-2e/chapter57/html/ftv2link.png differ diff --git a/exploring-cpp-2e/chapter57/html/ftv2mlastnode.png b/exploring-cpp-2e/chapter57/html/ftv2mlastnode.png new file mode 100644 index 0000000..0b63f6d Binary files /dev/null and b/exploring-cpp-2e/chapter57/html/ftv2mlastnode.png differ diff --git a/exploring-cpp-2e/chapter57/html/ftv2mnode.png b/exploring-cpp-2e/chapter57/html/ftv2mnode.png new file mode 100644 index 0000000..0b63f6d Binary files /dev/null and b/exploring-cpp-2e/chapter57/html/ftv2mnode.png differ diff --git a/exploring-cpp-2e/chapter57/html/ftv2mo.png b/exploring-cpp-2e/chapter57/html/ftv2mo.png new file mode 100644 index 0000000..4bfb80f Binary files /dev/null and b/exploring-cpp-2e/chapter57/html/ftv2mo.png differ diff --git a/exploring-cpp-2e/chapter57/html/ftv2node.png b/exploring-cpp-2e/chapter57/html/ftv2node.png new file mode 100644 index 0000000..63c605b Binary files /dev/null and b/exploring-cpp-2e/chapter57/html/ftv2node.png differ diff --git a/exploring-cpp-2e/chapter57/html/ftv2ns.png b/exploring-cpp-2e/chapter57/html/ftv2ns.png new file mode 100644 index 0000000..72e3d71 Binary files /dev/null and b/exploring-cpp-2e/chapter57/html/ftv2ns.png differ diff --git a/exploring-cpp-2e/chapter57/html/ftv2plastnode.png b/exploring-cpp-2e/chapter57/html/ftv2plastnode.png new file mode 100644 index 0000000..c6ee22f Binary files /dev/null and b/exploring-cpp-2e/chapter57/html/ftv2plastnode.png differ diff --git a/exploring-cpp-2e/chapter57/html/ftv2pnode.png b/exploring-cpp-2e/chapter57/html/ftv2pnode.png new file mode 100644 index 0000000..c6ee22f Binary files /dev/null and b/exploring-cpp-2e/chapter57/html/ftv2pnode.png differ diff --git a/exploring-cpp-2e/chapter57/html/ftv2splitbar.png b/exploring-cpp-2e/chapter57/html/ftv2splitbar.png new file mode 100644 index 0000000..fe895f2 Binary files /dev/null and b/exploring-cpp-2e/chapter57/html/ftv2splitbar.png differ diff --git a/exploring-cpp-2e/chapter57/html/ftv2vertline.png b/exploring-cpp-2e/chapter57/html/ftv2vertline.png new file mode 100644 index 0000000..63c605b Binary files /dev/null and b/exploring-cpp-2e/chapter57/html/ftv2vertline.png differ diff --git a/exploring-cpp-2e/chapter57/html/functions.html b/exploring-cpp-2e/chapter57/html/functions.html new file mode 100644 index 0000000..27f6ea9 --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/functions.html @@ -0,0 +1,241 @@ + + + + + + +Project 3 - Currency Type: Class Members + + + + + + +
+
+ + + + + + +
+
Project 3 - Currency Type +
+
+
+ + + + + + +
+
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- a -

+ + +

- c -

+ + +

- d -

+ + +

- f -

+ + +

- i -

+ + +

- n -

+ + +

- o -

+ + +

- p -

+ + +

- r -

+ + +

- v -

+ + +

- z -

+ + +

- ~ -

+
+ + + + diff --git a/exploring-cpp-2e/chapter57/html/functions_func.html b/exploring-cpp-2e/chapter57/html/functions_func.html new file mode 100644 index 0000000..1e15ef2 --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/functions_func.html @@ -0,0 +1,222 @@ + + + + + + +Project 3 - Currency Type: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Project 3 - Currency Type +
+
+
+ + + + + + +
+
+  + +

- a -

+ + +

- c -

+ + +

- d -

+ + +

- f -

+ + +

- i -

+ + +

- n -

+ + +

- o -

+ + +

- r -

+ + +

- v -

+ + +

- z -

+ + +

- ~ -

+
+ + + + diff --git a/exploring-cpp-2e/chapter57/html/functions_type.html b/exploring-cpp-2e/chapter57/html/functions_type.html new file mode 100644 index 0000000..85d5572 --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/functions_type.html @@ -0,0 +1,71 @@ + + + + + + +Project 3 - Currency Type: Class Members - Typedefs + + + + + + +
+
+ + + + + + +
+
Project 3 - Currency Type +
+
+
+ + + + + +
+
+
+ + + + diff --git a/exploring-cpp-2e/chapter57/html/functions_vars.html b/exploring-cpp-2e/chapter57/html/functions_vars.html new file mode 100644 index 0000000..36dd9be --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/functions_vars.html @@ -0,0 +1,69 @@ + + + + + + +Project 3 - Currency Type: Class Members - Variables + + + + + + +
+
+ + + + + + +
+
Project 3 - Currency Type +
+
+
+ + + + + +
+
+
+ + + + diff --git a/exploring-cpp-2e/chapter57/html/gcd_8cpp_source.html b/exploring-cpp-2e/chapter57/html/gcd_8cpp_source.html new file mode 100644 index 0000000..349284f --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/gcd_8cpp_source.html @@ -0,0 +1,69 @@ + + + + + + +Project 3 - Currency Type: gcd.cpp Source File + + + + + + +
+
+ + + + + + +
+
Project 3 - Currency Type +
+
+
+ + + + +
+
+
+
gcd.cpp
+
+
+
1 #include "gcd.hpp"
+
2 
+
3 int gcd(int n, int m)
+
4 {
+
5  if (n < 0)
+
6  n = -n;
+
7  while (m != 0) {
+
8  int tmp{n % m};
+
9  n = m;
+
10  m = tmp;
+
11  }
+
12  return n;
+
13 }
+
+ + + + diff --git a/exploring-cpp-2e/chapter57/html/gcd_8hpp_source.html b/exploring-cpp-2e/chapter57/html/gcd_8hpp_source.html new file mode 100644 index 0000000..47e21f9 --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/gcd_8hpp_source.html @@ -0,0 +1,74 @@ + + + + + + +Project 3 - Currency Type: gcd.hpp Source File + + + + + + +
+
+ + + + + + +
+
Project 3 - Currency Type +
+
+
+ + + + +
+
+
+
gcd.hpp
+
+
+
1 #ifndef GCD_HPP_
+
2 #define GCD_HPP_
+
3 
+
7 template<class T>
+
8 T gcd(T n, T m)
+
9 {
+
10  static const T zero{};
+
11  if (n < zero)
+
12  n = -n;
+
13  while (m != zero) {
+
14  T tmp{n % m};
+
15  n = m;
+
16  m = tmp;
+
17  }
+
18  return n;
+
19 }
+
20 
+
21 #endif
+
+ + + + diff --git a/exploring-cpp-2e/chapter57/html/globals.html b/exploring-cpp-2e/chapter57/html/globals.html new file mode 100644 index 0000000..caac6cd --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/globals.html @@ -0,0 +1,132 @@ + + + + + + +Project 3 - Currency Type: File Members + + + + + + +
+
+ + + + + + +
+
Project 3 - Currency Type +
+
+
+ + + + + + +
+
+
Here is a list of all documented file members with links to the documentation:
+ +

- m -

+ + +

- o -

+
+ + + + diff --git a/exploring-cpp-2e/chapter57/html/globals_func.html b/exploring-cpp-2e/chapter57/html/globals_func.html new file mode 100644 index 0000000..5a77de6 --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/globals_func.html @@ -0,0 +1,132 @@ + + + + + + +Project 3 - Currency Type: File Members + + + + + + +
+
+ + + + + + +
+
Project 3 - Currency Type +
+
+
+ + + + + + +
+
+  + +

- m -

+ + +

- o -

+
+ + + + diff --git a/exploring-cpp-2e/chapter57/html/hierarchy.html b/exploring-cpp-2e/chapter57/html/hierarchy.html new file mode 100644 index 0000000..9af899a --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/hierarchy.html @@ -0,0 +1,67 @@ + + + + + + +Project 3 - Currency Type: Class Hierarchy + + + + + + +
+
+ + + + + + +
+
Project 3 - Currency Type +
+
+
+ + + + +
+
+
+
Class Hierarchy
+
+
+
This inheritance list is sorted roughly, but not completely, alphabetically:
+
[detail level 12]
+ + + + + + +
oCcurrency< T, N >
oCfixed< T, N >Implement a fixed-point number class template. Values have N places after the decimal point. All arithmetic follows the usual rules
oCioflags
oClogic_error
|\Crational< T >::zero_denominatorException class if the denominator is ever zero
\Crational< T >Represent a rational number (fraction) as a numerator and denominator
+
+
+ + + + diff --git a/exploring-cpp-2e/chapter57/html/index.html b/exploring-cpp-2e/chapter57/html/index.html new file mode 100644 index 0000000..83014c7 --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/index.html @@ -0,0 +1,54 @@ + + + + + + +Project 3 - Currency Type: Project 3: Currency Type + + + + + + +
+
+ + + + + + +
+
Project 3 - Currency Type +
+
+
+ + + +
+
+
+
Project 3: Currency Type
+
+
+

It’s time for another project. You’re going to continue building on the fixed type from Project 2 and incorporate what you’ve learned about locales and I/O. Your task this time is to write a currency type.

+

The value is stored as a fixed-point value. I/O is formatted using the get_money and put_money manipulators.

+

Make sure you can add two currency amounts to get a currency value, subtract two currency amounts to get currency, multiply and divide currency by an integer or rational value to get a currency result, and divide two currency values to get a rational result.

+

As with any project, start small and add functionality as you go. For example, start with the basic data representation, then add I/O operators. Add arithmetic operators one at a time. Write each test function before you implement the feature.

+
+ + + + diff --git a/exploring-cpp-2e/chapter57/html/ioflags_8hpp.html b/exploring-cpp-2e/chapter57/html/ioflags_8hpp.html new file mode 100644 index 0000000..50a40d9 --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/ioflags_8hpp.html @@ -0,0 +1,73 @@ + + + + + + +Project 3 - Currency Type: ioflags.hpp File Reference + + + + + + +
+
+ + + + + + +
+
Project 3 - Currency Type +
+
+
+ + + + +
+
+ +
+
ioflags.hpp File Reference
+
+
+ +

Save and restore I/O stream flags. +More...

+ +

Go to the source code of this file.

+ + + + +

+Classes

class  ioflags
 
+

Detailed Description

+

Save and restore I/O stream flags.

+ +

Definition in file ioflags.hpp.

+
+ + + + diff --git a/exploring-cpp-2e/chapter57/html/ioflags_8hpp_source.html b/exploring-cpp-2e/chapter57/html/ioflags_8hpp_source.html new file mode 100644 index 0000000..bbc4bfa --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/ioflags_8hpp_source.html @@ -0,0 +1,77 @@ + + + + + + +Project 3 - Currency Type: ioflags.hpp Source File + + + + + + +
+
+ + + + + + +
+
Project 3 - Currency Type +
+
+
+ + + + +
+
+
+
ioflags.hpp
+
+
+Go to the documentation of this file.
1 #ifndef IOFLAGS_HPP_
+
2 #define IOFLAGS_HPP_
+
3 
+
15 class ioflags
+
16 {
+
17 public:
+
20  ioflags(std::basic_ios<char>& stream) : stream_(stream), flags_{stream.flags()} {}
+
22  ~ioflags() { stream_.flags(flags_); }
+
23 
+
24  ioflags(ioflags const&) = delete;
+
25  ioflags& operator=(ioflags const&) = delete;
+
26 
+
27 private:
+
28  std::basic_ios<char>& stream_;
+
29  std::ios_base::fmtflags flags_;
+
30 };
+
31 
+
32 #endif
+
ioflags(std::basic_ios< char > &stream)
Definition: ioflags.hpp:20
+ +
~ioflags()
Restore the formatting flags.
Definition: ioflags.hpp:22
+
+ + + + diff --git a/exploring-cpp-2e/chapter57/html/jquery.js b/exploring-cpp-2e/chapter57/html/jquery.js new file mode 100644 index 0000000..6aa2e4c --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/jquery.js @@ -0,0 +1,39 @@ +/*! + * jQuery JavaScript Library v1.7.1 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Mon Nov 21 21:11:03 2011 -0500 + */ +(function(bb,L){var av=bb.document,bu=bb.navigator,bl=bb.location;var b=(function(){var bF=function(b0,b1){return new bF.fn.init(b0,b1,bD)},bU=bb.jQuery,bH=bb.$,bD,bY=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,bM=/\S/,bI=/^\s+/,bE=/\s+$/,bA=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,bN=/^[\],:{}\s]*$/,bW=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,bP=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,bJ=/(?:^|:|,)(?:\s*\[)+/g,by=/(webkit)[ \/]([\w.]+)/,bR=/(opera)(?:.*version)?[ \/]([\w.]+)/,bQ=/(msie) ([\w.]+)/,bS=/(mozilla)(?:.*? rv:([\w.]+))?/,bB=/-([a-z]|[0-9])/ig,bZ=/^-ms-/,bT=function(b0,b1){return(b1+"").toUpperCase()},bX=bu.userAgent,bV,bC,e,bL=Object.prototype.toString,bG=Object.prototype.hasOwnProperty,bz=Array.prototype.push,bK=Array.prototype.slice,bO=String.prototype.trim,bv=Array.prototype.indexOf,bx={};bF.fn=bF.prototype={constructor:bF,init:function(b0,b4,b3){var b2,b5,b1,b6;if(!b0){return this}if(b0.nodeType){this.context=this[0]=b0;this.length=1;return this}if(b0==="body"&&!b4&&av.body){this.context=av;this[0]=av.body;this.selector=b0;this.length=1;return this}if(typeof b0==="string"){if(b0.charAt(0)==="<"&&b0.charAt(b0.length-1)===">"&&b0.length>=3){b2=[null,b0,null]}else{b2=bY.exec(b0)}if(b2&&(b2[1]||!b4)){if(b2[1]){b4=b4 instanceof bF?b4[0]:b4;b6=(b4?b4.ownerDocument||b4:av);b1=bA.exec(b0);if(b1){if(bF.isPlainObject(b4)){b0=[av.createElement(b1[1])];bF.fn.attr.call(b0,b4,true)}else{b0=[b6.createElement(b1[1])]}}else{b1=bF.buildFragment([b2[1]],[b6]);b0=(b1.cacheable?bF.clone(b1.fragment):b1.fragment).childNodes}return bF.merge(this,b0)}else{b5=av.getElementById(b2[2]);if(b5&&b5.parentNode){if(b5.id!==b2[2]){return b3.find(b0)}this.length=1;this[0]=b5}this.context=av;this.selector=b0;return this}}else{if(!b4||b4.jquery){return(b4||b3).find(b0)}else{return this.constructor(b4).find(b0)}}}else{if(bF.isFunction(b0)){return b3.ready(b0)}}if(b0.selector!==L){this.selector=b0.selector;this.context=b0.context}return bF.makeArray(b0,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return bK.call(this,0)},get:function(b0){return b0==null?this.toArray():(b0<0?this[this.length+b0]:this[b0])},pushStack:function(b1,b3,b0){var b2=this.constructor();if(bF.isArray(b1)){bz.apply(b2,b1)}else{bF.merge(b2,b1)}b2.prevObject=this;b2.context=this.context;if(b3==="find"){b2.selector=this.selector+(this.selector?" ":"")+b0}else{if(b3){b2.selector=this.selector+"."+b3+"("+b0+")"}}return b2},each:function(b1,b0){return bF.each(this,b1,b0)},ready:function(b0){bF.bindReady();bC.add(b0);return this},eq:function(b0){b0=+b0;return b0===-1?this.slice(b0):this.slice(b0,b0+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(bK.apply(this,arguments),"slice",bK.call(arguments).join(","))},map:function(b0){return this.pushStack(bF.map(this,function(b2,b1){return b0.call(b2,b1,b2)}))},end:function(){return this.prevObject||this.constructor(null)},push:bz,sort:[].sort,splice:[].splice};bF.fn.init.prototype=bF.fn;bF.extend=bF.fn.extend=function(){var b9,b2,b0,b1,b6,b7,b5=arguments[0]||{},b4=1,b3=arguments.length,b8=false;if(typeof b5==="boolean"){b8=b5;b5=arguments[1]||{};b4=2}if(typeof b5!=="object"&&!bF.isFunction(b5)){b5={}}if(b3===b4){b5=this;--b4}for(;b40){return}bC.fireWith(av,[bF]);if(bF.fn.trigger){bF(av).trigger("ready").off("ready")}}},bindReady:function(){if(bC){return}bC=bF.Callbacks("once memory");if(av.readyState==="complete"){return setTimeout(bF.ready,1)}if(av.addEventListener){av.addEventListener("DOMContentLoaded",e,false);bb.addEventListener("load",bF.ready,false)}else{if(av.attachEvent){av.attachEvent("onreadystatechange",e);bb.attachEvent("onload",bF.ready);var b0=false;try{b0=bb.frameElement==null}catch(b1){}if(av.documentElement.doScroll&&b0){bw()}}}},isFunction:function(b0){return bF.type(b0)==="function"},isArray:Array.isArray||function(b0){return bF.type(b0)==="array"},isWindow:function(b0){return b0&&typeof b0==="object"&&"setInterval" in b0},isNumeric:function(b0){return !isNaN(parseFloat(b0))&&isFinite(b0)},type:function(b0){return b0==null?String(b0):bx[bL.call(b0)]||"object"},isPlainObject:function(b2){if(!b2||bF.type(b2)!=="object"||b2.nodeType||bF.isWindow(b2)){return false}try{if(b2.constructor&&!bG.call(b2,"constructor")&&!bG.call(b2.constructor.prototype,"isPrototypeOf")){return false}}catch(b1){return false}var b0;for(b0 in b2){}return b0===L||bG.call(b2,b0)},isEmptyObject:function(b1){for(var b0 in b1){return false}return true},error:function(b0){throw new Error(b0)},parseJSON:function(b0){if(typeof b0!=="string"||!b0){return null}b0=bF.trim(b0);if(bb.JSON&&bb.JSON.parse){return bb.JSON.parse(b0)}if(bN.test(b0.replace(bW,"@").replace(bP,"]").replace(bJ,""))){return(new Function("return "+b0))()}bF.error("Invalid JSON: "+b0)},parseXML:function(b2){var b0,b1;try{if(bb.DOMParser){b1=new DOMParser();b0=b1.parseFromString(b2,"text/xml")}else{b0=new ActiveXObject("Microsoft.XMLDOM");b0.async="false";b0.loadXML(b2)}}catch(b3){b0=L}if(!b0||!b0.documentElement||b0.getElementsByTagName("parsererror").length){bF.error("Invalid XML: "+b2)}return b0},noop:function(){},globalEval:function(b0){if(b0&&bM.test(b0)){(bb.execScript||function(b1){bb["eval"].call(bb,b1)})(b0)}},camelCase:function(b0){return b0.replace(bZ,"ms-").replace(bB,bT)},nodeName:function(b1,b0){return b1.nodeName&&b1.nodeName.toUpperCase()===b0.toUpperCase()},each:function(b3,b6,b2){var b1,b4=0,b5=b3.length,b0=b5===L||bF.isFunction(b3);if(b2){if(b0){for(b1 in b3){if(b6.apply(b3[b1],b2)===false){break}}}else{for(;b40&&b0[0]&&b0[b1-1])||b1===0||bF.isArray(b0));if(b3){for(;b21?aJ.call(arguments,0):bG;if(!(--bw)){bC.resolveWith(bC,bx)}}}function bz(bF){return function(bG){bB[bF]=arguments.length>1?aJ.call(arguments,0):bG;bC.notifyWith(bE,bB)}}if(e>1){for(;bv
a";bI=bv.getElementsByTagName("*");bF=bv.getElementsByTagName("a")[0];if(!bI||!bI.length||!bF){return{}}bG=av.createElement("select");bx=bG.appendChild(av.createElement("option"));bE=bv.getElementsByTagName("input")[0];bJ={leadingWhitespace:(bv.firstChild.nodeType===3),tbody:!bv.getElementsByTagName("tbody").length,htmlSerialize:!!bv.getElementsByTagName("link").length,style:/top/.test(bF.getAttribute("style")),hrefNormalized:(bF.getAttribute("href")==="/a"),opacity:/^0.55/.test(bF.style.opacity),cssFloat:!!bF.style.cssFloat,checkOn:(bE.value==="on"),optSelected:bx.selected,getSetAttribute:bv.className!=="t",enctype:!!av.createElement("form").enctype,html5Clone:av.createElement("nav").cloneNode(true).outerHTML!=="<:nav>",submitBubbles:true,changeBubbles:true,focusinBubbles:false,deleteExpando:true,noCloneEvent:true,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableMarginRight:true};bE.checked=true;bJ.noCloneChecked=bE.cloneNode(true).checked;bG.disabled=true;bJ.optDisabled=!bx.disabled;try{delete bv.test}catch(bC){bJ.deleteExpando=false}if(!bv.addEventListener&&bv.attachEvent&&bv.fireEvent){bv.attachEvent("onclick",function(){bJ.noCloneEvent=false});bv.cloneNode(true).fireEvent("onclick")}bE=av.createElement("input");bE.value="t";bE.setAttribute("type","radio");bJ.radioValue=bE.value==="t";bE.setAttribute("checked","checked");bv.appendChild(bE);bD=av.createDocumentFragment();bD.appendChild(bv.lastChild);bJ.checkClone=bD.cloneNode(true).cloneNode(true).lastChild.checked;bJ.appendChecked=bE.checked;bD.removeChild(bE);bD.appendChild(bv);bv.innerHTML="";if(bb.getComputedStyle){bA=av.createElement("div");bA.style.width="0";bA.style.marginRight="0";bv.style.width="2px";bv.appendChild(bA);bJ.reliableMarginRight=(parseInt((bb.getComputedStyle(bA,null)||{marginRight:0}).marginRight,10)||0)===0}if(bv.attachEvent){for(by in {submit:1,change:1,focusin:1}){bB="on"+by;bw=(bB in bv);if(!bw){bv.setAttribute(bB,"return;");bw=(typeof bv[bB]==="function")}bJ[by+"Bubbles"]=bw}}bD.removeChild(bv);bD=bG=bx=bA=bv=bE=null;b(function(){var bM,bU,bV,bT,bN,bO,bL,bS,bR,e,bP,bQ=av.getElementsByTagName("body")[0];if(!bQ){return}bL=1;bS="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;";bR="visibility:hidden;border:0;";e="style='"+bS+"border:5px solid #000;padding:0;'";bP="
";bM=av.createElement("div");bM.style.cssText=bR+"width:0;height:0;position:static;top:0;margin-top:"+bL+"px";bQ.insertBefore(bM,bQ.firstChild);bv=av.createElement("div");bM.appendChild(bv);bv.innerHTML="
t
";bz=bv.getElementsByTagName("td");bw=(bz[0].offsetHeight===0);bz[0].style.display="";bz[1].style.display="none";bJ.reliableHiddenOffsets=bw&&(bz[0].offsetHeight===0);bv.innerHTML="";bv.style.width=bv.style.paddingLeft="1px";b.boxModel=bJ.boxModel=bv.offsetWidth===2;if(typeof bv.style.zoom!=="undefined"){bv.style.display="inline";bv.style.zoom=1;bJ.inlineBlockNeedsLayout=(bv.offsetWidth===2);bv.style.display="";bv.innerHTML="
";bJ.shrinkWrapBlocks=(bv.offsetWidth!==2)}bv.style.cssText=bS+bR;bv.innerHTML=bP;bU=bv.firstChild;bV=bU.firstChild;bN=bU.nextSibling.firstChild.firstChild;bO={doesNotAddBorder:(bV.offsetTop!==5),doesAddBorderForTableAndCells:(bN.offsetTop===5)};bV.style.position="fixed";bV.style.top="20px";bO.fixedPosition=(bV.offsetTop===20||bV.offsetTop===15);bV.style.position=bV.style.top="";bU.style.overflow="hidden";bU.style.position="relative";bO.subtractsBorderForOverflowNotVisible=(bV.offsetTop===-5);bO.doesNotIncludeMarginInBodyOffset=(bQ.offsetTop!==bL);bQ.removeChild(bM);bv=bM=null;b.extend(bJ,bO)});return bJ})();var aS=/^(?:\{.*\}|\[.*\])$/,aA=/([A-Z])/g;b.extend({cache:{},uuid:0,expando:"jQuery"+(b.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},hasData:function(e){e=e.nodeType?b.cache[e[b.expando]]:e[b.expando];return !!e&&!S(e)},data:function(bx,bv,bz,by){if(!b.acceptData(bx)){return}var bG,bA,bD,bE=b.expando,bC=typeof bv==="string",bF=bx.nodeType,e=bF?b.cache:bx,bw=bF?bx[bE]:bx[bE]&&bE,bB=bv==="events";if((!bw||!e[bw]||(!bB&&!by&&!e[bw].data))&&bC&&bz===L){return}if(!bw){if(bF){bx[bE]=bw=++b.uuid}else{bw=bE}}if(!e[bw]){e[bw]={};if(!bF){e[bw].toJSON=b.noop}}if(typeof bv==="object"||typeof bv==="function"){if(by){e[bw]=b.extend(e[bw],bv)}else{e[bw].data=b.extend(e[bw].data,bv)}}bG=bA=e[bw];if(!by){if(!bA.data){bA.data={}}bA=bA.data}if(bz!==L){bA[b.camelCase(bv)]=bz}if(bB&&!bA[bv]){return bG.events}if(bC){bD=bA[bv];if(bD==null){bD=bA[b.camelCase(bv)]}}else{bD=bA}return bD},removeData:function(bx,bv,by){if(!b.acceptData(bx)){return}var bB,bA,bz,bC=b.expando,bD=bx.nodeType,e=bD?b.cache:bx,bw=bD?bx[bC]:bC;if(!e[bw]){return}if(bv){bB=by?e[bw]:e[bw].data;if(bB){if(!b.isArray(bv)){if(bv in bB){bv=[bv]}else{bv=b.camelCase(bv);if(bv in bB){bv=[bv]}else{bv=bv.split(" ")}}}for(bA=0,bz=bv.length;bA-1){return true}}return false},val:function(bx){var e,bv,by,bw=this[0];if(!arguments.length){if(bw){e=b.valHooks[bw.nodeName.toLowerCase()]||b.valHooks[bw.type];if(e&&"get" in e&&(bv=e.get(bw,"value"))!==L){return bv}bv=bw.value;return typeof bv==="string"?bv.replace(aU,""):bv==null?"":bv}return}by=b.isFunction(bx);return this.each(function(bA){var bz=b(this),bB;if(this.nodeType!==1){return}if(by){bB=bx.call(this,bA,bz.val())}else{bB=bx}if(bB==null){bB=""}else{if(typeof bB==="number"){bB+=""}else{if(b.isArray(bB)){bB=b.map(bB,function(bC){return bC==null?"":bC+""})}}}e=b.valHooks[this.nodeName.toLowerCase()]||b.valHooks[this.type];if(!e||!("set" in e)||e.set(this,bB,"value")===L){this.value=bB}})}});b.extend({valHooks:{option:{get:function(e){var bv=e.attributes.value;return !bv||bv.specified?e.value:e.text}},select:{get:function(e){var bA,bv,bz,bx,by=e.selectedIndex,bB=[],bC=e.options,bw=e.type==="select-one";if(by<0){return null}bv=bw?by:0;bz=bw?by+1:bC.length;for(;bv=0});if(!e.length){bv.selectedIndex=-1}return e}}},attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(bA,bx,bB,bz){var bw,e,by,bv=bA.nodeType; +if(!bA||bv===3||bv===8||bv===2){return}if(bz&&bx in b.attrFn){return b(bA)[bx](bB)}if(typeof bA.getAttribute==="undefined"){return b.prop(bA,bx,bB)}by=bv!==1||!b.isXMLDoc(bA);if(by){bx=bx.toLowerCase();e=b.attrHooks[bx]||(ao.test(bx)?aY:be)}if(bB!==L){if(bB===null){b.removeAttr(bA,bx);return}else{if(e&&"set" in e&&by&&(bw=e.set(bA,bB,bx))!==L){return bw}else{bA.setAttribute(bx,""+bB);return bB}}}else{if(e&&"get" in e&&by&&(bw=e.get(bA,bx))!==null){return bw}else{bw=bA.getAttribute(bx);return bw===null?L:bw}}},removeAttr:function(bx,bz){var by,bA,bv,e,bw=0;if(bz&&bx.nodeType===1){bA=bz.toLowerCase().split(af);e=bA.length;for(;bw=0)}}})});var bd=/^(?:textarea|input|select)$/i,n=/^([^\.]*)?(?:\.(.+))?$/,J=/\bhover(\.\S+)?\b/,aO=/^key/,bf=/^(?:mouse|contextmenu)|click/,T=/^(?:focusinfocus|focusoutblur)$/,U=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,Y=function(e){var bv=U.exec(e);if(bv){bv[1]=(bv[1]||"").toLowerCase();bv[3]=bv[3]&&new RegExp("(?:^|\\s)"+bv[3]+"(?:\\s|$)")}return bv},j=function(bw,e){var bv=bw.attributes||{};return((!e[1]||bw.nodeName.toLowerCase()===e[1])&&(!e[2]||(bv.id||{}).value===e[2])&&(!e[3]||e[3].test((bv["class"]||{}).value)))},bt=function(e){return b.event.special.hover?e:e.replace(J,"mouseenter$1 mouseleave$1")};b.event={add:function(bx,bC,bJ,bA,by){var bD,bB,bK,bI,bH,bF,e,bG,bv,bz,bw,bE;if(bx.nodeType===3||bx.nodeType===8||!bC||!bJ||!(bD=b._data(bx))){return}if(bJ.handler){bv=bJ;bJ=bv.handler}if(!bJ.guid){bJ.guid=b.guid++}bK=bD.events;if(!bK){bD.events=bK={}}bB=bD.handle;if(!bB){bD.handle=bB=function(bL){return typeof b!=="undefined"&&(!bL||b.event.triggered!==bL.type)?b.event.dispatch.apply(bB.elem,arguments):L};bB.elem=bx}bC=b.trim(bt(bC)).split(" ");for(bI=0;bI=0){bG=bG.slice(0,-1);bw=true}if(bG.indexOf(".")>=0){bx=bG.split(".");bG=bx.shift();bx.sort()}if((!bA||b.event.customEvent[bG])&&!b.event.global[bG]){return}bv=typeof bv==="object"?bv[b.expando]?bv:new b.Event(bG,bv):new b.Event(bG);bv.type=bG;bv.isTrigger=true;bv.exclusive=bw;bv.namespace=bx.join(".");bv.namespace_re=bv.namespace?new RegExp("(^|\\.)"+bx.join("\\.(?:.*\\.)?")+"(\\.|$)"):null;by=bG.indexOf(":")<0?"on"+bG:"";if(!bA){e=b.cache;for(bC in e){if(e[bC].events&&e[bC].events[bG]){b.event.trigger(bv,bD,e[bC].handle.elem,true)}}return}bv.result=L;if(!bv.target){bv.target=bA}bD=bD!=null?b.makeArray(bD):[];bD.unshift(bv);bF=b.event.special[bG]||{};if(bF.trigger&&bF.trigger.apply(bA,bD)===false){return}bB=[[bA,bF.bindType||bG]];if(!bJ&&!bF.noBubble&&!b.isWindow(bA)){bI=bF.delegateType||bG;bH=T.test(bI+bG)?bA:bA.parentNode;bz=null;for(;bH;bH=bH.parentNode){bB.push([bH,bI]);bz=bH}if(bz&&bz===bA.ownerDocument){bB.push([bz.defaultView||bz.parentWindow||bb,bI])}}for(bC=0;bCbA){bH.push({elem:this,matches:bz.slice(bA)})}for(bC=0;bC0?this.on(e,null,bx,bw):this.trigger(e)};if(b.attrFn){b.attrFn[e]=true}if(aO.test(e)){b.event.fixHooks[e]=b.event.keyHooks}if(bf.test(e)){b.event.fixHooks[e]=b.event.mouseHooks}}); +/*! + * Sizzle CSS Selector Engine + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){var bH=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,bC="sizcache"+(Math.random()+"").replace(".",""),bI=0,bL=Object.prototype.toString,bB=false,bA=true,bK=/\\/g,bO=/\r\n/g,bQ=/\W/;[0,0].sort(function(){bA=false;return 0});var by=function(bV,e,bY,bZ){bY=bY||[];e=e||av;var b1=e;if(e.nodeType!==1&&e.nodeType!==9){return[]}if(!bV||typeof bV!=="string"){return bY}var bS,b3,b6,bR,b2,b5,b4,bX,bU=true,bT=by.isXML(e),bW=[],b0=bV;do{bH.exec("");bS=bH.exec(b0);if(bS){b0=bS[3];bW.push(bS[1]);if(bS[2]){bR=bS[3];break}}}while(bS);if(bW.length>1&&bD.exec(bV)){if(bW.length===2&&bE.relative[bW[0]]){b3=bM(bW[0]+bW[1],e,bZ)}else{b3=bE.relative[bW[0]]?[e]:by(bW.shift(),e);while(bW.length){bV=bW.shift();if(bE.relative[bV]){bV+=bW.shift()}b3=bM(bV,b3,bZ)}}}else{if(!bZ&&bW.length>1&&e.nodeType===9&&!bT&&bE.match.ID.test(bW[0])&&!bE.match.ID.test(bW[bW.length-1])){b2=by.find(bW.shift(),e,bT);e=b2.expr?by.filter(b2.expr,b2.set)[0]:b2.set[0]}if(e){b2=bZ?{expr:bW.pop(),set:bF(bZ)}:by.find(bW.pop(),bW.length===1&&(bW[0]==="~"||bW[0]==="+")&&e.parentNode?e.parentNode:e,bT);b3=b2.expr?by.filter(b2.expr,b2.set):b2.set;if(bW.length>0){b6=bF(b3)}else{bU=false}while(bW.length){b5=bW.pop();b4=b5;if(!bE.relative[b5]){b5=""}else{b4=bW.pop()}if(b4==null){b4=e}bE.relative[b5](b6,b4,bT)}}else{b6=bW=[]}}if(!b6){b6=b3}if(!b6){by.error(b5||bV)}if(bL.call(b6)==="[object Array]"){if(!bU){bY.push.apply(bY,b6)}else{if(e&&e.nodeType===1){for(bX=0;b6[bX]!=null;bX++){if(b6[bX]&&(b6[bX]===true||b6[bX].nodeType===1&&by.contains(e,b6[bX]))){bY.push(b3[bX])}}}else{for(bX=0;b6[bX]!=null;bX++){if(b6[bX]&&b6[bX].nodeType===1){bY.push(b3[bX])}}}}}else{bF(b6,bY)}if(bR){by(bR,b1,bY,bZ);by.uniqueSort(bY)}return bY};by.uniqueSort=function(bR){if(bJ){bB=bA;bR.sort(bJ);if(bB){for(var e=1;e0};by.find=function(bX,e,bY){var bW,bS,bU,bT,bV,bR;if(!bX){return[]}for(bS=0,bU=bE.order.length;bS":function(bW,bR){var bV,bU=typeof bR==="string",bS=0,e=bW.length;if(bU&&!bQ.test(bR)){bR=bR.toLowerCase();for(;bS=0)){if(!bS){e.push(bV)}}else{if(bS){bR[bU]=false}}}}return false},ID:function(e){return e[1].replace(bK,"")},TAG:function(bR,e){return bR[1].replace(bK,"").toLowerCase()},CHILD:function(e){if(e[1]==="nth"){if(!e[2]){by.error(e[0])}e[2]=e[2].replace(/^\+|\s*/g,"");var bR=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(e[2]==="even"&&"2n"||e[2]==="odd"&&"2n+1"||!/\D/.test(e[2])&&"0n+"+e[2]||e[2]);e[2]=(bR[1]+(bR[2]||1))-0;e[3]=bR[3]-0}else{if(e[2]){by.error(e[0])}}e[0]=bI++;return e},ATTR:function(bU,bR,bS,e,bV,bW){var bT=bU[1]=bU[1].replace(bK,"");if(!bW&&bE.attrMap[bT]){bU[1]=bE.attrMap[bT]}bU[4]=(bU[4]||bU[5]||"").replace(bK,"");if(bU[2]==="~="){bU[4]=" "+bU[4]+" "}return bU},PSEUDO:function(bU,bR,bS,e,bV){if(bU[1]==="not"){if((bH.exec(bU[3])||"").length>1||/^\w/.test(bU[3])){bU[3]=by(bU[3],null,null,bR)}else{var bT=by.filter(bU[3],bR,bS,true^bV);if(!bS){e.push.apply(e,bT)}return false}}else{if(bE.match.POS.test(bU[0])||bE.match.CHILD.test(bU[0])){return true}}return bU},POS:function(e){e.unshift(true);return e}},filters:{enabled:function(e){return e.disabled===false&&e.type!=="hidden"},disabled:function(e){return e.disabled===true},checked:function(e){return e.checked===true},selected:function(e){if(e.parentNode){e.parentNode.selectedIndex}return e.selected===true},parent:function(e){return !!e.firstChild},empty:function(e){return !e.firstChild},has:function(bS,bR,e){return !!by(e[3],bS).length},header:function(e){return(/h\d/i).test(e.nodeName)},text:function(bS){var e=bS.getAttribute("type"),bR=bS.type;return bS.nodeName.toLowerCase()==="input"&&"text"===bR&&(e===bR||e===null)},radio:function(e){return e.nodeName.toLowerCase()==="input"&&"radio"===e.type},checkbox:function(e){return e.nodeName.toLowerCase()==="input"&&"checkbox"===e.type},file:function(e){return e.nodeName.toLowerCase()==="input"&&"file"===e.type},password:function(e){return e.nodeName.toLowerCase()==="input"&&"password"===e.type},submit:function(bR){var e=bR.nodeName.toLowerCase();return(e==="input"||e==="button")&&"submit"===bR.type},image:function(e){return e.nodeName.toLowerCase()==="input"&&"image"===e.type},reset:function(bR){var e=bR.nodeName.toLowerCase();return(e==="input"||e==="button")&&"reset"===bR.type},button:function(bR){var e=bR.nodeName.toLowerCase();return e==="input"&&"button"===bR.type||e==="button"},input:function(e){return(/input|select|textarea|button/i).test(e.nodeName)},focus:function(e){return e===e.ownerDocument.activeElement}},setFilters:{first:function(bR,e){return e===0},last:function(bS,bR,e,bT){return bR===bT.length-1},even:function(bR,e){return e%2===0},odd:function(bR,e){return e%2===1 +},lt:function(bS,bR,e){return bRe[3]-0},nth:function(bS,bR,e){return e[3]-0===bR},eq:function(bS,bR,e){return e[3]-0===bR}},filter:{PSEUDO:function(bS,bX,bW,bY){var e=bX[1],bR=bE.filters[e];if(bR){return bR(bS,bW,bX,bY)}else{if(e==="contains"){return(bS.textContent||bS.innerText||bw([bS])||"").indexOf(bX[3])>=0}else{if(e==="not"){var bT=bX[3];for(var bV=0,bU=bT.length;bV=0)}}},ID:function(bR,e){return bR.nodeType===1&&bR.getAttribute("id")===e},TAG:function(bR,e){return(e==="*"&&bR.nodeType===1)||!!bR.nodeName&&bR.nodeName.toLowerCase()===e},CLASS:function(bR,e){return(" "+(bR.className||bR.getAttribute("class"))+" ").indexOf(e)>-1},ATTR:function(bV,bT){var bS=bT[1],e=by.attr?by.attr(bV,bS):bE.attrHandle[bS]?bE.attrHandle[bS](bV):bV[bS]!=null?bV[bS]:bV.getAttribute(bS),bW=e+"",bU=bT[2],bR=bT[4];return e==null?bU==="!=":!bU&&by.attr?e!=null:bU==="="?bW===bR:bU==="*="?bW.indexOf(bR)>=0:bU==="~="?(" "+bW+" ").indexOf(bR)>=0:!bR?bW&&e!==false:bU==="!="?bW!==bR:bU==="^="?bW.indexOf(bR)===0:bU==="$="?bW.substr(bW.length-bR.length)===bR:bU==="|="?bW===bR||bW.substr(0,bR.length+1)===bR+"-":false},POS:function(bU,bR,bS,bV){var e=bR[2],bT=bE.setFilters[e];if(bT){return bT(bU,bS,bR,bV)}}}};var bD=bE.match.POS,bx=function(bR,e){return"\\"+(e-0+1)};for(var bz in bE.match){bE.match[bz]=new RegExp(bE.match[bz].source+(/(?![^\[]*\])(?![^\(]*\))/.source));bE.leftMatch[bz]=new RegExp(/(^(?:.|\r|\n)*?)/.source+bE.match[bz].source.replace(/\\(\d+)/g,bx))}var bF=function(bR,e){bR=Array.prototype.slice.call(bR,0);if(e){e.push.apply(e,bR);return e}return bR};try{Array.prototype.slice.call(av.documentElement.childNodes,0)[0].nodeType}catch(bP){bF=function(bU,bT){var bS=0,bR=bT||[];if(bL.call(bU)==="[object Array]"){Array.prototype.push.apply(bR,bU)}else{if(typeof bU.length==="number"){for(var e=bU.length;bS";e.insertBefore(bR,e.firstChild);if(av.getElementById(bS)){bE.find.ID=function(bU,bV,bW){if(typeof bV.getElementById!=="undefined"&&!bW){var bT=bV.getElementById(bU[1]);return bT?bT.id===bU[1]||typeof bT.getAttributeNode!=="undefined"&&bT.getAttributeNode("id").nodeValue===bU[1]?[bT]:L:[]}};bE.filter.ID=function(bV,bT){var bU=typeof bV.getAttributeNode!=="undefined"&&bV.getAttributeNode("id");return bV.nodeType===1&&bU&&bU.nodeValue===bT}}e.removeChild(bR);e=bR=null})();(function(){var e=av.createElement("div");e.appendChild(av.createComment(""));if(e.getElementsByTagName("*").length>0){bE.find.TAG=function(bR,bV){var bU=bV.getElementsByTagName(bR[1]);if(bR[1]==="*"){var bT=[];for(var bS=0;bU[bS];bS++){if(bU[bS].nodeType===1){bT.push(bU[bS])}}bU=bT}return bU}}e.innerHTML="";if(e.firstChild&&typeof e.firstChild.getAttribute!=="undefined"&&e.firstChild.getAttribute("href")!=="#"){bE.attrHandle.href=function(bR){return bR.getAttribute("href",2)}}e=null})();if(av.querySelectorAll){(function(){var e=by,bT=av.createElement("div"),bS="__sizzle__";bT.innerHTML="

";if(bT.querySelectorAll&&bT.querySelectorAll(".TEST").length===0){return}by=function(b4,bV,bZ,b3){bV=bV||av;if(!b3&&!by.isXML(bV)){var b2=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b4);if(b2&&(bV.nodeType===1||bV.nodeType===9)){if(b2[1]){return bF(bV.getElementsByTagName(b4),bZ)}else{if(b2[2]&&bE.find.CLASS&&bV.getElementsByClassName){return bF(bV.getElementsByClassName(b2[2]),bZ)}}}if(bV.nodeType===9){if(b4==="body"&&bV.body){return bF([bV.body],bZ)}else{if(b2&&b2[3]){var bY=bV.getElementById(b2[3]);if(bY&&bY.parentNode){if(bY.id===b2[3]){return bF([bY],bZ)}}else{return bF([],bZ)}}}try{return bF(bV.querySelectorAll(b4),bZ)}catch(b0){}}else{if(bV.nodeType===1&&bV.nodeName.toLowerCase()!=="object"){var bW=bV,bX=bV.getAttribute("id"),bU=bX||bS,b6=bV.parentNode,b5=/^\s*[+~]/.test(b4);if(!bX){bV.setAttribute("id",bU)}else{bU=bU.replace(/'/g,"\\$&")}if(b5&&b6){bV=bV.parentNode}try{if(!b5||b6){return bF(bV.querySelectorAll("[id='"+bU+"'] "+b4),bZ)}}catch(b1){}finally{if(!bX){bW.removeAttribute("id")}}}}}return e(b4,bV,bZ,b3)};for(var bR in e){by[bR]=e[bR]}bT=null})()}(function(){var e=av.documentElement,bS=e.matchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.msMatchesSelector;if(bS){var bU=!bS.call(av.createElement("div"),"div"),bR=false;try{bS.call(av.documentElement,"[test!='']:sizzle")}catch(bT){bR=true}by.matchesSelector=function(bW,bY){bY=bY.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!by.isXML(bW)){try{if(bR||!bE.match.PSEUDO.test(bY)&&!/!=/.test(bY)){var bV=bS.call(bW,bY);if(bV||!bU||bW.document&&bW.document.nodeType!==11){return bV}}}catch(bX){}}return by(bY,null,null,[bW]).length>0}}})();(function(){var e=av.createElement("div");e.innerHTML="
";if(!e.getElementsByClassName||e.getElementsByClassName("e").length===0){return}e.lastChild.className="e";if(e.getElementsByClassName("e").length===1){return}bE.order.splice(1,0,"CLASS");bE.find.CLASS=function(bR,bS,bT){if(typeof bS.getElementsByClassName!=="undefined"&&!bT){return bS.getElementsByClassName(bR[1])}};e=null})();function bv(bR,bW,bV,bZ,bX,bY){for(var bT=0,bS=bZ.length;bT0){bU=e;break}}}e=e[bR]}bZ[bT]=bU}}}if(av.documentElement.contains){by.contains=function(bR,e){return bR!==e&&(bR.contains?bR.contains(e):true)}}else{if(av.documentElement.compareDocumentPosition){by.contains=function(bR,e){return !!(bR.compareDocumentPosition(e)&16)}}else{by.contains=function(){return false}}}by.isXML=function(e){var bR=(e?e.ownerDocument||e:0).documentElement;return bR?bR.nodeName!=="HTML":false};var bM=function(bS,e,bW){var bV,bX=[],bU="",bY=e.nodeType?[e]:e;while((bV=bE.match.PSEUDO.exec(bS))){bU+=bV[0];bS=bS.replace(bE.match.PSEUDO,"")}bS=bE.relative[bS]?bS+"*":bS;for(var bT=0,bR=bY.length;bT0){for(bB=bA;bB=0:b.filter(e,this).length>0:this.filter(e).length>0)},closest:function(by,bx){var bv=[],bw,e,bz=this[0];if(b.isArray(by)){var bB=1;while(bz&&bz.ownerDocument&&bz!==bx){for(bw=0;bw-1:b.find.matchesSelector(bz,by)){bv.push(bz);break}else{bz=bz.parentNode;if(!bz||!bz.ownerDocument||bz===bx||bz.nodeType===11){break}}}}bv=bv.length>1?b.unique(bv):bv;return this.pushStack(bv,"closest",by)},index:function(e){if(!e){return(this[0]&&this[0].parentNode)?this.prevAll().length:-1}if(typeof e==="string"){return b.inArray(this[0],b(e))}return b.inArray(e.jquery?e[0]:e,this)},add:function(e,bv){var bx=typeof e==="string"?b(e,bv):b.makeArray(e&&e.nodeType?[e]:e),bw=b.merge(this.get(),bx);return this.pushStack(C(bx[0])||C(bw[0])?bw:b.unique(bw))},andSelf:function(){return this.add(this.prevObject)}});function C(e){return !e||!e.parentNode||e.parentNode.nodeType===11}b.each({parent:function(bv){var e=bv.parentNode;return e&&e.nodeType!==11?e:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(bv,e,bw){return b.dir(bv,"parentNode",bw)},next:function(e){return b.nth(e,2,"nextSibling")},prev:function(e){return b.nth(e,2,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(bv,e,bw){return b.dir(bv,"nextSibling",bw)},prevUntil:function(bv,e,bw){return b.dir(bv,"previousSibling",bw)},siblings:function(e){return b.sibling(e.parentNode.firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:b.makeArray(e.childNodes)}},function(e,bv){b.fn[e]=function(by,bw){var bx=b.map(this,bv,by);if(!ab.test(e)){bw=by}if(bw&&typeof bw==="string"){bx=b.filter(bw,bx)}bx=this.length>1&&!ay[e]?b.unique(bx):bx;if((this.length>1||a9.test(bw))&&aq.test(e)){bx=bx.reverse()}return this.pushStack(bx,e,P.call(arguments).join(","))}});b.extend({filter:function(bw,e,bv){if(bv){bw=":not("+bw+")"}return e.length===1?b.find.matchesSelector(e[0],bw)?[e[0]]:[]:b.find.matches(bw,e)},dir:function(bw,bv,by){var e=[],bx=bw[bv];while(bx&&bx.nodeType!==9&&(by===L||bx.nodeType!==1||!b(bx).is(by))){if(bx.nodeType===1){e.push(bx)}bx=bx[bv]}return e},nth:function(by,e,bw,bx){e=e||1;var bv=0;for(;by;by=by[bw]){if(by.nodeType===1&&++bv===e){break}}return by},sibling:function(bw,bv){var e=[];for(;bw;bw=bw.nextSibling){if(bw.nodeType===1&&bw!==bv){e.push(bw)}}return e}});function aG(bx,bw,e){bw=bw||0;if(b.isFunction(bw)){return b.grep(bx,function(bz,by){var bA=!!bw.call(bz,by,bz);return bA===e})}else{if(bw.nodeType){return b.grep(bx,function(bz,by){return(bz===bw)===e})}else{if(typeof bw==="string"){var bv=b.grep(bx,function(by){return by.nodeType===1});if(bp.test(bw)){return b.filter(bw,bv,!e)}else{bw=b.filter(bw,bv)}}}}return b.grep(bx,function(bz,by){return(b.inArray(bz,bw)>=0)===e})}function a(e){var bw=aR.split("|"),bv=e.createDocumentFragment();if(bv.createElement){while(bw.length){bv.createElement(bw.pop())}}return bv}var aR="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",ag=/ jQuery\d+="(?:\d+|null)"/g,ar=/^\s+/,R=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,d=/<([\w:]+)/,w=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},ac=a(av); +ax.optgroup=ax.option;ax.tbody=ax.tfoot=ax.colgroup=ax.caption=ax.thead;ax.th=ax.td;if(!b.support.htmlSerialize){ax._default=[1,"div
","
"]}b.fn.extend({text:function(e){if(b.isFunction(e)){return this.each(function(bw){var bv=b(this);bv.text(e.call(this,bw,bv.text()))})}if(typeof e!=="object"&&e!==L){return this.empty().append((this[0]&&this[0].ownerDocument||av).createTextNode(e))}return b.text(this)},wrapAll:function(e){if(b.isFunction(e)){return this.each(function(bw){b(this).wrapAll(e.call(this,bw))})}if(this[0]){var bv=b(e,this[0].ownerDocument).eq(0).clone(true);if(this[0].parentNode){bv.insertBefore(this[0])}bv.map(function(){var bw=this;while(bw.firstChild&&bw.firstChild.nodeType===1){bw=bw.firstChild}return bw}).append(this)}return this},wrapInner:function(e){if(b.isFunction(e)){return this.each(function(bv){b(this).wrapInner(e.call(this,bv))})}return this.each(function(){var bv=b(this),bw=bv.contents();if(bw.length){bw.wrapAll(e)}else{bv.append(e)}})},wrap:function(e){var bv=b.isFunction(e);return this.each(function(bw){b(this).wrapAll(bv?e.call(this,bw):e)})},unwrap:function(){return this.parent().each(function(){if(!b.nodeName(this,"body")){b(this).replaceWith(this.childNodes)}}).end()},append:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.appendChild(e)}})},prepend:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.insertBefore(e,this.firstChild)}})},before:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bv){this.parentNode.insertBefore(bv,this)})}else{if(arguments.length){var e=b.clean(arguments);e.push.apply(e,this.toArray());return this.pushStack(e,"before",arguments)}}},after:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bv){this.parentNode.insertBefore(bv,this.nextSibling)})}else{if(arguments.length){var e=this.pushStack(this,"after",arguments);e.push.apply(e,b.clean(arguments));return e}}},remove:function(e,bx){for(var bv=0,bw;(bw=this[bv])!=null;bv++){if(!e||b.filter(e,[bw]).length){if(!bx&&bw.nodeType===1){b.cleanData(bw.getElementsByTagName("*"));b.cleanData([bw])}if(bw.parentNode){bw.parentNode.removeChild(bw)}}}return this},empty:function(){for(var e=0,bv;(bv=this[e])!=null;e++){if(bv.nodeType===1){b.cleanData(bv.getElementsByTagName("*"))}while(bv.firstChild){bv.removeChild(bv.firstChild)}}return this},clone:function(bv,e){bv=bv==null?false:bv;e=e==null?bv:e;return this.map(function(){return b.clone(this,bv,e)})},html:function(bx){if(bx===L){return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(ag,""):null}else{if(typeof bx==="string"&&!ae.test(bx)&&(b.support.leadingWhitespace||!ar.test(bx))&&!ax[(d.exec(bx)||["",""])[1].toLowerCase()]){bx=bx.replace(R,"<$1>");try{for(var bw=0,bv=this.length;bw1&&bw0?this.clone(true):this).get();b(bC[bA])[bv](by);bz=bz.concat(by)}return this.pushStack(bz,e,bC.selector)}}});function bg(e){if(typeof e.getElementsByTagName!=="undefined"){return e.getElementsByTagName("*")}else{if(typeof e.querySelectorAll!=="undefined"){return e.querySelectorAll("*")}else{return[]}}}function az(e){if(e.type==="checkbox"||e.type==="radio"){e.defaultChecked=e.checked}}function E(e){var bv=(e.nodeName||"").toLowerCase();if(bv==="input"){az(e)}else{if(bv!=="script"&&typeof e.getElementsByTagName!=="undefined"){b.grep(e.getElementsByTagName("input"),az)}}}function al(e){var bv=av.createElement("div");ac.appendChild(bv);bv.innerHTML=e.outerHTML;return bv.firstChild}b.extend({clone:function(by,bA,bw){var e,bv,bx,bz=b.support.html5Clone||!ah.test("<"+by.nodeName)?by.cloneNode(true):al(by);if((!b.support.noCloneEvent||!b.support.noCloneChecked)&&(by.nodeType===1||by.nodeType===11)&&!b.isXMLDoc(by)){ai(by,bz);e=bg(by);bv=bg(bz);for(bx=0;e[bx];++bx){if(bv[bx]){ai(e[bx],bv[bx])}}}if(bA){t(by,bz);if(bw){e=bg(by);bv=bg(bz);for(bx=0;e[bx];++bx){t(e[bx],bv[bx])}}}e=bv=null;return bz},clean:function(bw,by,bH,bA){var bF;by=by||av;if(typeof by.createElement==="undefined"){by=by.ownerDocument||by[0]&&by[0].ownerDocument||av}var bI=[],bB;for(var bE=0,bz;(bz=bw[bE])!=null;bE++){if(typeof bz==="number"){bz+=""}if(!bz){continue}if(typeof bz==="string"){if(!W.test(bz)){bz=by.createTextNode(bz)}else{bz=bz.replace(R,"<$1>");var bK=(d.exec(bz)||["",""])[1].toLowerCase(),bx=ax[bK]||ax._default,bD=bx[0],bv=by.createElement("div");if(by===av){ac.appendChild(bv)}else{a(by).appendChild(bv)}bv.innerHTML=bx[1]+bz+bx[2];while(bD--){bv=bv.lastChild}if(!b.support.tbody){var e=w.test(bz),bC=bK==="table"&&!e?bv.firstChild&&bv.firstChild.childNodes:bx[1]===""&&!e?bv.childNodes:[];for(bB=bC.length-1;bB>=0;--bB){if(b.nodeName(bC[bB],"tbody")&&!bC[bB].childNodes.length){bC[bB].parentNode.removeChild(bC[bB])}}}if(!b.support.leadingWhitespace&&ar.test(bz)){bv.insertBefore(by.createTextNode(ar.exec(bz)[0]),bv.firstChild)}bz=bv.childNodes}}var bG;if(!b.support.appendChecked){if(bz[0]&&typeof(bG=bz.length)==="number"){for(bB=0;bB=0){return bx+"px"}}else{return bx}}}});if(!b.support.opacity){b.cssHooks.opacity={get:function(bv,e){return au.test((e&&bv.currentStyle?bv.currentStyle.filter:bv.style.filter)||"")?(parseFloat(RegExp.$1)/100)+"":e?"1":""},set:function(by,bz){var bx=by.style,bv=by.currentStyle,e=b.isNumeric(bz)?"alpha(opacity="+bz*100+")":"",bw=bv&&bv.filter||bx.filter||"";bx.zoom=1;if(bz>=1&&b.trim(bw.replace(ak,""))===""){bx.removeAttribute("filter");if(bv&&!bv.filter){return}}bx.filter=ak.test(bw)?bw.replace(ak,e):bw+" "+e}}}b(function(){if(!b.support.reliableMarginRight){b.cssHooks.marginRight={get:function(bw,bv){var e;b.swap(bw,{display:"inline-block"},function(){if(bv){e=Z(bw,"margin-right","marginRight")}else{e=bw.style.marginRight}});return e}}}});if(av.defaultView&&av.defaultView.getComputedStyle){aI=function(by,bw){var bv,bx,e;bw=bw.replace(z,"-$1").toLowerCase();if((bx=by.ownerDocument.defaultView)&&(e=bx.getComputedStyle(by,null))){bv=e.getPropertyValue(bw);if(bv===""&&!b.contains(by.ownerDocument.documentElement,by)){bv=b.style(by,bw)}}return bv}}if(av.documentElement.currentStyle){aX=function(bz,bw){var bA,e,by,bv=bz.currentStyle&&bz.currentStyle[bw],bx=bz.style;if(bv===null&&bx&&(by=bx[bw])){bv=by}if(!bc.test(bv)&&bn.test(bv)){bA=bx.left;e=bz.runtimeStyle&&bz.runtimeStyle.left;if(e){bz.runtimeStyle.left=bz.currentStyle.left}bx.left=bw==="fontSize"?"1em":(bv||0);bv=bx.pixelLeft+"px";bx.left=bA;if(e){bz.runtimeStyle.left=e}}return bv===""?"auto":bv}}Z=aI||aX;function p(by,bw,bv){var bA=bw==="width"?by.offsetWidth:by.offsetHeight,bz=bw==="width"?an:a1,bx=0,e=bz.length; +if(bA>0){if(bv!=="border"){for(;bx)<[^<]*)*<\/script>/gi,q=/^(?:select|textarea)/i,h=/\s+/,br=/([?&])_=[^&]*/,K=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,A=b.fn.load,aa={},r={},aE,s,aV=["*/"]+["*"];try{aE=bl.href}catch(aw){aE=av.createElement("a");aE.href="";aE=aE.href}s=K.exec(aE.toLowerCase())||[];function f(e){return function(by,bA){if(typeof by!=="string"){bA=by;by="*"}if(b.isFunction(bA)){var bx=by.toLowerCase().split(h),bw=0,bz=bx.length,bv,bB,bC;for(;bw=0){var e=bw.slice(by,bw.length);bw=bw.slice(0,by)}var bx="GET";if(bz){if(b.isFunction(bz)){bA=bz;bz=L}else{if(typeof bz==="object"){bz=b.param(bz,b.ajaxSettings.traditional);bx="POST"}}}var bv=this;b.ajax({url:bw,type:bx,dataType:"html",data:bz,complete:function(bC,bB,bD){bD=bC.responseText;if(bC.isResolved()){bC.done(function(bE){bD=bE});bv.html(e?b("
").append(bD.replace(a6,"")).find(e):bD)}if(bA){bv.each(bA,[bD,bB,bC])}}});return this},serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?b.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||q.test(this.nodeName)||aZ.test(this.type))}).map(function(e,bv){var bw=b(this).val();return bw==null?null:b.isArray(bw)?b.map(bw,function(by,bx){return{name:bv.name,value:by.replace(bs,"\r\n")}}):{name:bv.name,value:bw.replace(bs,"\r\n")}}).get()}});b.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(e,bv){b.fn[bv]=function(bw){return this.on(bv,bw)}});b.each(["get","post"],function(e,bv){b[bv]=function(bw,by,bz,bx){if(b.isFunction(by)){bx=bx||bz;bz=by;by=L}return b.ajax({type:bv,url:bw,data:by,success:bz,dataType:bx})}});b.extend({getScript:function(e,bv){return b.get(e,L,bv,"script")},getJSON:function(e,bv,bw){return b.get(e,bv,bw,"json")},ajaxSetup:function(bv,e){if(e){am(bv,b.ajaxSettings)}else{e=bv;bv=b.ajaxSettings}am(bv,e);return bv},ajaxSettings:{url:aE,isLocal:aM.test(s[1]),global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":aV},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":bb.String,"text html":true,"text json":b.parseJSON,"text xml":b.parseXML},flatOptions:{context:true,url:true}},ajaxPrefilter:f(aa),ajaxTransport:f(r),ajax:function(bz,bx){if(typeof bz==="object"){bx=bz;bz=L}bx=bx||{};var bD=b.ajaxSetup({},bx),bS=bD.context||bD,bG=bS!==bD&&(bS.nodeType||bS instanceof b)?b(bS):b.event,bR=b.Deferred(),bN=b.Callbacks("once memory"),bB=bD.statusCode||{},bC,bH={},bO={},bQ,by,bL,bE,bI,bA=0,bw,bK,bJ={readyState:0,setRequestHeader:function(bT,bU){if(!bA){var e=bT.toLowerCase();bT=bO[e]=bO[e]||bT;bH[bT]=bU}return this},getAllResponseHeaders:function(){return bA===2?bQ:null},getResponseHeader:function(bT){var e;if(bA===2){if(!by){by={};while((e=aD.exec(bQ))){by[e[1].toLowerCase()]=e[2]}}e=by[bT.toLowerCase()]}return e===L?null:e},overrideMimeType:function(e){if(!bA){bD.mimeType=e}return this},abort:function(e){e=e||"abort";if(bL){bL.abort(e)}bF(0,e);return this}};function bF(bZ,bU,b0,bW){if(bA===2){return}bA=2;if(bE){clearTimeout(bE)}bL=L;bQ=bW||"";bJ.readyState=bZ>0?4:0;var bT,b4,b3,bX=bU,bY=b0?bj(bD,bJ,b0):L,bV,b2;if(bZ>=200&&bZ<300||bZ===304){if(bD.ifModified){if((bV=bJ.getResponseHeader("Last-Modified"))){b.lastModified[bC]=bV}if((b2=bJ.getResponseHeader("Etag"))){b.etag[bC]=b2}}if(bZ===304){bX="notmodified";bT=true}else{try{b4=G(bD,bY);bX="success";bT=true}catch(b1){bX="parsererror";b3=b1}}}else{b3=bX;if(!bX||bZ){bX="error";if(bZ<0){bZ=0}}}bJ.status=bZ;bJ.statusText=""+(bU||bX);if(bT){bR.resolveWith(bS,[b4,bX,bJ])}else{bR.rejectWith(bS,[bJ,bX,b3])}bJ.statusCode(bB);bB=L;if(bw){bG.trigger("ajax"+(bT?"Success":"Error"),[bJ,bD,bT?b4:b3])}bN.fireWith(bS,[bJ,bX]);if(bw){bG.trigger("ajaxComplete",[bJ,bD]);if(!(--b.active)){b.event.trigger("ajaxStop")}}}bR.promise(bJ);bJ.success=bJ.done;bJ.error=bJ.fail;bJ.complete=bN.add;bJ.statusCode=function(bT){if(bT){var e;if(bA<2){for(e in bT){bB[e]=[bB[e],bT[e]]}}else{e=bT[bJ.status];bJ.then(e,e)}}return this};bD.url=((bz||bD.url)+"").replace(bq,"").replace(c,s[1]+"//");bD.dataTypes=b.trim(bD.dataType||"*").toLowerCase().split(h);if(bD.crossDomain==null){bI=K.exec(bD.url.toLowerCase());bD.crossDomain=!!(bI&&(bI[1]!=s[1]||bI[2]!=s[2]||(bI[3]||(bI[1]==="http:"?80:443))!=(s[3]||(s[1]==="http:"?80:443))))}if(bD.data&&bD.processData&&typeof bD.data!=="string"){bD.data=b.param(bD.data,bD.traditional)}aW(aa,bD,bx,bJ);if(bA===2){return false}bw=bD.global;bD.type=bD.type.toUpperCase();bD.hasContent=!aQ.test(bD.type);if(bw&&b.active++===0){b.event.trigger("ajaxStart")}if(!bD.hasContent){if(bD.data){bD.url+=(M.test(bD.url)?"&":"?")+bD.data;delete bD.data}bC=bD.url;if(bD.cache===false){var bv=b.now(),bP=bD.url.replace(br,"$1_="+bv);bD.url=bP+((bP===bD.url)?(M.test(bD.url)?"&":"?")+"_="+bv:"")}}if(bD.data&&bD.hasContent&&bD.contentType!==false||bx.contentType){bJ.setRequestHeader("Content-Type",bD.contentType)}if(bD.ifModified){bC=bC||bD.url;if(b.lastModified[bC]){bJ.setRequestHeader("If-Modified-Since",b.lastModified[bC])}if(b.etag[bC]){bJ.setRequestHeader("If-None-Match",b.etag[bC])}}bJ.setRequestHeader("Accept",bD.dataTypes[0]&&bD.accepts[bD.dataTypes[0]]?bD.accepts[bD.dataTypes[0]]+(bD.dataTypes[0]!=="*"?", "+aV+"; q=0.01":""):bD.accepts["*"]);for(bK in bD.headers){bJ.setRequestHeader(bK,bD.headers[bK])}if(bD.beforeSend&&(bD.beforeSend.call(bS,bJ,bD)===false||bA===2)){bJ.abort();return false}for(bK in {success:1,error:1,complete:1}){bJ[bK](bD[bK])}bL=aW(r,bD,bx,bJ);if(!bL){bF(-1,"No Transport")}else{bJ.readyState=1;if(bw){bG.trigger("ajaxSend",[bJ,bD])}if(bD.async&&bD.timeout>0){bE=setTimeout(function(){bJ.abort("timeout")},bD.timeout)}try{bA=1;bL.send(bH,bF)}catch(bM){if(bA<2){bF(-1,bM)}else{throw bM}}}return bJ},param:function(e,bw){var bv=[],by=function(bz,bA){bA=b.isFunction(bA)?bA():bA;bv[bv.length]=encodeURIComponent(bz)+"="+encodeURIComponent(bA)};if(bw===L){bw=b.ajaxSettings.traditional}if(b.isArray(e)||(e.jquery&&!b.isPlainObject(e))){b.each(e,function(){by(this.name,this.value)})}else{for(var bx in e){v(bx,e[bx],bw,by)}}return bv.join("&").replace(k,"+")}});function v(bw,by,bv,bx){if(b.isArray(by)){b.each(by,function(bA,bz){if(bv||ap.test(bw)){bx(bw,bz)}else{v(bw+"["+(typeof bz==="object"||b.isArray(bz)?bA:"")+"]",bz,bv,bx)}})}else{if(!bv&&by!=null&&typeof by==="object"){for(var e in by){v(bw+"["+e+"]",by[e],bv,bx)}}else{bx(bw,by)}}}b.extend({active:0,lastModified:{},etag:{}});function bj(bD,bC,bz){var bv=bD.contents,bB=bD.dataTypes,bw=bD.responseFields,by,bA,bx,e;for(bA in bw){if(bA in bz){bC[bw[bA]]=bz[bA]}}while(bB[0]==="*"){bB.shift();if(by===L){by=bD.mimeType||bC.getResponseHeader("content-type")}}if(by){for(bA in bv){if(bv[bA]&&bv[bA].test(by)){bB.unshift(bA);break}}}if(bB[0] in bz){bx=bB[0]}else{for(bA in bz){if(!bB[0]||bD.converters[bA+" "+bB[0]]){bx=bA;break}if(!e){e=bA}}bx=bx||e}if(bx){if(bx!==bB[0]){bB.unshift(bx)}return bz[bx]}}function G(bH,bz){if(bH.dataFilter){bz=bH.dataFilter(bz,bH.dataType)}var bD=bH.dataTypes,bG={},bA,bE,bw=bD.length,bB,bC=bD[0],bx,by,bF,bv,e;for(bA=1;bA=bw.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();bw.animatedProperties[this.prop]=true;for(bA in bw.animatedProperties){if(bw.animatedProperties[bA]!==true){e=false}}if(e){if(bw.overflow!=null&&!b.support.shrinkWrapBlocks){b.each(["","X","Y"],function(bC,bD){bz.style["overflow"+bD]=bw.overflow[bC]})}if(bw.hide){b(bz).hide()}if(bw.hide||bw.show){for(bA in bw.animatedProperties){b.style(bz,bA,bw.orig[bA]);b.removeData(bz,"fxshow"+bA,true);b.removeData(bz,"toggle"+bA,true)}}bv=bw.complete;if(bv){bw.complete=false;bv.call(bz)}}return false}else{if(bw.duration==Infinity){this.now=bx}else{bB=bx-this.startTime;this.state=bB/bw.duration;this.pos=b.easing[bw.animatedProperties[this.prop]](this.state,bB,0,1,bw.duration);this.now=this.start+((this.end-this.start)*this.pos)}this.update()}return true}};b.extend(b.fx,{tick:function(){var bw,bv=b.timers,e=0;for(;e").appendTo(e),bw=bv.css("display");bv.remove();if(bw==="none"||bw===""){if(!a8){a8=av.createElement("iframe");a8.frameBorder=a8.width=a8.height=0}e.appendChild(a8);if(!m||!a8.createElement){m=(a8.contentWindow||a8.contentDocument).document;m.write((av.compatMode==="CSS1Compat"?"":"")+"");m.close()}bv=m.createElement(bx);m.body.appendChild(bv);bw=b.css(bv,"display");e.removeChild(a8)}Q[bx]=bw}return Q[bx]}var V=/^t(?:able|d|h)$/i,ad=/^(?:body|html)$/i;if("getBoundingClientRect" in av.documentElement){b.fn.offset=function(bI){var by=this[0],bB;if(bI){return this.each(function(e){b.offset.setOffset(this,bI,e)})}if(!by||!by.ownerDocument){return null}if(by===by.ownerDocument.body){return b.offset.bodyOffset(by)}try{bB=by.getBoundingClientRect()}catch(bF){}var bH=by.ownerDocument,bw=bH.documentElement;if(!bB||!b.contains(bw,by)){return bB?{top:bB.top,left:bB.left}:{top:0,left:0}}var bC=bH.body,bD=aK(bH),bA=bw.clientTop||bC.clientTop||0,bE=bw.clientLeft||bC.clientLeft||0,bv=bD.pageYOffset||b.support.boxModel&&bw.scrollTop||bC.scrollTop,bz=bD.pageXOffset||b.support.boxModel&&bw.scrollLeft||bC.scrollLeft,bG=bB.top+bv-bA,bx=bB.left+bz-bE;return{top:bG,left:bx}}}else{b.fn.offset=function(bF){var bz=this[0];if(bF){return this.each(function(bG){b.offset.setOffset(this,bF,bG)})}if(!bz||!bz.ownerDocument){return null}if(bz===bz.ownerDocument.body){return b.offset.bodyOffset(bz)}var bC,bw=bz.offsetParent,bv=bz,bE=bz.ownerDocument,bx=bE.documentElement,bA=bE.body,bB=bE.defaultView,e=bB?bB.getComputedStyle(bz,null):bz.currentStyle,bD=bz.offsetTop,by=bz.offsetLeft;while((bz=bz.parentNode)&&bz!==bA&&bz!==bx){if(b.support.fixedPosition&&e.position==="fixed"){break}bC=bB?bB.getComputedStyle(bz,null):bz.currentStyle;bD-=bz.scrollTop;by-=bz.scrollLeft;if(bz===bw){bD+=bz.offsetTop;by+=bz.offsetLeft;if(b.support.doesNotAddBorder&&!(b.support.doesAddBorderForTableAndCells&&V.test(bz.nodeName))){bD+=parseFloat(bC.borderTopWidth)||0;by+=parseFloat(bC.borderLeftWidth)||0}bv=bw;bw=bz.offsetParent}if(b.support.subtractsBorderForOverflowNotVisible&&bC.overflow!=="visible"){bD+=parseFloat(bC.borderTopWidth)||0;by+=parseFloat(bC.borderLeftWidth)||0}e=bC}if(e.position==="relative"||e.position==="static"){bD+=bA.offsetTop;by+=bA.offsetLeft}if(b.support.fixedPosition&&e.position==="fixed"){bD+=Math.max(bx.scrollTop,bA.scrollTop);by+=Math.max(bx.scrollLeft,bA.scrollLeft)}return{top:bD,left:by}}}b.offset={bodyOffset:function(e){var bw=e.offsetTop,bv=e.offsetLeft;if(b.support.doesNotIncludeMarginInBodyOffset){bw+=parseFloat(b.css(e,"marginTop"))||0;bv+=parseFloat(b.css(e,"marginLeft"))||0}return{top:bw,left:bv}},setOffset:function(bx,bG,bA){var bB=b.css(bx,"position");if(bB==="static"){bx.style.position="relative"}var bz=b(bx),bv=bz.offset(),e=b.css(bx,"top"),bE=b.css(bx,"left"),bF=(bB==="absolute"||bB==="fixed")&&b.inArray("auto",[e,bE])>-1,bD={},bC={},bw,by;if(bF){bC=bz.position();bw=bC.top;by=bC.left}else{bw=parseFloat(e)||0;by=parseFloat(bE)||0}if(b.isFunction(bG)){bG=bG.call(bx,bA,bv)}if(bG.top!=null){bD.top=(bG.top-bv.top)+bw}if(bG.left!=null){bD.left=(bG.left-bv.left)+by}if("using" in bG){bG.using.call(bx,bD)}else{bz.css(bD)}}};b.fn.extend({position:function(){if(!this[0]){return null}var bw=this[0],bv=this.offsetParent(),bx=this.offset(),e=ad.test(bv[0].nodeName)?{top:0,left:0}:bv.offset();bx.top-=parseFloat(b.css(bw,"marginTop"))||0;bx.left-=parseFloat(b.css(bw,"marginLeft"))||0;e.top+=parseFloat(b.css(bv[0],"borderTopWidth"))||0;e.left+=parseFloat(b.css(bv[0],"borderLeftWidth"))||0;return{top:bx.top-e.top,left:bx.left-e.left}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||av.body;while(e&&(!ad.test(e.nodeName)&&b.css(e,"position")==="static")){e=e.offsetParent}return e})}});b.each(["Left","Top"],function(bv,e){var bw="scroll"+e;b.fn[bw]=function(bz){var bx,by;if(bz===L){bx=this[0];if(!bx){return null}by=aK(bx);return by?("pageXOffset" in by)?by[bv?"pageYOffset":"pageXOffset"]:b.support.boxModel&&by.document.documentElement[bw]||by.document.body[bw]:bx[bw]}return this.each(function(){by=aK(this);if(by){by.scrollTo(!bv?bz:b(by).scrollLeft(),bv?bz:b(by).scrollTop())}else{this[bw]=bz}})}});function aK(e){return b.isWindow(e)?e:e.nodeType===9?e.defaultView||e.parentWindow:false}b.each(["Height","Width"],function(bv,e){var bw=e.toLowerCase();b.fn["inner"+e]=function(){var bx=this[0];return bx?bx.style?parseFloat(b.css(bx,bw,"padding")):this[bw]():null};b.fn["outer"+e]=function(by){var bx=this[0];return bx?bx.style?parseFloat(b.css(bx,bw,by?"margin":"border")):this[bw]():null};b.fn[bw]=function(bz){var bA=this[0];if(!bA){return bz==null?null:this}if(b.isFunction(bz)){return this.each(function(bE){var bD=b(this);bD[bw](bz.call(this,bE,bD[bw]()))})}if(b.isWindow(bA)){var bB=bA.document.documentElement["client"+e],bx=bA.document.body;return bA.document.compatMode==="CSS1Compat"&&bB||bx&&bx["client"+e]||bB}else{if(bA.nodeType===9){return Math.max(bA.documentElement["client"+e],bA.body["scroll"+e],bA.documentElement["scroll"+e],bA.body["offset"+e],bA.documentElement["offset"+e])}else{if(bz===L){var bC=b.css(bA,bw),by=parseFloat(bC);return b.isNumeric(by)?by:bC}else{return this.css(bw,typeof bz==="string"?bz:bz+"px")}}}}});bb.jQuery=bb.$=b;if(typeof define==="function"&&define.amd&&define.amd.jQuery){define("jquery",[],function(){return b +})}})(window); +/*! + PowerTip - v1.2.0 - 2013-04-03 + http://stevenbenner.github.com/jquery-powertip/ + Copyright (c) 2013 Steven Benner (http://stevenbenner.com/). + Released under MIT license. + https://raw.github.com/stevenbenner/jquery-powertip/master/LICENSE.txt +*/ +(function(a){if(typeof define==="function"&&define.amd){define(["jquery"],a)}else{a(jQuery)}}(function(k){var A=k(document),s=k(window),w=k("body");var n="displayController",e="hasActiveHover",d="forcedOpen",u="hasMouseMove",f="mouseOnToPopup",g="originalTitle",y="powertip",o="powertipjq",l="powertiptarget",E=180/Math.PI;var c={isTipOpen:false,isFixedTipOpen:false,isClosing:false,tipOpenImminent:false,activeHover:null,currentX:0,currentY:0,previousX:0,previousY:0,desyncTimeout:null,mouseTrackingActive:false,delayInProgress:false,windowWidth:0,windowHeight:0,scrollTop:0,scrollLeft:0};var p={none:0,top:1,bottom:2,left:4,right:8};k.fn.powerTip=function(F,N){if(!this.length){return this}if(k.type(F)==="string"&&k.powerTip[F]){return k.powerTip[F].call(this,this,N)}var O=k.extend({},k.fn.powerTip.defaults,F),G=new x(O);h();this.each(function M(){var R=k(this),Q=R.data(y),P=R.data(o),T=R.data(l),S;if(R.data(n)){k.powerTip.destroy(R)}S=R.attr("title");if(!Q&&!T&&!P&&S){R.data(y,S);R.data(g,S);R.removeAttr("title")}R.data(n,new t(R,O,G))});if(!O.manual){this.on({"mouseenter.powertip":function J(P){k.powerTip.show(this,P)},"mouseleave.powertip":function L(){k.powerTip.hide(this)},"focus.powertip":function K(){k.powerTip.show(this)},"blur.powertip":function H(){k.powerTip.hide(this,true)},"keydown.powertip":function I(P){if(P.keyCode===27){k.powerTip.hide(this,true)}}})}return this};k.fn.powerTip.defaults={fadeInTime:200,fadeOutTime:100,followMouse:false,popupId:"powerTip",intentSensitivity:7,intentPollInterval:100,closeDelay:100,placement:"n",smartPlacement:false,offset:10,mouseOnToPopup:false,manual:false};k.fn.powerTip.smartPlacementLists={n:["n","ne","nw","s"],e:["e","ne","se","w","nw","sw","n","s","e"],s:["s","se","sw","n"],w:["w","nw","sw","e","ne","se","n","s","w"],nw:["nw","w","sw","n","s","se","nw"],ne:["ne","e","se","n","s","sw","ne"],sw:["sw","w","nw","s","n","ne","sw"],se:["se","e","ne","s","n","nw","se"],"nw-alt":["nw-alt","n","ne-alt","sw-alt","s","se-alt","w","e"],"ne-alt":["ne-alt","n","nw-alt","se-alt","s","sw-alt","e","w"],"sw-alt":["sw-alt","s","se-alt","nw-alt","n","ne-alt","w","e"],"se-alt":["se-alt","s","sw-alt","ne-alt","n","nw-alt","e","w"]};k.powerTip={show:function z(F,G){if(G){i(G);c.previousX=G.pageX;c.previousY=G.pageY;k(F).data(n).show()}else{k(F).first().data(n).show(true,true)}return F},reposition:function r(F){k(F).first().data(n).resetPosition();return F},hide:function D(G,F){if(G){k(G).first().data(n).hide(F)}else{if(c.activeHover){c.activeHover.data(n).hide(true)}}return G},destroy:function C(G){k(G).off(".powertip").each(function F(){var I=k(this),H=[g,n,e,d];if(I.data(g)){I.attr("title",I.data(g));H.push(y)}I.removeData(H)});return G}};k.powerTip.showTip=k.powerTip.show;k.powerTip.closeTip=k.powerTip.hide;function b(){var F=this;F.top="auto";F.left="auto";F.right="auto";F.bottom="auto";F.set=function(H,G){if(k.isNumeric(G)){F[H]=Math.round(G)}}}function t(K,N,F){var J=null;function L(P,Q){M();if(!K.data(e)){if(!P){c.tipOpenImminent=true;J=setTimeout(function O(){J=null;I()},N.intentPollInterval)}else{if(Q){K.data(d,true)}F.showTip(K)}}}function G(P){M();c.tipOpenImminent=false;if(K.data(e)){K.data(d,false);if(!P){c.delayInProgress=true;J=setTimeout(function O(){J=null;F.hideTip(K);c.delayInProgress=false},N.closeDelay)}else{F.hideTip(K)}}}function I(){var Q=Math.abs(c.previousX-c.currentX),O=Math.abs(c.previousY-c.currentY),P=Q+O;if(P",{id:Q.popupId});if(w.length===0){w=k("body")}w.append(O)}if(Q.followMouse){if(!O.data(u)){A.on("mousemove",M);s.on("scroll",M);O.data(u,true)}}if(Q.mouseOnToPopup){O.on({mouseenter:function L(){if(O.data(f)){if(c.activeHover){c.activeHover.data(n).cancel()}}},mouseleave:function N(){if(c.activeHover){c.activeHover.data(n).hide()}}})}function I(S){S.data(e,true);O.queue(function R(T){H(S);T()})}function H(S){var U;if(!S.data(e)){return}if(c.isTipOpen){if(!c.isClosing){K(c.activeHover)}O.delay(100).queue(function R(V){H(S);V()});return}S.trigger("powerTipPreRender");U=B(S);if(U){O.empty().append(U)}else{return}S.trigger("powerTipRender");c.activeHover=S;c.isTipOpen=true;O.data(f,Q.mouseOnToPopup);if(!Q.followMouse){G(S);c.isFixedTipOpen=true}else{M()}O.fadeIn(Q.fadeInTime,function T(){if(!c.desyncTimeout){c.desyncTimeout=setInterval(J,500)}S.trigger("powerTipOpen")})}function K(R){c.isClosing=true;c.activeHover=null;c.isTipOpen=false;c.desyncTimeout=clearInterval(c.desyncTimeout);R.data(e,false);R.data(d,false);O.fadeOut(Q.fadeOutTime,function S(){var T=new b();c.isClosing=false;c.isFixedTipOpen=false;O.removeClass();T.set("top",c.currentY+Q.offset);T.set("left",c.currentX+Q.offset);O.css(T);R.trigger("powerTipClose")})}function M(){if(!c.isFixedTipOpen&&(c.isTipOpen||(c.tipOpenImminent&&O.data(u)))){var R=O.outerWidth(),V=O.outerHeight(),U=new b(),S,T;U.set("top",c.currentY+Q.offset);U.set("left",c.currentX+Q.offset);S=m(U,R,V);if(S!==p.none){T=a(S);if(T===1){if(S===p.right){U.set("left",c.windowWidth-R)}else{if(S===p.bottom){U.set("top",c.scrollTop+c.windowHeight-V)}}}else{U.set("left",c.currentX-R-Q.offset);U.set("top",c.currentY-V-Q.offset)}}O.css(U)}}function G(S){var R,T;if(Q.smartPlacement){R=k.fn.powerTip.smartPlacementLists[Q.placement];k.each(R,function(U,W){var V=m(F(S,W),O.outerWidth(),O.outerHeight());T=W;if(V===p.none){return false}})}else{F(S,Q.placement);T=Q.placement}O.addClass(T)}function F(U,T){var R=0,S,W,V=new b();V.set("top",0);V.set("left",0);O.css(V);do{S=O.outerWidth();W=O.outerHeight();V=P.compute(U,T,S,W,Q.offset);O.css(V)}while(++R<=5&&(S!==O.outerWidth()||W!==O.outerHeight()));return V}function J(){var R=false;if(c.isTipOpen&&!c.isClosing&&!c.delayInProgress){if(c.activeHover.data(e)===false||c.activeHover.is(":disabled")){R=true}else{if(!v(c.activeHover)&&!c.activeHover.is(":focus")&&!c.activeHover.data(d)){if(O.data(f)){if(!v(O)){R=true}}else{R=true}}}if(R){K(c.activeHover)}}}this.showTip=I;this.hideTip=K;this.resetPosition=G}function q(F){return window.SVGElement&&F[0] instanceof SVGElement}function h(){if(!c.mouseTrackingActive){c.mouseTrackingActive=true;k(function H(){c.scrollLeft=s.scrollLeft();c.scrollTop=s.scrollTop();c.windowWidth=s.width();c.windowHeight=s.height()});A.on("mousemove",i);s.on({resize:function G(){c.windowWidth=s.width();c.windowHeight=s.height()},scroll:function F(){var I=s.scrollLeft(),J=s.scrollTop();if(I!==c.scrollLeft){c.currentX+=I-c.scrollLeft;c.scrollLeft=I}if(J!==c.scrollTop){c.currentY+=J-c.scrollTop;c.scrollTop=J}}})}}function i(F){c.currentX=F.pageX;c.currentY=F.pageY}function v(F){var H=F.offset(),J=F[0].getBoundingClientRect(),I=J.right-J.left,G=J.bottom-J.top;return c.currentX>=H.left&&c.currentX<=H.left+I&&c.currentY>=H.top&&c.currentY<=H.top+G}function B(I){var G=I.data(y),F=I.data(o),K=I.data(l),H,J;if(G){if(k.isFunction(G)){G=G.call(I[0])}J=G}else{if(F){if(k.isFunction(F)){F=F.call(I[0])}if(F.length>0){J=F.clone(true,true)}}else{if(K){H=k("#"+K);if(H.length>0){J=H.html()}}}}return J}function m(M,L,K){var G=c.scrollTop,J=c.scrollLeft,I=G+c.windowHeight,F=J+c.windowWidth,H=p.none;if(M.topI||Math.abs(M.bottom-c.windowHeight)>I){H|=p.bottom}if(M.leftF){H|=p.left}if(M.left+L>F||M.right + + + + + +Project 3 - Currency Type: power10.hpp Source File + + + + + + +
+
+
+ + + + + +
+
Project 3 - Currency Type +
+
+ + + + + + +
+
+
power10.hpp
+
+
+
1 #ifndef POWER10_HPP_
+
2 #define POWER10_HPP_
+
3 
+
4 // Listing 51-6. Computing a Power of 10 at Compile Time
+
6 template<class T>
+
7 T constexpr power10_helper(T n, T result)
+
8 {
+
9  return n == T{} ? result : power10_helper(n - T{1}, T{10} * result);
+
10 }
+
11 
+
13 template<class T>
+
14 T constexpr power10(T n)
+
15 {
+
16  return power10_helper(n, T{1});
+
17 }
+
18 
+
19 #endif
+
+ + + + diff --git a/exploring-cpp-2e/chapter57/html/rational_8hpp_source.html b/exploring-cpp-2e/chapter57/html/rational_8hpp_source.html new file mode 100644 index 0000000..ee67d71 --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/rational_8hpp_source.html @@ -0,0 +1,576 @@ + + + + + + +Project 3 - Currency Type: rational.hpp Source File + + + + + + +
+
+ + + + + + +
+
Project 3 - Currency Type +
+
+
+ + + + +
+
+
+
rational.hpp
+
+
+
1 #ifndef RATIONAL_HPP_
+
2 #define RATIONAL_HPP_
+
3 
+
4 #include <istream>
+
5 #include <limits>
+
6 #include <ostream>
+
7 #include <sstream>
+
8 #include <stdexcept>
+
9 #include <string>
+
10 
+
11 #include "gcd.hpp"
+
12 #include "ioflags.hpp"
+
13 
+
15 template<class T>
+
16 class rational
+
17 {
+
18 public:
+
20  typedef T value_type;
+
22  class zero_denominator : public std::logic_error
+
23  {
+
24  public:
+
26  zero_denominator(std::string const& what) : logic_error{what} {}
+
27  };
+
28 
+
33  rational(value_type num = 0): numerator_{num}, denominator_{1} {}
+
38  rational(value_type num, value_type den);
+
41  rational(double r);
+
43  template<class U>
+
44  rational(rational<U> const& that);
+
45 
+
47  value_type numerator() const { return numerator_; }
+
49  value_type denominator() const { return denominator_; }
+
51  template<class U>
+
52  U as() const { return static_cast<U>(numerator()) / denominator(); }
+
53 
+
55  rational& operator=(value_type); // optimization to avoid an unneeded call to reduce()
+
56 
+
58  template<class U>
+
59  rational& operator=(rational<U> const& rhs);
+
60 
+
62  rational& operator+=(rational const& rhs);
+
64  rational& operator+=(value_type const& rhs);
+
65 
+
67  rational& operator-=(rational const& rhs);
+
69  rational& operator-=(value_type const& rhs);
+
70 
+
72  rational& operator*=(rational const& rhs);
+
74  rational& operator*=(value_type const& rhs);
+
75 
+
77  rational& operator/=(rational const& rhs);
+
79  rational& operator/=(value_type const& rhs);
+
80 
+ + +
86  rational operator++(int);
+
88  rational operator--(int);
+
89 
+
90 private:
+
92  void reduce();
+
95  void normalize();
+
98  template<class U>
+
99  value_type scale(U value);
+
100 
+
101  value_type numerator_;
+
102  value_type denominator_;
+
103 };
+
104 
+
105 template<class T>
+ +
107 : numerator_(num),
+
108  denominator_(den == value_type() ? throw zero_denominator("zero denominator") : den)
+
109 {
+
110  normalize();
+
111 }
+
112 
+
113 template<class T>
+ +
115 : numerator_(static_cast<T>(r / 100000)), denominator_(static_cast<T>(100000))
+
116 {}
+
117 
+
118 template<class T>
+
119 template<class U>
+ +
121 : numerator_(scale<U>(that.numerator())), denominator_(scale<U>(that.denominator()))
+
122 {
+
123  reduce();
+
124 }
+
125 
+
126 template<class T>
+
127 template<class U>
+
128 T rational<T>::scale(U value)
+
129 {
+
130  if (std::numeric_limits<T>::digits >= std::numeric_limits<U>::digits)
+
131  return T(value);
+
132  else
+
133  return T(value >> (std::numeric_limits<U>::digits - std::numeric_limits<T>::digits));
+
134 }
+
135 
+
136 template<class T>
+ +
138 {
+
139  if (denominator_ < value_type())
+
140  {
+
141  denominator_ = -denominator_;
+
142  numerator_ = -numerator_;
+
143  }
+
144  reduce();
+
145 }
+
146 
+
147 template<class T>
+
148 void rational<T>::reduce()
+
149 {
+
150  value_type div(gcd(numerator(), denominator()));
+
151  if (div == value_type())
+
152  throw zero_denominator("zero denominator");
+
153  numerator_ /= div;
+
154  denominator_ /= div;
+
155 }
+
156 
+
157 template<class T>
+ +
159 {
+
160  numerator_ = num;
+
161  denominator_ = value_type(1);
+
162  return *this;
+
163 }
+
164 
+
165 template<class T>
+
166 template<class U>
+ +
168 {
+
169  numerator_ = scale<U>(rhs.numerator());
+
170  denominator_ = scale<U>(rhs.denominator());
+
171  reduce();
+
172  return *this;
+
173 }
+
174 
+
175 template<class T>
+ +
177 {
+
178  numerator_ = numerator() * rhs.denominator() + rhs.numerator() * denominator();
+
179  denominator_ *= rhs.denominator();
+
180  reduce();
+
181  return *this;
+
182 }
+
183 
+
184 template<class T>
+ +
186 {
+
187  numerator_ = numerator() + rhs * denominator();
+
188  reduce();
+
189  return *this;
+
190 }
+
191 
+
192 template<class T>
+ +
194 {
+
195  numerator_ = numerator() * rhs.denominator() - rhs.numerator() * denominator();
+
196  denominator_ *= rhs.denominator();
+
197  reduce();
+
198  return *this;
+
199 }
+
200 
+
201 template<class T>
+ +
203 {
+
204  numerator_ = numerator() - rhs * denominator();
+
205  reduce();
+
206  return *this;
+
207 }
+
208 
+
209 template<class T>
+ +
211 {
+
212  numerator_ *= rhs.numerator();
+
213  denominator_ *= rhs.denominator();
+
214  reduce();
+
215  return *this;
+
216 }
+
217 
+
218 template<class T>
+ +
220 {
+
221  numerator_ *= rhs;
+
222  reduce();
+
223  return *this;
+
224 }
+
225 
+
226 template<class T>
+ +
228 {
+
229  if (rhs.numerator() == value_type())
+
230  throw zero_denominator("divide by zero");
+
231  numerator_ *= rhs.denominator();
+
232  denominator_ *= rhs.numerator();
+
233  normalize();
+
234  return *this;
+
235 }
+
236 
+
237 template<class T>
+ +
239 {
+
240  if (rhs == value_type())
+
241  throw zero_denominator("divide by zero");
+
242  denominator_ *= rhs;
+
243  normalize();
+
244  return *this;
+
245 }
+
246 
+
247 template<class T>
+ +
249 {
+
250  numerator_ += denominator();
+
251  return *this;
+
252 }
+
253 
+
254 template<class T>
+ +
256 {
+
257  rational result(*this);
+
258  ++*this;
+
259  return result;
+
260 }
+
261 
+
262 template<class T>
+ +
264 {
+
265  numerator_ -= denominator();
+
266  return *this;
+
267 }
+
268 
+
269 template<class T>
+ +
271 {
+
272  rational result(*this);
+
273  --*this;
+
274  return result;
+
275 }
+
276 
+
278 template<class T>
+ +
280 {
+
281  return rational<T>(-r.numerator(), r.denominator());
+
282 }
+
283 
+
284 template<class T>
+
285 rational<T> absval(rational<T> const& r)
+
286 {
+
287  using namespace std;
+
288  return rational<T>(abs(r.numerator()), r.denominator());
+
289 }
+
290 
+
292 template<class T>
+ +
294 {
+
295  lhs += rhs;
+
296  return lhs;
+
297 }
+
298 
+
300 template<class T>
+
301 rational<T> operator+(rational<T> lhs, T const& rhs)
+
302 {
+
303  lhs += rhs;
+
304  return lhs;
+
305 }
+
306 
+
308 template<class T>
+
309 rational<T> operator+(T const& lhs, rational<T> rhs)
+
310 {
+
311  rhs += lhs;
+
312  return rhs;
+
313 }
+
314 
+
316 template<class T>
+ +
318 {
+
319  lhs -= rhs;
+
320  return lhs;
+
321 }
+
322 
+
324 template<class T>
+
325 rational<T> operator-(rational<T> lhs, T const& rhs)
+
326 {
+
327  lhs -= rhs;
+
328  return lhs;
+
329 }
+
330 
+
332 template<class T>
+
333 rational<T> operator-(T const& lhs, rational<T> rhs)
+
334 {
+
335  // Gotta be a little tricky.
+
336  rhs += -lhs;
+
337  return -rhs;
+
338 }
+
339 
+
341 template<class T>
+ +
343 {
+
344  lhs *= rhs;
+
345  return lhs;
+
346 }
+
347 
+
349 template<class T>
+
350 rational<T> operator*(rational<T> lhs, T const& rhs)
+
351 {
+
352  lhs *= rhs;
+
353  return lhs;
+
354 }
+
355 
+
357 template<class T>
+
358  rational<T> operator*(T const& lhs, rational<T> rhs)
+
359 {
+
360  rhs *= lhs;
+
361  return rhs;
+
362 }
+
363 
+
365 template<class T>
+ +
367 {
+
368  lhs /= rhs;
+
369  return lhs;
+
370 }
+
371 
+
373 template<class T>
+
374 rational<T> operator/(rational<T> lhs, T const& rhs)
+
375 {
+
376  lhs /= rhs;
+
377  return lhs;
+
378 }
+
379 
+
381 template<class T>
+
382 rational<T> operator/(T const& lhs, rational<T> rhs)
+
383 {
+
384  return rational<T>(lhs * rhs.denominator(), rhs.numerator());
+
385 }
+
386 
+
387 
+
389 template<class T, class U>
+
390 bool operator==(rational<T> const& a, rational<U> const& b)
+
391 {
+
392  return a.numerator() == b.numerator() and
+
393  a.denominator() == b.denominator();
+
394 }
+
395 
+
397 template<class T>
+
398 bool operator==(rational<T> const& lhs, T rhs)
+
399 {
+
400  return lhs.denominator() == 1 and
+
401  lhs.numerator() == rhs;
+
402 }
+
403 
+
405 template<class T>
+
406 bool operator==(T lhs, rational<T> const& rhs)
+
407 {
+
408  return rhs.denominator() == 1 and
+
409  rhs.numerator() == lhs;
+
410 }
+
411 
+
413 template<class T>
+
414 bool operator<(rational<T> const& a, rational<T> const& b)
+
415 {
+
416  return a.numerator() * b.denominator() < b.numerator() * a.denominator();
+
417 }
+
418 
+
420 template<class T>
+
421 bool operator<(rational<T> const& a, T const& b)
+
422 {
+
423  return a.numerator() < b * a.denominator();
+
424 }
+
425 
+
427 template<class T>
+
428 bool operator<(T const& a, rational<T> const& b)
+
429 {
+
430  return a * b.denominator() < b.numerator();
+
431 }
+
432 
+
434 template<class T, class U>
+
435 inline bool operator!=(rational<T> const& a, rational<U> const& b)
+
436 {
+
437  return not (a == b);
+
438 }
+
439 
+
441 template<class T>
+
442 inline bool operator!=(rational<T> const& a, T b)
+
443 {
+
444  return not (a == b);
+
445 }
+
446 
+
448 template<class T>
+
449 inline bool operator!=(T a, rational<T> const& b)
+
450 {
+
451  return not (a == b);
+
452 }
+
453 
+
455 template<class T>
+
456 inline bool operator<=(rational<T> const& a, rational<T> const& b)
+
457 {
+
458  return not (b < a);
+
459 }
+
460 
+
462 template<class T>
+
463 inline bool operator<=(rational<T> const& a, T const& b)
+
464 {
+
465  return not (b < a);
+
466 }
+
467 
+
469 template<class T>
+
470 inline bool operator<=(T const& a, rational<T> const& b)
+
471 {
+
472  return not (b < a);
+
473 }
+
474 
+
476 template<class T>
+
477 inline bool operator>(rational<T> const& a, rational<T> const& b)
+
478 {
+
479  return b < a;
+
480 }
+
481 
+
483 template<class T>
+
484 inline bool operator>(rational<T> const& a, T const& b)
+
485 {
+
486  return b < a;
+
487 }
+
488 
+
490 template<class T>
+
491 inline bool operator>(T const& a, rational<T> const& b)
+
492 {
+
493  return b < a;
+
494 }
+
495 
+
497 template<class T>
+
498 inline bool operator>=(rational<T> const& a, rational<T> const& b)
+
499 {
+
500  return not (b > a);
+
501 }
+
502 
+
504 template<class T>
+
505 inline bool operator>=(rational<T> const& a, T const& b)
+
506 {
+
507  return not (b > a);
+
508 }
+
509 
+
511 template<class T>
+
512 inline bool operator>=(T const& a, rational<T> const& b)
+
513 {
+
514  return not (b > a);
+
515 }
+
516 
+
518 template<class T, class Char, class Traits>
+
519 std::basic_istream<Char, Traits>& operator>>(std::basic_istream<Char, Traits>& in, rational<T>& rat)
+
520 {
+
521  typename std::basic_istream<Char, Traits>::sentry sentry(in, false);
+
522  ioflags flags(in);
+
523 
+
524  T n = T();
+
525  if (not (in >> n))
+
526  // Error reading the numerator.
+
527  return in;
+
528 
+
529  in >> std::noskipws;
+
530  char sep('\0');
+
531  if (not (in >> sep))
+
532  // Error reading the separator character.
+
533  return in;
+
534  else if (sep != '/')
+
535  {
+
536  // Push sep back into the input stream, so the next input operation
+
537  // will read it.
+
538  in.unget();
+
539  rat = n;
+
540  return in;
+
541  }
+
542  else
+
543  {
+
544  T d = T();
+
545  if (in >> d)
+
546  // Successfully read numerator, separator, and denominator.
+
547  rat = rational<T>(n, d);
+
548  }
+
549 
+
550  return in;
+
551 }
+
552 
+
554 template<class T, class Char, class Traits>
+
555 std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& out, rational<T> const& rat)
+
556 {
+
557  typename std::basic_ostream<Char, Traits>::sentry sentry(out);
+
558  std::ostringstream stream;
+
559  stream << rat.numerator() << '/' << rat.denominator();
+
560  out << stream.str();
+
561  return out;
+
562 }
+
563 
+
564 #endif
+
currency< T, N > operator+(currency< T, N > a, currency< T, N > b)
Definition: currency.hpp:304
+
bool operator==(currency< T, N > a, currency< T, N > b)
Definition: currency.hpp:366
+
currency< T, N > operator*(currency< T, N > a, T b)
Definition: currency.hpp:324
+
rational & operator=(value_type)
Assignment of an integer.
Definition: rational.hpp:158
+
value_type denominator() const
Return the denominator.
Definition: rational.hpp:49
+
zero_denominator(std::string const &what)
Construct the exception object.
Definition: rational.hpp:26
+
currency< T, N > operator/(currency< T, N > a, T b)
Definition: currency.hpp:344
+
rational & operator-=(rational const &rhs)
Subtraction assignment operator.
Definition: rational.hpp:193
+
value_type numerator() const
Return the numerator.
Definition: rational.hpp:47
+
rational & operator--()
Pre-decrement.
Definition: rational.hpp:263
+
Save and restore I/O stream flags.
+
rational & operator+=(rational const &rhs)
Addition assignment operator.
Definition: rational.hpp:176
+
bool operator!=(currency< T, N > a, currency< T, N > b)
Definition: currency.hpp:391
+
rational(value_type num=0)
Definition: rational.hpp:33
+
rational & operator*=(rational const &rhs)
Multiplication assignment operator.
Definition: rational.hpp:210
+
rational & operator/=(rational const &rhs)
Division assignment operator.
Definition: rational.hpp:227
+
Represent a rational number (fraction) as a numerator and denominator.
Definition: rational.hpp:16
+
bool operator>=(currency< T, N > a, currency< T, N > b)
Definition: currency.hpp:491
+
T value_type
Convenience typedef for the integral type of the numerator and denominator.
Definition: rational.hpp:20
+
U as() const
Convert the rational number to another type, especially floating-point.
Definition: rational.hpp:52
+
rational & operator++()
Pre-increment.
Definition: rational.hpp:248
+
Exception class if the denominator is ever zero.
Definition: rational.hpp:22
+ +
bool operator>(currency< T, N > a, currency< T, N > b)
Definition: currency.hpp:441
+
std::basic_istream< Char, Traits > & operator>>(std::basic_istream< Char, Traits > &strm, currency< T, N > &c)
Definition: currency.hpp:274
+
currency< T, N > operator-(currency< T, N > a)
Negate a currency value.
Definition: currency.hpp:294
+
+ + + + diff --git a/exploring-cpp-2e/chapter57/html/sync_off.png b/exploring-cpp-2e/chapter57/html/sync_off.png new file mode 100644 index 0000000..3b443fc Binary files /dev/null and b/exploring-cpp-2e/chapter57/html/sync_off.png differ diff --git a/exploring-cpp-2e/chapter57/html/sync_on.png b/exploring-cpp-2e/chapter57/html/sync_on.png new file mode 100644 index 0000000..e08320f Binary files /dev/null and b/exploring-cpp-2e/chapter57/html/sync_on.png differ diff --git a/exploring-cpp-2e/chapter57/html/tab_a.png b/exploring-cpp-2e/chapter57/html/tab_a.png new file mode 100644 index 0000000..3b725c4 Binary files /dev/null and b/exploring-cpp-2e/chapter57/html/tab_a.png differ diff --git a/exploring-cpp-2e/chapter57/html/tab_b.png b/exploring-cpp-2e/chapter57/html/tab_b.png new file mode 100644 index 0000000..e2b4a86 Binary files /dev/null and b/exploring-cpp-2e/chapter57/html/tab_b.png differ diff --git a/exploring-cpp-2e/chapter57/html/tab_h.png b/exploring-cpp-2e/chapter57/html/tab_h.png new file mode 100644 index 0000000..fd5cb70 Binary files /dev/null and b/exploring-cpp-2e/chapter57/html/tab_h.png differ diff --git a/exploring-cpp-2e/chapter57/html/tab_s.png b/exploring-cpp-2e/chapter57/html/tab_s.png new file mode 100644 index 0000000..ab478c9 Binary files /dev/null and b/exploring-cpp-2e/chapter57/html/tab_s.png differ diff --git a/exploring-cpp-2e/chapter57/html/tabs.css b/exploring-cpp-2e/chapter57/html/tabs.css new file mode 100644 index 0000000..9cf578f --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/tabs.css @@ -0,0 +1,60 @@ +.tabs, .tabs2, .tabs3 { + background-image: url('tab_b.png'); + width: 100%; + z-index: 101; + font-size: 13px; + font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; +} + +.tabs2 { + font-size: 10px; +} +.tabs3 { + font-size: 9px; +} + +.tablist { + margin: 0; + padding: 0; + display: table; +} + +.tablist li { + float: left; + display: table-cell; + background-image: url('tab_b.png'); + line-height: 36px; + list-style: none; +} + +.tablist a { + display: block; + padding: 0 20px; + font-weight: bold; + background-image:url('tab_s.png'); + background-repeat:no-repeat; + background-position:right; + color: #283A5D; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + text-decoration: none; + outline: none; +} + +.tabs3 .tablist a { + padding: 0 10px; +} + +.tablist a:hover { + background-image: url('tab_h.png'); + background-repeat:repeat-x; + color: #fff; + text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); + text-decoration: none; +} + +.tablist li.current a { + background-image: url('tab_a.png'); + background-repeat:repeat-x; + color: #fff; + text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); +} diff --git a/exploring-cpp-2e/chapter57/html/test_8cpp.html b/exploring-cpp-2e/chapter57/html/test_8cpp.html new file mode 100644 index 0000000..f6253b2 --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/test_8cpp.html @@ -0,0 +1,104 @@ + + + + + + +Project 3 - Currency Type: test.cpp File Reference + + + + + + +
+
+ + + + + + +
+
Project 3 - Currency Type +
+
+
+ + + + +
+
+ +
+
test.cpp File Reference
+
+
+
#include <iostream>
+#include <istream>
+#include <locale>
+#include <ostream>
+#include <sstream>
+#include <stdexcept>
+#include "test.hpp"
+#include "currency.hpp"
+
+

Go to the source code of this file.

+ + + + +

+Functions

int main (int argc, char **argv)
 
+

Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + +
int main (int argc,
char ** argv 
)
+
+

Listing 45-1. Testing the fixed Class

+ +

Definition at line 13 of file test.cpp.

+ +
+
+
+ + + + diff --git a/exploring-cpp-2e/chapter57/html/test_8cpp_source.html b/exploring-cpp-2e/chapter57/html/test_8cpp_source.html new file mode 100644 index 0000000..a0a3789 --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/test_8cpp_source.html @@ -0,0 +1,200 @@ + + + + + + +Project 3 - Currency Type: test.cpp Source File + + + + + + +
+
+ + + + + + +
+
Project 3 - Currency Type +
+
+
+ + + + +
+
+
+
test.cpp
+
+
+Go to the documentation of this file.
1 
+
3 #include <iostream>
+
4 #include <istream>
+
5 #include <locale>
+
6 #include <ostream>
+
7 #include <sstream>
+
8 #include <stdexcept>
+
9 
+
10 #include "test.hpp"
+
11 #include "currency.hpp"
+
12 
+
13 int main(int argc, char** argv)
+
14 {
+
15  if (argc >= 2)
+
16  std::locale::global(std::locale(argv[1]));
+
17  else
+
18  std::locale::global(std::locale(""));
+
19  std::cin.imbue(std::locale());
+
20  std::cout.imbue(std::locale());
+
21  typedef currency<long,4> currency4;
+
22  typedef currency<long,2> currency2;
+
23  currency2 c1;
+
24  TEST(c1.value().value() == 0);
+
25  currency2 c2(1L);
+
26  TEST(c2.value().value() == 100);
+
27  currency2 c3(3, 1416);
+
28  TEST(c3.value().value() == 314);
+
29  currency2 c4(6, 275);
+
30  TEST(c4.value().value() == 628);
+
31  currency2 c5(5, 279);
+
32  TEST(c5.value().value() == 528);
+
33  TEST(c3 + c3 == c1 + c4);
+
34  TEST(c3 + c3 <= c1 + c4);
+
35  TEST(c3 + c3 >= c1 + c4);
+
36  TEST(c1 < c2);
+
37  TEST(c1 <= c2);
+
38  TEST(c1 != c2);
+
39  TEST(c2 > c1);
+
40  TEST(c2 >= c1);
+
41  TEST(c2 != c1);
+
42  TEST(c2 / 2L == currency2(0, 50));
+
43 
+
44  TEST(c4 - c5 == c2);
+
45  TEST(c3 * 2L == c4);
+
46  TEST(c4 / 2L == c3);
+
47  c5 += c2;
+
48  TEST(c5 == c4);
+
49  c5 /= 2L;
+
50  TEST(c3 == c5);
+
51  c3 *= 2L;
+
52  TEST(c3 == c4);
+
53  c3 -= c5;
+
54  TEST(c3 == c5);
+
55 
+
56  TEST(-c4 == c1 - c4);
+
57  TEST(-(-c4) == c4);
+
58  TEST(c3 + c5 == --c4 + c2);
+
59  TEST(c3 + c5 == c4 + c2);
+
60  TEST(c3 + c5 == c4-- + c2);
+
61  TEST(c3 + c5 == c4 + c2 + c2);
+
62  TEST(c3 + c5 == ++c4 + c2);
+
63  TEST(c3 + c5 == c4 + c2);
+
64  TEST(c3 + c5 == c4++ + c2);
+
65  TEST(c3 + c5 == c4);
+
66 
+
67  c2 *= 2L;
+
68  TEST(c4 / c2 == rational<long>(314, 100));
+
69  TEST((c4 /= 2L) == c5);
+
70  TEST(c4 == c5);
+
71 
+
72  TEST(c4.as_string() == "3.14");
+
73  TEST(c4.integer() == 3);
+
74  c4 += currency2(-1,8);
+
75  TEST((c4 == currency2(2.06)));
+
76  TEST(c4.integer() == 2);
+
77  TEST(c4.round() == 2);
+
78  c4 += c2 / 2L;
+
79  TEST(c4.round() == 3);
+
80 
+
81  TEST(c3.integer() == 3);
+
82  TEST((-c3).integer() == -3);
+
83  TEST(c3.fraction() == 14);
+
84  TEST((-c3).fraction() == 14);
+
85 
+
86  TEST(currency4(7,4999).round() == 7L);
+
87  TEST(currency4(7,5000).round() == 8L);
+
88  TEST(currency4(7,5001).round() == 8L);
+
89  TEST(currency4(7,4999).round() == 7L);
+
90  TEST(currency4(8,5000).round() == 8L);
+
91  TEST(currency4(8,5001).round() == 9L);
+
92 
+
93  TEST(currency4(123,2345500) == currency4(123,2346));
+
94  TEST(currency4(123,2345501) == currency4(123,2346));
+
95  TEST(currency4(123,2345499) == currency4(123,2345));
+
96  TEST(currency4(123,2346500) == currency4(123,2346));
+
97  TEST(currency4(123,2346501) == currency4(123,2347));
+
98  TEST(currency4(123,2346499) == currency4(123,2346));
+
99  TEST(currency4(123,2346400) == currency4(123,2346));
+
100  TEST(currency4(123,2346600) == currency4(123,2347));
+
101 
+
102  TEST(currency4(-3.14159265).value().value() == -31416L);
+
103  TEST(currency4(123,456789).value().value() == 1234568L);
+
104  TEST(currency4(123,4).value().value() == 1230004L);
+
105  TEST(currency4(-10,1111).value().value() == -101111L);
+
106 
+
107  std::ostringstream out;
+
108  c3 = currency2(3, 14);
+
109  out << std::showbase << c3 << " 3.14 " << currency2(-10,12) << " 3.00 421.40 end";
+
110  currency2 c6;
+
111  std::istringstream in(out.str());
+
112  TEST(in >> c6);
+
113  TEST(c6 == c3);
+
114  c6 = currency2();
+
115  TEST(in >> c6);
+
116  TEST(c6 == c3);
+
117  TEST(in >> c6);
+
118  TEST(c6.value() == -1012L);
+
119  TEST(in >> c6);
+
120  TEST(c6.value() == 300L);
+
121  TEST(in >> c6);
+
122  TEST(c6.value() == 42140L);
+
123  TEST(not (in >> c6));
+
124 
+
125  TEST(currency2(31.59265) == currency2(31, 59));
+
126  TEST(currency2(31.595) == currency2(31, 60));
+
127 
+
128  // Adjust the following test to match your native locale.
+
129  currency2 big(1234567, 89);
+
130  TEST(big.as_string() == "1,234,567.89");
+
131 
+
132  bool okay(false);
+
133  try {
+
134  currency2 c7(1, -1);
+
135  } catch (std::invalid_argument const& ex) {
+
136  okay = true;
+
137  } catch (std::exception const& ex) {
+
138  std::cerr << "wrong exception: " << ex.what() << '\n';
+
139  }
+
140  TEST(okay);
+
141 }
+ +
Represent a rational number (fraction) as a numerator and denominator.
Definition: rational.hpp:16
+
int main(int argc, char **argv)
Definition: test.cpp:13
+ +
+ + + + diff --git a/exploring-cpp-2e/chapter57/html/test_8hpp_source.html b/exploring-cpp-2e/chapter57/html/test_8hpp_source.html new file mode 100644 index 0000000..09aef65 --- /dev/null +++ b/exploring-cpp-2e/chapter57/html/test_8hpp_source.html @@ -0,0 +1,102 @@ + + + + + + +Project 3 - Currency Type: test.hpp Source File + + + + + + +
+
+ + + + + + +
+
Project 3 - Currency Type +
+
+
+ + + + +
+
+
+
test.hpp
+
+
+
1 #ifndef TEST_HPP_
+
2 #define TEST_HPP_
+
3 
+
4 #include <exception>
+
5 #include <iostream>
+
6 #include <ostream>
+
7 
+
8 // For internal use by the TEST() macro.
+
9 // Turn the macro argument into a character string literal
+
10 #define TEST_STRINGIFY(x) #x
+
11 
+
12 // For internal use by the TEST() macro.
+
13 // Report a test failure.
+
14 inline void test_failed(char const* expr, char const* file, int line)
+
15 {
+
16  std::cerr << file << ", line " << line << ": test failed: " << expr << '\n';
+
17 }
+
18 
+
19 // For internal use by the TEST() macro
+
20 // Run a test. Report a failure if the condition is false or
+
21 inline void test_run(bool condition, char const* expr, char const* file, int line)
+
22 {
+
23  if (not condition)
+
24  test_failed(expr, file, line);
+
25 }
+
26 
+
27 // For internal use by the TEST() macro.
+
28 // Report an exception.
+
29 inline void test_exception(std::exception const& ex, char const* expr, char const* file, int line)
+
30 {
+
31  std::string msg( expr );
+
32  msg += " threw an exception: ";
+
33  msg += ex.what();
+
34  test_failed(msg.c_str(), file, line);
+
35 }
+
36 
+
45 #define TEST(x) \
+
46 try {\
+
47  test_run(x, TEST_STRINGIFY(x), __FILE__, __LINE__);\
+
48 }\
+
49 catch(std::exception const& ex)\
+
50 {\
+
51  test_exception(ex, TEST_STRINGIFY(x), __FILE__, __LINE__);\
+
52 }
+
53 
+
54 #endif
+
+ + + + diff --git a/exploring-cpp-2e/chapter57/ioflags.hpp b/exploring-cpp-2e/chapter57/ioflags.hpp new file mode 100644 index 0000000..45e28e2 --- /dev/null +++ b/exploring-cpp-2e/chapter57/ioflags.hpp @@ -0,0 +1,32 @@ +#ifndef IOFLAGS_HPP_ +#define IOFLAGS_HPP_ + +/** @file + * @brief Save and restore I/O stream flags. + */ + +/** Save and restore I/O stream flags. + * When a function needs to temporarily alter an I/O stream flags, + * simply define an object of type @c ioflags. Set whatever flags + * you want. When the block exits or function returns, the + * original flags are restored. + */ + +class ioflags +{ +public: + /// Save the formatting flags from @p stream. + /// @param stream The stream that will have its flags modified and restored. + ioflags(std::basic_ios& stream) : stream_(stream), flags_{stream.flags()} {} + /// Restore the formatting flags. + ~ioflags() { stream_.flags(flags_); } + + ioflags(ioflags const&) = delete; + ioflags& operator=(ioflags const&) = delete; + +private: + std::basic_ios& stream_; + std::ios_base::fmtflags flags_; +}; + +#endif diff --git a/exploring-cpp-2e/chapter57/power10.hpp b/exploring-cpp-2e/chapter57/power10.hpp new file mode 100644 index 0000000..ff1c696 --- /dev/null +++ b/exploring-cpp-2e/chapter57/power10.hpp @@ -0,0 +1,19 @@ +#ifndef POWER10_HPP_ +#define POWER10_HPP_ + +// Listing 51-6. Computing a Power of 10 at Compile Time +/// Called from power10 to compute 10@p n, storing the result so far in @p result. +template +T constexpr power10_helper(T n, T result) +{ + return n == T{} ? result : power10_helper(n - T{1}, T{10} * result); +} + +/// Compute a power of 10 at compile time. The type T must support subtraction and multiplication. +template +T constexpr power10(T n) +{ + return power10_helper(n, T{1}); +} + +#endif diff --git a/exploring-cpp-2e/chapter57/rational.hpp b/exploring-cpp-2e/chapter57/rational.hpp new file mode 100644 index 0000000..42df50a --- /dev/null +++ b/exploring-cpp-2e/chapter57/rational.hpp @@ -0,0 +1,564 @@ +#ifndef RATIONAL_HPP_ +#define RATIONAL_HPP_ + +#include +#include +#include +#include +#include +#include + +#include "gcd.hpp" +#include "ioflags.hpp" + +/// Represent a rational number (fraction) as a numerator and denominator. +template +class rational +{ +public: + /// Convenience typedef for the integral type of the numerator and denominator. + typedef T value_type; + /// Exception class if the denominator is ever zero. + class zero_denominator : public std::logic_error + { + public: + /// Construct the exception object. + zero_denominator(std::string const& what) : logic_error{what} {} + }; + + /// Default constructor and constructor from a single value. + /// As a default constructor, initializes to zero. + /// Otherwise, initializes to the integer @p num. + /// @param num The integer value to use as the initial value + rational(value_type num = 0): numerator_{num}, denominator_{1} {} + /// Construct a rational number + /// @param num numerator + /// @param den denominator + /// @throws zero_denominator if @p den == 0 + rational(value_type num, value_type den); + /// Initialize the rational number with an approximation of @p r + /// @param r the initial value + rational(double r); + /// Copy from a different type of rational. + template + rational(rational const& that); + + /// Return the numerator + value_type numerator() const { return numerator_; } + /// Return the denominator + value_type denominator() const { return denominator_; } + /// Convert the rational number to another type, especially floating-point. + template + U as() const { return static_cast(numerator()) / denominator(); } + + /// Assignment of an integer + rational& operator=(value_type); // optimization to avoid an unneeded call to reduce() + + /// Assignment of a rational with a different size. + template + rational& operator=(rational const& rhs); + + /// Addition assignment operator + rational& operator+=(rational const& rhs); + /// Addition assignment operator + rational& operator+=(value_type const& rhs); + + /// Subtraction assignment operator + rational& operator-=(rational const& rhs); + /// Subtraction assignment operator + rational& operator-=(value_type const& rhs); + + /// Multiplication assignment operator + rational& operator*=(rational const& rhs); + /// Multiplication assignment operator + rational& operator*=(value_type const& rhs); + + /// Division assignment operator + rational& operator/=(rational const& rhs); + /// Division assignment operator + rational& operator/=(value_type const& rhs); + + /// Pre-increment + rational& operator++(); + /// Pre-decrement + rational& operator--(); + /// Post-increment + rational operator++(int); + /// Post-decrement + rational operator--(int); + +private: + /// Reduce the numerator and denominator by their GCD. + void reduce(); + /// Reduce the numerator and denominator, and normalize the signs of both, + /// that is, ensure denominator is not negative. + void normalize(); + /// Scale an integer of type @p U to the value_type. If @p U has more + /// digits than @p value_type shift @p value to the right. + template + value_type scale(U value); + + value_type numerator_; + value_type denominator_; +}; + +template +rational::rational(value_type num, value_type den) +: numerator_(num), + denominator_(den == value_type() ? throw zero_denominator("zero denominator") : den) +{ + normalize(); +} + +template +rational::rational(double r) +: numerator_(static_cast(r / 100000)), denominator_(static_cast(100000)) +{} + +template +template +rational::rational(rational const& that) +: numerator_(scale(that.numerator())), denominator_(scale(that.denominator())) +{ + reduce(); +} + +template +template +T rational::scale(U value) +{ + if (std::numeric_limits::digits >= std::numeric_limits::digits) + return T(value); + else + return T(value >> (std::numeric_limits::digits - std::numeric_limits::digits)); +} + +template +void rational::normalize() +{ + if (denominator_ < value_type()) + { + denominator_ = -denominator_; + numerator_ = -numerator_; + } + reduce(); +} + +template +void rational::reduce() +{ + value_type div(gcd(numerator(), denominator())); + if (div == value_type()) + throw zero_denominator("zero denominator"); + numerator_ /= div; + denominator_ /= div; +} + +template +rational& rational::operator=(T num) +{ + numerator_ = num; + denominator_ = value_type(1); + return *this; +} + +template +template +rational& rational::operator=(rational const& rhs) +{ + numerator_ = scale(rhs.numerator()); + denominator_ = scale(rhs.denominator()); + reduce(); + return *this; +} + +template +rational& rational::operator+=(rational const& rhs) +{ + numerator_ = numerator() * rhs.denominator() + rhs.numerator() * denominator(); + denominator_ *= rhs.denominator(); + reduce(); + return *this; +} + +template +rational& rational::operator+=(value_type const& rhs) +{ + numerator_ = numerator() + rhs * denominator(); + reduce(); + return *this; +} + +template +rational& rational::operator-=(rational const& rhs) +{ + numerator_ = numerator() * rhs.denominator() - rhs.numerator() * denominator(); + denominator_ *= rhs.denominator(); + reduce(); + return *this; +} + +template +rational& rational::operator-=(value_type const& rhs) +{ + numerator_ = numerator() - rhs * denominator(); + reduce(); + return *this; +} + +template +rational& rational::operator*=(rational const& rhs) +{ + numerator_ *= rhs.numerator(); + denominator_ *= rhs.denominator(); + reduce(); + return *this; +} + +template +rational& rational::operator*=(value_type const& rhs) +{ + numerator_ *= rhs; + reduce(); + return *this; +} + +template +rational& rational::operator/=(rational const& rhs) +{ + if (rhs.numerator() == value_type()) + throw zero_denominator("divide by zero"); + numerator_ *= rhs.denominator(); + denominator_ *= rhs.numerator(); + normalize(); + return *this; +} + +template +rational& rational::operator/=(value_type const& rhs) +{ + if (rhs == value_type()) + throw zero_denominator("divide by zero"); + denominator_ *= rhs; + normalize(); + return *this; +} + +template +rational& rational::operator++() +{ + numerator_ += denominator(); + return *this; +} + +template +rational rational::operator++(int) +{ + rational result(*this); + ++*this; + return result; +} + +template +rational& rational::operator--() +{ + numerator_ -= denominator(); + return *this; +} + +template +rational rational::operator--(int) +{ + rational result(*this); + --*this; + return result; +} + +/// Negate a rational number +template +rational operator-(rational const& r) +{ + return rational(-r.numerator(), r.denominator()); +} + +template +rational absval(rational const& r) +{ + using namespace std; + return rational(abs(r.numerator()), r.denominator()); +} + +/// Addition +template +rational operator+(rational lhs, rational const& rhs) +{ + lhs += rhs; + return lhs; +} + +/// Addition +template +rational operator+(rational lhs, T const& rhs) +{ + lhs += rhs; + return lhs; +} + +/// Addition +template +rational operator+(T const& lhs, rational rhs) +{ + rhs += lhs; + return rhs; +} + +/// Subtraction +template +rational operator-(rational lhs, rational const& rhs) +{ + lhs -= rhs; + return lhs; +} + +/// Subtraction +template +rational operator-(rational lhs, T const& rhs) +{ + lhs -= rhs; + return lhs; +} + +/// Subtraction +template +rational operator-(T const& lhs, rational rhs) +{ + // Gotta be a little tricky. + rhs += -lhs; + return -rhs; +} + +/// Multiplication +template +rational operator*(rational lhs, rational const& rhs) +{ + lhs *= rhs; + return lhs; +} + +/// Multiplication +template +rational operator*(rational lhs, T const& rhs) +{ + lhs *= rhs; + return lhs; +} + +/// Multiplication +template + rational operator*(T const& lhs, rational rhs) +{ + rhs *= lhs; + return rhs; +} + +/// Division +template +rational operator/(rational lhs, rational const& rhs) +{ + lhs /= rhs; + return lhs; +} + +/// Division +template +rational operator/(rational lhs, T const& rhs) +{ + lhs /= rhs; + return lhs; +} + +/// Division +template +rational operator/(T const& lhs, rational rhs) +{ + return rational(lhs * rhs.denominator(), rhs.numerator()); +} + + +/// Equality comparison +template +bool operator==(rational const& a, rational const& b) +{ + return a.numerator() == b.numerator() and + a.denominator() == b.denominator(); +} + +/// Equality comparison +template +bool operator==(rational const& lhs, T rhs) +{ + return lhs.denominator() == 1 and + lhs.numerator() == rhs; +} + +/// Equality comparison +template +bool operator==(T lhs, rational const& rhs) +{ + return rhs.denominator() == 1 and + rhs.numerator() == lhs; +} + +/// Less-than comparison +template +bool operator<(rational const& a, rational const& b) +{ + return a.numerator() * b.denominator() < b.numerator() * a.denominator(); +} + +/// Less-than comparison +template +bool operator<(rational const& a, T const& b) +{ + return a.numerator() < b * a.denominator(); +} + +/// Less-than comparison +template +bool operator<(T const& a, rational const& b) +{ + return a * b.denominator() < b.numerator(); +} + +/// Inequality comparison +template +inline bool operator!=(rational const& a, rational const& b) +{ + return not (a == b); +} + +/// Inequality comparison +template +inline bool operator!=(rational const& a, T b) +{ + return not (a == b); +} + +/// Inequality comparison +template +inline bool operator!=(T a, rational const& b) +{ + return not (a == b); +} + +/// Less-than-or-equal comparison +template +inline bool operator<=(rational const& a, rational const& b) +{ + return not (b < a); +} + +/// Less-than-or-equal comparison +template +inline bool operator<=(rational const& a, T const& b) +{ + return not (b < a); +} + +/// Less-than-or-equal comparison +template +inline bool operator<=(T const& a, rational const& b) +{ + return not (b < a); +} + +/// Greater-than comparison +template +inline bool operator>(rational const& a, rational const& b) +{ + return b < a; +} + +/// Greater-than comparison +template +inline bool operator>(rational const& a, T const& b) +{ + return b < a; +} + +/// Greater-than comparison +template +inline bool operator>(T const& a, rational const& b) +{ + return b < a; +} + +/// Greater-than-or-equal comparison +template +inline bool operator>=(rational const& a, rational const& b) +{ + return not (b > a); +} + +/// Greater-than-or-equal comparison +template +inline bool operator>=(rational const& a, T const& b) +{ + return not (b > a); +} + +/// Greater-than-or-equal comparison +template +inline bool operator>=(T const& a, rational const& b) +{ + return not (b > a); +} + +/// Input operator +template +std::basic_istream& operator>>(std::basic_istream& in, rational& rat) +{ + typename std::basic_istream::sentry sentry(in, false); + ioflags flags(in); + + T n = T(); + if (not (in >> n)) + // Error reading the numerator. + return in; + + in >> std::noskipws; + char sep('\0'); + if (not (in >> sep)) + // Error reading the separator character. + return in; + else if (sep != '/') + { + // Push sep back into the input stream, so the next input operation + // will read it. + in.unget(); + rat = n; + return in; + } + else + { + T d = T(); + if (in >> d) + // Successfully read numerator, separator, and denominator. + rat = rational(n, d); + } + + return in; +} + +/// Output operator +template +std::basic_ostream& operator<<(std::basic_ostream& out, rational const& rat) +{ + typename std::basic_ostream::sentry sentry(out); + std::ostringstream stream; + stream << rat.numerator() << '/' << rat.denominator(); + out << stream.str(); + return out; +} + +#endif diff --git a/exploring-cpp-2e/chapter57/test.cpp b/exploring-cpp-2e/chapter57/test.cpp new file mode 100644 index 0000000..9d90950 --- /dev/null +++ b/exploring-cpp-2e/chapter57/test.cpp @@ -0,0 +1,141 @@ +/** @file test.cpp */ +/** Listing 45-1. Testing the fixed Class */ +#include +#include +#include +#include +#include +#include + +#include "test.hpp" +#include "currency.hpp" + +int main(int argc, char** argv) +{ + if (argc >= 2) + std::locale::global(std::locale(argv[1])); + else + std::locale::global(std::locale("")); + std::cin.imbue(std::locale()); + std::cout.imbue(std::locale()); + typedef currency currency4; + typedef currency currency2; + currency2 c1; + TEST(c1.value().value() == 0); + currency2 c2(1L); + TEST(c2.value().value() == 100); + currency2 c3(3, 1416); + TEST(c3.value().value() == 314); + currency2 c4(6, 275); + TEST(c4.value().value() == 628); + currency2 c5(5, 279); + TEST(c5.value().value() == 528); + TEST(c3 + c3 == c1 + c4); + TEST(c3 + c3 <= c1 + c4); + TEST(c3 + c3 >= c1 + c4); + TEST(c1 < c2); + TEST(c1 <= c2); + TEST(c1 != c2); + TEST(c2 > c1); + TEST(c2 >= c1); + TEST(c2 != c1); + TEST(c2 / 2L == currency2(0, 50)); + + TEST(c4 - c5 == c2); + TEST(c3 * 2L == c4); + TEST(c4 / 2L == c3); + c5 += c2; + TEST(c5 == c4); + c5 /= 2L; + TEST(c3 == c5); + c3 *= 2L; + TEST(c3 == c4); + c3 -= c5; + TEST(c3 == c5); + + TEST(-c4 == c1 - c4); + TEST(-(-c4) == c4); + TEST(c3 + c5 == --c4 + c2); + TEST(c3 + c5 == c4 + c2); + TEST(c3 + c5 == c4-- + c2); + TEST(c3 + c5 == c4 + c2 + c2); + TEST(c3 + c5 == ++c4 + c2); + TEST(c3 + c5 == c4 + c2); + TEST(c3 + c5 == c4++ + c2); + TEST(c3 + c5 == c4); + + c2 *= 2L; + TEST(c4 / c2 == rational(314, 100)); + TEST((c4 /= 2L) == c5); + TEST(c4 == c5); + + TEST(c4.as_string() == "3.14"); + TEST(c4.integer() == 3); + c4 += currency2(-1,8); + TEST((c4 == currency2(2.06))); + TEST(c4.integer() == 2); + TEST(c4.round() == 2); + c4 += c2 / 2L; + TEST(c4.round() == 3); + + TEST(c3.integer() == 3); + TEST((-c3).integer() == -3); + TEST(c3.fraction() == 14); + TEST((-c3).fraction() == 14); + + TEST(currency4(7,4999).round() == 7L); + TEST(currency4(7,5000).round() == 8L); + TEST(currency4(7,5001).round() == 8L); + TEST(currency4(7,4999).round() == 7L); + TEST(currency4(8,5000).round() == 8L); + TEST(currency4(8,5001).round() == 9L); + + TEST(currency4(123,2345500) == currency4(123,2346)); + TEST(currency4(123,2345501) == currency4(123,2346)); + TEST(currency4(123,2345499) == currency4(123,2345)); + TEST(currency4(123,2346500) == currency4(123,2346)); + TEST(currency4(123,2346501) == currency4(123,2347)); + TEST(currency4(123,2346499) == currency4(123,2346)); + TEST(currency4(123,2346400) == currency4(123,2346)); + TEST(currency4(123,2346600) == currency4(123,2347)); + + TEST(currency4(-3.14159265).value().value() == -31416L); + TEST(currency4(123,456789).value().value() == 1234568L); + TEST(currency4(123,4).value().value() == 1230004L); + TEST(currency4(-10,1111).value().value() == -101111L); + + std::ostringstream out; + c3 = currency2(3, 14); + out << std::showbase << c3 << " 3.14 " << currency2(-10,12) << " 3.00 421.40 end"; + currency2 c6; + std::istringstream in(out.str()); + TEST(in >> c6); + TEST(c6 == c3); + c6 = currency2(); + TEST(in >> c6); + TEST(c6 == c3); + TEST(in >> c6); + TEST(c6.value() == -1012L); + TEST(in >> c6); + TEST(c6.value() == 300L); + TEST(in >> c6); + TEST(c6.value() == 42140L); + TEST(not (in >> c6)); + + TEST(currency2(31.59265) == currency2(31, 59)); + TEST(currency2(31.595) == currency2(31, 60)); + + // Adjust the following test to match your native locale. + currency2 big(1234567, 89); + TEST(big.as_string() == "1,234,567.89"); + + bool okay(false); + try { + currency2 c7(1, -1); + } catch (std::invalid_argument const& ex) { + okay = true; + } catch (std::exception const& ex) { + std::cerr << "wrong exception: " << ex.what() << '\n'; + } + TEST(okay); +} diff --git a/exploring-cpp-2e/chapter57/test.hpp b/exploring-cpp-2e/chapter57/test.hpp new file mode 100644 index 0000000..c65caaa --- /dev/null +++ b/exploring-cpp-2e/chapter57/test.hpp @@ -0,0 +1,54 @@ +#ifndef TEST_HPP_ +#define TEST_HPP_ + +#include +#include +#include + +// For internal use by the TEST() macro. +// Turn the macro argument into a character string literal +#define TEST_STRINGIFY(x) #x + +// For internal use by the TEST() macro. +// Report a test failure. +inline void test_failed(char const* expr, char const* file, int line) +{ + std::cerr << file << ", line " << line << ": test failed: " << expr << '\n'; +} + +// For internal use by the TEST() macro +// Run a test. Report a failure if the condition is false or +inline void test_run(bool condition, char const* expr, char const* file, int line) +{ + if (not condition) + test_failed(expr, file, line); +} + +// For internal use by the TEST() macro. +// Report an exception. +inline void test_exception(std::exception const& ex, char const* expr, char const* file, int line) +{ + std::string msg( expr ); + msg += " threw an exception: "; + msg += ex.what(); + test_failed(msg.c_str(), file, line); +} + +/// Test a condition, @p x. +/// If @p x evaluates to @c true the test passes. +/// If not, the test fails, and a message is printed to @c cerr. +/// The text of @p x, plus the file name and line number are printed. +/// +/// See Boost.Test for a real test framework +/// +/// @param x A condition to test; the condition must be able to be converted implicitly to @c bool. +#define TEST(x) \ +try {\ + test_run(x, TEST_STRINGIFY(x), __FILE__, __LINE__);\ +}\ +catch(std::exception const& ex)\ +{\ + test_exception(ex, TEST_STRINGIFY(x), __FILE__, __LINE__);\ +} + +#endif diff --git a/exploring-cpp-2e/chapter58/artifact.hpp b/exploring-cpp-2e/chapter58/artifact.hpp new file mode 100644 index 0000000..b3b96a7 --- /dev/null +++ b/exploring-cpp-2e/chapter58/artifact.hpp @@ -0,0 +1,41 @@ +// Listing 58-3. New Definition of an Artifact +#ifndef ARTIFACT_HPP_ +#define ARTIFACT_HPP_ + +#include +#include + +class artifact +{ +public: + typedef std::chrono::system_clock clock; + artifact() : name_{}, mod_time_{clock::time_point{}} {} + artifact(std::string const& name) + : name_{name}, mod_time_{get_mod_time()} + {} + + std::string const& name() const { return name_; } + clock::time_point mod_time() const { return mod_time_; } + + /// Build a target. + /// After completing the actions (not yet implemented), + /// update the modification time. + void build(); + + /// Look up the modification time of the artifact. + /// Return time_point{} if the artifact does not + /// exist (and therefore must be built) or if the time cannot + /// be obtained for any other reason. + /// Also see boost::file_system::last_write_time. + clock::time_point get_mod_time() + { + // Real programs should get this information from the + // operating system. This program returns the current time. + return clock::now(); + } +private: + std::string name_; + clock::time_point mod_time_; +}; + +#endif // ARTIFACT_HPP_ diff --git a/exploring-cpp-2e/chapter58/list5801.hpp b/exploring-cpp-2e/chapter58/list5801.hpp new file mode 100644 index 0000000..1521142 --- /dev/null +++ b/exploring-cpp-2e/chapter58/list5801.hpp @@ -0,0 +1,66 @@ +// Listing 58-1. Topological Sort of a Directed Acyclic Graph +#ifndef TOPOLOGICAL_SORT_HPP_ +#define TOPOLOGICAL_SORT_HPP_ + +#include +#include + +/// Helper function for topological_sort(). +/// Finds all the nodes in the graph with no incoming edges, +/// that is, with empty values. Removes each one from the graph +/// and adds it to the set @p nodes. +/// @param[in,out] graph A map of node/set pairs +/// @param[in,out] nodes A queue of nodes with no incoming edges +template +void topsort_clean_graph(Graph& graph, Nodes& nodes) +{ + for (auto iter(graph.begin()), end(graph.end()); iter != end;) + { + if (iter->second.empty()) + { + nodes.push_back(iter->first); + graph.erase(iter++); // advance iterator before erase invalidates it + } + else + ++iter; + } +} + +/// Topological sort of a directed acyclic graph. +/// A graph is a map keyed by nodes, with sets of nodes as values. +/// Edges run from values to keys. The sorted list of nodes +/// is copied to an output iterator in reverse order. +/// @param graph The graph +/// @param sorted The output iterator +/// @throws std::runtime_error if the graph contains a cycle +/// @pre Graph::key_type == Graph::mapped_type::key_type +template +void topological_sort(Graph graph, OutIterator sorted) +{ + std::deque nodes{}; + // Start with the set of nodes with no incoming edges. + topsort_clean_graph(graph, nodes); + + while (not nodes.empty()) + { + // Grab the first node to process, output it to sorted, + // and remove it from the graph. + typename Graph::key_type n{nodes.front()}; + nodes.pop_front(); + *sorted = n; + ++sorted; + + // Erase n from the graph + for (auto& node : graph) + { + node.second.erase(n); + } + // After removing n, find any nodes that no longer + // have any incoming edges. + topsort_clean_graph(graph, nodes); + } + if (not graph.empty()) + throw std::invalid_argument("Dependency graph contains cycles"); +} + +#endif // TOPOLOGICAL_SORT_HPP_ diff --git a/exploring-cpp-2e/chapter58/list5802.cpp b/exploring-cpp-2e/chapter58/list5802.cpp new file mode 100644 index 0000000..3b4b7e1 --- /dev/null +++ b/exploring-cpp-2e/chapter58/list5802.cpp @@ -0,0 +1,71 @@ +// Listing 58-2. First Draft of the Pseudo-make Program +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "topological_sort.hpp" + +typedef std::string artifact; ///< A target, dependency, or both + +class dependency_graph +{ +public: + typedef std::unordered_map> graph_type; + + void store_dependency(artifact const& target, artifact const& dependency) + { + graph_[dependency].insert(target); + graph_[target]; // ensures that target is in the graph + } + + graph_type const& graph() const { return graph_; } + + template + void sort(OutIter sorted) + const + { + topological_sort(graph_, sorted); + } + +private: + graph_type graph_; +}; + +int main() +{ + dependency_graph graph{}; + + std::string line{}; + while (std::getline(std::cin, line)) + { + std::string target{}, dependency{}; + std::istringstream stream{line}; + if (stream >> target >> dependency) + graph.store_dependency(target, dependency); + else if (not target.empty()) + // Input line has a target with no dependency, + // so report an error. + std::cerr << "malformed input: target, " << target << + ", must be followed by a dependency name\n"; + // else ignore blank lines + } + + try { + // Get the artifacts. The sort stores them in reverse order. + std::vector sorted{}; + graph.sort(std::back_inserter(sorted)); + // Then print them in the correct order. + std::copy(sorted.rbegin(), sorted.rend(), + std::ostream_iterator(std::cout, "\n")); + } catch (std::runtime_error const& ex) { + std::cerr << ex.what() << '\n'; + return EXIT_FAILURE; + } +} diff --git a/exploring-cpp-2e/chapter58/list5803.hpp b/exploring-cpp-2e/chapter58/list5803.hpp new file mode 100644 index 0000000..b3b96a7 --- /dev/null +++ b/exploring-cpp-2e/chapter58/list5803.hpp @@ -0,0 +1,41 @@ +// Listing 58-3. New Definition of an Artifact +#ifndef ARTIFACT_HPP_ +#define ARTIFACT_HPP_ + +#include +#include + +class artifact +{ +public: + typedef std::chrono::system_clock clock; + artifact() : name_{}, mod_time_{clock::time_point{}} {} + artifact(std::string const& name) + : name_{name}, mod_time_{get_mod_time()} + {} + + std::string const& name() const { return name_; } + clock::time_point mod_time() const { return mod_time_; } + + /// Build a target. + /// After completing the actions (not yet implemented), + /// update the modification time. + void build(); + + /// Look up the modification time of the artifact. + /// Return time_point{} if the artifact does not + /// exist (and therefore must be built) or if the time cannot + /// be obtained for any other reason. + /// Also see boost::file_system::last_write_time. + clock::time_point get_mod_time() + { + // Real programs should get this information from the + // operating system. This program returns the current time. + return clock::now(); + } +private: + std::string name_; + clock::time_point mod_time_; +}; + +#endif // ARTIFACT_HPP_ diff --git a/exploring-cpp-2e/chapter58/list5804.cpp b/exploring-cpp-2e/chapter58/list5804.cpp new file mode 100644 index 0000000..284f554 --- /dev/null +++ b/exploring-cpp-2e/chapter58/list5804.cpp @@ -0,0 +1,93 @@ +// Listing 58-4. Second Draft, Adding Modification Times to Artifacts +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "artifact.hpp" +#include "topological_sort.hpp" + +typedef std::size_t artifact_index; + +class dependency_graph +{ +public: + typedef std::unordered_map> graph_type; + + void store_dependency(artifact_index target, artifact_index dependency) + { + graph_[dependency].insert(target); + graph_[target]; // ensures that target is in the graph + } + + graph_type const& graph() const { return graph_; } + + template + void sort(OutIter sorted) + const + { + topological_sort(graph_, sorted); + } + +private: + graph_type graph_; +}; + +std::vector artifacts{}; +artifact_index lookup_artifact(std::string const& name) +{ + auto iter( std::find_if(artifacts.begin(), artifacts.end(), + [&name](artifact const& a) { return a.name() == name; }) + ); + if (iter != artifacts.end()) + return iter - artifacts.begin(); + // Artifact not found, so add it to the end. + artifacts.push_back(artifact{name}); + return artifacts.size() - 1; +} + +int main() +{ + dependency_graph graph{}; + + std::string line{}; + while (std::getline(std::cin, line)) + { + std::string target_name{}, dependency_name{}; + std::istringstream stream{line}; + if (stream >> target_name >> dependency_name) + { + artifact_index target{lookup_artifact(target_name)}; + artifact_index dependency{lookup_artifact(dependency_name)}; + graph.store_dependency(target, dependency); + } + else if (not target_name.empty()) + // Input line has a target with no dependency, + // so report an error. + std::cerr << "malformed input: target, " << target_name << + ", must be followed by a dependency name\n"; + // else ignore blank lines + } + + try { + // Get the sorted artifact indices in reverse order. + std::vector sorted{}; + graph.sort(std::back_inserter(sorted)); + // Then print the artifacts in the correct order. + for (auto it(sorted.rbegin()), end(sorted.rend()); + it != end; + ++it) + { + std::cout << artifacts.at(*it).name() << '\n'; + } + } catch (std::runtime_error const& ex) { + std::cerr << ex.what() << '\n'; + return EXIT_FAILURE; + } +} diff --git a/exploring-cpp-2e/chapter58/list5805.cpp b/exploring-cpp-2e/chapter58/list5805.cpp new file mode 100644 index 0000000..a121983 --- /dev/null +++ b/exploring-cpp-2e/chapter58/list5805.cpp @@ -0,0 +1,88 @@ +// Listing 58-5. Storing Pointers in the Dependency Graph +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "artifact.hpp" +#include "topological_sort.hpp" + +class dependency_graph +{ +public: + typedef std::unordered_map> graph_type; + + void store_dependency(artifact* target, artifact* dependency) + { + graph_[dependency].insert(target); + graph_[target]; // ensures that target is in the graph + } + + graph_type const& graph() const { return graph_; } + + template + void sort(OutIter sorted) + const + { + topological_sort(graph_, sorted); + } + +private: + graph_type graph_; +}; + +std::map artifacts{}; + +artifact* lookup_artifact(std::string const& name) +{ + auto a( artifacts.find(name) ); + if (a == artifacts.end()) + artifacts.emplace(name, artifact{name}); + return &artifacts[name]; +} + +int main() +{ + dependency_graph graph{}; + + std::string line{}; + while (std::getline(std::cin, line)) + { + std::string target_name{}, dependency_name{}; + std::istringstream stream{line}; + if (stream >> target_name >> dependency_name) + { + artifact* target{lookup_artifact(target_name)}; + artifact* dependency{lookup_artifact(dependency_name)}; + graph.store_dependency(target, dependency); + } + else if (not target_name.empty()) + // Input line has a target with no dependency, so report an error. + std::cerr << "malformed input: target, " << target_name << + ", must be followed by a dependency name\n"; + // else ignore blank lines + } + + try { + // Get the sorted artifacts in reverse order. + std::vector sorted{}; + graph.sort(std::back_inserter(sorted)); + // Then print the artifacts in the correct order. + for (auto it(sorted.rbegin()), end(sorted.rend()); + it != end; + ++it) + { + std::cout << (*it)->name() << '\n'; + } + } catch (std::runtime_error const& ex) { + std::cerr << ex.what() << '\n'; + return EXIT_FAILURE; + } +} diff --git a/exploring-cpp-2e/chapter58/topological_sort.hpp b/exploring-cpp-2e/chapter58/topological_sort.hpp new file mode 100644 index 0000000..1521142 --- /dev/null +++ b/exploring-cpp-2e/chapter58/topological_sort.hpp @@ -0,0 +1,66 @@ +// Listing 58-1. Topological Sort of a Directed Acyclic Graph +#ifndef TOPOLOGICAL_SORT_HPP_ +#define TOPOLOGICAL_SORT_HPP_ + +#include +#include + +/// Helper function for topological_sort(). +/// Finds all the nodes in the graph with no incoming edges, +/// that is, with empty values. Removes each one from the graph +/// and adds it to the set @p nodes. +/// @param[in,out] graph A map of node/set pairs +/// @param[in,out] nodes A queue of nodes with no incoming edges +template +void topsort_clean_graph(Graph& graph, Nodes& nodes) +{ + for (auto iter(graph.begin()), end(graph.end()); iter != end;) + { + if (iter->second.empty()) + { + nodes.push_back(iter->first); + graph.erase(iter++); // advance iterator before erase invalidates it + } + else + ++iter; + } +} + +/// Topological sort of a directed acyclic graph. +/// A graph is a map keyed by nodes, with sets of nodes as values. +/// Edges run from values to keys. The sorted list of nodes +/// is copied to an output iterator in reverse order. +/// @param graph The graph +/// @param sorted The output iterator +/// @throws std::runtime_error if the graph contains a cycle +/// @pre Graph::key_type == Graph::mapped_type::key_type +template +void topological_sort(Graph graph, OutIterator sorted) +{ + std::deque nodes{}; + // Start with the set of nodes with no incoming edges. + topsort_clean_graph(graph, nodes); + + while (not nodes.empty()) + { + // Grab the first node to process, output it to sorted, + // and remove it from the graph. + typename Graph::key_type n{nodes.front()}; + nodes.pop_front(); + *sorted = n; + ++sorted; + + // Erase n from the graph + for (auto& node : graph) + { + node.second.erase(n); + } + // After removing n, find any nodes that no longer + // have any incoming edges. + topsort_clean_graph(graph, nodes); + } + if (not graph.empty()) + throw std::invalid_argument("Dependency graph contains cycles"); +} + +#endif // TOPOLOGICAL_SORT_HPP_ diff --git a/exploring-cpp-2e/chapter59/all.cpp b/exploring-cpp-2e/chapter59/all.cpp new file mode 100644 index 0000000..dae841b --- /dev/null +++ b/exploring-cpp-2e/chapter59/all.cpp @@ -0,0 +1,157 @@ +// Assemble all the pieces of the pseudo-make program. +#include +#include +#include +#include +#include +#include +#include + +#include "artifact.hpp" + +#include "topological_sort.hpp" + +class dependency_graph +{ +public: + typedef std::unordered_map> graph_type; + + void store_dependency(artifact* target, artifact* dependency) + { + graph_[dependency].insert(target); + graph_[target]; // ensures that target is in the graph + } + + graph_type const& graph() const { return graph_; } + + template + void sort(OutIter sorted) + const + { + topological_sort(graph_, sorted); + } + +private: + graph_type graph_; +}; + +std::map artifacts{}; + +artifact* lookup_artifact(std::string const& name) +{ + auto a( artifacts.find(name) ); + if (a == artifacts.end()) + artifacts.emplace(name, artifact{name}); + return &artifacts[name]; +} + +// Listing 59-7. The variables.cpp File Implements the expand Function +#include "variables.hpp" + +variable_map global_variables{}; + +// Get a variable's value. Try the local variables first; if not found +// try the global variables. If still not found, define the name with +// an empty string and return an empty string. Subsequent lookups of +// the same name will find the empty string. Exercise for reader: +// print a message the first time the undefined variable's name +// is used. +std::string get_value(std::string const& name, variable_map const* local_variables) +{ + if (local_variables != nullptr) + { + variable_map::const_iterator iter{local_variables->find(name)}; + if (iter != local_variables->end()) + return iter->second; + } + return global_variables[name]; +} + +std::string expand(std::string str, variable_map const* local_variables) +{ + std::string::size_type start{0}; // start searching here + while (true) + { + // Find a dollar sign. + std::string::size_type pos{str.find('$', start)}; + if (pos == std::string::npos) + // No more dollar signs. + return str; + if (pos == str.size() - 1 or str[pos + 1] != '(') + // Not a variable reference. + // Skip the dollar sign, and keep searching. + start = pos + 1; + else + { + std::string::size_type end{str.find(')', pos)}; + if (end == std::string::npos) + // No closing parenthesis. + return str; + + // Get the variable name. + std::string varname{str.substr(pos + 2, end - pos - 2)}; + // Replace the entire variable reference. + std::string value{get_value(varname, local_variables)}; + str.replace(pos, end - pos + 1, value); + // Scan the replacement text for more variables. + start = pos; + } + } +} + +// Listing 59-4. Parsing Variable Definitions +void parse_graph(std::istream& in, dependency_graph& graph) +{ + std::string line{}; + while (std::getline(in, line)) + { + std::string target_name{}, dependency_name{}; + std::istringstream stream{line}; + if (stream >> target_name >> dependency_name) + { + artifact* target{lookup_artifact(expand(target_name, nullptr))}; + artifact* dependency{lookup_artifact(expand(dependency_name, nullptr))}; + graph.store_dependency(target, dependency); + } + else if (not target_name.empty()) + { + std::string::size_type equal{target_name.find('=')}; + if (equal == std::string::npos) + // Input line has a target with no dependency, + // so report an error. + std::cerr << "malformed input: target, " << target_name << + ", must be followed by a dependency name\n"; + else + { + std::string variable_name{target_name.substr(0, equal)}; + std::string variable_value{target_name.substr(equal+1)}; + global_variables[variable_name] = variable_value; + } + } + // else ignore blank lines + } +} + +int main() +{ + dependency_graph graph{}; + + parse_graph(std::cin, graph); + + try { + // Get the sorted artifacts in reverse order. + std::vector sorted; + graph.sort(std::back_inserter(sorted)); + + // Then print the artifacts in the correct order. + for (auto it(sorted.rbegin()), end(sorted.rend()); + it != end; + ++it) + { + std::cout << (*it)->name() << '\n'; + } + } catch (std::runtime_error const& ex) { + std::cerr << ex.what() << '\n'; + return EXIT_FAILURE; + } +} diff --git a/exploring-cpp-2e/chapter59/artifact.hpp b/exploring-cpp-2e/chapter59/artifact.hpp new file mode 100644 index 0000000..b06b018 --- /dev/null +++ b/exploring-cpp-2e/chapter59/artifact.hpp @@ -0,0 +1,61 @@ +// Listing 59-5. Adding Variable Storage and Lookup to the artifact Class +#ifndef ARTIFACT_HPP_ +#define ARTIFACT_HPP_ + +#include +#include + +#include "variables.hpp" + +class artifact +{ +public: + typedef std::chrono::system_clock clock; + artifact() + : name_{}, mod_time_{clock::time_point{}}, variables_{nullptr} + {} + artifact(std::string const& name) + : name_{name}, mod_time_{get_mod_time()}, variables_{nullptr} + {} + ~artifact() + { + delete variables_; + } + + std::string const& name() const { return name_; } + clock::time_point mod_time() const { return mod_time_; } + std::string expand(std::string str) const + { + return ::expand(str, variables_); + } + + /// Build a target. + /// After completing the actions (not yet implemented), + /// update the modification time. + void build(); + + /// Look up the modification time of the artifact. + /// Return time_point{} if the artifact does not + /// exist (and therefore must be built) or if the time cannot + /// be obtained for any other reason. + clock::time_point get_mod_time() + { + // Real programs should get this information from the + // operating system. This program returns the current time. + return clock::now(); + } + + /// Store a per-target variable. + void store_variable(std::string const& name, std::string const& value) + { + if (variables_ == nullptr) + variables_ = new variable_map; + (*variables_)[name] = value; + } +private: + std::string name_; + clock::time_point mod_time_; + variable_map* variables_; +}; + +#endif // ARTIFACT_HPP_ diff --git a/exploring-cpp-2e/chapter59/list5901.cpp b/exploring-cpp-2e/chapter59/list5901.cpp new file mode 100644 index 0000000..95c21a0 --- /dev/null +++ b/exploring-cpp-2e/chapter59/list5901.cpp @@ -0,0 +1,30 @@ +// Listing 59-1. Defining the list Class Template +template +class list +{ +public: + list() + : head_{nullptr}, tail_{nullptr}, size_{0} + {} + ~list() { clear(); } + + void clear(); ///< Erase all nodes in the list. Reset size to 0. + void push_back(T const& x); ///< Add to tail. + void pop_back(); ///< Erase from tail. + // Other useful functions omitted for brevity... +private: + class node + { + public: + node(T const& key) + : next_{nullptr}, prev_{nullptr}, value_{key} + {} + node* next_; + node* prev_; + T value_; + }; + + node* head_; ///< Start of the list + node* tail_; ///< End of the list + std::size_t size_; ///< Number of nodes in the list +}; diff --git a/exploring-cpp-2e/chapter59/list5902.cpp b/exploring-cpp-2e/chapter59/list5902.cpp new file mode 100644 index 0000000..738c6d8 --- /dev/null +++ b/exploring-cpp-2e/chapter59/list5902.cpp @@ -0,0 +1,29 @@ +// Listing 59-2. Implementing list::push_back and list::pop_back +template +void list::push_back(T const& x) +{ + node* n{new node{x}}; + if (tail_ == nullptr) + head_ = tail_ = n; + else + { + n->prev_ = tail_; + tail_->next = n; + } + ++size_; +} + +template +void list::pop_back() +{ + node* n{tail_}; + if (head_ == tail_) + head_ = tail_ = nullptr; + else + { + tail_ = tail_->prev_; + tail_->next_ = nullptr; + } + --size_; + delete n; +} diff --git a/exploring-cpp-2e/chapter59/list5903.cpp b/exploring-cpp-2e/chapter59/list5903.cpp new file mode 100644 index 0000000..cdc7857 --- /dev/null +++ b/exploring-cpp-2e/chapter59/list5903.cpp @@ -0,0 +1,34 @@ +// Listing 59-3. Expanding Variables +typedef std::map variable_map; +variable_map variables{}; + +std::string expand(std::string str) +{ + std::string::size_type start{0}; // start searching here + while (true) + { + // Find a dollar sign. + std::string::size_type pos{str.find('$', start)}; + if (pos == std::string::npos) + // No more dollar signs. + return str; + if (pos == str.size() - 1 or str[pos + 1] != '(') + // Not a variable reference. Skip the dollar sign, + // and keep searching. + start = pos + 1; + else + { + std::string::size_type end{str.find(')', pos)}; + if (end == std::string::npos) + // No closing parenthesis. + return str; + + // Get the variable name. + std::string varname{str.substr(pos + 2, end - pos - 2)}; + // Replace the entire variable reference. + str.replace(pos, end - pos + 1, variables[varname]); + // Scan the replacement text for more variables. + start = pos; + } + } +} diff --git a/exploring-cpp-2e/chapter59/list5904.cpp b/exploring-cpp-2e/chapter59/list5904.cpp new file mode 100644 index 0000000..c92b3ce --- /dev/null +++ b/exploring-cpp-2e/chapter59/list5904.cpp @@ -0,0 +1,56 @@ +// Listing 59-4. Parsing Variable Definitions +void parse_graph(std::istream& in, dependency_graph& graph) +{ + std::string line{}; + while (std::getline(in, line)) + { + std::string target_name{}, dependency_name{}; + std::istringstream stream{line}; + if (stream >> target_name >> dependency_name) + { + artifact* target{lookup_artifact(expand(target_name))}; + artifact* dependency{lookup_artifact(expand(dependency_name))}; + graph.store_dependency(target, dependency); + } + else if (not target_name.empty()) + { + std::string::size_type equal{target_name.find('=')}; + if (equal == std::string::npos) + // Input line has a target with no dependency, + // so report an error. + std::cerr << "malformed input: target, " << target_name << + ", must be followed by a dependency name\n"; + else + { + std::string variable_name{target_name.substr(0, equal)}; + std::string variable_value{target_name.substr(equal+1)}; + variables[variable_name] = variable_value; + } + } + // else ignore blank lines + } +} + +int main() +{ + dependency_graph graph{}; + + parse_graph(std::cin, graph); + + try { + // Get the sorted artifacts in reverse order. + std::vector sorted; + graph.sort(std::back_inserter(sorted)); + + // Then print the artifacts in the correct order. + for (auto it(sorted.rbegin()), end(sorted.rend()); + it != end; + ++it) + { + std::cout << (*it)->name() << '\n'; + } + } catch (std::runtime_error const& ex) { + std::cerr << ex.what() << '\n'; + return EXIT_FAILURE; + } +} diff --git a/exploring-cpp-2e/chapter59/list5905.hpp b/exploring-cpp-2e/chapter59/list5905.hpp new file mode 100644 index 0000000..b06b018 --- /dev/null +++ b/exploring-cpp-2e/chapter59/list5905.hpp @@ -0,0 +1,61 @@ +// Listing 59-5. Adding Variable Storage and Lookup to the artifact Class +#ifndef ARTIFACT_HPP_ +#define ARTIFACT_HPP_ + +#include +#include + +#include "variables.hpp" + +class artifact +{ +public: + typedef std::chrono::system_clock clock; + artifact() + : name_{}, mod_time_{clock::time_point{}}, variables_{nullptr} + {} + artifact(std::string const& name) + : name_{name}, mod_time_{get_mod_time()}, variables_{nullptr} + {} + ~artifact() + { + delete variables_; + } + + std::string const& name() const { return name_; } + clock::time_point mod_time() const { return mod_time_; } + std::string expand(std::string str) const + { + return ::expand(str, variables_); + } + + /// Build a target. + /// After completing the actions (not yet implemented), + /// update the modification time. + void build(); + + /// Look up the modification time of the artifact. + /// Return time_point{} if the artifact does not + /// exist (and therefore must be built) or if the time cannot + /// be obtained for any other reason. + clock::time_point get_mod_time() + { + // Real programs should get this information from the + // operating system. This program returns the current time. + return clock::now(); + } + + /// Store a per-target variable. + void store_variable(std::string const& name, std::string const& value) + { + if (variables_ == nullptr) + variables_ = new variable_map; + (*variables_)[name] = value; + } +private: + std::string name_; + clock::time_point mod_time_; + variable_map* variables_; +}; + +#endif // ARTIFACT_HPP_ diff --git a/exploring-cpp-2e/chapter59/list5906.hpp b/exploring-cpp-2e/chapter59/list5906.hpp new file mode 100644 index 0000000..ce699c3 --- /dev/null +++ b/exploring-cpp-2e/chapter59/list5906.hpp @@ -0,0 +1,18 @@ +// Listing 59-6. The variables.hpp File +#ifndef VARIABLES_HPP_ +#define VARIABLES_HPP_ + +#include +#include + +typedef std::map variable_map; +extern variable_map global_variables; + +/// Expand variables in a string using a local map +/// and the global map. +/// @param str The string to expand +/// @param local_variables The optional, local map; can be null +/// @return The expanded string +std::string expand(std::string str, variable_map const* local_variables); + +#endif // VARIABLES_HPP_ diff --git a/exploring-cpp-2e/chapter59/list5907.cpp b/exploring-cpp-2e/chapter59/list5907.cpp new file mode 100644 index 0000000..7069c1b --- /dev/null +++ b/exploring-cpp-2e/chapter59/list5907.cpp @@ -0,0 +1,53 @@ +// Listing 59-7. The variables.cpp File Implements the expand Function +#include "variables.hpp" + +variable_map global_variables{}; + +// Get a variable's value. Try the local variables first; if not found +// try the global variables. If still not found, define the name with +// an empty string and return an empty string. Subsequent lookups of +// the same name will find the empty string. Exercise for reader: +// print a message the first time the undefined variable's name +// is used. +std::string get_value(std::string const& name, variable_map const* local_variables) +{ + if (local_variables != nullptr) + { + variable_map::const_iterator iter{local_variables->find(name)}; + if (iter != local_variables->end()) + return iter->second; + } + return global_variables[name]; +} + +std::string expand(std::string str, variable_map const* local_variables) +{ + std::string::size_type start{0}; // start searching here + while (true) + { + // Find a dollar sign. + std::string::size_type pos{str.find('$', start)}; + if (pos == std::string::npos) + // No more dollar signs. + return str; + if (pos == str.size() - 1 or str[pos + 1] != '(') + // Not a variable reference. + // Skip the dollar sign, and keep searching. + start = pos + 1; + else + { + std::string::size_type end{str.find(')', pos)}; + if (end == std::string::npos) + // No closing parenthesis. + return str; + + // Get the variable name. + std::string varname{str.substr(pos + 2, end - pos - 2)}; + // Replace the entire variable reference. + std::string value{get_value(varname, local_variables)}; + str.replace(pos, end - pos + 1, value); + // Scan the replacement text for more variables. + start = pos; + } + } +} diff --git a/exploring-cpp-2e/chapter59/list5908.cpp b/exploring-cpp-2e/chapter59/list5908.cpp new file mode 100644 index 0000000..6f70c12 --- /dev/null +++ b/exploring-cpp-2e/chapter59/list5908.cpp @@ -0,0 +1,38 @@ +// Listing 59-8. Adding per-Target Variables to parse_graph +void parse_graph(std::istream& in, dependency_graph& graph) +{ + std::string line{}; + while (std::getline(in, line)) + { + std::string target_name{}, dependency_name{}; + std::istringstream stream{line}; + if (stream >> target_name >> dependency_name) + { + artifact* target{lookup_artifact(expand(target_name, 0))}; + std::string::size_type equal{dependency_name.find('=')}; + if (equal == std::string::npos) + { + // It's a dependency specification + artifact* dependency{lookup_artifact(target->expand(dependency_name))}; + graph.store_dependency(target, dependency); + } + else + // It's a target-specific variable + target->store_variable(dependency_name.substr(0, equal-1), + dependency_name.substr(equal+1)); + } + else if (not target_name.empty()) + { + std::string::size_type equal{target_name.find('=')}; + if (equal == std::string::npos) + // Input line has a target with no dependency, + // so report an error. + std::cerr << "malformed input: target, " << target_name << + ", must be followed by a dependency name\n"; + else + global_variables[target_name.substr(0, equal)] = + target_name.substr(equal+1); + } + // else ignore blank lines + } +} diff --git a/exploring-cpp-2e/chapter59/list5909.cpp b/exploring-cpp-2e/chapter59/list5909.cpp new file mode 100644 index 0000000..cc0f5a7 --- /dev/null +++ b/exploring-cpp-2e/chapter59/list5909.cpp @@ -0,0 +1,28 @@ +// Listing 59-9. Simple Wrapper for Dynamic Memory +#include + +class wrapper +{ +public: + wrapper(int x) : p_{new int{x}} {} + ~wrapper() { delete p_; } + int value() const { return *p_; } +private: + int* p_; +}; + +void print(wrapper w) +{ + std::cout << w.value() << '\n'; +} + +wrapper increment(wrapper w) +{ + return wrapper(w.value() + 1); +} + +int main() +{ + wrapper w{42}; + print(increment(w)); +} diff --git a/exploring-cpp-2e/chapter59/list5910.cpp b/exploring-cpp-2e/chapter59/list5910.cpp new file mode 100644 index 0000000..5e50bb6 --- /dev/null +++ b/exploring-cpp-2e/chapter59/list5910.cpp @@ -0,0 +1,40 @@ +// Listing 59-10. Making a Deep Copy +#include + +class wrapper +{ +public: + wrapper(int x) : p_{new int{x}} {} + wrapper(wrapper const& w) : p_{new int{w.value()}} {} + ~wrapper() { delete p_; } + wrapper& operator=(wrapper w) + { + swap(w); + return *this; + } + void swap(wrapper& w) + { + int* tmp{w.p_}; + w.p_ = p_; + p_ = tmp; + } + int value() const { return *p_; } +private: + int* p_; +}; + +void print(wrapper w) +{ + std::cout << w.value() << '\n'; +} + +wrapper increment(wrapper w) +{ + return wrapper{w.value() + 1}; +} + +int main() +{ + wrapper w{42}; + print(increment(w)); +} diff --git a/exploring-cpp-2e/chapter59/topological_sort.hpp b/exploring-cpp-2e/chapter59/topological_sort.hpp new file mode 100644 index 0000000..1521142 --- /dev/null +++ b/exploring-cpp-2e/chapter59/topological_sort.hpp @@ -0,0 +1,66 @@ +// Listing 58-1. Topological Sort of a Directed Acyclic Graph +#ifndef TOPOLOGICAL_SORT_HPP_ +#define TOPOLOGICAL_SORT_HPP_ + +#include +#include + +/// Helper function for topological_sort(). +/// Finds all the nodes in the graph with no incoming edges, +/// that is, with empty values. Removes each one from the graph +/// and adds it to the set @p nodes. +/// @param[in,out] graph A map of node/set pairs +/// @param[in,out] nodes A queue of nodes with no incoming edges +template +void topsort_clean_graph(Graph& graph, Nodes& nodes) +{ + for (auto iter(graph.begin()), end(graph.end()); iter != end;) + { + if (iter->second.empty()) + { + nodes.push_back(iter->first); + graph.erase(iter++); // advance iterator before erase invalidates it + } + else + ++iter; + } +} + +/// Topological sort of a directed acyclic graph. +/// A graph is a map keyed by nodes, with sets of nodes as values. +/// Edges run from values to keys. The sorted list of nodes +/// is copied to an output iterator in reverse order. +/// @param graph The graph +/// @param sorted The output iterator +/// @throws std::runtime_error if the graph contains a cycle +/// @pre Graph::key_type == Graph::mapped_type::key_type +template +void topological_sort(Graph graph, OutIterator sorted) +{ + std::deque nodes{}; + // Start with the set of nodes with no incoming edges. + topsort_clean_graph(graph, nodes); + + while (not nodes.empty()) + { + // Grab the first node to process, output it to sorted, + // and remove it from the graph. + typename Graph::key_type n{nodes.front()}; + nodes.pop_front(); + *sorted = n; + ++sorted; + + // Erase n from the graph + for (auto& node : graph) + { + node.second.erase(n); + } + // After removing n, find any nodes that no longer + // have any incoming edges. + topsort_clean_graph(graph, nodes); + } + if (not graph.empty()) + throw std::invalid_argument("Dependency graph contains cycles"); +} + +#endif // TOPOLOGICAL_SORT_HPP_ diff --git a/exploring-cpp-2e/chapter59/variables.hpp b/exploring-cpp-2e/chapter59/variables.hpp new file mode 100644 index 0000000..ce699c3 --- /dev/null +++ b/exploring-cpp-2e/chapter59/variables.hpp @@ -0,0 +1,18 @@ +// Listing 59-6. The variables.hpp File +#ifndef VARIABLES_HPP_ +#define VARIABLES_HPP_ + +#include +#include + +typedef std::map variable_map; +extern variable_map global_variables; + +/// Expand variables in a string using a local map +/// and the global map. +/// @param str The string to expand +/// @param local_variables The optional, local map; can be null +/// @return The expanded string +std::string expand(std::string str, variable_map const* local_variables); + +#endif // VARIABLES_HPP_ diff --git a/exploring-cpp-2e/chapter60/list6001.cpp b/exploring-cpp-2e/chapter60/list6001.cpp new file mode 100644 index 0000000..6480172 --- /dev/null +++ b/exploring-cpp-2e/chapter60/list6001.cpp @@ -0,0 +1,28 @@ +// Listing 60-1. Exposing How Strings Are Copied +#include +#include +#include + +class mystring : public std::string +{ +public: + mystring() : std::string{} { std::cout << "mystring()\n"; } + mystring(mystring const& copy) : std::string(copy) { + std::cout << "mystring copy(\"" << *this << "\")\n"; + } +}; + +std::vector read_data() +{ + std::vector strings{}; + mystring line{}; + while (std::getline(std::cin, line)) + strings.push_back(line); + return strings; +} + +int main() +{ + std::vector strings{}; + strings = read_data(); +} diff --git a/exploring-cpp-2e/chapter60/list6002.cpp b/exploring-cpp-2e/chapter60/list6002.cpp new file mode 100644 index 0000000..7e015e7 --- /dev/null +++ b/exploring-cpp-2e/chapter60/list6002.cpp @@ -0,0 +1,33 @@ +// Listing 60-2. Moving Strings Instead of Copying Them +#include +#include +#include +#include + +class mystring : public std::string +{ +public: + mystring() : std::string() { std::cout << "mystring()\n"; } + mystring(mystring const& copy) : std::string(copy) { + std::cout << "mystring copy(\"" << *this << "\")\n"; + } + mystring(mystring&& move) noexcept + : std::string(std::move(move)) { + std::cout << "mystring move(\"" << *this << "\")\n"; + } +}; + +std::vector read_data() +{ + std::vector strings; + mystring line; + while (std::getline(std::cin, line)) + strings.push_back(std::move(line)); + return strings; +} + +int main() +{ + std::vector strings; + strings = read_data(); +} diff --git a/exploring-cpp-2e/chapter60/list6003.cpp b/exploring-cpp-2e/chapter60/list6003.cpp new file mode 100644 index 0000000..6e467b4 --- /dev/null +++ b/exploring-cpp-2e/chapter60/list6003.cpp @@ -0,0 +1,23 @@ +// Listing 60-3. Adding a Move Constructor to the artifact Class +class artifact { +public: + typedef std::chrono::system_clock clock; + artifact(artifact&& source) noexcept + : name_{std::move(source.name_)}, + mod_time_{std::move(source.mod_time_)}, + variables_{source.variables_} + { + source.variables_ = nullptr; + } + + artifact& operator=(artifact&& source) noexcept + { + delete variables_; + variables_ = source.variables_; + source.variables_ = nullptr; + name_ = std::move(source.name_); + mod_time_ = std::move(source.mod_time_); + return *this; + } + ... rest of artifact ... +}; diff --git a/exploring-cpp-2e/chapter60/list6004.cpp b/exploring-cpp-2e/chapter60/list6004.cpp new file mode 100644 index 0000000..045116e --- /dev/null +++ b/exploring-cpp-2e/chapter60/list6004.cpp @@ -0,0 +1,25 @@ +// Listing 60-4. Examining Expression Categories +#include +#include + +void print(std::string&& move) +{ + std::cout << "move: " << std::move(move) << '\n'; +} + +void print(std::string const& copy) +{ + std::cout << "copy: " << copy << '\n'; +} + +int main() +{ + std::string a{"a"}, b{"b"}, c{"c"}; + + print(a); + print(a + b); + print(std::move(a)); + print(std::move(a + b)); + print(a + std::move(b)); + print(a + b + c); +} diff --git a/exploring-cpp-2e/chapter61/list6101.cpp b/exploring-cpp-2e/chapter61/list6101.cpp new file mode 100644 index 0000000..2f2641a --- /dev/null +++ b/exploring-cpp-2e/chapter61/list6101.cpp @@ -0,0 +1,31 @@ +// Listing 61-1. Silly Program to Demonstrate Memory Leaks +#include +#include +#include + +int* read(std::istream& in) +{ + int value{}; + if (in >> value) + return new int{value}; + else + return nullptr; +} + +int divide(int x, int y) +{ + return x / y; +} + +int main() +{ + std::cout << "Enter pairs of numbers, and I will divide them.\n"; + std::string line{}; + while(std::getline(std::cin, line)) + { + std::istringstream input{line}; + if (int* x{read(input)}) + if (int* y{read(input)}) + std::cout << divide(*x, *y) << '\n'; + } +} diff --git a/exploring-cpp-2e/chapter61/list6102.cpp b/exploring-cpp-2e/chapter61/list6102.cpp new file mode 100644 index 0000000..66f350d --- /dev/null +++ b/exploring-cpp-2e/chapter61/list6102.cpp @@ -0,0 +1,37 @@ +// Listing 61-2. Adding delete Expressions to the Silly Program +#include +#include +#include + +int* read(std::istream& in) +{ + int value{}; + if (in >> value) + return new int{value}; + else + return nullptr; +} + +int divide(int x, int y) +{ + return x / y; +} + +int main() +{ + std::cout << "Enter pairs of numbers, and I will divide them.\n"; + std::string line{}; + while(std::getline(std::cin, line)) + { + std::istringstream input{line}; + if (int* x{read(input)}) + { + if (int* y{read(input)}) + { + std::cout << divide(*x, *y) << '\n'; + delete y; + } + delete x; + } + } +} diff --git a/exploring-cpp-2e/chapter61/list6103.cpp b/exploring-cpp-2e/chapter61/list6103.cpp new file mode 100644 index 0000000..3f544eb --- /dev/null +++ b/exploring-cpp-2e/chapter61/list6103.cpp @@ -0,0 +1,46 @@ +// Listing 61-3. Demonstrating Issues with Exceptions and Dynamic Memory +#include +#include +#include +#include + +int* read(std::istream& in) +{ + int value{}; + if (in >> value) + return new int{value}; + else + return nullptr; +} + +int divide(int x, int y) +{ + if (y == 0) + throw std::runtime_error{"integer divide by zero"}; + else if (x < y) + throw std::underflow_error{"result is less than 1"}; + else + return x / y; +} + +int main() +{ + std::cout << "Enter pairs of numbers, and I will divide them.\n"; + std::string line{}; + while(std::getline(std::cin, line)) + try + { + std::istringstream input{line}; + if (int* x{read(input)}) + { + if (int* y{read(input)}) + { + std::cout << divide(*x, *y) << '\n'; + delete y; + } + delete x; + } + } catch (std::exception const& ex) { + std::cout << ex.what() << '\n'; + } +} diff --git a/exploring-cpp-2e/chapter61/list6104.cpp b/exploring-cpp-2e/chapter61/list6104.cpp new file mode 100644 index 0000000..fb0b037 --- /dev/null +++ b/exploring-cpp-2e/chapter61/list6104.cpp @@ -0,0 +1,38 @@ +// Listing 61-4. Using the unique_ptr Class Template +#include +#include + +class see_me +{ +public: + see_me(int x) : x_{x} { std::cout << "see_me(" << x_ << ")\n"; } + ~see_me() { std::cout << "~see_me(" << x_ << ")\n"; } + int value() const { return x_; } +private: + int x_; +}; + +std::unique_ptr nothing(std::unique_ptr&& arg) +{ + return std::move(arg); +} + +template +std::unique_ptr make(int x) +{ + return std::unique_ptr{new T{x}}; +} + +int main() +{ + std::cout << "program begin...\n"; + std::unique_ptr sm{make(42)}; + std::unique_ptr other; + other = nothing(std::move(sm)); + if (sm.get() == nullptr) + std::cout << "sm is null, having lost ownership of its pointer\n"; + if (other.get() != nullptr) + std::cout << "other now has ownership of the int, " << + other->value() << '\n'; + std::cout << "program ends...\n"; +} diff --git a/exploring-cpp-2e/chapter61/list6105.cpp b/exploring-cpp-2e/chapter61/list6105.cpp new file mode 100644 index 0000000..dc43679 --- /dev/null +++ b/exploring-cpp-2e/chapter61/list6105.cpp @@ -0,0 +1,43 @@ +// Listing 61-5. Fixing Memory Leaks +#include +#include +#include +#include +#include + +std::unique_ptr read(std::istream& in) +{ + int value; + if (in >> value) + return std::unique_ptr{new int{value}}; + else + return std::unique_ptr{}; +} + +int divide(int x, int y) +{ + if (y == 0) + throw std::runtime_error("integer divide by zero"); + else if (x < y) + throw std::underflow_error("result is less than 1"); + else + return x / y; +} + +int main() +{ + std::cout << "Enter pairs of numbers, and I will divide them.\n"; + std::string line{}; + while(std::getline(std::cin, line)) + try + { + std::istringstream input{line}; + if (std::unique_ptr x{read(input)}) + { + if (std::unique_ptr y{read(input)}) + std::cout << divide(*x, *y) << '\n'; + } + } catch (std::exception const& ex) { + std::cout << ex.what() << '\n'; + } +} diff --git a/exploring-cpp-2e/chapter61/list6106.cpp b/exploring-cpp-2e/chapter61/list6106.cpp new file mode 100644 index 0000000..f87a765 --- /dev/null +++ b/exploring-cpp-2e/chapter61/list6106.cpp @@ -0,0 +1,33 @@ +// Listing 61-6. Demonstrating Constructors That Throw Exceptions +#include + +class see_me +{ +public: + see_me(int x) : x_{x} { std::cout << "see_me(" << x_ << ")\n"; } + ~see_me() { std::cout << "~see_me(" << x_ << ")\n"; } +private: + int x_; +}; + +class bomb : public see_me +{ +public: + bomb() : see_me{1}, a_{new see_me{2}} { throw 0; } + ~bomb() { + delete a_; + } +private: + see_me *a_; +}; + +int main() +{ + bomb *b{nullptr}; + try { + b = new bomb; + } catch(int) { + if (b == nullptr) + std::cout << "b is null\n"; + } +} diff --git a/exploring-cpp-2e/chapter61/list6107.cpp b/exploring-cpp-2e/chapter61/list6107.cpp new file mode 100644 index 0000000..6e7517e --- /dev/null +++ b/exploring-cpp-2e/chapter61/list6107.cpp @@ -0,0 +1,32 @@ +// Listing 61-7. Using unique_ptr in bomb +#include +#include + +class see_me +{ +public: + see_me(int x) : x_{x} { std::cout << "see_me(" << x_ << ")\n"; } + ~see_me() { std::cout << "~see_me(" << x_ << ")\n"; } +private: + int x_; +}; + +class bomb : public see_me +{ +public: + bomb() : see_me{1}, a_{new see_me{2}} { throw 0; } + ~bomb() {} +private: + std::unique_ptr a_; +}; + +int main() +{ + bomb *b{nullptr}; + try { + b = new bomb; + } catch(int) { + if (b == nullptr) + std::cout << "b is null\n"; + } +} diff --git a/exploring-cpp-2e/chapter61/list6108.cpp b/exploring-cpp-2e/chapter61/list6108.cpp new file mode 100644 index 0000000..37b5c3f --- /dev/null +++ b/exploring-cpp-2e/chapter61/list6108.cpp @@ -0,0 +1,30 @@ +// Listing 61-8. Mystery Program That Uses unique_ptr +#include +#include + +class mystery +{ +public: + mystery() {} + mystery(mystery const&) { throw "oops"; } +}; + +class demo +{ +public: + demo(int* x, mystery m, int* y) : x_{x}, m_{m}, y_{y} {} + demo(demo const&) = delete; + demo& operator=(demo const&) = delete; + int x() const { return *x_; } + int y() const { return *y_; } +private: + std::unique_ptr x_; + mystery m_; + std::unique_ptr y_; +}; + +int main() +{ + demo d{new int{42}, mystery{}, new int{24}}; + std::cout << d.x() << d.y() << '\n'; +} diff --git a/exploring-cpp-2e/chapter62/list6201.cpp b/exploring-cpp-2e/chapter62/list6201.cpp new file mode 100644 index 0000000..089c3e3 --- /dev/null +++ b/exploring-cpp-2e/chapter62/list6201.cpp @@ -0,0 +1,18 @@ +// Listing 62-1. Array Type in Function Parameters +#include + +int sum(int* array, int size); + +int main() +{ + int data[5]{ 1, 2, 3, 4, 5 }; + std::cout << sum(data, 5) << '\n'; +} + +int sum(int array[], int size) +{ + int result{0}; + while (size-- != 0) + result += array[size]; + return result; +} diff --git a/exploring-cpp-2e/chapter62/list6202.cpp b/exploring-cpp-2e/chapter62/list6202.cpp new file mode 100644 index 0000000..bc95b64 --- /dev/null +++ b/exploring-cpp-2e/chapter62/list6202.cpp @@ -0,0 +1,15 @@ +// Listing 62-2. Deliberate Errors with new and delete +#include + +int main() +{ + int* p{ new int[10] }; + delete p; + p = new int; + delete[] p; + std::unique_ptr up{ new int[10] }; + up.reset(); + std::unique_ptr upa{ new int }; + upa.reset(); +} + diff --git a/exploring-cpp-2e/chapter62/list6203.cpp b/exploring-cpp-2e/chapter62/list6203.cpp new file mode 100644 index 0000000..5d49893 --- /dev/null +++ b/exploring-cpp-2e/chapter62/list6203.cpp @@ -0,0 +1,12 @@ +// Listing 62-3. Echoing Command-Line Arguments +#include + +int main(int argc, char* argv[]) +{ + char const* separator{""}; + while (--argc != 0) + { + std::cout << separator << *++argv; + separator = " "; + } +} diff --git a/exploring-cpp-2e/chapter62/list6204.cpp b/exploring-cpp-2e/chapter62/list6204.cpp new file mode 100644 index 0000000..c621c6a --- /dev/null +++ b/exploring-cpp-2e/chapter62/list6204.cpp @@ -0,0 +1,44 @@ +// Listing 62-4. Copying a File Named on the Command Line +#include +#include +#include +#include + +int main(int argc, char* argv[]) +{ + if (argc != 3) + { + std::cerr << "usage: " << argv[0] << " INPUT OUTPUT\n"; + return EXIT_FAILURE; + } + std::ifstream input{argv[1]}; + if (not input) + { + std::perror(argv[1]); + return EXIT_FAILURE; + } + std::ofstream output{argv[2]}; + if (not output) + { + std::perror(argv[2]); + return EXIT_FAILURE; + } + + input.exceptions(input.badbit); // throw for serious errors + output.exceptions(output.failbit); // throw for any error + + try + { + // Lots of ways to copy: use std::copy, use a loop to read & write + // The following is a little-known technique that is probably fastest. + output << input.rdbuf(); + output.close(); + input.close(); + } + catch (std::ios_base::failure const& ex) + { + std::cerr << "Can’t copy " << argv[1] << " to " << argv[2] << ": " << + ex.what() << '\n'; + return EXIT_FAILURE; + } +} diff --git a/exploring-cpp-2e/chapter62/list6205.cpp b/exploring-cpp-2e/chapter62/list6205.cpp new file mode 100644 index 0000000..ce1462c --- /dev/null +++ b/exploring-cpp-2e/chapter62/list6205.cpp @@ -0,0 +1,10 @@ +// Listing 62-5. Using Pointer Arithmetic to Determine the Length of a C String +#include + +std::size_t my_std_strlen(char const* str) +{ + char const* start{str}; // remember the start of the string + while (*str != 0) // while not at the end of the string + ++str; // advance to the next character + return str - start; // compute string length by subtracting pointers +} diff --git a/exploring-cpp-2e/chapter63/all.cpp b/exploring-cpp-2e/chapter63/all.cpp new file mode 100644 index 0000000..f1c66cb --- /dev/null +++ b/exploring-cpp-2e/chapter63/all.cpp @@ -0,0 +1,206 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "artifact.hpp" +#include "artifact_hash.hpp" +#include "artifact_impl.hpp" +#include "depgraph.hpp" // Listing 58-5 +#include "variables.hpp" // Listing 59-6 + +// Listing 59-7. The variables.cpp File Implements the expand Function +variable_map global_variables{}; + +// Get a variable's value. Try the local variables first; if not found +// try the global variables. If still not found, define the name with +// an empty string and return an empty string. Subsequent lookups of +// the same name will find the empty string. Exercise for reader: +// print a message the first time the undefined variable's name +// is used. +std::string get_value(std::string const& name, variable_map const* local_variables) +{ + if (local_variables != nullptr) + { + variable_map::const_iterator iter{local_variables->find(name)}; + if (iter != local_variables->end()) + return iter->second; + } + return global_variables[name]; +} + +std::string expand(std::string str, variable_map const* local_variables) +{ + std::string::size_type start{0}; // start searching here + while (true) + { + // Find a dollar sign. + std::string::size_type pos{str.find('$', start)}; + if (pos == std::string::npos) + // No more dollar signs. + return str; + if (pos == str.size() - 1 or str[pos + 1] != '(') + // Not a variable reference. + // Skip the dollar sign, and keep searching. + start = pos + 1; + else + { + std::string::size_type end{str.find(')', pos)}; + if (end == std::string::npos) + // No closing parenthesis. + return str; + + // Get the variable name. + std::string varname{str.substr(pos + 2, end - pos - 2)}; + // Replace the entire variable reference. + std::string value{get_value(varname, local_variables)}; + str.replace(pos, end - pos + 1, value); + // Scan the replacement text for more variables. + start = pos; + } + } +} + +artifact_impl::artifact_impl() +: name_{}, mod_time_{clock::time_point{}}, variables_{} +{} + +artifact_impl::artifact_impl(std::string const& name) +: name_{name}, mod_time_{get_mod_time()}, variables_{} +{} + +std::string artifact_impl::expand(std::string str) +const +{ + return ::expand(str, variables_.get()); +} + +void artifact_impl::build() +{ + std::cout << name() << '\n'; +} + +artifact::clock::time_point artifact_impl::get_mod_time() +{ + return clock::now(); +} + +void artifact_impl::store_variable(std::string const& name, std::string const& value) +{ + if (variables_ == nullptr) + variables_.reset(new variable_map); + (*variables_)[name] = value; +} + +// Listing 63-4. Implementing the artifact Class + +artifact::artifact() : pimpl_{std::make_shared()} {} + +artifact::artifact(std::string const& name) +: pimpl_(std::make_shared(name)) +{} + +std::string const& artifact::name() +const +{ + return pimpl_->name(); +} + +artifact::clock::time_point artifact::mod_time() +const +{ + return pimpl_->mod_time(); +} + +std::string artifact::expand(std::string str) +const +{ + return pimpl_->expand(str); +} + +void artifact::build() +{ + pimpl_->build(); +} + +artifact::clock::time_point artifact::get_mod_time() +{ + return pimpl_->get_mod_time(); +} + +void artifact::store_variable(std::string const& name, std::string const& value) +{ + pimpl_->store_variable(name, value); +} + +// Listing 63-6. Rewriting the Program to Use the New artifact Value Class +void parse_graph(std::istream& in, dependency_graph& graph) +{ + std::map artifacts{}; + std::string line{}; + while (std::getline(in, line)) + { + std::string target_name{}, dependency_name{}; + std::istringstream stream{line}; + if (stream >> target_name >> dependency_name) + { + artifact target{expand(target_name, nullptr)}; + if (artifacts.find(target.name()) == artifacts.end()) + artifacts.emplace(target.name(), target); + std::string::size_type equal{dependency_name.find('=')}; + if (equal == std::string::npos) + { + // It's a dependency specification + artifact dependency{target.expand(dependency_name)}; + if (artifacts.find(dependency.name()) == artifacts.end()) + artifacts.emplace(dependency.name(), dependency); + graph.store_dependency(target, dependency); + } + else + // It's a target-specific variable + target.store_variable(dependency_name.substr(0, equal-1), + dependency_name.substr(equal+1)); + } + else if (not target_name.empty()) + { + std::string::size_type equal{target_name.find('=')}; + if (equal == std::string::npos) + // Input line has a target with no dependency, + // so report an error. + std::cerr << "malformed input: target, " << target_name << + ", must be followed by a dependency name\n"; + else + global_variables[target_name.substr(0, equal)] = + target_name.substr(equal+1); + } + // else ignore blank lines + } +} + +int main() +{ + dependency_graph graph{}; + + parse_graph(std::cin, graph); + graph.dump(); + + try { + // Get the sorted artifacts in reverse order. + std::vector sorted{}; + graph.sort(std::back_inserter(sorted)); + + // Then print the artifacts in the correct order. + for (auto it(sorted.rbegin()), end(sorted.rend()); + it != end; + ++it) + { + std::cout << it->name() << '\n'; + } + } catch (std::runtime_error const& ex) { + std::cerr << ex.what() << '\n'; + return EXIT_FAILURE; + } +} diff --git a/exploring-cpp-2e/chapter63/artifact.hpp b/exploring-cpp-2e/chapter63/artifact.hpp new file mode 100644 index 0000000..bd88d77 --- /dev/null +++ b/exploring-cpp-2e/chapter63/artifact.hpp @@ -0,0 +1,39 @@ +// Listing 63-3. Defining an artifact Pimpl Wrapper Class +#ifndef ARTIFACT_HPP_ +#define ARTIFACT_HPP_ + +#include +#include +#include + +class artifact_impl; + +class artifact +{ +public: + typedef std::chrono::system_clock clock; + artifact(); + artifact(std::string const& name); + artifact(artifact const&) = default; + ~artifact() = default; + artifact& operator=(artifact const&) = default; + + std::string const& name() const; + clock::time_point mod_time() const; + std::string expand(std::string str) const; + + void build(); + clock::time_point get_mod_time(); + + void store_variable(std::string const& name, std::string const& value); + +private: + std::shared_ptr pimpl_; +}; + +inline bool operator<(artifact const& a, artifact const& b) +{ + return a.name() < b.name(); +} + +#endif // ARTIFACT_HPP_ diff --git a/exploring-cpp-2e/chapter63/artifact_hash.hpp b/exploring-cpp-2e/chapter63/artifact_hash.hpp new file mode 100644 index 0000000..81bca99 --- /dev/null +++ b/exploring-cpp-2e/chapter63/artifact_hash.hpp @@ -0,0 +1,38 @@ +#ifndef ARTIFACT_HASH_HPP_ +#define ARTIFACT_HASH_HPP_ + +#include +#include + +#include "artifact.hpp" + +namespace std +{ + +/** Hash an artifact so it can be used in a unordered container. */ +template<> +struct hash : std::hash +{ + /** Hash an artifact by hashing its name */ + std::size_t operator()(artifact const& a) const + { + return static_cast const&>(*this)(a.name()); + } +}; + +template<> +struct equal_to +{ + typedef artifact first_argument_type; + typedef artifact second_argument_type; + typedef bool result_type; + + result_type operator()(artifact const& a, artifact const& b) const + { + return a.name() == b.name(); + } +}; + +} // namespace + +#endif diff --git a/exploring-cpp-2e/chapter63/artifact_impl.hpp b/exploring-cpp-2e/chapter63/artifact_impl.hpp new file mode 100644 index 0000000..51b9b30 --- /dev/null +++ b/exploring-cpp-2e/chapter63/artifact_impl.hpp @@ -0,0 +1,36 @@ +// Listing 63-5. Defining the Artifact Implementation Class +#ifndef ARTIFACT_IMPL_HPP_ +#define ARTIFACT_IMPL_HPP_ + +#include +#include +#include +#include +#include "variables.hpp" + +class artifact_impl +{ +public: + typedef std::chrono::system_clock clock; + artifact_impl(); + artifact_impl(std::string const& name); + artifact_impl(artifact_impl&&) = default; + artifact_impl(artifact_impl const&) = delete; + ~artifact_impl() = default; + artifact_impl& operator=(artifact_impl&&) = default; + artifact_impl& operator=(artifact_impl&) = delete; + + std::string const& name() const { return name_; } + clock::time_point mod_time() const { return mod_time_; } + + std::string expand(std::string str) const; + void build(); + clock::time_point get_mod_time(); + void store_variable(std::string const& name, std::string const& value); +private: + std::string name_; + clock::time_point mod_time_; + std::unique_ptr variables_; +}; + +#endif // ARTIFACT_IMPL_HPP_ diff --git a/exploring-cpp-2e/chapter63/depgraph.hpp b/exploring-cpp-2e/chapter63/depgraph.hpp new file mode 100644 index 0000000..f781245 --- /dev/null +++ b/exploring-cpp-2e/chapter63/depgraph.hpp @@ -0,0 +1,47 @@ +#ifndef DEPGRAPH_HPP_ +#define DEPGRAPH_HPP_ + +#include +#include + +#include "artifact.hpp" +#include "topological_sort.hpp" + +/// Dependency graph. +/// From Listing 58-5 +class dependency_graph +{ +public: + typedef std::unordered_map> graph_type; + + void store_dependency(artifact target, artifact dependency) + { + graph_[dependency].insert(target); + graph_[target]; // ensures that target is in the graph + } + + graph_type const& graph() const { return graph_; } + + template + void sort(OutIter sorted) + const + { + topological_sort(graph_, sorted); + } + + void dump() + { + for (auto const& target : graph()) { + std::cout << target.first.name() << ": "; + for (auto const& dep : target.second) + std::cout << dep.name(); + std::cout << '\n'; + } + } + +private: + graph_type graph_; +}; + +#endif + diff --git a/exploring-cpp-2e/chapter63/list6301.cpp b/exploring-cpp-2e/chapter63/list6301.cpp new file mode 100644 index 0000000..bef6e3b --- /dev/null +++ b/exploring-cpp-2e/chapter63/list6301.cpp @@ -0,0 +1,30 @@ +// Listing 63-1. Working with shared_ptr +#include +#include +#include + +class see_me +{ +public: + see_me(int x) : x_{x} { std::cout << "see_me(" << x_ << ")\n"; } + ~see_me() { std::cout << "~see_me(" << x_ << ")\n"; } + int value() const { return x_; } +private: + int x_; +}; + +std::shared_ptr does_this_work(std::shared_ptr x) +{ + std::shared_ptr y{x}; + return y; +} + +int main() +{ + std::shared_ptr a{}, b{}; + a = std::make_shared(42); + b = does_this_work(a); + std::vector> v{}; + v.push_back(a); + v.push_back(b); +} diff --git a/exploring-cpp-2e/chapter63/list6302.cpp b/exploring-cpp-2e/chapter63/list6302.cpp new file mode 100644 index 0000000..5115c17 --- /dev/null +++ b/exploring-cpp-2e/chapter63/list6302.cpp @@ -0,0 +1,14 @@ +// Listing 63-2. Using Smart Pointers to Manage Artifacts +std::map> artifacts; + +std::shared_ptr +lookup_artifact(std::string const& name) +{ + std::shared_ptr a{artifacts[name]}; + if (a.get() == nullptr) + { + a = std::make_shared(name); + artifacts[name] = a; + } + return a; +} diff --git a/exploring-cpp-2e/chapter63/list6303.hpp b/exploring-cpp-2e/chapter63/list6303.hpp new file mode 100644 index 0000000..bd88d77 --- /dev/null +++ b/exploring-cpp-2e/chapter63/list6303.hpp @@ -0,0 +1,39 @@ +// Listing 63-3. Defining an artifact Pimpl Wrapper Class +#ifndef ARTIFACT_HPP_ +#define ARTIFACT_HPP_ + +#include +#include +#include + +class artifact_impl; + +class artifact +{ +public: + typedef std::chrono::system_clock clock; + artifact(); + artifact(std::string const& name); + artifact(artifact const&) = default; + ~artifact() = default; + artifact& operator=(artifact const&) = default; + + std::string const& name() const; + clock::time_point mod_time() const; + std::string expand(std::string str) const; + + void build(); + clock::time_point get_mod_time(); + + void store_variable(std::string const& name, std::string const& value); + +private: + std::shared_ptr pimpl_; +}; + +inline bool operator<(artifact const& a, artifact const& b) +{ + return a.name() < b.name(); +} + +#endif // ARTIFACT_HPP_ diff --git a/exploring-cpp-2e/chapter63/list6304.cpp b/exploring-cpp-2e/chapter63/list6304.cpp new file mode 100644 index 0000000..4fe87f0 --- /dev/null +++ b/exploring-cpp-2e/chapter63/list6304.cpp @@ -0,0 +1,42 @@ +// Listing 63-4. Implementing the artifact Class +#include "artifact.hpp" +#include "artifact_impl.hpp" + +artifact::artifact() : pimpl_{std::make_shared()} {} + +artifact::artifact(std::string const& name) +: pimpl_(std::make_shared(name)) +{} + +std::string const& artifact::name() +const +{ + return pimpl_->name(); +} + +artifact::clock::time_point artifact::mod_time() +const +{ + return pimpl_->mod_time(); +} + +std::string artifact::expand(std::string str) +const +{ + return pimpl_->expand(str); +} + +void artifact::build() +{ + pimpl_->build(); +} + +artifact::clock::time_point artifact::get_mod_time() +{ + return pimpl_->get_mod_time(); +} + +void artifact::store_variable(std::string const& name, std::string const& value) +{ + pimpl_->store_variable(name, value); +} diff --git a/exploring-cpp-2e/chapter63/list6305.hpp b/exploring-cpp-2e/chapter63/list6305.hpp new file mode 100644 index 0000000..51b9b30 --- /dev/null +++ b/exploring-cpp-2e/chapter63/list6305.hpp @@ -0,0 +1,36 @@ +// Listing 63-5. Defining the Artifact Implementation Class +#ifndef ARTIFACT_IMPL_HPP_ +#define ARTIFACT_IMPL_HPP_ + +#include +#include +#include +#include +#include "variables.hpp" + +class artifact_impl +{ +public: + typedef std::chrono::system_clock clock; + artifact_impl(); + artifact_impl(std::string const& name); + artifact_impl(artifact_impl&&) = default; + artifact_impl(artifact_impl const&) = delete; + ~artifact_impl() = default; + artifact_impl& operator=(artifact_impl&&) = default; + artifact_impl& operator=(artifact_impl&) = delete; + + std::string const& name() const { return name_; } + clock::time_point mod_time() const { return mod_time_; } + + std::string expand(std::string str) const; + void build(); + clock::time_point get_mod_time(); + void store_variable(std::string const& name, std::string const& value); +private: + std::string name_; + clock::time_point mod_time_; + std::unique_ptr variables_; +}; + +#endif // ARTIFACT_IMPL_HPP_ diff --git a/exploring-cpp-2e/chapter63/list6306.cpp b/exploring-cpp-2e/chapter63/list6306.cpp new file mode 100644 index 0000000..8e0b7f6 --- /dev/null +++ b/exploring-cpp-2e/chapter63/list6306.cpp @@ -0,0 +1,81 @@ +// Listing 63-6. Rewriting the Program to Use the New artifact Value Class +#include +#include +#include +#include +#include +#include +#include + +#include "artifact.hpp" +#include "artifact_hash.hpp" +#include "depgraph.hpp" // Listing 58-5 +#include "variables.hpp" // Listing 59-6 + + +void parse_graph(std::istream& in, dependency_graph& graph) +{ + std::map artifacts{}; + std::string line{}; + while (std::getline(in, line)) + { + std::string target_name{}, dependency_name{}; + std::istringstream stream{line}; + if (stream >> target_name >> dependency_name) + { + artifact target{expand(target_name, nullptr)}; + if (artifacts.find(target.name()) == artifacts.end()) + artifacts.emplace(target.name(), target); + std::string::size_type equal{dependency_name.find('=')}; + if (equal == std::string::npos) + { + // It's a dependency specification + artifact dependency{target.expand(dependency_name)}; + if (artifacts.find(dependency.name()) == artifacts.end()) + artifacts.emplace(dependency.name(), dependency); + graph.store_dependency(target, dependency); + } + else + // It's a target-specific variable + target.store_variable(dependency_name.substr(0, equal-1), + dependency_name.substr(equal+1)); + } + else if (not target_name.empty()) + { + std::string::size_type equal{target_name.find('=')}; + if (equal == std::string::npos) + // Input line has a target with no dependency, + // so report an error. + std::cerr << "malformed input: target, " << target_name << + ", must be followed by a dependency name\n"; + else + global_variables[target_name.substr(0, equal)] = + target_name.substr(equal+1); + } + // else ignore blank lines + } +} + +int main() +{ + dependency_graph graph{}; + + parse_graph(std::cin, graph); + + try { + // Get the sorted artifacts in reverse order. + std::vector sorted{}; + graph.sort(std::back_inserter(sorted)); + + // Then print the artifacts in the correct order. + for (auto it(sorted.rbegin()), end(sorted.rend()); + it != end; + ++it) + { + std::cout << it->name() << '\n'; + } + } catch (std::runtime_error const& ex) { + std::cerr << ex.what() << '\n'; + return EXIT_FAILURE; + } +} diff --git a/exploring-cpp-2e/chapter63/topological_sort.hpp b/exploring-cpp-2e/chapter63/topological_sort.hpp new file mode 100644 index 0000000..1521142 --- /dev/null +++ b/exploring-cpp-2e/chapter63/topological_sort.hpp @@ -0,0 +1,66 @@ +// Listing 58-1. Topological Sort of a Directed Acyclic Graph +#ifndef TOPOLOGICAL_SORT_HPP_ +#define TOPOLOGICAL_SORT_HPP_ + +#include +#include + +/// Helper function for topological_sort(). +/// Finds all the nodes in the graph with no incoming edges, +/// that is, with empty values. Removes each one from the graph +/// and adds it to the set @p nodes. +/// @param[in,out] graph A map of node/set pairs +/// @param[in,out] nodes A queue of nodes with no incoming edges +template +void topsort_clean_graph(Graph& graph, Nodes& nodes) +{ + for (auto iter(graph.begin()), end(graph.end()); iter != end;) + { + if (iter->second.empty()) + { + nodes.push_back(iter->first); + graph.erase(iter++); // advance iterator before erase invalidates it + } + else + ++iter; + } +} + +/// Topological sort of a directed acyclic graph. +/// A graph is a map keyed by nodes, with sets of nodes as values. +/// Edges run from values to keys. The sorted list of nodes +/// is copied to an output iterator in reverse order. +/// @param graph The graph +/// @param sorted The output iterator +/// @throws std::runtime_error if the graph contains a cycle +/// @pre Graph::key_type == Graph::mapped_type::key_type +template +void topological_sort(Graph graph, OutIterator sorted) +{ + std::deque nodes{}; + // Start with the set of nodes with no incoming edges. + topsort_clean_graph(graph, nodes); + + while (not nodes.empty()) + { + // Grab the first node to process, output it to sorted, + // and remove it from the graph. + typename Graph::key_type n{nodes.front()}; + nodes.pop_front(); + *sorted = n; + ++sorted; + + // Erase n from the graph + for (auto& node : graph) + { + node.second.erase(n); + } + // After removing n, find any nodes that no longer + // have any incoming edges. + topsort_clean_graph(graph, nodes); + } + if (not graph.empty()) + throw std::invalid_argument("Dependency graph contains cycles"); +} + +#endif // TOPOLOGICAL_SORT_HPP_ diff --git a/exploring-cpp-2e/chapter63/variables.hpp b/exploring-cpp-2e/chapter63/variables.hpp new file mode 100644 index 0000000..ce699c3 --- /dev/null +++ b/exploring-cpp-2e/chapter63/variables.hpp @@ -0,0 +1,18 @@ +// Listing 59-6. The variables.hpp File +#ifndef VARIABLES_HPP_ +#define VARIABLES_HPP_ + +#include +#include + +typedef std::map variable_map; +extern variable_map global_variables; + +/// Expand variables in a string using a local map +/// and the global map. +/// @param str The string to expand +/// @param local_variables The optional, local map; can be null +/// @return The expanded string +std::string expand(std::string str, variable_map const* local_variables); + +#endif // VARIABLES_HPP_ diff --git a/exploring-cpp-2e/chapter64/list6401.cpp b/exploring-cpp-2e/chapter64/list6401.cpp new file mode 100644 index 0000000..b53faf1 --- /dev/null +++ b/exploring-cpp-2e/chapter64/list6401.cpp @@ -0,0 +1,8 @@ +// Listing 64-1. An Initial Definition of Formatting Flags +typedef int fmtflags; +fmtflags const showbase = 0x01; +fmtflags const boolalpha = 0x02; +fmtflags const skipws = 0x04; +fmtflags const showpoint = 0x08; +fmtflags const showpos = 0x10; +// etc. for other flags... diff --git a/exploring-cpp-2e/chapter64/list6402.cpp b/exploring-cpp-2e/chapter64/list6402.cpp new file mode 100644 index 0000000..afddd0f --- /dev/null +++ b/exploring-cpp-2e/chapter64/list6402.cpp @@ -0,0 +1,5 @@ +// Listing 64-2. A Simple Implementation of the setf Member Function +void setf(fmtflags f) +{ + flags_ = flags_ | f; +} diff --git a/exploring-cpp-2e/chapter64/list6403.cpp b/exploring-cpp-2e/chapter64/list6403.cpp new file mode 100644 index 0000000..6602023 --- /dev/null +++ b/exploring-cpp-2e/chapter64/list6403.cpp @@ -0,0 +1,5 @@ +// Listing 64-3. A Simple Implementation of the unsetf Member Function +void unsetf(fmtflags f) +{ + flags_ = flags_ & ~f; +} diff --git a/exploring-cpp-2e/chapter64/list6404.cpp b/exploring-cpp-2e/chapter64/list6404.cpp new file mode 100644 index 0000000..7cb7957 --- /dev/null +++ b/exploring-cpp-2e/chapter64/list6404.cpp @@ -0,0 +1,10 @@ +// Listing 64-4. Using Assignment Operators in the Flags Functions +void setf(fmtflags f) +{ + flags_ |= f; +} + +void unsetf(fmtflags f) +{ + flags_ &= ~f; +} diff --git a/exploring-cpp-2e/chapter64/list6405.cpp b/exploring-cpp-2e/chapter64/list6405.cpp new file mode 100644 index 0000000..31160c3 --- /dev/null +++ b/exploring-cpp-2e/chapter64/list6405.cpp @@ -0,0 +1,10 @@ +// Listing 64-5. Declarations for Formatting Fields +fmtflags static constexpr adjustfield = 0x300; +fmtflags static constexpr left = 0x000; +fmtflags static constexpr right = 0x100; +fmtflags static constexpr internal = 0x200; +fmtflags static constexpr floatfield = 0xC00; +fmtflags static constexpr scientific = 0x400; +fmtflags static constexpr fixed = 0x800; +fmtflags static constexpr hexfloat = 0xC00; +// general does not have a name; its value is zero diff --git a/exploring-cpp-2e/chapter64/list6406.cpp b/exploring-cpp-2e/chapter64/list6406.cpp new file mode 100644 index 0000000..c785c12 --- /dev/null +++ b/exploring-cpp-2e/chapter64/list6406.cpp @@ -0,0 +1,6 @@ +// Listing 64-6. Two-Argument Form of the setf Function +void setf(fmtflags flags_to_set, fmtflags field) +{ + flags_ &= ~field; + flags_ |= flags_to_set; +} diff --git a/exploring-cpp-2e/chapter64/list6407.cpp b/exploring-cpp-2e/chapter64/list6407.cpp new file mode 100644 index 0000000..6e8c6f5 --- /dev/null +++ b/exploring-cpp-2e/chapter64/list6407.cpp @@ -0,0 +1,26 @@ +// Listing 64-7. Using Shift Operators to Define the Formatting Fields +int static constexpr boolalpha_pos = 0; +int static constexpr showbase_pos = 1; +int static constexpr showpoint_pos = 2; +int static constexpr showpos_pos = 3; +int static constexpr skipws_pos = 4; +int static constexpr adjust_pos = 5; +int static constexpr adjust_size = 2; +int static constexpr float_pos = 7; +int static constexpr float_size = 2; + +fmtflags static constexpr boolalpha = 1 << boolalpha_pos; +fmtflags static constexpr showbase = 1 << showbase_pos; +fmtflags static constexpr showpos = 1 << showpos_pos; +fmtflags static constexpr showpoint = 1 << showpoint_pos; +fmtflags static constexpr skipws = 1 << showpoint_pos; +fmtflags static constexpr adjustfield = 3 << adjust_pos; +fmtflags static constexpr floatfield = 3 << float_pos; + +fmtflags static constexpr left = 0 << adjust_pos; +fmtflags static constexpr right = 1 << adjust_pos; +fmtflags static constexpr internal = 2 << adjust_pos; + +fmtflags static constexpr fixed = 1 << float_pos; +fmtflags static constexpr scientific = 2 << float_pos; +fmtflags static constexpr hexfloat = 3 << float_pos; diff --git a/exploring-cpp-2e/chapter64/list6408.cpp b/exploring-cpp-2e/chapter64/list6408.cpp new file mode 100644 index 0000000..0e7734f --- /dev/null +++ b/exploring-cpp-2e/chapter64/list6408.cpp @@ -0,0 +1,21 @@ +// Listing 64-8. Exploring How Negative and Unsigned Values Are Shifted +#include +#include + +template +void print(std::string const& label, T value) +{ + std::cout << label << " = "; + std::cout << std::dec << value << " = "; + std::cout.width(8); + std::cout.fill('0'); + std::cout << std::hex << std::internal << std::showbase << value << '\n'; +} + +int main() +{ + int i{~0}; // all bits set to 1; on most systems, ~0 == -1 + unsigned int u{~0u}; // all bits set to 1 + print("int >> 15", i >> 15); + print("unsigned >> 15", u >> 15); +} diff --git a/exploring-cpp-2e/chapter64/list6409.cpp b/exploring-cpp-2e/chapter64/list6409.cpp new file mode 100644 index 0000000..34a2b69 --- /dev/null +++ b/exploring-cpp-2e/chapter64/list6409.cpp @@ -0,0 +1,14 @@ +#include + +// Listing 64-9. Mixing Signed and Unsigned Integers +void show(unsigned u) +{ + std::cout << u << '\n'; +} + +int main() +{ + int i{-1}; + std::cout << i << '\n'; + show(i); +} diff --git a/exploring-cpp-2e/chapter64/list6410.cpp b/exploring-cpp-2e/chapter64/list6410.cpp new file mode 100644 index 0000000..563c4c7 --- /dev/null +++ b/exploring-cpp-2e/chapter64/list6410.cpp @@ -0,0 +1,25 @@ +// Listing 64-10. Mystery Program +#include +#include +#include +#include + +template +void append(std::vector& data, const T& value, int max_size) +{ + if (data.size() < max_size - 1) + data.push_back(value); +} + +int main() +{ + std::vector data{}; + append(data, 10, 3); + append(data, 20, 2); + append(data, 30, 1); + append(data, 40, 0); + append(data, 50, 0); + std::copy(data.begin(), data.end(), + std::ostream_iterator(std::cout, " ")); + std::cout << '\n'; +} diff --git a/exploring-cpp-2e/chapter64/list6411.cpp b/exploring-cpp-2e/chapter64/list6411.cpp new file mode 100644 index 0000000..0479699 --- /dev/null +++ b/exploring-cpp-2e/chapter64/list6411.cpp @@ -0,0 +1,47 @@ +// Listing 64-11. Another Mystery Program +#include +#include +#include +#include + +/** Return the index of a value in a range. + * Look for the first occurrence of @p value in the range + * [first, last), and return the zero-based + * index or -1 if @p value is not found. + * @param first The start of the range to search + * @param last One past the end of the range to search + * @param value The value to search for + * @return [0, size), such that size == last-first, or -1 + */ +template +typename std::iterator_traits::difference_type +index_of(InputIter first, InputIter last, + typename std::iterator_traits::value_type const& value) +{ + InputIter iter{std::find(first, last, value)}; + if (iter == last) + return -1; + else + return std::distance(first, iter); +} + +/** Determine whether the first occurrence of a value in a container is + * in the last position in the container. + * @param container Any standard container + * @param value The value to search for. + * @return true if @p value is at the last position, + * or false if @p value is not found or at any other position. + */ +template +bool is_last(T const& container, typename T::value_type const& value) +{ + return index_of(container.begin(), container.end(), value) == + container.size() - 1; +} + +int main() +{ + std::vector data{}; + if (is_last(data, 10)) + std::cout << "10 is the last item in data\n"; +} diff --git a/exploring-cpp-2e/chapter64/list6412.cpp b/exploring-cpp-2e/chapter64/list6412.cpp new file mode 100644 index 0000000..614e5f9 --- /dev/null +++ b/exploring-cpp-2e/chapter64/list6412.cpp @@ -0,0 +1,49 @@ +// Listing 64-12. Fixing the Second Mystery Program +#include +#include +#include +#include + +/** Return the index of a value in a range. + * Look for the first occurrence of @p value in the range + * [first, last), and return the zero-based + * index or -1 if @p value is not found. + * @param first The start of the range to search + * @param last One past the end of the range to search + * @param value The value to search for + * @return [0, size), such that size == last-first, or -1 + */ +template +typename std::iterator_traits::difference_type +index_of(InputIter first, InputIter last, + typename std::iterator_traits::value_type const& value) +{ + InputIter iter{std::find(first, last, value)}; + if (iter == last) + return -1; + else + return std::distance(first, iter); +} + +/** Determine whether the first occurrence of a value in a container is + * in the last position in the container. + * @param container Any standard container + * @param value The value to search for. + * @return true if @p value is at the last position, + * or false if @p value is not found or at any other position. + */ +template +bool is_last(T const& container, typename T::value_type const& value) +{ + typename T::difference_type + pos(index_of(container.begin(), container.end(), value)); + auto last_index(static_cast(container.size() - 1)); + return pos != -1 and pos == last_index; +} + +int main() +{ + std::vector data{}; + if (is_last(data, 10)) + std::cout << "10 is the last item in data\n"; +} diff --git a/exploring-cpp-2e/chapter64/list6413.cpp b/exploring-cpp-2e/chapter64/list6413.cpp new file mode 100644 index 0000000..6ac71a0 --- /dev/null +++ b/exploring-cpp-2e/chapter64/list6413.cpp @@ -0,0 +1,19 @@ +// Listing 64-13. Declaring Formatting Flags with Bitfields +struct fmtflags +{ + bool skipws_f : 1; + bool boolalpha_f: 1; + bool showpoint_f: 1; + bool showbase_f: 1; + bool showpos_f: 1; + unsigned adjustfield_f: 2; + unsigned floatfield_f: 2; + + static unsigned constexpr left = 0; + static unsigned constexpr right = 1; + static unsigned constexpr internal = 2; + + static unsigned constexpr fixed = 1; + static unsigned constexpr scientific = 2; + static unsigned constexpr hexfloat = 3; +}; diff --git a/exploring-cpp-2e/chapter64/list6414.cpp b/exploring-cpp-2e/chapter64/list6414.cpp new file mode 100644 index 0000000..c7e39cb --- /dev/null +++ b/exploring-cpp-2e/chapter64/list6414.cpp @@ -0,0 +1,32 @@ +// Listing 64-14. Example of Using std::bitset +#include +#include +#include +#include + +/** Find the first 1 bit in a bitset, starting from the most significant bit. + * @param bitset The bitset to examine + * @return A value in the range [0, bitset.size()-1) or + * size_t(-1) if bitset.none() is true. + */ +template +std::size_t first(std::bitset const& bitset) +{ + for (std::size_t i{bitset.size()}; i-- != 0;) + if (bitset.test(i)) + return i; + return std::size_t(-1); +} + +int main() +{ + std::bitset<50> lots_o_bits{std::string{"1011011101111011111011111101111111"}}; + std::cout << "bitset: " << lots_o_bits << '\n'; + std::cout << "first 1 bit: " << first(lots_o_bits) << '\n'; + std::cout << "count of 1 bits: " << lots_o_bits.count() << '\n'; + lots_o_bits[first(lots_o_bits)] = false; + std::cout << "new first 1 bit: " << first(lots_o_bits) << '\n'; + lots_o_bits.flip(); + std::cout << "bitset: " << lots_o_bits << '\n'; + std::cout << "first 1 bit: " << first(lots_o_bits) << '\n'; +} diff --git a/exploring-cpp-2e/chapter64/list6415.cpp b/exploring-cpp-2e/chapter64/list6415.cpp new file mode 100644 index 0000000..b7413b0 --- /dev/null +++ b/exploring-cpp-2e/chapter64/list6415.cpp @@ -0,0 +1,55 @@ +// Listing 64-15. The find_pair Function and Test Program +#include +#include +#include +#include + +template +std::size_t find_pair(std::bitset const& bitset, bool value) +{ + if (bitset.size() >= 2) + for (std::size_t i{bitset.size()}; i-- != 1; ) + if (bitset[i] == value and bitset[i-1] == value) + return i; + return std::size_t(-1); +} + +int main() +{ + std::size_t const not_found{~0u}; + std::bitset<0> bs0{}; + std::bitset<1> bs1{}; + std::bitset<2> bs2{}; + std::bitset<3> bs3{}; + std::bitset<100> bs100{}; + + assert(find_pair(bs0, false) == not_found); + assert(find_pair(bs0, true) == not_found); + assert(find_pair(bs1, false) == not_found); + assert(find_pair(bs1, true) == not_found); + assert(find_pair(bs2, false) == 1); + assert(find_pair(bs2, true) == not_found); + bs2[0] = true; + assert(find_pair(bs2, false) == not_found); + assert(find_pair(bs2, true) == not_found); + bs2.flip(); + assert(find_pair(bs2, false) == not_found); + assert(find_pair(bs2, true) == not_found); + bs2[0] = true; + assert(find_pair(bs2, false) == not_found); + assert(find_pair(bs2, true) == 1); + assert(find_pair(bs3, false) == 2); + assert(find_pair(bs3, true) == not_found); + bs3[2].flip(); + assert(find_pair(bs3, false) == 1); + assert(find_pair(bs3, true) == not_found); + bs3[1].flip(); + assert(find_pair(bs3, false) == not_found); + assert(find_pair(bs3, true) == 2); + assert(find_pair(bs100, false) == 99); + assert(find_pair(bs100, true) == not_found); + bs100[50] = true; + assert(find_pair(bs100, true) == not_found); + bs100[51] = true; + assert(find_pair(bs100, true) == 51); +} diff --git a/exploring-cpp-2e/chapter65/card.hpp b/exploring-cpp-2e/chapter65/card.hpp new file mode 100644 index 0000000..c705392 --- /dev/null +++ b/exploring-cpp-2e/chapter65/card.hpp @@ -0,0 +1,65 @@ +// Listing 65-4. Improving the card Class with Enumerations +#ifndef CARD_HPP_ +#define CARD_HPP_ + +#include +#include + +enum class suit { nosuit, diamonds, clubs, hearts, spades }; +enum class rank { norank=0, r2=2, r3, r4, r5, r6, r7, r8, r9, r10, jack, queen, king, ace }; + +suit& operator++(suit& s) +{ + if (s == suit::spades) + s = suit::diamonds; + else + s = static_cast(static_cast(s) + 1); + return s; +} + +rank operator++(rank& r) +{ + if (r == rank::norank or r == rank::ace) + r = rank::r2; + else + r = static_cast(static_cast(r) + 1); + return r; +} + +/// Represent a standard western playing card. +class card +{ +public: + card() : rank_(rank::norank), suit_(suit::nosuit) {} + card(rank r, suit s) : rank_(r), suit_(s) {} + + void assign(rank r, suit s); + suit get_suit() const { return suit_; } + rank get_rank() const { return rank_; } +private: + rank rank_; + suit suit_; +}; + +bool operator==(card a, card b); +std::ostream& operator<<(std::ostream& out, card c); +std::istream& operator>>(std::istream& in, card& c); + +/// In some games, Aces are high. In other Aces are low. Use different +/// comparison functors depending on the game. +bool acehigh_compare(card a, card b); +bool acelow_compare(card a, card b); + +/// Generate successive playing cards, in a well-defined order, +/// namely, 2-10, J, Q, K, A. Diamonds first, then Clubs, Hearts, and Spades. +/// Roll-over and start at the beginning again after generating 52 cards. +class card_generator +{ +public: + card_generator(); + card operator()(); +private: + card card_; +}; + +#endif diff --git a/exploring-cpp-2e/chapter65/list6501.cpp b/exploring-cpp-2e/chapter65/list6501.cpp new file mode 100644 index 0000000..900ee08 --- /dev/null +++ b/exploring-cpp-2e/chapter65/list6501.cpp @@ -0,0 +1,19 @@ +// Listing 65-1. One Way to Implement openmode Type +enum class openmode : unsigned { in, out, binary, trunc, app, ate }; + +openmode operator|(openmode lhs, openmode rhs) +{ + return static_cast( + static_cast(lhs) | static_cast(rhs) ); +} + +openmode operator&(openmode lhs, openmode rhs) +{ + return static_cast( + static_cast(lhs) & static_cast(rhs) ); +} + +openmode operator~(openmode arg) +{ + return static_cast( ~static_cast(arg) ); +} diff --git a/exploring-cpp-2e/chapter65/list6502.cpp b/exploring-cpp-2e/chapter65/list6502.cpp new file mode 100644 index 0000000..b567d45 --- /dev/null +++ b/exploring-cpp-2e/chapter65/list6502.cpp @@ -0,0 +1,56 @@ +// Listing 65-2. Mapping a language Value to and from Strings +#include +#include +#include +#include +#include +#include + + +enum class language { apl, low=apl, c, cpp, forth, haskell, jovial, lisp, scala, high=scala }; + +std::unordered_map from_string_map_; +std::array to_string_map_; + +void store(std::string const& name, language lang) +{ + from_string_map_.emplace(name, lang); + to_string_map_.at(static_cast(lang)) = name; +} + +void initialize_language() +{ + store("apl", language::apl); + store("c", language::c); + store("cpp", language::cpp); + store("forth", language::forth); + store("haskell", language::haskell); + store("jovial", language::jovial); + store("lisp", language::lisp); + store("scala", language::scala); +} + +std::string const& to_string(language lang) +{ + return to_string_map_.at(static_cast(lang)); +} + +language from_string(std::string const& text) +{ + return from_string_map_.at(text); +} + +std::ostream& operator<<(std::ostream& stream, language lang) +{ + stream << to_string(lang); + return stream; +} + +std::istream& operator>>(std::istream& stream, language& lang) +{ + std::string text; + if (stream >> text) + lang = from_string(text); + return stream; +} + diff --git a/exploring-cpp-2e/chapter65/list6503.cpp b/exploring-cpp-2e/chapter65/list6503.cpp new file mode 100644 index 0000000..038a153 --- /dev/null +++ b/exploring-cpp-2e/chapter65/list6503.cpp @@ -0,0 +1,6 @@ +// Listing 65-3. Automatically Initializing the Language Data Structures +class initializer { +public: + initializer() { initialize_language(); } +}; +initializer init; diff --git a/exploring-cpp-2e/chapter65/list6504.hpp b/exploring-cpp-2e/chapter65/list6504.hpp new file mode 100644 index 0000000..c705392 --- /dev/null +++ b/exploring-cpp-2e/chapter65/list6504.hpp @@ -0,0 +1,65 @@ +// Listing 65-4. Improving the card Class with Enumerations +#ifndef CARD_HPP_ +#define CARD_HPP_ + +#include +#include + +enum class suit { nosuit, diamonds, clubs, hearts, spades }; +enum class rank { norank=0, r2=2, r3, r4, r5, r6, r7, r8, r9, r10, jack, queen, king, ace }; + +suit& operator++(suit& s) +{ + if (s == suit::spades) + s = suit::diamonds; + else + s = static_cast(static_cast(s) + 1); + return s; +} + +rank operator++(rank& r) +{ + if (r == rank::norank or r == rank::ace) + r = rank::r2; + else + r = static_cast(static_cast(r) + 1); + return r; +} + +/// Represent a standard western playing card. +class card +{ +public: + card() : rank_(rank::norank), suit_(suit::nosuit) {} + card(rank r, suit s) : rank_(r), suit_(s) {} + + void assign(rank r, suit s); + suit get_suit() const { return suit_; } + rank get_rank() const { return rank_; } +private: + rank rank_; + suit suit_; +}; + +bool operator==(card a, card b); +std::ostream& operator<<(std::ostream& out, card c); +std::istream& operator>>(std::istream& in, card& c); + +/// In some games, Aces are high. In other Aces are low. Use different +/// comparison functors depending on the game. +bool acehigh_compare(card a, card b); +bool acelow_compare(card a, card b); + +/// Generate successive playing cards, in a well-defined order, +/// namely, 2-10, J, Q, K, A. Diamonds first, then Clubs, Hearts, and Spades. +/// Roll-over and start at the beginning again after generating 52 cards. +class card_generator +{ +public: + card_generator(); + card operator()(); +private: + card card_; +}; + +#endif diff --git a/exploring-cpp-2e/chapter66/assignment_mixin.hpp b/exploring-cpp-2e/chapter66/assignment_mixin.hpp new file mode 100644 index 0000000..c44b98b --- /dev/null +++ b/exploring-cpp-2e/chapter66/assignment_mixin.hpp @@ -0,0 +1,10 @@ +// Listing 66-8. The assignment_mixin Class Template +template +class assignment_mixin { +public: + T& operator=(T rhs) + { + rhs.swap(static_cast(*this)); + return static_cast(*this); + } +}; diff --git a/exploring-cpp-2e/chapter66/hash.hpp b/exploring-cpp-2e/chapter66/hash.hpp new file mode 100644 index 0000000..b2ebb87 --- /dev/null +++ b/exploring-cpp-2e/chapter66/hash.hpp @@ -0,0 +1,29 @@ +#ifndef HASH_HPP_ +#define HASH_HPP_ + +// Listing 66-6. The hash<> Class Template +template +class hash +{ +public: + std::size_t operator()(T const& x) const + { + return reinterpret_cast(&x); + } +}; + +template<> +class hash +{ +public: + std::size_t operator()(std::string const& str) const + { + std::size_t h(0); + for (auto c : str) + h = h << 1 | c; + return h; + } +}; + +#endif + diff --git a/exploring-cpp-2e/chapter66/list6601.cpp b/exploring-cpp-2e/chapter66/list6601.cpp new file mode 100644 index 0000000..aca633b --- /dev/null +++ b/exploring-cpp-2e/chapter66/list6601.cpp @@ -0,0 +1,46 @@ +// Listing 66-1. Demonstrating the Order of Initialization of Base Classes +#include +#include +#include + +class visible { +public: + visible(std::string&& msg) : msg_{std::move(msg)} { std::cout << msg_ << '\n'; } + std::string const& msg() const { return msg_; } +private: + std::string msg_; +}; + +class base1 : public visible { +public: + base1(int x) : visible{"base1 constructed"}, value_{x} {} + int value() const { return value_; } +private: + int value_; +}; + +class base2 : public visible { +public: + base2(std::string const& str) : visible{"base2{" + str + "} constructed"} {} +}; + +class base3 : public visible { +public: + base3() : visible{"base3 constructed"} {} + int value() const { return 42; } +}; + +class derived : public base1, public base2, public base3 { +public: + derived(int i, std::string const& str) : base3{}, base2{str}, base1{i} {} + int value() const { return base1::value() + base3::value(); } + std::string msg() const + { + return base1::msg() + "\n" + base2::msg() + "\n" + base3::msg(); + } +}; + +int main() +{ + derived d{42, "example"}; +} diff --git a/exploring-cpp-2e/chapter66/list6602.cpp b/exploring-cpp-2e/chapter66/list6602.cpp new file mode 100644 index 0000000..688e1d3 --- /dev/null +++ b/exploring-cpp-2e/chapter66/list6602.cpp @@ -0,0 +1,50 @@ +// Listing 66-2. Changing the Inheritance of Visible to Virtual +#include +#include +#include + +class visible { +public: + visible(std::string&& msg) : msg_{std::move(msg)} { std::cout << msg_ << '\n'; } + std::string const& msg() const { return msg_; } +private: + std::string msg_; +}; + +class base1 : virtual public visible { +public: + base1(int x) : visible{"base1 constructed"}, value_{x} {} + int value() const { return value_; } +private: + int value_; +}; + +class base2 : virtual public visible { +public: + base2(std::string const& str) : visible{"base2{" + str + "} constructed"} {} +}; + +class base3 : virtual public visible { +public: + base3() : visible{"base3 constructed"} {} + int value() const { return 42; } +}; + +class derived : public base1, public base2, public base3 { +public: + derived(int i, std::string const& str) + : base3{}, base2{str}, base1{i}, visible{"derived"} + {} + int value() const { return base1::value() + base3::value(); } + std::string msg() const + { + return base1::msg() + "\n" + base2::msg() + "\n" + base3::msg(); + } +}; + +int main() +{ + derived d{42, "example"}; + std::cout << d.value() << '\n' << d.msg() << '\n'; +} + diff --git a/exploring-cpp-2e/chapter66/list6603.cpp b/exploring-cpp-2e/chapter66/list6603.cpp new file mode 100644 index 0000000..99d3ba2 --- /dev/null +++ b/exploring-cpp-2e/chapter66/list6603.cpp @@ -0,0 +1,8 @@ +// Listing 66-3. The Hashable Interface in C++ +class Hashable +{ +public: + virtual ~Hashable(); + virtual unsigned long hash() const = 0; + virtual bool equalTo(Hashable const&) const = 0; +}; diff --git a/exploring-cpp-2e/chapter66/list6604.cpp b/exploring-cpp-2e/chapter66/list6604.cpp new file mode 100644 index 0000000..a97b70a --- /dev/null +++ b/exploring-cpp-2e/chapter66/list6604.cpp @@ -0,0 +1,13 @@ +// Listing 66-4. The HashableString Class +class HashableString : public Hashable +{ +public: + HashableString() : string_{} {} + ~HashableString() override; + unsigned long hash() const override; + bool equalTo(Hashable const&) const override; + + // Implement the entire interface of std::string ... +private: + std::string string_; +}; diff --git a/exploring-cpp-2e/chapter66/list6605.cpp b/exploring-cpp-2e/chapter66/list6605.cpp new file mode 100644 index 0000000..69bfc96 --- /dev/null +++ b/exploring-cpp-2e/chapter66/list6605.cpp @@ -0,0 +1,63 @@ +// Listing 66-5. Undefined Behavior Arises from HashableString That Derives from std::string +#include +#include +#include +#include +#include + +class Hashable +{ +public: + virtual ~Hashable() {} + virtual unsigned long hash() const = 0; + virtual bool equalTo(Hashable const&) const = 0; +}; + +class HashableString : public std::string, public Hashable +{ +public: + HashableString() : std::string{} {} + HashableString(std::string&& str) : std::string{std::move(str)} {} + ~HashableString() override {} + + unsigned long hash() const override { + return std::hash()(*this); + } + + bool equalTo(Hashable const& s) const override { + return dynamic_cast(s) == *this; + } + +}; + +class string_pool +{ +public: + string_pool() : pool_{} {} + ~string_pool() { + while (not pool_.empty()) { + std::string* ptr{ *pool_.begin() }; + pool_.erase(pool_.begin()); + delete ptr; + } + } + std::string* add(std::string&& str) { + std::string* ptr = new std::string{std::move(str)}; + pool_.insert(ptr); + return ptr; + } +private: + std::unordered_set pool_; +}; + +int main() +{ + string_pool pool{}; + HashableString str{}; + while (std::cin >> str) + { + std::cout << "hash of \"" << str << "\" = " << str.hash() << '\n'; + pool.add(std::move(str)); + } +} + diff --git a/exploring-cpp-2e/chapter66/list6606.hpp b/exploring-cpp-2e/chapter66/list6606.hpp new file mode 100644 index 0000000..b2ebb87 --- /dev/null +++ b/exploring-cpp-2e/chapter66/list6606.hpp @@ -0,0 +1,29 @@ +#ifndef HASH_HPP_ +#define HASH_HPP_ + +// Listing 66-6. The hash<> Class Template +template +class hash +{ +public: + std::size_t operator()(T const& x) const + { + return reinterpret_cast(&x); + } +}; + +template<> +class hash +{ +public: + std::size_t operator()(std::string const& str) const + { + std::size_t h(0); + for (auto c : str) + h = h << 1 | c; + return h; + } +}; + +#endif + diff --git a/exploring-cpp-2e/chapter66/list6607.cpp b/exploring-cpp-2e/chapter66/list6607.cpp new file mode 100644 index 0000000..876f62f --- /dev/null +++ b/exploring-cpp-2e/chapter66/list6607.cpp @@ -0,0 +1,20 @@ +// Listing 66-7. Rewriting string_pool to Use hash<> +#include +#include +#include +#include "hash.hpp" // Listing 66-6 + +#include "string_pool.hpp" // Copied from Listing 66-5 + + +int main() +{ + string_pool pool{}; + std::string str{}; + hash hasher{}; + while (std::cin >> str) + { + std::cout << "hash of \"" << str << "\" = " << hasher(str) << '\n'; + pool.add(std::move(str)); + } +} diff --git a/exploring-cpp-2e/chapter66/list6608.hpp b/exploring-cpp-2e/chapter66/list6608.hpp new file mode 100644 index 0000000..c44b98b --- /dev/null +++ b/exploring-cpp-2e/chapter66/list6608.hpp @@ -0,0 +1,10 @@ +// Listing 66-8. The assignment_mixin Class Template +template +class assignment_mixin { +public: + T& operator=(T rhs) + { + rhs.swap(static_cast(*this)); + return static_cast(*this); + } +}; diff --git a/exploring-cpp-2e/chapter66/list6609.cpp b/exploring-cpp-2e/chapter66/list6609.cpp new file mode 100644 index 0000000..007c2c5 --- /dev/null +++ b/exploring-cpp-2e/chapter66/list6609.cpp @@ -0,0 +1,27 @@ +// Listing 66-9. Using mix-in Class Template +#include +#include +#include +#include "assignment_mixin.hpp" // Listing 66-8 + +class thing: public assignment_mixin { +public: + thing() : value_{} {} + thing(std::string&& s) : value_{std::move(s)} {} + void swap(thing& other) { value_.swap(other.value_); } + + std::string const& str() const { return value_; } + +private: + std::string value_; +}; + +int main() +{ + thing one{}; + thing two{"two"}; + one = two; + + std::cout << "one=" << one.str() << "\ntwo=" << two.str() << '\n'; +} + diff --git a/exploring-cpp-2e/chapter66/list6610.cpp b/exploring-cpp-2e/chapter66/list6610.cpp new file mode 100644 index 0000000..02ee05d --- /dev/null +++ b/exploring-cpp-2e/chapter66/list6610.cpp @@ -0,0 +1,12 @@ +// Listing 66-10. Adding a Protected Constructor to the assignment_mixin Class Template +template +class assignment_mixin { +public: + T& operator=(T rhs) + { + rhs.swap(static_cast(*this)); + return static_cast(*this); + } +protected: + assignment_mixin() {} +}; diff --git a/exploring-cpp-2e/chapter66/string_pool.hpp b/exploring-cpp-2e/chapter66/string_pool.hpp new file mode 100644 index 0000000..b25b0e2 --- /dev/null +++ b/exploring-cpp-2e/chapter66/string_pool.hpp @@ -0,0 +1,30 @@ +#ifndef STRING_POOL_HPP_ +#define STRING_POOL_HPP_ + +#include +#include + +/// Pool of strings. +/// From Listing 66-5. +class string_pool +{ +public: + string_pool() : pool_{} {} + ~string_pool() { + while (not pool_.empty()) { + std::string* ptr{ *pool_.begin() }; + pool_.erase(pool_.begin()); + delete ptr; + } + } + std::string* add(std::string&& str) { + std::string* ptr = new std::string{std::move(str)}; + pool_.insert(ptr); + return ptr; + } +private: + std::unordered_set pool_; +}; + +#endif + diff --git a/exploring-cpp-2e/chapter67/advance.hpp b/exploring-cpp-2e/chapter67/advance.hpp new file mode 100644 index 0000000..9a202a8 --- /dev/null +++ b/exploring-cpp-2e/chapter67/advance.hpp @@ -0,0 +1,56 @@ +#ifndef ADVANCE_HPP_ +#define ADVANCE_HPP_ + +// Listing 67-1. One Possible Implementation of std::advance +#include +#include +#include +#include + +void trace(std::string const& msg) +{ + std::cout << msg << '\n'; +} + +// Default implementation: advance the slow way +template +class iterator_advancer +{ +public: + template + void operator()(InIter& iter, Distance distance) + { + trace("iterator_advancer<>"); + for ( ; distance != 0; --distance) + ++iter; + } +}; + +// Partial specialization for bi-directional iterators +template<> +class iterator_advancer +{ +public: + template + void operator()(BiDiIter& iter, Distance distance) + { + trace("iterator_advancer"); + if (distance < 0) + for ( ; distance != 0; ++distance) + --iter; + else + for ( ; distance != 0; --distance) + ++iter; + } +}; + +template +void my_advance(InIter& iter, Distance distance) +{ + iterator_advancer::iterator_category>{} + + (iter, distance); +} + +#endif + diff --git a/exploring-cpp-2e/chapter67/list6701.hpp b/exploring-cpp-2e/chapter67/list6701.hpp new file mode 100644 index 0000000..9a202a8 --- /dev/null +++ b/exploring-cpp-2e/chapter67/list6701.hpp @@ -0,0 +1,56 @@ +#ifndef ADVANCE_HPP_ +#define ADVANCE_HPP_ + +// Listing 67-1. One Possible Implementation of std::advance +#include +#include +#include +#include + +void trace(std::string const& msg) +{ + std::cout << msg << '\n'; +} + +// Default implementation: advance the slow way +template +class iterator_advancer +{ +public: + template + void operator()(InIter& iter, Distance distance) + { + trace("iterator_advancer<>"); + for ( ; distance != 0; --distance) + ++iter; + } +}; + +// Partial specialization for bi-directional iterators +template<> +class iterator_advancer +{ +public: + template + void operator()(BiDiIter& iter, Distance distance) + { + trace("iterator_advancer"); + if (distance < 0) + for ( ; distance != 0; ++distance) + --iter; + else + for ( ; distance != 0; --distance) + ++iter; + } +}; + +template +void my_advance(InIter& iter, Distance distance) +{ + iterator_advancer::iterator_category>{} + + (iter, distance); +} + +#endif + diff --git a/exploring-cpp-2e/chapter67/list6702.cpp b/exploring-cpp-2e/chapter67/list6702.cpp new file mode 100644 index 0000000..33617a7 --- /dev/null +++ b/exploring-cpp-2e/chapter67/list6702.cpp @@ -0,0 +1,26 @@ +// Listing 67-2. Example Program to Use the my_advance Function +#include +#include +#include +#include +#include +#include +#include +#include + +#include "advance.hpp" // Listing 67-1 + +int main() +{ + std::vector vector{ 10, 20, 30, 40 }; + std::list list(vector.begin(), vector.end()); + std::vector::iterator vector_iterator{vector.begin()}; + std::list::iterator list_iterator{list.begin()}; + std::ifstream file{"advance.hpp"}; + std::istream_iterator input_iterator{file}; + + my_advance(input_iterator, 2); + my_advance(list_iterator, 2); + my_advance(vector_iterator, 2); +} + diff --git a/exploring-cpp-2e/chapter67/list6703.cpp b/exploring-cpp-2e/chapter67/list6703.cpp new file mode 100644 index 0000000..dc8806c --- /dev/null +++ b/exploring-cpp-2e/chapter67/list6703.cpp @@ -0,0 +1,13 @@ +// Listing 67-3. Specializing iterator_advancer for Random Access Iterators +// Partial specialization for random access iterators +template<> +class iterator_advancer +{ +public: + template + void operator()(RandomIter& iter, Distance distance) + { + trace("iterator_advancer"); + iter += distance; + } +}; diff --git a/exploring-cpp-2e/chapter67/list6704.cpp b/exploring-cpp-2e/chapter67/list6704.cpp new file mode 100644 index 0000000..10b8a59 --- /dev/null +++ b/exploring-cpp-2e/chapter67/list6704.cpp @@ -0,0 +1,13 @@ +// Listing 67-4. Using Character Traits When Copying Input to Output +#include +#include +#include +#include // for char_traits + +int main() +{ + typedef std::char_traits char_traits; // for brevity and clarity + char_traits::int_type c{}; + while (c = std::cin.get(), not char_traits::eq_int_type(c, char_traits::eof())) + std::cout.put(char_traits::to_char_type(c)); +} diff --git a/exploring-cpp-2e/chapter67/list6705.cpp b/exploring-cpp-2e/chapter67/list6705.cpp new file mode 100644 index 0000000..e975856 --- /dev/null +++ b/exploring-cpp-2e/chapter67/list6705.cpp @@ -0,0 +1,91 @@ +// Listing 67-5. The newstring Class Template +#include +#include + +template> +class newstring { +public: + typedef Char value_type; + typedef std::size_t size_type; + typedef typename Storage::iterator iterator; + typedef typename Storage::const_iterator const_iterator; + + newstring() : storage_() {} + newstring(newstring&&) = default; + newstring(newstring const&) = default; + newstring(Storage const& storage) : storage_(storage) {} + newstring(Char const* ptr, size_type size) : storage_() { + resize(size); + std::copy(ptr, ptr + size, begin()); + } + + static const size_type npos = static_cast(-1); + + newstring& operator=(newstring const&) = default; + newstring& operator=(newstring&&) = default; + + void swap(newstring& str) { storage_.swap(str.storage_); } + + Char operator[](size_type i) const { return *(storage_.begin() + i); } + Char& operator[](size_type i) { return *(storage_.begin() + i); } + + void resize(size_type size, Char value = Char()) { + storage_.resize(size, value); + } + void reserve(size_type size) { storage_.reserve(size); } + size_type size() const noexcept { return storage_.end() - storage_.begin(); } + size_type max_size() const noexcept { return storage_.max_size(); } + bool empty() const noexcept { return size() == 0; } + void clear() { resize(0); } + void push_back(Char c) { resize(size() + 1, c); } + + Char const* c_str() const { return storage_.c_str(); } + Char const* data() const { return storage_.c_str(); } + + iterator begin() { return storage_.begin(); } + const_iterator begin() const { return storage_.begin(); } + const_iterator cbegin() const { return storage_.begin(); } + iterator end() { return storage_.end(); } + const_iterator end() const { return storage_.end(); } + const_iterator cend() const { return storage_.end(); } + + size_type find(newstring const& s, size_type pos = 0) const { + pos = std::min(pos, size()); + const_iterator result( std::search(begin() + pos, end(), + s.begin(), s.end(), Traits::eq) ); + if (result == end()) + return npos; + else + return result - begin(); + } + +private: + Storage storage_; +}; + +template +class newstringcmp +{ +public: + bool operator()(typename Traits::value_type a, typename Traits::value_type b) + const + { + return Traits::cmp(a, b) < 0; + } +}; + +template +bool operator <(newstring const& a, + newstring const& b) +{ + return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end(), + newstringcmp()); +} + +template +bool operator ==(newstring const& a, + newstring const& b) +{ + return std::equal(a.begin(), a.end(), b.begin(), b.end(), Traits::eq); +} + diff --git a/exploring-cpp-2e/chapter67/list6706.cpp b/exploring-cpp-2e/chapter67/list6706.cpp new file mode 100644 index 0000000..c0a807a --- /dev/null +++ b/exploring-cpp-2e/chapter67/list6706.cpp @@ -0,0 +1,37 @@ +// Listing 67-6. The vector_storage Class Template +#include + +template +class vector_storage { +public: + typedef std::size_t size_type; + typedef Char value_type; + typedef typename std::vector::iterator iterator; + typedef typename std::vector::const_iterator const_iterator; + + vector_storage() : string_(1, Char()) {} + + void swap(vector_storage& storage) { string_.swap(storage.string_); } + size_type max_size() const { return string_.max_size() - 1; } + void reserve(size_type size) { string_.reserve(size + 1); } + void resize(size_type newsize, value_type value) { + // if the string grows, overwrite the null character, then resize + if (newsize >= string_.size()) { + string_[string_.size() - 1] = value; + string_.resize(newsize + 1, value); + } + else + string_.resize(newsize + 1); + string_[string_.size() - 1] = Char(); + } + Char const* c_str() const { return &string_[0]; } + + iterator begin() { return string_.begin(); } + const_iterator begin() const { return string_.begin(); } + // Skip over the trailing null character at the end of the vector + iterator end() { return string_.end() - 1; } + const_iterator end() const { return string_.end() - 1; } + +private: + std::vector string_; +}; diff --git a/exploring-cpp-2e/chapter67/list6707.cpp b/exploring-cpp-2e/chapter67/list6707.cpp new file mode 100644 index 0000000..64801e5 --- /dev/null +++ b/exploring-cpp-2e/chapter67/list6707.cpp @@ -0,0 +1,44 @@ +// Listing 67-7. The array_storage Class Template +#include +#include +#include +#include + +template +class array_storage { +public: + typedef std::array array_type; + typedef std::size_t size_type; + typedef Char value_type; + typedef typename array_type::iterator iterator; + typedef typename array_type::const_iterator const_iterator; + + array_storage() : size_(0), string_() { string_[0] = Char(); } + + void swap(array_storage& storage) { + string_.swap(storage.string_); + std::swap(size_, storage.size_); + } + size_type max_size() const { return string_.max_size() - 1; } + void reserve(size_type size) { + if (size > max_size()) throw std::length_error("reserve"); + } + void resize(size_type newsize, value_type value) { + if (newsize > max_size()) + throw std::length_error("resize"); + if (newsize > size_) + std::fill(begin() + size_, begin() + newsize, value); + size_ = newsize; + string_[size_] = Char(); + } + Char const* c_str() const { return &string_[0]; } + + iterator begin() { return string_.begin(); } + const_iterator begin() const { return string_.begin(); } + iterator end() { return begin() + size_; } + const_iterator end() const { return begin() + size_; } + +private: + size_type size_; + array_type string_; +}; diff --git a/exploring-cpp-2e/chapter67/list6708.cpp b/exploring-cpp-2e/chapter67/list6708.cpp new file mode 100644 index 0000000..eaa6a54 --- /dev/null +++ b/exploring-cpp-2e/chapter67/list6708.cpp @@ -0,0 +1,28 @@ +// Listing 67-8. Output Function for newstring +template +std::basic_ostream& + operator<<(std::basic_ostream& stream, + newstring const& string) +{ + typename std::basic_ostream::sentry sentry{stream}; + if (sentry) + { + bool needs_fill{stream.width() != 0 and string.size() > stream.width()}; + bool is_left_adjust{ + (stream.flags() & std::ios_base::adjustfield) == std::ios_base::left }; + if (needs_fill and not is_left_adjust) + { + for (std::size_t i{stream.width() - string.size()}; i != 0; --i) + stream.rdbuf()->sputc(stream.fill()); + } + stream.rdbuf()->sputn(string.data(), string.size()); + if (needs_fill and is_left_adjust) + { + for (std::size_t i{stream.width() - string.size()}; i != 0; --i) + stream.rdbuf()->sputc(stream.fill()); + } + } + stream.width(0); + return stream; +} + diff --git a/exploring-cpp-2e/chapter67/list6709.cpp b/exploring-cpp-2e/chapter67/list6709.cpp new file mode 100644 index 0000000..7e2b076 --- /dev/null +++ b/exploring-cpp-2e/chapter67/list6709.cpp @@ -0,0 +1,37 @@ +// Listing 67-9. Input Function for newstring +template +std::basic_istream& + operator>>(std::basic_istream& stream, + newstring& string) +{ + typename std::basic_istream::sentry sentry{stream}; + if (sentry) + { + std::ctype const& ctype( + std::use_facet>(stream.getloc()) ); + std::ios_base::iostate state{ std::ios_base::goodbit }; + std::size_t max_chars{ string.max_size() }; + if (stream.width() != 0 and stream.width() < max_chars) + max_chars = stream.width(); + string.clear(); + while (max_chars-- != 0) { + typename Traits::int_type c{ stream.rdbuf()->sgetc() }; + if (Traits::eq_int_type(Traits::eof(), c)) { + state |= std::ios_base::eofbit; + break; // is_eof + } + else if (ctype.is(ctype.space, Traits::to_char_type(c))) + break; + else { + string.push_back(Traits::to_char_type(c)); + stream.rdbuf()->sbumpc(); + } + } + if (string.empty()) + state |= std::ios_base::failbit; + stream.setstate(state); + stream.width(0); + } + return stream; +} + diff --git a/exploring-cpp-2e/chapter67/rational.cpp b/exploring-cpp-2e/chapter67/rational.cpp new file mode 100644 index 0000000..b66777d --- /dev/null +++ b/exploring-cpp-2e/chapter67/rational.cpp @@ -0,0 +1,265 @@ +#include +#include +#include +#include + +#include "rational.hpp" + +/// Compute the greatest common divisor of two integers, using Euclid’s algorithm. +int gcd(int n, int m) +{ + n = std::abs(n); + while (m != 0) { + int tmp(n % m); + n = m; + m = tmp; + } + return n; +} + +// Listing 46-2. Using a Function and Conditional Statements Instead of Conditional Expressions +/// Construct a rational object from a numerator and a denominator. +/// If the denominator is zero, throw zero_denominator. If the denominator +/// is negative, normalize the value by negating the numerator and denominator. +/// @post denominator_ > 0 +/// @throws zero_denominator +rational::rational(int num, int den) +: numerator_{den < 0 ? -num : num}, denominator_{init_denominator(den)} +{ + reduce(); +} + +/// Return an initial value for the denominator_ member. This function is used +/// only in a constructor's initializer list. +int rational::init_denominator(int den) +{ + if (den == 0) + throw zero_denominator("0 denominator"); + else if (den < 0) + return -den; + else + return den; +} + +rational::rational(double r) +: rational{static_cast(r * 10000), 10000} +{ + reduce(); +} + +float rational::to_float() +const +{ + return static_cast(numerator()) / denominator(); +} + +double rational::to_double() +const +{ + return static_cast(numerator()) / denominator(); +} + +long double rational::to_long_double() +const +{ + return static_cast(numerator()) / denominator(); +} + +/// Assign a numerator and a denominator, then reduce to normal form. +void assign(int num, int den) +{ + numerator_ = den < 0 ? -num : num; + denominator_ = init_denominator(den); + reduce(); +} + +void rational::reduce() +{ + int div{gcd(numerator(), denominator())}; + numerator_ = numerator() / div; + denominator_ = denominator() / div; +} + +// Listing 46-5. Implementing the Multiplication Assignment Operator +rational& rational::operator*=(rational const& rhs) +{ + numerator_ *= rhs.numerator(); + denominator_ *= rhs.denominator(); + reduce(); + return *this; +} + +// Listing 46-7. Other Arithmetic Assignment Operators +rational& rational::operator+=(rational const& rhs) +{ + numerator_ = numerator() * rhs.denominator() + rhs.numerator() * denominator(); + denominator_ *= rhs.denominator(); + reduce(); + return *this; +} + +rational& rational::operator-=(rational const& rhs) +{ + numerator_ = numerator() * rhs.denominator() - rhs.numerator() * denominator(); + denominator_ *= rhs.denominator(); + reduce(); + return *this; +} + +rational& rational::operator/=(rational const& rhs) +{ + if (rhs.numerator() == 0) + throw zero_denominator{"divide by zero"}; + numerator_ *= rhs.denominator(); + denominator_ *= rhs.numerator(); + if (denominator_ < 0) + { + denominator_ = -denominator_; + numerator_ = -numerator_; + } + reduce(); + return *this; +} + +// Listing 46-8. The Prefix Increment Operator for rational +rational& rational::operator++() +{ + numerator_ += denominator_; + return *this; +} + +rational& rational::operator--() +{ + numerator_ -= denominator_; + return *this; +} + +// Listing 46-9. Postfix Increment and Decrement Operators +rational rational::operator++(int) +{ + rational result{*this}; + numerator_ += denominator_; + return result; +} + +rational rational::operator--(int) +{ + rational result{*this}; + numerator_ -= denominator_; + return result; +} + +/// Absolute value of a rational number. +rational abs(rational const& r) +{ + return rational{std::abs(r.numerator()), r.denominator()}; +} + +/// Unary negation of a rational number. +rational operator-(rational const& r) +{ + return rational{-r.numerator(), r.denominator()}; +} + +/// Add rational numbers. +rational operator+(rational const& lhs, rational const& rhs) +{ + rational result{lhs}; + result += rhs; + return result; +} + +/// Subtraction of rational numbers. +rational operator-(rational const& lhs, rational const& rhs) +{ + rational result{lhs}; + result -= rhs; + return result; +} + +/// Multiplication of rational numbers. +rational operator*(rational const& lhs, rational const& rhs) +{ + rational result{lhs}; + result *= rhs; + return result; +} + +rational operator/(rational const& lhs, rational const& rhs) +{ + rational result{lhs}; + result /= rhs; + return result; +} + + +/// Compare two rational numbers for equality. +bool operator==(rational const& a, rational const& b) +{ + return a.numerator() == b.numerator() and a.denominator() == b.denominator(); +} + +/// Compare two rational numbers for inequality. +inline bool operator!=(rational const& a, rational const& b) +{ + return not (a == b); +} +/// Compare two rational numbers for less-than. +bool operator<(rational const& a, rational const& b) +{ + return a.numerator() * b.denominator() < b.numerator() * a.denominator(); +} + +/// Compare two rational numbers for less-than-or-equal. +inline bool operator<=(rational const& a, rational const& b) +{ + return not (b < a); +} +/// Compare two rational numbers for greater-than. +inline bool operator>(rational const& a, rational const& b) +{ + return b < a; +} + +/// Compare two rational numbers for greater-than-or-equal. +inline bool operator>=(rational const& a, rational const& b) +{ + return not (b > a); +} + +/// Read a rational number. +/// Format is @em integer @c / @em integer. +std::istream& operator>>(std::istream& in, rational& rat) +{ + int n{}, d{}; + char sep{}; + if (not (in >> n >> sep)) + // Error reading the numerator or the separator character. + in.setstate(in.failbit); + else if (sep != '/') + { + // Push sep back into the input stream, so the next input operation + // will read it. + in.unget(); + rat.assign(n, 1); + } + else if (in >> d) + // Successfully read numerator, separator, and denominator. + rat.assign(n, d); + else + // Error reading denominator. + in.setstate(in.failbit); + + return in; +} + +/// Write a rational numbers. +/// Format is @em numerator @c / @em denominator. +std::ostream& operator<<(std::ostream& out, rational const& rat) +{ + std::ostringstream tmp{}; + tmp << rat.numerator() << '/' << rat.denominator(); + out << tmp.str(); + + return out; +} diff --git a/exploring-cpp-2e/chapter67/rational.hpp b/exploring-cpp-2e/chapter67/rational.hpp new file mode 100644 index 0000000..a8e76a1 --- /dev/null +++ b/exploring-cpp-2e/chapter67/rational.hpp @@ -0,0 +1,88 @@ +// Listing 46-10. The rational Class Definition +#ifndef RATIONAL_HPP_ +#define RATIONAL_HPP_ + +#include +#include +#include + +/// Represent a rational number (fraction) as a numerator and denominator. +class rational +{ +public: + class zero_denominator : public std::logic_error + { + public: + zero_denominator(std::string const& what) : logic_error{what} {} + }; + rational(): rational{0} {} + rational(int num): numerator_{num}, denominator_{1} {} + rational(int num, int den); + rational(double r); + + int numerator() const { return numerator_; } + int denominator() const { return denominator_; } + float as_float() const; + double as_double() const; + long double as_long_double() const; + + rational& operator=(int); // optimization to avoid an unneeded call to reduce() + rational& operator+=(rational const& rhs); + rational& operator-=(rational const& rhs); + rational& operator*=(rational const& rhs); + rational& operator/=(rational const& rhs); + rational& operator++(); + rational& operator--(); + rational operator++(int); + rational operator--(int); + +private: + /// Reduce the numerator and denominator by their GCD. + void reduce(); + /// Reduce the numerator and denominator, and normalize the signs of both, + /// that is, ensure denominator is not negative. + void normalize(); + /// Return an initial value for denominator_. Throw a zero_denominator + /// exception if @p den is zero. Always return a positive number. + int init_denominator(int den); + int numerator_; + int denominator_; +}; + +/// Compute the greatest common divisor of two integers, using Euclid's algorithm. +int gcd(int n, int m); + +rational abs(rational const& r); +rational operator-(rational const& r); +rational operator+(rational const& lhs, rational const& rhs); +rational operator-(rational const& lhs, rational const& rhs); +rational operator*(rational const& lhs, rational const& rhs); +rational operator/(rational const& lhs, rational const& rhs); + +bool operator==(rational const& a, rational const& b); +bool operator<(rational const& a, rational const& b); + +inline bool operator!=(rational const& a, rational const& b) +{ + return not (a == b); +} + +inline bool operator<=(rational const& a, rational const& b) +{ + return not (b < a); +} + +inline bool operator>(rational const& a, rational const& b) +{ + return b < a; +} + +inline bool operator>=(rational const& a, rational const& b) +{ + return not (b > a); +} + +std::istream& operator>>(std::istream& in, rational& rat); +std::ostream& operator<<(std::ostream& out, rational const& rat); + +#endif diff --git a/exploring-cpp-2e/chapter68/gcd.hpp b/exploring-cpp-2e/chapter68/gcd.hpp new file mode 100644 index 0000000..5a4d407 --- /dev/null +++ b/exploring-cpp-2e/chapter68/gcd.hpp @@ -0,0 +1,21 @@ +#ifndef GCD_HPP_ +#define GCD_HPP_ + +/// Compute greatest-common-denominator. +/// @param n +/// @param m +template +T gcd(T n, T m) +{ + static const T zero{}; + if (n < zero) + n = -n; + while (m != zero) { + T tmp{n % m}; + n = m; + m = tmp; + } + return n; +} + +#endif diff --git a/exploring-cpp-2e/chapter68/ioflags.hpp b/exploring-cpp-2e/chapter68/ioflags.hpp new file mode 100644 index 0000000..45e28e2 --- /dev/null +++ b/exploring-cpp-2e/chapter68/ioflags.hpp @@ -0,0 +1,32 @@ +#ifndef IOFLAGS_HPP_ +#define IOFLAGS_HPP_ + +/** @file + * @brief Save and restore I/O stream flags. + */ + +/** Save and restore I/O stream flags. + * When a function needs to temporarily alter an I/O stream flags, + * simply define an object of type @c ioflags. Set whatever flags + * you want. When the block exits or function returns, the + * original flags are restored. + */ + +class ioflags +{ +public: + /// Save the formatting flags from @p stream. + /// @param stream The stream that will have its flags modified and restored. + ioflags(std::basic_ios& stream) : stream_(stream), flags_{stream.flags()} {} + /// Restore the formatting flags. + ~ioflags() { stream_.flags(flags_); } + + ioflags(ioflags const&) = delete; + ioflags& operator=(ioflags const&) = delete; + +private: + std::basic_ios& stream_; + std::ios_base::fmtflags flags_; +}; + +#endif diff --git a/exploring-cpp-2e/chapter68/list6801.cpp b/exploring-cpp-2e/chapter68/list6801.cpp new file mode 100644 index 0000000..2caa97c --- /dev/null +++ b/exploring-cpp-2e/chapter68/list6801.cpp @@ -0,0 +1,53 @@ +// Listing 68-1. Member Access Operators +#include +#include + +template +class point2d { +public: + point2d(T x, T y) : x_(x), y_(y) {} + virtual ~point2d() {} + T x() const { return x_; } + T y() const { return y_; } + T abs() const { return std::sqrt(x() * x() + y() * y()); } + virtual void print(std::ostream& stream) const { + stream << '(' << x() << ", " << y() << ')'; + } +private: + T x_, y_; +}; + +template +class point3d : public point2d { +public: + point3d(T x, T y, T z) : point2d(x, y), z_(z) {} + T z() const { return z_; } + T abs() const { + return static_cast(std::sqrt(this->x() * this->x() + + this->y() * this->y() + + this->z() * this->z())); + } + virtual void print(std::ostream& stream) const { + stream << '(' << this->x() << ", " << this->y() << ", " << z() << ')'; + } +private: + T z_; +}; + +template +std::ostream& operator<<(std::ostream& stream, point2d const& pt) +{ + pt.print(stream); + return stream; +} + +int main() +{ + point3d origin{0, 0, 0}; + std::cout << "abs(origin) = " << origin.abs() << '\n'; + + point3d unit{1, 1, 1}; + point2d* ptr{ &unit }; + std::cout << "abs(unit) = " << ptr->abs() << '\n'; + std::cout << "*ptr = " << *ptr << '\n'; +} diff --git a/exploring-cpp-2e/chapter68/list6802.cpp b/exploring-cpp-2e/chapter68/list6802.cpp new file mode 100644 index 0000000..2b6954a --- /dev/null +++ b/exploring-cpp-2e/chapter68/list6802.cpp @@ -0,0 +1,50 @@ +// Listing 68-2. Qualified Name Lookup +#include +#include + +namespace outer { + namespace inner { + class base { + public: + int value() const { return 1; } + static int value(long x) { return static_cast(x); } + }; + } + + template + class derived : public inner::base { + public: + typedef T value_type; + using inner::base::value; + static value_type example; + value_type value(value_type i) const { return i * example; } + }; + + template + typename derived::value_type derived::example = 2; +} + +template +class more_derived : public outer::derived{ +public: + typedef outer::derived base_type; + typedef typename base_type::value_type value_type; + more_derived(value_type v) : value_{this->value(v)} {} + value_type get_value() const { return value_; } +private: + value_type value_; +}; + +int main() +{ + std::chrono::system_clock::time_point now{std::chrono::system_clock::now()}; + std::cout << now.time_since_epoch().count() << '\n'; + + outer::derived d; + std::cout << d.value() << '\n'; + std::cout << d.value(42L) << '\n'; + std::cout << outer::inner::base::value(2) << '\n'; + + more_derived md(2); + std::cout << md.get_value() << '\n'; +} diff --git a/exploring-cpp-2e/chapter68/list6803.cpp b/exploring-cpp-2e/chapter68/list6803.cpp new file mode 100644 index 0000000..d541e0d --- /dev/null +++ b/exploring-cpp-2e/chapter68/list6803.cpp @@ -0,0 +1,24 @@ +// Listing 68-3. Unqualified Name Lookup +#include + +namespace outer { + namespace inner { + struct point { int x, y; }; + inline std::ostream& operator<<(std::ostream& stream, point const& p) + { + stream << '(' << p.x << ", " << p.y << ')'; + return stream; + } + } +} + +typedef int Integer; + +int main() +{ + const int multiplier{2}; + for (Integer i : { 1, 2, 3}) { + outer::inner::point p{ i, i * multiplier }; + std::cout << p << '\n'; + } +} diff --git a/exploring-cpp-2e/chapter68/list6804.cpp b/exploring-cpp-2e/chapter68/list6804.cpp new file mode 100644 index 0000000..fc29212 --- /dev/null +++ b/exploring-cpp-2e/chapter68/list6804.cpp @@ -0,0 +1,38 @@ +// Listing 68-4. Argument-Dependent Name Lookup +#include +#include +#include "rational.hpp" + +namespace data { + template + struct point { + T x, y; + }; + template + std::basic_ostream& operator<<(std::basic_ostream& stream, point const& pt) + { + stream << '(' << pt.x << ", " << pt.y << ')'; + return stream; + } + template + T abs(point const& pt) { + using namespace std; + return sqrt(pt.x * pt.x + pt.y * pt.y); + } +} + +namespace numeric { + template + rational sqrt(rational r) + { + using std::sqrt; + return rational{sqrt(static_cast(r))}; + } +} + +int main() +{ + using namespace std; + data::point> a{ numeric::rational{1, 2}, numeric::rational{2, 4} }; + std::cout << "abs(" << a << ") = " << abs(a) << '\n'; +} diff --git a/exploring-cpp-2e/chapter68/rational.hpp b/exploring-cpp-2e/chapter68/rational.hpp new file mode 100644 index 0000000..e3ca630 --- /dev/null +++ b/exploring-cpp-2e/chapter68/rational.hpp @@ -0,0 +1,567 @@ +#ifndef RATIONAL_HPP_ +#define RATIONAL_HPP_ + +#include +#include +#include +#include +#include +#include + +#include "gcd.hpp" +#include "ioflags.hpp" + +namespace numeric { + +/// Represent a rational number (fraction) as a numerator and denominator. +template +class rational +{ +public: + /// Convenience typedef for the integral type of the numerator and denominator. + typedef T value_type; + /// Exception class if the denominator is ever zero. + class zero_denominator : public std::logic_error + { + public: + /// Construct the exception object. + zero_denominator(std::string const& what) : logic_error{what} {} + }; + + /// Default constructor and constructor from a single value. + /// As a default constructor, initializes to zero. + /// Otherwise, initializes to the integer @p num. + /// @param num The integer value to use as the initial value + rational(value_type num = 0): numerator_{num}, denominator_{1} {} + /// Construct a rational number + /// @param num numerator + /// @param den denominator + /// @throws zero_denominator if @p den == 0 + rational(value_type num, value_type den); + /// Initialize the rational number with an approximation of @p r + /// @param r the initial value + rational(double r); + /// Copy from a different type of rational. + template + rational(rational const& that); + + /// Return the numerator + value_type numerator() const { return numerator_; } + /// Return the denominator + value_type denominator() const { return denominator_; } + /// Convert the rational number to another type, especially floating-point. + template + explicit operator U() const { return static_cast(numerator()) / denominator(); } + + /// Assignment of an integer + rational& operator=(value_type); // optimization to avoid an unneeded call to reduce() + + /// Assignment of a rational with a different size. + template + rational& operator=(rational const& rhs); + + /// Addition assignment operator + rational& operator+=(rational const& rhs); + /// Addition assignment operator + rational& operator+=(value_type const& rhs); + + /// Subtraction assignment operator + rational& operator-=(rational const& rhs); + /// Subtraction assignment operator + rational& operator-=(value_type const& rhs); + + /// Multiplication assignment operator + rational& operator*=(rational const& rhs); + /// Multiplication assignment operator + rational& operator*=(value_type const& rhs); + + /// Division assignment operator + rational& operator/=(rational const& rhs); + /// Division assignment operator + rational& operator/=(value_type const& rhs); + + /// Pre-increment + rational& operator++(); + /// Pre-decrement + rational& operator--(); + /// Post-increment + rational operator++(int); + /// Post-decrement + rational operator--(int); + +private: + /// Reduce the numerator and denominator by their GCD. + void reduce(); + /// Reduce the numerator and denominator, and normalize the signs of both, + /// that is, ensure denominator is not negative. + void normalize(); + /// Scale an integer of type @p U to the value_type. If @p U has more + /// digits than @p value_type shift @p value to the right. + template + value_type scale(U value); + + value_type numerator_; + value_type denominator_; +}; + +template +rational::rational(value_type num, value_type den) +: numerator_(num), + denominator_(den == value_type() ? throw zero_denominator("zero denominator") : den) +{ + normalize(); +} + +template +rational::rational(double r) +: numerator_(static_cast(r / 100000)), denominator_(static_cast(100000)) +{} + +template +template +rational::rational(rational const& that) +: numerator_(scale(that.numerator())), denominator_(scale(that.denominator())) +{ + reduce(); +} + +template +template +T rational::scale(U value) +{ + if (std::numeric_limits::digits >= std::numeric_limits::digits) + return T(value); + else + return T(value >> (std::numeric_limits::digits - std::numeric_limits::digits)); +} + +template +void rational::normalize() +{ + if (denominator_ < value_type()) + { + denominator_ = -denominator_; + numerator_ = -numerator_; + } + reduce(); +} + +template +void rational::reduce() +{ + value_type div(gcd(numerator(), denominator())); + if (div == value_type()) + throw zero_denominator("zero denominator"); + numerator_ /= div; + denominator_ /= div; +} + +template +rational& rational::operator=(T num) +{ + numerator_ = num; + denominator_ = value_type(1); + return *this; +} + +template +template +rational& rational::operator=(rational const& rhs) +{ + numerator_ = scale(rhs.numerator()); + denominator_ = scale(rhs.denominator()); + reduce(); + return *this; +} + +template +rational& rational::operator+=(rational const& rhs) +{ + numerator_ = numerator() * rhs.denominator() + rhs.numerator() * denominator(); + denominator_ *= rhs.denominator(); + reduce(); + return *this; +} + +template +rational& rational::operator+=(value_type const& rhs) +{ + numerator_ = numerator() + rhs * denominator(); + reduce(); + return *this; +} + +template +rational& rational::operator-=(rational const& rhs) +{ + numerator_ = numerator() * rhs.denominator() - rhs.numerator() * denominator(); + denominator_ *= rhs.denominator(); + reduce(); + return *this; +} + +template +rational& rational::operator-=(value_type const& rhs) +{ + numerator_ = numerator() - rhs * denominator(); + reduce(); + return *this; +} + +template +rational& rational::operator*=(rational const& rhs) +{ + numerator_ *= rhs.numerator(); + denominator_ *= rhs.denominator(); + reduce(); + return *this; +} + +template +rational& rational::operator*=(value_type const& rhs) +{ + numerator_ *= rhs; + reduce(); + return *this; +} + +template +rational& rational::operator/=(rational const& rhs) +{ + if (rhs.numerator() == value_type()) + throw zero_denominator("divide by zero"); + numerator_ *= rhs.denominator(); + denominator_ *= rhs.numerator(); + normalize(); + return *this; +} + +template +rational& rational::operator/=(value_type const& rhs) +{ + if (rhs == value_type()) + throw zero_denominator("divide by zero"); + denominator_ *= rhs; + normalize(); + return *this; +} + +template +rational& rational::operator++() +{ + numerator_ += denominator(); + return *this; +} + +template +rational rational::operator++(int) +{ + rational result(*this); + ++*this; + return result; +} + +template +rational& rational::operator--() +{ + numerator_ -= denominator(); + return *this; +} + +template +rational rational::operator--(int) +{ + rational result(*this); + --*this; + return result; +} + +/// Negate a rational number +template +rational operator-(rational const& r) +{ + return rational(-r.numerator(), r.denominator()); +} + +template +rational absval(rational const& r) +{ + using namespace std; + return rational(abs(r.numerator()), r.denominator()); +} + +/// Addition +template +rational operator+(rational lhs, rational const& rhs) +{ + lhs += rhs; + return lhs; +} + +/// Addition +template +rational operator+(rational lhs, T const& rhs) +{ + lhs += rhs; + return lhs; +} + +/// Addition +template +rational operator+(T const& lhs, rational rhs) +{ + rhs += lhs; + return rhs; +} + +/// Subtraction +template +rational operator-(rational lhs, rational const& rhs) +{ + lhs -= rhs; + return lhs; +} + +/// Subtraction +template +rational operator-(rational lhs, T const& rhs) +{ + lhs -= rhs; + return lhs; +} + +/// Subtraction +template +rational operator-(T const& lhs, rational rhs) +{ + // Gotta be a little tricky. + rhs += -lhs; + return -rhs; +} + +/// Multiplication +template +rational operator*(rational lhs, rational const& rhs) +{ + lhs *= rhs; + return lhs; +} + +/// Multiplication +template +rational operator*(rational lhs, T const& rhs) +{ + lhs *= rhs; + return lhs; +} + +/// Multiplication +template + rational operator*(T const& lhs, rational rhs) +{ + rhs *= lhs; + return rhs; +} + +/// Division +template +rational operator/(rational lhs, rational const& rhs) +{ + lhs /= rhs; + return lhs; +} + +/// Division +template +rational operator/(rational lhs, T const& rhs) +{ + lhs /= rhs; + return lhs; +} + +/// Division +template +rational operator/(T const& lhs, rational rhs) +{ + return rational(lhs * rhs.denominator(), rhs.numerator()); +} + + +/// Equality comparison +template +bool operator==(rational const& a, rational const& b) +{ + return a.numerator() == b.numerator() and + a.denominator() == b.denominator(); +} + +/// Equality comparison +template +bool operator==(rational const& lhs, T rhs) +{ + return lhs.denominator() == 1 and + lhs.numerator() == rhs; +} + +/// Equality comparison +template +bool operator==(T lhs, rational const& rhs) +{ + return rhs.denominator() == 1 and + rhs.numerator() == lhs; +} + +/// Less-than comparison +template +bool operator<(rational const& a, rational const& b) +{ + return a.numerator() * b.denominator() < b.numerator() * a.denominator(); +} + +/// Less-than comparison +template +bool operator<(rational const& a, T const& b) +{ + return a.numerator() < b * a.denominator(); +} + +/// Less-than comparison +template +bool operator<(T const& a, rational const& b) +{ + return a * b.denominator() < b.numerator(); +} + +/// Inequality comparison +template +inline bool operator!=(rational const& a, rational const& b) +{ + return not (a == b); +} + +/// Inequality comparison +template +inline bool operator!=(rational const& a, T b) +{ + return not (a == b); +} + +/// Inequality comparison +template +inline bool operator!=(T a, rational const& b) +{ + return not (a == b); +} + +/// Less-than-or-equal comparison +template +inline bool operator<=(rational const& a, rational const& b) +{ + return not (b < a); +} + +/// Less-than-or-equal comparison +template +inline bool operator<=(rational const& a, T const& b) +{ + return not (b < a); +} + +/// Less-than-or-equal comparison +template +inline bool operator<=(T const& a, rational const& b) +{ + return not (b < a); +} + +/// Greater-than comparison +template +inline bool operator>(rational const& a, rational const& b) +{ + return b < a; +} + +/// Greater-than comparison +template +inline bool operator>(rational const& a, T const& b) +{ + return b < a; +} + +/// Greater-than comparison +template +inline bool operator>(T const& a, rational const& b) +{ + return b < a; +} + +/// Greater-than-or-equal comparison +template +inline bool operator>=(rational const& a, rational const& b) +{ + return not (b > a); +} + +/// Greater-than-or-equal comparison +template +inline bool operator>=(rational const& a, T const& b) +{ + return not (b > a); +} + +/// Greater-than-or-equal comparison +template +inline bool operator>=(T const& a, rational const& b) +{ + return not (b > a); +} + +/// Input operator +template +std::basic_istream& operator>>(std::basic_istream& in, rational& rat) +{ + typename std::basic_istream::sentry sentry(in, false); + ioflags flags(in); + + T n = T(); + if (not (in >> n)) + // Error reading the numerator. + return in; + + in >> std::noskipws; + char sep('\0'); + if (not (in >> sep)) + // Error reading the separator character. + return in; + else if (sep != '/') + { + // Push sep back into the input stream, so the next input operation + // will read it. + in.unget(); + rat = n; + return in; + } + else + { + T d = T(); + if (in >> d) + // Successfully read numerator, separator, and denominator. + rat = rational(n, d); + } + + return in; +} + +/// Output operator +template +std::basic_ostream& operator<<(std::basic_ostream& out, rational const& rat) +{ + typename std::basic_ostream::sentry sentry(out); + std::ostringstream stream; + stream << rat.numerator() << '/' << rat.denominator(); + out << stream.str(); + return out; +} + +} // namespace numeric +#endif diff --git a/exploring-cpp-2e/chapter69/list6901.cpp b/exploring-cpp-2e/chapter69/list6901.cpp new file mode 100644 index 0000000..39bb60b --- /dev/null +++ b/exploring-cpp-2e/chapter69/list6901.cpp @@ -0,0 +1,19 @@ +// Listing 69-1. Qualifying a Member Function with the Base Class Name +#include + +class base { +public: + void print(int x) { std::cout << "int: " << x << '\n'; } +}; +class derived : public base { +public: + void print(double x) { std::cout << "double: " << x << '\n'; } +}; +int main() +{ + derived d{}; + d.print(3); // prints double: 3 + d.print(3.0); // prints double: 3 + d.base::print(3); // prints int: 3 + d.base::print(3.0); // prints int: 3 +} diff --git a/exploring-cpp-2e/chapter69/list6902.cpp b/exploring-cpp-2e/chapter69/list6902.cpp new file mode 100644 index 0000000..b41f960 --- /dev/null +++ b/exploring-cpp-2e/chapter69/list6902.cpp @@ -0,0 +1,18 @@ +// Listing 69-2. Overloading Named with a using Declaration +#include + +class base { +public: + void print(int x) { std::cout << "int: " << x << '\n'; } +}; +class derived : public base { +public: + void print(double x) { std::cout << "double: " << x << '\n'; } + using base::print; +}; +int main() +{ + derived d{}; + d.print(3); // prints int: 3 + d.print(3.0); // prints double: 3 +} diff --git a/exploring-cpp-2e/chapter69/list6903.cpp b/exploring-cpp-2e/chapter69/list6903.cpp new file mode 100644 index 0000000..a622d3e --- /dev/null +++ b/exploring-cpp-2e/chapter69/list6903.cpp @@ -0,0 +1,20 @@ +// Listing 69-3. Adding a Base Class Overload +#include + +class base { +public: + void print(int x) { std::cout << "int: " << x << '\n'; } + void print(long x) { std::cout << "long: " << x << '\n'; } +}; +class derived : public base { +public: + void print(double x) { std::cout << "double: " << x << '\n'; } + using base::print; +}; +int main() +{ + derived d{}; + d.print(3); // prints int: 3 + d.print(3.0); // prints double: 3 + d.print(3L); // prints long: 3 +} diff --git a/exploring-cpp-2e/chapter69/list6904.cpp b/exploring-cpp-2e/chapter69/list6904.cpp new file mode 100644 index 0000000..c579cd7 --- /dev/null +++ b/exploring-cpp-2e/chapter69/list6904.cpp @@ -0,0 +1,58 @@ +// Listing 69-4. Ranking Functions for Overload Resolution + 1 #include + 2 #include + 3 + 4 void print(std::string const& str) { std::cout << str; } + 5 void print(int x) { std::cout << "int: " << x; } + 6 void print(double x) { std::cout << "double: " << x; } + 7 + 8 class base { + 9 public: +10 void print(std::string const& str) const { ::print(str); ::print("\n"); } +11 void print(std::string const& s1, std::string const& s2) +12 { +13 print(s1); print(s2); +14 } +15 }; +16 +17 class convert : public base { +18 public: +19 convert() { print("convert()"); } +20 convert(double) { print("convert(double)"); } +21 operator int() const { print("convert::operator int()"); return 42; } +22 operator float() const { print("convert::operator float()"); return 3.14159f; } +23 }; +24 +25 class demo : public base { +26 public: +27 demo(int) { print("demo(int)"); } +28 demo(long) { print("demo(long)"); } +29 demo(convert) { print("demo(convert)"); } +30 demo(int, int) { print("demo(int, int)"); } +31 }; +32 +33 class other { +34 public: +35 other() { std::cout << "other::other()\n"; } +36 other(int,int) { std::cout << "other::other(int, int)\n"; } +37 operator convert() const +38 { +39 std::cout << "other::operator convert()\n"; return convert(); +40 } +41 }; +42 +43 int operator+(demo const&, demo const&) +44 { +45 print("operator+(demo,demo)\n"); return 42; +46 } +47 +48 int operator+(int, demo const&) { print("operator+(int,demo)\n"); return 42; } +49 +50 int main() +51 { +52 other x{}; +53 demo d{x}; +54 3L + d; +55 short s{2}; +56 d + s; +57 } diff --git a/exploring-cpp-2e/chapter69/list6905.cpp b/exploring-cpp-2e/chapter69/list6905.cpp new file mode 100644 index 0000000..d4541bf --- /dev/null +++ b/exploring-cpp-2e/chapter69/list6905.cpp @@ -0,0 +1,45 @@ +// Listing 69-5. Fix the Overloading Errors +#include +#include + +void easy(long) {} +void easy(double) {} +void call_easy() { + easy(42); +} + +void pointer(double*) {} +void pointer(void*) {} +const int zero = 0; +void call_pointer() { + pointer(&zero); +} + +int add(int a) { return a; } +int add(int a, int b) { return a + b; } +int add(int a, int b, int c) { return a + b + c; } +int add(int a, int b, int c, int d) { return a + b + c + d; } +int add(int a, int b, int c, int d, int e) { return a + b + c + d + e; } +void call_add() { + add(1, 2, 3L, 4.0); +} + +void ref(int const&) {} +void ref(int) {} +void call_ref() { + int x; + ref(x); +} + +class base {}; +class derived : public base {}; +class sibling : public base {}; +class most_derived : public derived {}; + +void tree(derived&, sibling&) {} +void tree(most_derived&, base&) {} +void call_tree() { + sibling s; + most_derived md; + tree(md, s); +} diff --git a/exploring-cpp-2e/chapter69/list6906.cpp b/exploring-cpp-2e/chapter69/list6906.cpp new file mode 100644 index 0000000..07bf596 --- /dev/null +++ b/exploring-cpp-2e/chapter69/list6906.cpp @@ -0,0 +1,14 @@ +// Listing 69-6. Default Arguments +#include + +int add(int x = 0, int y = 0) +{ + return x + y; +} + +int main() +{ + std::cout << add() << '\n'; + std::cout << add(5) << '\n'; + std::cout << add(32, add(4, add(6))) << '\n'; +} diff --git a/exploring-cpp-2e/chapter70/list7001.cpp b/exploring-cpp-2e/chapter70/list7001.cpp new file mode 100644 index 0000000..0a9d2fb --- /dev/null +++ b/exploring-cpp-2e/chapter70/list7001.cpp @@ -0,0 +1,36 @@ +// Listing 70-1. Computing a Power of 10 at Compile Time with Templates +template +struct power10; // forward declaration + +template +struct square +{ + // A metaprogramming function to square a value. + enum t { value = N * N }; +}; + +template +struct power10_aux +{ + // Primary template is for odd N (Even is false) + enum t { value = 10 * power10::value }; +}; + +template +struct power10_aux +{ + // Specialization when N is even: square the value + enum t { value = square::value>::value }; +}; + +template +struct power10 +{ + enum t { value = power10_aux::value }; +}; + +template<> +struct power10<0> +{ + enum t { value = 1 }; +}; diff --git a/exploring-cpp-2e/chapter70/list7002.cpp b/exploring-cpp-2e/chapter70/list7002.cpp new file mode 100644 index 0000000..63dc520 --- /dev/null +++ b/exploring-cpp-2e/chapter70/list7002.cpp @@ -0,0 +1,25 @@ +// Listing 70-2. Implementing the _binary User-Defined Literal Operator +/// Compute one bit of a binary integer. +/// Compute a new result by taking the right-most decimal digit from @p digits, +/// and if it is 1, shifting the 1 left by @p shift places and bitwise ORing +/// the value with @p result. Ignore digits other than 0 or 1. Recurse +/// to compute the remaining result. +/// @param digits The user-supplied decimal digits, should use only 0 and 1 +/// @param result The numeric result so far +/// @param shift The number of places to shift the right-most digit in @p digits +/// @return if @p digits is zero, return @p result; otherwise return the result +/// of converting @p digits to binary +constexpr unsigned long long binary_helper(unsigned long long digits, + unsigned long long result, int shift) +{ + return digits == 0 ? + result : + binary_helper(digits / 10, + result | ((digits % 10 == 1) << shift), + digits % 10 < 2 ? shift + 1 : shift); +} + +constexpr unsigned long long operator"" _binary(unsigned long long digits) +{ + return binary_helper(digits, 0ULL, 0); +} diff --git a/exploring-cpp-2e/chapter70/list7003.cpp b/exploring-cpp-2e/chapter70/list7003.cpp new file mode 100644 index 0000000..9db5f7e --- /dev/null +++ b/exploring-cpp-2e/chapter70/list7003.cpp @@ -0,0 +1,32 @@ +// Listing 70-3. Using a Function Parameter Pack to Print Arbitrary Values +#include +#include + +// Forward declaration. +template +void print(std::ostream& stream, Types&&...); + +// Print the first value in the list, then recursively +// call print() to print the rest of the list. +template +void print_split(std::ostream& stream, T&& head, Types&& ... rest) +{ + stream << head << ' '; + print(stream, std::forward(rest)...); +} + +// End recursion when there are no more values to print. +void print_split(std::ostream&) +{} + +// Print an arbitrary list of values to a stream. +template +void print(std::ostream& stream, Types&&... args) +{ + print_split(stream, std::forward(args)...); +} + +int main() +{ + print(std::cout, 42, 'x', "hello", 3.14159, 0, '\n'); +} diff --git a/exploring-cpp-2e/chapter70/list7004.cpp b/exploring-cpp-2e/chapter70/list7004.cpp new file mode 100644 index 0000000..a94acdb --- /dev/null +++ b/exploring-cpp-2e/chapter70/list7004.cpp @@ -0,0 +1,39 @@ +// Listing 70-4. Using a Function Parameter Pack to Implement the _binary Operator +/// Extract one bit from a bit string and then recurse. +template +struct binary_helper +{ + constexpr unsigned long long operator()(unsigned long long result) const; +}; + +/// Teminate recursion when interpreting a bit string. + +template +struct binary_helper +{ + constexpr unsigned long long operator()(unsigned long long result) const; +}; + +template +constexpr unsigned long long +binary_helper::operator()(unsigned long long result) +const +{ + static_assert(Head == '0' or Head == '1', "_binary contains only 0 or 1"); + return binary_helper{}(result << 1 | (Head - '0')); +} + +template +constexpr unsigned long long +binary_helper::operator()(unsigned long long result) +const +{ + static_assert(Head == '0' or Head == '1', "_binary contains only 0 or 1"); + return result << 1 | (Head - '0'); +} + +template +constexpr unsigned long long operator"" _binary() +{ + return binary_helper{}(0ULL); +} diff --git a/exploring-cpp-2e/chapter70/list7005.cpp b/exploring-cpp-2e/chapter70/list7005.cpp new file mode 100644 index 0000000..28b8a43 --- /dev/null +++ b/exploring-cpp-2e/chapter70/list7005.cpp @@ -0,0 +1,7 @@ +// Listing 70-5. Implementing the is_same Metafunction +template +struct is_same : std::false_type {}; + +template +struct is_same : std::true_type {}; + diff --git a/exploring-cpp-2e/chapter70/list7006.cpp b/exploring-cpp-2e/chapter70/list7006.cpp new file mode 100644 index 0000000..fc0ebf2 --- /dev/null +++ b/exploring-cpp-2e/chapter70/list7006.cpp @@ -0,0 +1,8 @@ +// Listing 70-6. One Implementation of the promote Metafunction +template struct promote { typedef T type; }; +template<> struct promote { typedef int type; }; +template<> struct promote { typedef int type; }; +template<> struct promote { typedef int type; }; +template<> struct promote { typedef int type; }; +template<> struct promote { typedef int type; }; +template<> struct promote { typedef int type; }; diff --git a/exploring-cpp-2e/chapter70/list7007.cpp b/exploring-cpp-2e/chapter70/list7007.cpp new file mode 100644 index 0000000..ab0270b --- /dev/null +++ b/exploring-cpp-2e/chapter70/list7007.cpp @@ -0,0 +1,18 @@ +// Listing 70-7. Another Implementation of the promote Metafunction +// Primary template when IsMember=std::true_type. +template +struct get_member { + typedef T type; +}; + +template +struct get_member +{ + typedef int type; +}; + +template +struct promote { + typedef typename get_member::type, T>::type type; +}; diff --git a/exploring-cpp-2e/chapter70/list7008.cpp b/exploring-cpp-2e/chapter70/list7008.cpp new file mode 100644 index 0000000..e9ff841 --- /dev/null +++ b/exploring-cpp-2e/chapter70/list7008.cpp @@ -0,0 +1,19 @@ +// Listing 70-8. Implementing the is_member Metafunction +template struct is_member; + +// Helper metafunction to separate Args into Head, Rest +template +struct is_member_helper : + std::conditional::value, + std::true_type, + is_member>::type +{}; + +/// Test whether Check is the same type as a type in Args. +template +struct is_member : is_member_helper {}; + +// Partial specialization for empty Args +template +struct is_member : std::false_type {}; + diff --git a/exploring-cpp-2e/chapter70/list7009.cpp b/exploring-cpp-2e/chapter70/list7009.cpp new file mode 100644 index 0000000..4df57b4 --- /dev/null +++ b/exploring-cpp-2e/chapter70/list7009.cpp @@ -0,0 +1,12 @@ +// Listing 70-9. One Way to Implement std::conditional +template +struct conditional +{ + typedef IfFalse type; +}; + +template +struct conditional +{ + typedef IfTrue type; +}; diff --git a/exploring-cpp-2e/chapter70/list7010.cpp b/exploring-cpp-2e/chapter70/list7010.cpp new file mode 100644 index 0000000..db0d977 --- /dev/null +++ b/exploring-cpp-2e/chapter70/list7010.cpp @@ -0,0 +1,38 @@ +// Listing 70-10. Implementing an Integer-Keyed Type Choice +#include +#include + +// forward declaration +template +struct choice; + +// Default: subtract one, drop the head of the list, and recurse. +template +struct choice_split { + typedef typename choice::type type; +}; + +// Index 0: pick the first type in the list. +template +struct choice_split<0, T, Ts...> { + typedef T type; +}; + +// Define type member as the N-th type in Types. +template +struct choice { + typedef typename choice_split::type type; +}; + +// N is out of bounds +template +struct choice {}; + +// Tests + +static_assert(std::is_same::type>::value, "error in choice<0>"); +static_assert(std::is_same::type>::value, "error in choice<1>"); +static_assert(std::is_same::type>::value, "error in choice<2>"); diff --git a/exploring-cpp-2e/chapter70/list7011.cpp b/exploring-cpp-2e/chapter70/list7011.cpp new file mode 100644 index 0000000..4d0c6b4 --- /dev/null +++ b/exploring-cpp-2e/chapter70/list7011.cpp @@ -0,0 +1,10 @@ +// Listing 70-11. Implementing an Integer-Keyed Type Choice +#include +#include + +template +typename std::enable_if::is_signed, T>::type +minus(T const& x) +{ + return -x; +} diff --git a/exploring-cpp-2e/chapter70/list7012.cpp b/exploring-cpp-2e/chapter70/list7012.cpp new file mode 100644 index 0000000..6fb5e5d --- /dev/null +++ b/exploring-cpp-2e/chapter70/list7012.cpp @@ -0,0 +1,12 @@ +// Listing 70-12. Specializing the rational Class Using enable_if +#include +#include + +template::is_integer, T>::type> +class rational { +public: + ... normal class definition here ... +}; + +rational okay{1, 2}; +rational problem{1, 2}; diff --git a/exploring-cpp-2e/chapter70/list7013.cpp b/exploring-cpp-2e/chapter70/list7013.cpp new file mode 100644 index 0000000..42bd0d1 --- /dev/null +++ b/exploring-cpp-2e/chapter70/list7013.cpp @@ -0,0 +1,44 @@ +// Listing 70-13. Using enable_if to Direct Overload Resolution +#include +#include + +template +void encode(std::ostream& stream, T const& int_value, + typename std::enable_if::value, T>::type* = nullptr) +{ + // All integer types end up here. + stream << "int: " << int_value << '\n'; +} + +template +void encode(std::ostream& stream, T const& enum_value, + typename std::enable_if::value>::type* = nullptr) +{ + // All enumerated types end up here. + // Record the underlying integer value. + stream << "enum: " << + static_cast::type>(enum_value) << '\n'; +} + +template +void encode(std::ostream& stream, T const& float_value, + typename std::enable_if::value>::type* = nullptr) +{ + // All floating-point types end up here. + stream << "float: " << float_value << '\n'; +} + +// enable_if forms cooperate with normal overloading +void encode(std::ostream& stream, std::string const& string_value) +{ + stream << "str: " << string_value << '\n'; +} + +int main() +{ + encode(std::cout, 1); + enum class color { red, green, blue }; + encode(std::cout, color::blue); + encode(std::cout, 3.0); + encode(std::cout, std::string("string")); +} diff --git a/exploring-cpp-2e/chapter71/index.html b/exploring-cpp-2e/chapter71/index.html new file mode 100644 index 0000000..84ed4d3 --- /dev/null +++ b/exploring-cpp-2e/chapter71/index.html @@ -0,0 +1,30 @@ + + + + + Exploring C++: Project 4, Exploration 71: Calculator + + + +

Exploring C++ 11: Problems and Solutions Handbook

+

Project 4, Exploration 71: Calculator

+

The calculator project is the most complicated one, being the last. +I recommend following the six steps I outline in Exploration 71. +The files below show the evolution of my solution as I follow the six steps. +The parser undergoes the greatest change, +although its central spirit remains the same throughout all steps.

+

In this project, I use Boost.Test for the unit-testing framework. +The project was just too complicated for the trivial test.hpp +file that other projects use. If you do not have access to Boost for any reason, do not +compile the tester program, only the calc program.

+

See also the main projects page. +

    +
  1. Simple parser, arithmetic expressions +
  2. Add variables and assignment +
  3. Store and evaluate parse trees +
  4. Define simple functions +
  5. Save and load libraries +
  6. Support additional data types +
+ + diff --git a/exploring-cpp-2e/chapter71/step1/Doxyfile b/exploring-cpp-2e/chapter71/step1/Doxyfile new file mode 100644 index 0000000..e86843f --- /dev/null +++ b/exploring-cpp-2e/chapter71/step1/Doxyfile @@ -0,0 +1,2280 @@ +# Doxyfile 1.8.5 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = "Calculator" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = "Step 1" + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is included in +# the documentation. The maximum height of the logo should not exceed 55 pixels +# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo +# to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese- +# Traditional, Croatian, Czech, Danish, Dutch, English, Esperanto, Farsi, +# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en, +# Korean, Korean-en, Latvian, Norwegian, Macedonian, Persian, Polish, +# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, +# Turkish, Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a +# new page for each member. If set to NO, the documentation of a member will be +# part of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. +# +# Note For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by by putting a % sign in front of the word +# or globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO these classes will be included in the various overviews. This option has +# no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the +# todo list. This list is created by putting \todo commands in the +# documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the +# test list. This list is created by putting \test commands in the +# documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES the list +# will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. Do not use file names with spaces, bibtex cannot handle them. See +# also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO doxygen will only warn about wrong or incomplete parameter +# documentation, but not about the absence of documentation. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. +# Note: If this tag is empty the current directory is searched. + +INPUT = + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank the +# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, +# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, +# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, +# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, +# *.qsf, *.as and *.js. + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER ) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = YES + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES, then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 1 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user- +# defined cascading style sheet that is included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefor more robust against future updates. +# Doxygen will copy the style sheet file to the output directory. For an example +# see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the stylesheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to NO can help when comparing the output of multiple runs. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = NO + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler ( hhc.exe). If non-empty +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated ( +# YES) or that it should be included in the master .chm file ( NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated ( +# YES) or a normal table of contents ( NO) in the .chm file. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using prerendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , / +
+
+
Class List
+
+
+
Here are the classes, structs, unions and interfaces with brief descriptions:
+
+ + + + diff --git a/exploring-cpp-2e/chapter71/step1/html/bc_s.png b/exploring-cpp-2e/chapter71/step1/html/bc_s.png new file mode 100644 index 0000000..224b29a Binary files /dev/null and b/exploring-cpp-2e/chapter71/step1/html/bc_s.png differ diff --git a/exploring-cpp-2e/chapter71/step1/html/bdwn.png b/exploring-cpp-2e/chapter71/step1/html/bdwn.png new file mode 100644 index 0000000..940a0b9 Binary files /dev/null and b/exploring-cpp-2e/chapter71/step1/html/bdwn.png differ diff --git a/exploring-cpp-2e/chapter71/step1/html/calc_8cpp.html b/exploring-cpp-2e/chapter71/step1/html/calc_8cpp.html new file mode 100644 index 0000000..b33c39c --- /dev/null +++ b/exploring-cpp-2e/chapter71/step1/html/calc_8cpp.html @@ -0,0 +1,95 @@ + + + + + + +Calculator: calc.cpp File Reference + + + + + + +
+
+ + + + + + +
+
Calculator +  Step 1 +
+
+
+ + + + +
+
+ +
+
calc.cpp File Reference
+
+
+
#include <iostream>
+#include <sstream>
+#include <string>
+#include "parse.hpp"
+
+

Go to the source code of this file.

+ + + + +

+Functions

int main ()
 
+

Function Documentation

+ +
+
+ + + + + + + +
int main ()
+
+ +

Definition at line 14 of file calc.cpp.

+ +

References parse_loop().

+
15 {
+
16  parse_loop(std::cin, std::cout);
+
17 }
+
void parse_loop(std::istream &input, std::ostream &output)
Definition: parse.cpp:183
+
+
+
+
+ + + + diff --git a/exploring-cpp-2e/chapter71/step1/html/calc_8cpp_source.html b/exploring-cpp-2e/chapter71/step1/html/calc_8cpp_source.html new file mode 100644 index 0000000..69dcc06 --- /dev/null +++ b/exploring-cpp-2e/chapter71/step1/html/calc_8cpp_source.html @@ -0,0 +1,70 @@ + + + + + + +Calculator: calc.cpp Source File + + + + + + +
+
+ + + + + + +
+
Calculator +  Step 1 +
+
+
+ + + + +
+
+
+
calc.cpp
+
+
+Go to the documentation of this file.
1 #include <iostream>
+
2 #include <sstream>
+
3 #include <string>
+
4 
+
5 #include "parse.hpp"
+
6 
+
14 int main()
+
15 {
+
16  parse_loop(std::cin, std::cout);
+
17 }
+
void parse_loop(std::istream &input, std::ostream &output)
Definition: parse.cpp:183
+
int main()
Definition: calc.cpp:14
+ +
+ + + + diff --git a/exploring-cpp-2e/chapter71/step1/html/classes.html b/exploring-cpp-2e/chapter71/step1/html/classes.html new file mode 100644 index 0000000..ff17d1b --- /dev/null +++ b/exploring-cpp-2e/chapter71/step1/html/classes.html @@ -0,0 +1,69 @@ + + + + + + +Calculator: Class Index + + + + + + +
+
+ + + + + + +
+
Calculator +  Step 1 +
+
+
+ + + + +
+
+
+
Class Index
+
+
+ + + + + + + +
  P  
+
parse_error   
parser   
+ +
+ + + + diff --git a/exploring-cpp-2e/chapter71/step1/html/classparse__error-members.html b/exploring-cpp-2e/chapter71/step1/html/classparse__error-members.html new file mode 100644 index 0000000..303f921 --- /dev/null +++ b/exploring-cpp-2e/chapter71/step1/html/classparse__error-members.html @@ -0,0 +1,63 @@ + + + + + + +Calculator: Member List + + + + + + +
+
+ + + + + + +
+
Calculator +  Step 1 +
+
+
+ + + + +
+
+
+
parse_error Member List
+
+
+ +

This is the complete list of members for parse_error, including all inherited members.

+ + +
parse_error(std::string const &msg)parse_errorinline
+ + + + diff --git a/exploring-cpp-2e/chapter71/step1/html/classparse__error.html b/exploring-cpp-2e/chapter71/step1/html/classparse__error.html new file mode 100644 index 0000000..515de2f --- /dev/null +++ b/exploring-cpp-2e/chapter71/step1/html/classparse__error.html @@ -0,0 +1,113 @@ + + + + + + +Calculator: parse_error Class Reference + + + + + + +
+
+ + + + + + +
+
Calculator +  Step 1 +
+
+
+ + + + +
+
+ +
+
parse_error Class Reference
+
+
+ +

#include <parse.hpp>

+
+Inheritance diagram for parse_error:
+
+
+ + + +
+ + + + +

+Public Member Functions

 parse_error (std::string const &msg)
 
+

Detailed Description

+

Exception class for parser errors, usually syntax errors.

+ +

Definition at line 11 of file parse.hpp.

+

Constructor & Destructor Documentation

+ +
+
+ + + + + +
+ + + + + + + + +
parse_error::parse_error (std::string const & msg)
+
+inline
+
+ +

Definition at line 13 of file parse.hpp.

+
13 : runtime_error{msg} {}
+
+
+
+
The documentation for this class was generated from the following file: +
+ + + + diff --git a/exploring-cpp-2e/chapter71/step1/html/classparse__error.png b/exploring-cpp-2e/chapter71/step1/html/classparse__error.png new file mode 100644 index 0000000..7b9e438 Binary files /dev/null and b/exploring-cpp-2e/chapter71/step1/html/classparse__error.png differ diff --git a/exploring-cpp-2e/chapter71/step1/html/classparser-members.html b/exploring-cpp-2e/chapter71/step1/html/classparser-members.html new file mode 100644 index 0000000..5403651 --- /dev/null +++ b/exploring-cpp-2e/chapter71/step1/html/classparser-members.html @@ -0,0 +1,70 @@ + + + + + + +Calculator: Member List + + + + + + +
+
+ + + + + + +
+
Calculator +  Step 1 +
+
+
+ + + + +
+
+
+
parser Member List
+
+
+ +

This is the complete list of members for parser, including all inherited members.

+ + + + + + + + + +
charify(char c)parserprivate
ctype_parserprivate
get_expr(double &result)parser
get_mult_expr(double &result)parserprivate
get_number(double &result)parserprivate
get_primary(double &result)parserprivate
input_parserprivate
parser(std::istream &input)parser
+ + + + diff --git a/exploring-cpp-2e/chapter71/step1/html/classparser.html b/exploring-cpp-2e/chapter71/step1/html/classparser.html new file mode 100644 index 0000000..30a3bc1 --- /dev/null +++ b/exploring-cpp-2e/chapter71/step1/html/classparser.html @@ -0,0 +1,529 @@ + + + + + + +Calculator: parser Class Reference + + + + + + +
+
+ + + + + + +
+
Calculator +  Step 1 +
+
+
+ + + + +
+ +
+ +

#include <parse.hpp>

+ + + + + + +

+Public Member Functions

 parser (std::istream &input)
 
bool get_expr (double &result)
 
+ + + + + + + + + +

+Private Member Functions

std::string charify (char c)
 
bool get_number (double &result)
 
bool get_primary (double &result)
 
bool get_mult_expr (double &result)
 
+ + + + + +

+Private Attributes

std::istream & input_
 
std::ctype< char > const & ctype_
 
+

Detailed Description

+

Parser class template.

+ +

Definition at line 17 of file parse.hpp.

+

Constructor & Destructor Documentation

+ +
+
+ + + + + + + + +
parser::parser (std::istream & input)
+
+

Constructor. Save the input stream.

+
Parameters
+ + +
inputThe input stream
+
+
+ +

Definition at line 6 of file parse.cpp.

+
7 : input_(input),
+
8  ctype_(std::use_facet<std::ctype<char>>(input.getloc()))
+
9 {}
+
std::istream & input_
Definition: parse.hpp:55
+
std::ctype< char > const & ctype_
Definition: parse.hpp:56
+
+
+
+

Member Function Documentation

+ +
+
+ + + + + +
+ + + + + + + + +
std::string parser::charify (char c)
+
+private
+
+

Convert a characer to a readable form.

+
Parameters
+ + +
cThe character
+
+
+
Returns
A C++-style character literal that ensures c is readable.
+ +

Definition at line 11 of file parse.cpp.

+ +

Referenced by get_number(), and get_primary().

+
12 {
+
13  if (c == '\a') return R"('\a')";
+
14  if (c == '\b') return R"('\b')";
+
15  if (c == '\f') return R"('\f')";
+
16  if (c == '\n') return R"('\n')";
+
17  if (c == '\r') return R"('\r')";
+
18  if (c == '\t') return R"('\t')";
+
19  if (c == '\v') return R"('\v')";
+
20  if (c == '\'') return R"('\'')";
+
21  if (c == '\\') return R"('\\')";
+
22 
+
23  if (isprint(c))
+
24  return std::string{"\'"} + std::string(1,c) + "\'";
+
25  else {
+
26  std::ostringstream stream{};
+
27  stream << "'\\x" << std::hex;
+
28  stream.fill('0');
+
29  stream.width(2);
+
30  stream << (std::char_traits<char>::to_int_type(c) & 0xFF) << '\'';
+
31  return stream.str();
+
32  }
+
33 }
+
+
+
+ +
+
+ + + + + + + + +
bool parser::get_expr (double & result)
+
+

Read one expression and store the result in result.

+
Parameters
+ + +
resultWhere to store the result of the expression.
+
+
+
Returns
true to continue or false to end the loop
+
Exceptions
+ + +
parse_errorfor various syntax and other errors
+
+
+ +

Definition at line 110 of file parse.cpp.

+ +

References get_mult_expr(), and input_.

+ +

Referenced by get_primary().

+
111 {
+
112  if (not get_mult_expr(result))
+
113  return false;
+
114  char c{};
+
115  while (input_ >> c) {
+
116  if (c != '+' and c != '-') {
+
117  input_.unget();
+
118  return true;
+
119  } else {
+
120  double right{};
+
121  if (not get_mult_expr(right))
+
122  throw parse_error{"syntax error: unterminated expression. Expected a multiplicative-exprssion after " + std::string(c,1)};
+
123  if (c == '+')
+
124  result += right;
+
125  else
+
126  result -= right;
+
127  }
+
128  }
+
129  return true;
+
130 }
+ +
std::istream & input_
Definition: parse.hpp:55
+
bool get_mult_expr(double &result)
Definition: parse.cpp:135
+
+
+
+ +
+
+ + + + + +
+ + + + + + + + +
bool parser::get_mult_expr (double & result)
+
+private
+
+

Parse a multiplicative expression.

+
Parameters
+ + +
resultStore the number here
+
+
+
Returns
true to continue parsing or false to stop (end of file or error)
+ +

Definition at line 135 of file parse.cpp.

+ +

References get_primary(), and input_.

+ +

Referenced by get_expr().

+
136 {
+
137  if (not get_primary(result))
+
138  return false;
+
139  char c{};
+
140  while (input_ >> c) {
+
141  if (c != '*' and c != '/') {
+
142  input_.unget();
+
143  return true;
+
144  } else {
+
145  double right{};
+
146  if (not get_primary(right))
+
147  throw parse_error{"syntax error: unterminated expression. Expected a primary after " + std::string(c,1)};
+
148  if (c == '*')
+
149  result *= right;
+
150  else if (right == 0.0)
+
151  throw parse_error{"division by zero"};
+
152  else
+
153  result /= right;
+
154  }
+
155  }
+
156  return true;
+
157 }
+
bool get_primary(double &result)
Definition: parse.cpp:162
+ +
std::istream & input_
Definition: parse.hpp:55
+
+
+
+ +
+
+ + + + + +
+ + + + + + + + +
bool parser::get_number (double & result)
+
+private
+
+

Parse a number.

+
Parameters
+ + +
resultStore the number here
+
+
+
Returns
true to continue parsing or false to stop (end of file or error)
+ +

Definition at line 38 of file parse.cpp.

+ +

References charify(), and input_.

+ +

Referenced by get_primary().

+
39 {
+
40  std::string token{};
+
41  char c{};
+
42  if (not input_.get(c))
+
43  return false;
+
44  if (c == '+' or c == '-') {
+
45  token += c;
+
46  if (not input_.get(c))
+
47  throw parse_error{"unterminated number: expected a digit after the sign"};
+
48  }
+
49  if (c < '0' or c > '9') {
+
50  input_.unget();
+
51  throw parse_error{"syntax error: expected digit, got " + charify(c)};
+
52  }
+
53  while (c >= '0' and c <= '9') {
+
54  token += c;
+
55  if (not input_.get(c)) {
+
56  std::istringstream tmp{std::move(token)};
+
57  // If the value overflows, return false.
+
58  return (tmp >> result);
+
59  }
+
60  }
+
61  if (c == '.') {
+
62  token += c;
+
63  if (not input_.get(c))
+
64  throw parse_error{"unterminated number: expected digit after the decimal point"};
+
65  if (c < '0' or c > '9') {
+
66  input_.unget();
+
67  throw parse_error{"syntax error: expected digit after decimal point, got " + charify(c)};
+
68  }
+
69  while (c >= '0' and c <= '9') {
+
70  token += c;
+
71  if (not input_.get(c)) {
+
72  std::istringstream tmp{std::move(token)};
+
73  // If the value overflows or is otherwise invalid, return false.
+
74  return (tmp >> result);
+
75  }
+
76  }
+
77  }
+
78  if (c == 'e' or c == 'E') {
+
79  token += c;
+
80  if (not input_.get(c))
+
81  throw parse_error{"unterminated number: expected digit in the exponent"};
+
82  if (c == '-' or c == '+') {
+
83  token += c;
+
84  if (not input_.get(c))
+
85  throw parse_error{"unterminated number: expected digit after sign in the exponent"};
+
86  }
+
87  if (c < '0' or c > '9') {
+
88  input_.unget();
+
89  throw parse_error{"syntax error: expected digit in the exponent, got " + charify(c)};
+
90  }
+
91  while (c >= '0' and c <= '9') {
+
92  token += c;
+
93  if (not input_.get(c)) {
+
94  std::istringstream tmp{std::move(token)};
+
95  // If the value overflows or is otherwise invalid, return false.
+
96  return (tmp >> result);
+
97  }
+
98  }
+
99  }
+
100  input_.unget();
+
101 
+
102  std::istringstream tmp{std::move(token)};
+
103  // If the value overflows or is otherwise invalid, return false.
+
104  return (tmp >> result);
+
105 }
+
std::string charify(char c)
Definition: parse.cpp:11
+ +
std::istream & input_
Definition: parse.hpp:55
+
+
+
+ +
+
+ + + + + +
+ + + + + + + + +
bool parser::get_primary (double & result)
+
+private
+
+

Parse a primary expression. A primary is a parenthesized expression or a numeric literal.

+
Parameters
+ + +
resultStore the number here
+
+
+
Returns
true to continue parsing or false to stop (end of file or error)
+ +

Definition at line 162 of file parse.cpp.

+ +

References charify(), get_expr(), get_number(), and input_.

+ +

Referenced by get_mult_expr().

+
163 {
+
164  char c{};
+
165  if (not (input_ >> c))
+
166  // Can't read one character, so must be end-of-file
+
167  return false;
+
168  else if (c == '(') {
+
169  if (not get_expr(result))
+
170  return false;
+
171  if (not (input_ >> c))
+
172  throw parse_error{"syntax error: EOF when expecting ')'"};
+
173  else if (c != ')')
+
174  throw parse_error{"syntax error: expected ')', but got " + charify(c)};
+
175  else
+
176  return true;
+
177  } else {
+
178  input_.unget();
+
179  return get_number(result);
+
180  }
+
181 }
+
std::string charify(char c)
Definition: parse.cpp:11
+
bool get_number(double &result)
Definition: parse.cpp:38
+
bool get_expr(double &result)
Definition: parse.cpp:110
+ +
std::istream & input_
Definition: parse.hpp:55
+
+
+
+

Member Data Documentation

+ +
+
+ + + + + +
+ + + + +
std::ctype<char> const& parser::ctype_
+
+private
+
+ +

Definition at line 56 of file parse.hpp.

+ +
+
+ +
+
+ + + + + +
+ + + + +
std::istream& parser::input_
+
+private
+
+ +

Definition at line 55 of file parse.hpp.

+ +

Referenced by get_expr(), get_mult_expr(), get_number(), and get_primary().

+ +
+
+
The documentation for this class was generated from the following files: +
+ + + + diff --git a/exploring-cpp-2e/chapter71/step1/html/closed.png b/exploring-cpp-2e/chapter71/step1/html/closed.png new file mode 100644 index 0000000..98cc2c9 Binary files /dev/null and b/exploring-cpp-2e/chapter71/step1/html/closed.png differ diff --git a/exploring-cpp-2e/chapter71/step1/html/doxygen.css b/exploring-cpp-2e/chapter71/step1/html/doxygen.css new file mode 100644 index 0000000..4699e69 --- /dev/null +++ b/exploring-cpp-2e/chapter71/step1/html/doxygen.css @@ -0,0 +1,1357 @@ +/* The standard CSS for doxygen 1.8.5 */ + +body, table, div, p, dl { + font: 400 14px/22px Roboto,sans-serif; +} + +/* @group Heading Levels */ + +h1.groupheader { + font-size: 150%; +} + +.title { + font: 400 14px/28px Roboto,sans-serif; + font-size: 150%; + font-weight: bold; + margin: 10px 2px; +} + +h2.groupheader { + border-bottom: 1px solid #879ECB; + color: #354C7B; + font-size: 150%; + font-weight: normal; + margin-top: 1.75em; + padding-top: 8px; + padding-bottom: 4px; + width: 100%; +} + +h3.groupheader { + font-size: 100%; +} + +h1, h2, h3, h4, h5, h6 { + -webkit-transition: text-shadow 0.5s linear; + -moz-transition: text-shadow 0.5s linear; + -ms-transition: text-shadow 0.5s linear; + -o-transition: text-shadow 0.5s linear; + transition: text-shadow 0.5s linear; + margin-right: 15px; +} + +h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { + text-shadow: 0 0 15px cyan; +} + +dt { + font-weight: bold; +} + +div.multicol { + -moz-column-gap: 1em; + -webkit-column-gap: 1em; + -moz-column-count: 3; + -webkit-column-count: 3; +} + +p.startli, p.startdd, p.starttd { + margin-top: 2px; +} + +p.endli { + margin-bottom: 0px; +} + +p.enddd { + margin-bottom: 4px; +} + +p.endtd { + margin-bottom: 2px; +} + +/* @end */ + +caption { + font-weight: bold; +} + +span.legend { + font-size: 70%; + text-align: center; +} + +h3.version { + font-size: 90%; + text-align: center; +} + +div.qindex, div.navtab{ + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; +} + +div.qindex, div.navpath { + width: 100%; + line-height: 140%; +} + +div.navtab { + margin-right: 15px; +} + +/* @group Link Styling */ + +a { + color: #3D578C; + font-weight: normal; + text-decoration: none; +} + +.contents a:visited { + color: #4665A2; +} + +a:hover { + text-decoration: underline; +} + +a.qindex { + font-weight: bold; +} + +a.qindexHL { + font-weight: bold; + background-color: #9CAFD4; + color: #ffffff; + border: 1px double #869DCA; +} + +.contents a.qindexHL:visited { + color: #ffffff; +} + +a.el { + font-weight: bold; +} + +a.elRef { +} + +a.code, a.code:visited, a.line, a.line:visited { + color: #4665A2; +} + +a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited { + color: #4665A2; +} + +/* @end */ + +dl.el { + margin-left: -1cm; +} + +pre.fragment { + border: 1px solid #C4CFE5; + background-color: #FBFCFD; + padding: 4px 6px; + margin: 4px 8px 4px 2px; + overflow: auto; + word-wrap: break-word; + font-size: 9pt; + line-height: 125%; + font-family: monospace, fixed; + font-size: 105%; +} + +div.fragment { + padding: 0px; + margin: 0px; + background-color: #FBFCFD; + border: 1px solid #C4CFE5; +} + +div.line { + font-family: monospace, fixed; + font-size: 13px; + min-height: 13px; + line-height: 1.0; + text-wrap: unrestricted; + white-space: -moz-pre-wrap; /* Moz */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + white-space: pre-wrap; /* CSS3 */ + word-wrap: break-word; /* IE 5.5+ */ + text-indent: -53px; + padding-left: 53px; + padding-bottom: 0px; + margin: 0px; + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +div.line.glow { + background-color: cyan; + box-shadow: 0 0 10px cyan; +} + + +span.lineno { + padding-right: 4px; + text-align: right; + border-right: 2px solid #0F0; + background-color: #E8E8E8; + white-space: pre; +} +span.lineno a { + background-color: #D8D8D8; +} + +span.lineno a:hover { + background-color: #C8C8C8; +} + +div.ah { + background-color: black; + font-weight: bold; + color: #ffffff; + margin-bottom: 3px; + margin-top: 3px; + padding: 0.2em; + border: solid thin #333; + border-radius: 0.5em; + -webkit-border-radius: .5em; + -moz-border-radius: .5em; + box-shadow: 2px 2px 3px #999; + -webkit-box-shadow: 2px 2px 3px #999; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); + background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000); +} + +div.groupHeader { + margin-left: 16px; + margin-top: 12px; + font-weight: bold; +} + +div.groupText { + margin-left: 16px; + font-style: italic; +} + +body { + background-color: white; + color: black; + margin: 0; +} + +div.contents { + margin-top: 10px; + margin-left: 12px; + margin-right: 8px; +} + +td.indexkey { + background-color: #EBEFF6; + font-weight: bold; + border: 1px solid #C4CFE5; + margin: 2px 0px 2px 0; + padding: 2px 10px; + white-space: nowrap; + vertical-align: top; +} + +td.indexvalue { + background-color: #EBEFF6; + border: 1px solid #C4CFE5; + padding: 2px 10px; + margin: 2px 0px; +} + +tr.memlist { + background-color: #EEF1F7; +} + +p.formulaDsp { + text-align: center; +} + +img.formulaDsp { + +} + +img.formulaInl { + vertical-align: middle; +} + +div.center { + text-align: center; + margin-top: 0px; + margin-bottom: 0px; + padding: 0px; +} + +div.center img { + border: 0px; +} + +address.footer { + text-align: right; + padding-right: 12px; +} + +img.footer { + border: 0px; + vertical-align: middle; +} + +/* @group Code Colorization */ + +span.keyword { + color: #008000 +} + +span.keywordtype { + color: #604020 +} + +span.keywordflow { + color: #e08000 +} + +span.comment { + color: #800000 +} + +span.preprocessor { + color: #806020 +} + +span.stringliteral { + color: #002080 +} + +span.charliteral { + color: #008080 +} + +span.vhdldigit { + color: #ff00ff +} + +span.vhdlchar { + color: #000000 +} + +span.vhdlkeyword { + color: #700070 +} + +span.vhdllogic { + color: #ff0000 +} + +blockquote { + background-color: #F7F8FB; + border-left: 2px solid #9CAFD4; + margin: 0 24px 0 4px; + padding: 0 12px 0 16px; +} + +/* @end */ + +/* +.search { + color: #003399; + font-weight: bold; +} + +form.search { + margin-bottom: 0px; + margin-top: 0px; +} + +input.search { + font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #e8eef2; +} +*/ + +td.tiny { + font-size: 75%; +} + +.dirtab { + padding: 4px; + border-collapse: collapse; + border: 1px solid #A3B4D7; +} + +th.dirtab { + background: #EBEFF6; + font-weight: bold; +} + +hr { + height: 0px; + border: none; + border-top: 1px solid #4A6AAA; +} + +hr.footer { + height: 1px; +} + +/* @group Member Descriptions */ + +table.memberdecls { + border-spacing: 0px; + padding: 0px; +} + +.memberdecls td, .fieldtable tr { + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +.memberdecls td.glow, .fieldtable tr.glow { + background-color: cyan; + box-shadow: 0 0 15px cyan; +} + +.mdescLeft, .mdescRight, +.memItemLeft, .memItemRight, +.memTemplItemLeft, .memTemplItemRight, .memTemplParams { + background-color: #F9FAFC; + border: none; + margin: 4px; + padding: 1px 0 0 8px; +} + +.mdescLeft, .mdescRight { + padding: 0px 8px 4px 8px; + color: #555; +} + +.memSeparator { + border-bottom: 1px solid #DEE4F0; + line-height: 1px; + margin: 0px; + padding: 0px; +} + +.memItemLeft, .memTemplItemLeft { + white-space: nowrap; +} + +.memItemRight { + width: 100%; +} + +.memTemplParams { + color: #4665A2; + white-space: nowrap; + font-size: 80%; +} + +/* @end */ + +/* @group Member Details */ + +/* Styles for detailed member documentation */ + +.memtemplate { + font-size: 80%; + color: #4665A2; + font-weight: normal; + margin-left: 9px; +} + +.memnav { + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} + +.mempage { + width: 100%; +} + +.memitem { + padding: 0; + margin-bottom: 10px; + margin-right: 5px; + -webkit-transition: box-shadow 0.5s linear; + -moz-transition: box-shadow 0.5s linear; + -ms-transition: box-shadow 0.5s linear; + -o-transition: box-shadow 0.5s linear; + transition: box-shadow 0.5s linear; + display: table !important; + width: 100%; +} + +.memitem.glow { + box-shadow: 0 0 15px cyan; +} + +.memname { + font-weight: bold; + margin-left: 6px; +} + +.memname td { + vertical-align: bottom; +} + +.memproto, dl.reflist dt { + border-top: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 0px 6px 0px; + color: #253555; + font-weight: bold; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + /* opera specific markup */ + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + border-top-right-radius: 4px; + border-top-left-radius: 4px; + /* firefox specific markup */ + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + -moz-border-radius-topright: 4px; + -moz-border-radius-topleft: 4px; + /* webkit specific markup */ + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + -webkit-border-top-right-radius: 4px; + -webkit-border-top-left-radius: 4px; + +} + +.memdoc, dl.reflist dd { + border-bottom: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 10px 2px 10px; + background-color: #FBFCFD; + border-top-width: 0; + background-image:url('nav_g.png'); + background-repeat:repeat-x; + background-color: #FFFFFF; + /* opera specific markup */ + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + /* firefox specific markup */ + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-bottomright: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + /* webkit specific markup */ + -webkit-border-bottom-left-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); +} + +dl.reflist dt { + padding: 5px; +} + +dl.reflist dd { + margin: 0px 0px 10px 0px; + padding: 5px; +} + +.paramkey { + text-align: right; +} + +.paramtype { + white-space: nowrap; +} + +.paramname { + color: #602020; + white-space: nowrap; +} +.paramname em { + font-style: normal; +} +.paramname code { + line-height: 14px; +} + +.params, .retval, .exception, .tparams { + margin-left: 0px; + padding-left: 0px; +} + +.params .paramname, .retval .paramname { + font-weight: bold; + vertical-align: top; +} + +.params .paramtype { + font-style: italic; + vertical-align: top; +} + +.params .paramdir { + font-family: "courier new",courier,monospace; + vertical-align: top; +} + +table.mlabels { + border-spacing: 0px; +} + +td.mlabels-left { + width: 100%; + padding: 0px; +} + +td.mlabels-right { + vertical-align: bottom; + padding: 0px; + white-space: nowrap; +} + +span.mlabels { + margin-left: 8px; +} + +span.mlabel { + background-color: #728DC1; + border-top:1px solid #5373B4; + border-left:1px solid #5373B4; + border-right:1px solid #C4CFE5; + border-bottom:1px solid #C4CFE5; + text-shadow: none; + color: white; + margin-right: 4px; + padding: 2px 3px; + border-radius: 3px; + font-size: 7pt; + white-space: nowrap; + vertical-align: middle; +} + + + +/* @end */ + +/* these are for tree view when not used as main index */ + +div.directory { + margin: 10px 0px; + border-top: 1px solid #A8B8D9; + border-bottom: 1px solid #A8B8D9; + width: 100%; +} + +.directory table { + border-collapse:collapse; +} + +.directory td { + margin: 0px; + padding: 0px; + vertical-align: top; +} + +.directory td.entry { + white-space: nowrap; + padding-right: 6px; + padding-top: 3px; +} + +.directory td.entry a { + outline:none; +} + +.directory td.entry a img { + border: none; +} + +.directory td.desc { + width: 100%; + padding-left: 6px; + padding-right: 6px; + padding-top: 3px; + border-left: 1px solid rgba(0,0,0,0.05); +} + +.directory tr.even { + padding-left: 6px; + background-color: #F7F8FB; +} + +.directory img { + vertical-align: -30%; +} + +.directory .levels { + white-space: nowrap; + width: 100%; + text-align: right; + font-size: 9pt; +} + +.directory .levels span { + cursor: pointer; + padding-left: 2px; + padding-right: 2px; + color: #3D578C; +} + +div.dynheader { + margin-top: 8px; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +address { + font-style: normal; + color: #2A3D61; +} + +table.doxtable { + border-collapse:collapse; + margin-top: 4px; + margin-bottom: 4px; +} + +table.doxtable td, table.doxtable th { + border: 1px solid #2D4068; + padding: 3px 7px 2px; +} + +table.doxtable th { + background-color: #374F7F; + color: #FFFFFF; + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; +} + +table.fieldtable { + /*width: 100%;*/ + margin-bottom: 10px; + border: 1px solid #A8B8D9; + border-spacing: 0px; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + border-radius: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); +} + +.fieldtable td, .fieldtable th { + padding: 3px 7px 2px; +} + +.fieldtable td.fieldtype, .fieldtable td.fieldname { + white-space: nowrap; + border-right: 1px solid #A8B8D9; + border-bottom: 1px solid #A8B8D9; + vertical-align: top; +} + +.fieldtable td.fieldname { + padding-top: 3px; +} + +.fieldtable td.fielddoc { + border-bottom: 1px solid #A8B8D9; + /*width: 100%;*/ +} + +.fieldtable td.fielddoc p:first-child { + margin-top: 0px; +} + +.fieldtable td.fielddoc p:last-child { + margin-bottom: 2px; +} + +.fieldtable tr:last-child td { + border-bottom: none; +} + +.fieldtable th { + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + font-size: 90%; + color: #253555; + padding-bottom: 4px; + padding-top: 5px; + text-align:left; + -moz-border-radius-topleft: 4px; + -moz-border-radius-topright: 4px; + -webkit-border-top-left-radius: 4px; + -webkit-border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom: 1px solid #A8B8D9; +} + + +.tabsearch { + top: 0px; + left: 10px; + height: 36px; + background-image: url('tab_b.png'); + z-index: 101; + overflow: hidden; + font-size: 13px; +} + +.navpath ul +{ + font-size: 11px; + background-image:url('tab_b.png'); + background-repeat:repeat-x; + background-position: 0 -5px; + height:30px; + line-height:30px; + color:#8AA0CC; + border:solid 1px #C2CDE4; + overflow:hidden; + margin:0px; + padding:0px; +} + +.navpath li +{ + list-style-type:none; + float:left; + padding-left:10px; + padding-right:15px; + background-image:url('bc_s.png'); + background-repeat:no-repeat; + background-position:right; + color:#364D7C; +} + +.navpath li.navelem a +{ + height:32px; + display:block; + text-decoration: none; + outline: none; + color: #283A5D; + font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + text-decoration: none; +} + +.navpath li.navelem a:hover +{ + color:#6884BD; +} + +.navpath li.footer +{ + list-style-type:none; + float:right; + padding-left:10px; + padding-right:15px; + background-image:none; + background-repeat:no-repeat; + background-position:right; + color:#364D7C; + font-size: 8pt; +} + + +div.summary +{ + float: right; + font-size: 8pt; + padding-right: 5px; + width: 50%; + text-align: right; +} + +div.summary a +{ + white-space: nowrap; +} + +div.ingroups +{ + font-size: 8pt; + width: 50%; + text-align: left; +} + +div.ingroups a +{ + white-space: nowrap; +} + +div.header +{ + background-image:url('nav_h.png'); + background-repeat:repeat-x; + background-color: #F9FAFC; + margin: 0px; + border-bottom: 1px solid #C4CFE5; +} + +div.headertitle +{ + padding: 5px 5px 5px 10px; +} + +dl +{ + padding: 0 0 0 10px; +} + +/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */ +dl.section +{ + margin-left: 0px; + padding-left: 0px; +} + +dl.note +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #D0C000; +} + +dl.warning, dl.attention +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #FF0000; +} + +dl.pre, dl.post, dl.invariant +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #00D000; +} + +dl.deprecated +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #505050; +} + +dl.todo +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #00C0E0; +} + +dl.test +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #3030E0; +} + +dl.bug +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #C08050; +} + +dl.section dd { + margin-bottom: 6px; +} + + +#projectlogo +{ + text-align: center; + vertical-align: bottom; + border-collapse: separate; +} + +#projectlogo img +{ + border: 0px none; +} + +#projectname +{ + font: 300% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 2px 0px; +} + +#projectbrief +{ + font: 120% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#projectnumber +{ + font: 50% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#titlearea +{ + padding: 0px; + margin: 0px; + width: 100%; + border-bottom: 1px solid #5373B4; +} + +.image +{ + text-align: center; +} + +.dotgraph +{ + text-align: center; +} + +.mscgraph +{ + text-align: center; +} + +.caption +{ + font-weight: bold; +} + +div.zoom +{ + border: 1px solid #90A5CE; +} + +dl.citelist { + margin-bottom:50px; +} + +dl.citelist dt { + color:#334975; + float:left; + font-weight:bold; + margin-right:10px; + padding:5px; +} + +dl.citelist dd { + margin:2px 0; + padding:5px 0; +} + +div.toc { + padding: 14px 25px; + background-color: #F4F6FA; + border: 1px solid #D8DFEE; + border-radius: 7px 7px 7px 7px; + float: right; + height: auto; + margin: 0 20px 10px 10px; + width: 200px; +} + +div.toc li { + background: url("bdwn.png") no-repeat scroll 0 5px transparent; + font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif; + margin-top: 5px; + padding-left: 10px; + padding-top: 2px; +} + +div.toc h3 { + font: bold 12px/1.2 Arial,FreeSans,sans-serif; + color: #4665A2; + border-bottom: 0 none; + margin: 0; +} + +div.toc ul { + list-style: none outside none; + border: medium none; + padding: 0px; +} + +div.toc li.level1 { + margin-left: 0px; +} + +div.toc li.level2 { + margin-left: 15px; +} + +div.toc li.level3 { + margin-left: 30px; +} + +div.toc li.level4 { + margin-left: 45px; +} + +.inherit_header { + font-weight: bold; + color: gray; + cursor: pointer; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.inherit_header td { + padding: 6px 0px 2px 5px; +} + +.inherit { + display: none; +} + +tr.heading h2 { + margin-top: 12px; + margin-bottom: 4px; +} + +/* tooltip related style info */ + +.ttc { + position: absolute; + display: none; +} + +#powerTip { + cursor: default; + white-space: nowrap; + background-color: white; + border: 1px solid gray; + border-radius: 4px 4px 4px 4px; + box-shadow: 1px 1px 7px gray; + display: none; + font-size: smaller; + max-width: 80%; + opacity: 0.9; + padding: 1ex 1em 1em; + position: absolute; + z-index: 2147483647; +} + +#powerTip div.ttdoc { + color: grey; + font-style: italic; +} + +#powerTip div.ttname a { + font-weight: bold; +} + +#powerTip div.ttname { + font-weight: bold; +} + +#powerTip div.ttdeci { + color: #006318; +} + +#powerTip div { + margin: 0px; + padding: 0px; + font: 12px/16px Roboto,sans-serif; +} + +#powerTip:before, #powerTip:after { + content: ""; + position: absolute; + margin: 0px; +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.s:after, #powerTip.s:before, +#powerTip.w:after, #powerTip.w:before, +#powerTip.e:after, #powerTip.e:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.nw:after, #powerTip.nw:before, +#powerTip.sw:after, #powerTip.sw:before { + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; +} + +#powerTip.n:after, #powerTip.s:after, +#powerTip.w:after, #powerTip.e:after, +#powerTip.nw:after, #powerTip.ne:after, +#powerTip.sw:after, #powerTip.se:after { + border-color: rgba(255, 255, 255, 0); +} + +#powerTip.n:before, #powerTip.s:before, +#powerTip.w:before, #powerTip.e:before, +#powerTip.nw:before, #powerTip.ne:before, +#powerTip.sw:before, #powerTip.se:before { + border-color: rgba(128, 128, 128, 0); +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.nw:after, #powerTip.nw:before { + top: 100%; +} + +#powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after { + border-top-color: #ffffff; + border-width: 10px; + margin: 0px -10px; +} +#powerTip.n:before { + border-top-color: #808080; + border-width: 11px; + margin: 0px -11px; +} +#powerTip.n:after, #powerTip.n:before { + left: 50%; +} + +#powerTip.nw:after, #powerTip.nw:before { + right: 14px; +} + +#powerTip.ne:after, #powerTip.ne:before { + left: 14px; +} + +#powerTip.s:after, #powerTip.s:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.sw:after, #powerTip.sw:before { + bottom: 100%; +} + +#powerTip.s:after, #powerTip.se:after, #powerTip.sw:after { + border-bottom-color: #ffffff; + border-width: 10px; + margin: 0px -10px; +} + +#powerTip.s:before, #powerTip.se:before, #powerTip.sw:before { + border-bottom-color: #808080; + border-width: 11px; + margin: 0px -11px; +} + +#powerTip.s:after, #powerTip.s:before { + left: 50%; +} + +#powerTip.sw:after, #powerTip.sw:before { + right: 14px; +} + +#powerTip.se:after, #powerTip.se:before { + left: 14px; +} + +#powerTip.e:after, #powerTip.e:before { + left: 100%; +} +#powerTip.e:after { + border-left-color: #ffffff; + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.e:before { + border-left-color: #808080; + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +#powerTip.w:after, #powerTip.w:before { + right: 100%; +} +#powerTip.w:after { + border-right-color: #ffffff; + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.w:before { + border-right-color: #808080; + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +@media print +{ + #top { display: none; } + #side-nav { display: none; } + #nav-path { display: none; } + body { overflow:visible; } + h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } + .summary { display: none; } + .memitem { page-break-inside: avoid; } + #doc-content + { + margin-left:0 !important; + height:auto !important; + width:auto !important; + overflow:inherit; + display:inline; + } +} + diff --git a/exploring-cpp-2e/chapter71/step1/html/doxygen.png b/exploring-cpp-2e/chapter71/step1/html/doxygen.png new file mode 100644 index 0000000..3ff17d8 Binary files /dev/null and b/exploring-cpp-2e/chapter71/step1/html/doxygen.png differ diff --git a/exploring-cpp-2e/chapter71/step1/html/dynsections.js b/exploring-cpp-2e/chapter71/step1/html/dynsections.js new file mode 100644 index 0000000..2f15470 --- /dev/null +++ b/exploring-cpp-2e/chapter71/step1/html/dynsections.js @@ -0,0 +1,104 @@ +function toggleVisibility(linkObj) +{ + var base = $(linkObj).attr('id'); + var summary = $('#'+base+'-summary'); + var content = $('#'+base+'-content'); + var trigger = $('#'+base+'-trigger'); + var src=$(trigger).attr('src'); + if (content.is(':visible')===true) { + content.hide(); + summary.show(); + $(linkObj).addClass('closed').removeClass('opened'); + $(trigger).attr('src',src.substring(0,src.length-8)+'closed.png'); + } else { + content.show(); + summary.hide(); + $(linkObj).removeClass('closed').addClass('opened'); + $(trigger).attr('src',src.substring(0,src.length-10)+'open.png'); + } + return false; +} + +function updateStripes() +{ + $('table.directory tr'). + removeClass('even').filter(':visible:even').addClass('even'); +} +function toggleLevel(level) +{ + $('table.directory tr').each(function(){ + var l = this.id.split('_').length-1; + var i = $('#img'+this.id.substring(3)); + var a = $('#arr'+this.id.substring(3)); + if (l + + + + + +Calculator: File List + + + + + + +
+
+ + + + + + +
+
Calculator +  Step 1 +
+
+
+ + + + +
+
+
+
File List
+
+
+
Here is a list of all files with brief descriptions:
+
+ + + + diff --git a/exploring-cpp-2e/chapter71/step1/html/ftv2blank.png b/exploring-cpp-2e/chapter71/step1/html/ftv2blank.png new file mode 100644 index 0000000..63c605b Binary files /dev/null and b/exploring-cpp-2e/chapter71/step1/html/ftv2blank.png differ diff --git a/exploring-cpp-2e/chapter71/step1/html/ftv2cl.png b/exploring-cpp-2e/chapter71/step1/html/ftv2cl.png new file mode 100644 index 0000000..132f657 Binary files /dev/null and b/exploring-cpp-2e/chapter71/step1/html/ftv2cl.png differ diff --git a/exploring-cpp-2e/chapter71/step1/html/ftv2doc.png b/exploring-cpp-2e/chapter71/step1/html/ftv2doc.png new file mode 100644 index 0000000..17edabf Binary files /dev/null and b/exploring-cpp-2e/chapter71/step1/html/ftv2doc.png differ diff --git a/exploring-cpp-2e/chapter71/step1/html/ftv2folderclosed.png b/exploring-cpp-2e/chapter71/step1/html/ftv2folderclosed.png new file mode 100644 index 0000000..bb8ab35 Binary files /dev/null and b/exploring-cpp-2e/chapter71/step1/html/ftv2folderclosed.png differ diff --git a/exploring-cpp-2e/chapter71/step1/html/ftv2folderopen.png b/exploring-cpp-2e/chapter71/step1/html/ftv2folderopen.png new file mode 100644 index 0000000..d6c7f67 Binary files /dev/null and b/exploring-cpp-2e/chapter71/step1/html/ftv2folderopen.png differ diff --git a/exploring-cpp-2e/chapter71/step1/html/ftv2lastnode.png b/exploring-cpp-2e/chapter71/step1/html/ftv2lastnode.png new file mode 100644 index 0000000..63c605b Binary files /dev/null and b/exploring-cpp-2e/chapter71/step1/html/ftv2lastnode.png differ diff --git a/exploring-cpp-2e/chapter71/step1/html/ftv2link.png b/exploring-cpp-2e/chapter71/step1/html/ftv2link.png new file mode 100644 index 0000000..17edabf Binary files /dev/null and b/exploring-cpp-2e/chapter71/step1/html/ftv2link.png differ diff --git a/exploring-cpp-2e/chapter71/step1/html/ftv2mlastnode.png b/exploring-cpp-2e/chapter71/step1/html/ftv2mlastnode.png new file mode 100644 index 0000000..0b63f6d Binary files /dev/null and b/exploring-cpp-2e/chapter71/step1/html/ftv2mlastnode.png differ diff --git a/exploring-cpp-2e/chapter71/step1/html/ftv2mnode.png b/exploring-cpp-2e/chapter71/step1/html/ftv2mnode.png new file mode 100644 index 0000000..0b63f6d Binary files /dev/null and b/exploring-cpp-2e/chapter71/step1/html/ftv2mnode.png differ diff --git a/exploring-cpp-2e/chapter71/step1/html/ftv2mo.png b/exploring-cpp-2e/chapter71/step1/html/ftv2mo.png new file mode 100644 index 0000000..4bfb80f Binary files /dev/null and b/exploring-cpp-2e/chapter71/step1/html/ftv2mo.png differ diff --git a/exploring-cpp-2e/chapter71/step1/html/ftv2node.png b/exploring-cpp-2e/chapter71/step1/html/ftv2node.png new file mode 100644 index 0000000..63c605b Binary files /dev/null and b/exploring-cpp-2e/chapter71/step1/html/ftv2node.png differ diff --git a/exploring-cpp-2e/chapter71/step1/html/ftv2ns.png b/exploring-cpp-2e/chapter71/step1/html/ftv2ns.png new file mode 100644 index 0000000..72e3d71 Binary files /dev/null and b/exploring-cpp-2e/chapter71/step1/html/ftv2ns.png differ diff --git a/exploring-cpp-2e/chapter71/step1/html/ftv2plastnode.png b/exploring-cpp-2e/chapter71/step1/html/ftv2plastnode.png new file mode 100644 index 0000000..c6ee22f Binary files /dev/null and b/exploring-cpp-2e/chapter71/step1/html/ftv2plastnode.png differ diff --git a/exploring-cpp-2e/chapter71/step1/html/ftv2pnode.png b/exploring-cpp-2e/chapter71/step1/html/ftv2pnode.png new file mode 100644 index 0000000..c6ee22f Binary files /dev/null and b/exploring-cpp-2e/chapter71/step1/html/ftv2pnode.png differ diff --git a/exploring-cpp-2e/chapter71/step1/html/ftv2splitbar.png b/exploring-cpp-2e/chapter71/step1/html/ftv2splitbar.png new file mode 100644 index 0000000..fe895f2 Binary files /dev/null and b/exploring-cpp-2e/chapter71/step1/html/ftv2splitbar.png differ diff --git a/exploring-cpp-2e/chapter71/step1/html/ftv2vertline.png b/exploring-cpp-2e/chapter71/step1/html/ftv2vertline.png new file mode 100644 index 0000000..63c605b Binary files /dev/null and b/exploring-cpp-2e/chapter71/step1/html/ftv2vertline.png differ diff --git a/exploring-cpp-2e/chapter71/step1/html/functions.html b/exploring-cpp-2e/chapter71/step1/html/functions.html new file mode 100644 index 0000000..6b5e150 --- /dev/null +++ b/exploring-cpp-2e/chapter71/step1/html/functions.html @@ -0,0 +1,91 @@ + + + + + + +Calculator: Class Members + + + + + + +
+
+ + + + + + +
+
Calculator +  Step 1 +
+
+
+ + + + + +
+
+
Here is a list of all class members with links to the classes they belong to:
+
+ + + + diff --git a/exploring-cpp-2e/chapter71/step1/html/functions_func.html b/exploring-cpp-2e/chapter71/step1/html/functions_func.html new file mode 100644 index 0000000..f73f71b --- /dev/null +++ b/exploring-cpp-2e/chapter71/step1/html/functions_func.html @@ -0,0 +1,85 @@ + + + + + + +Calculator: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
Calculator +  Step 1 +
+
+
+ + + + + +
+
+
+ + + + diff --git a/exploring-cpp-2e/chapter71/step1/html/functions_vars.html b/exploring-cpp-2e/chapter71/step1/html/functions_vars.html new file mode 100644 index 0000000..b3843bf --- /dev/null +++ b/exploring-cpp-2e/chapter71/step1/html/functions_vars.html @@ -0,0 +1,70 @@ + + + + + + +Calculator: Class Members - Variables + + + + + + +
+
+ + + + + + +
+
Calculator +  Step 1 +
+
+
+ + + + + +
+
+
+ + + + diff --git a/exploring-cpp-2e/chapter71/step1/html/globals.html b/exploring-cpp-2e/chapter71/step1/html/globals.html new file mode 100644 index 0000000..d8924a1 --- /dev/null +++ b/exploring-cpp-2e/chapter71/step1/html/globals.html @@ -0,0 +1,75 @@ + + + + + + +Calculator: File Members + + + + + + +
+
+ + + + + + +
+
Calculator +  Step 1 +
+
+
+ + + + + +
+
+
Here is a list of all file members with links to the files they belong to:
+
+ + + + diff --git a/exploring-cpp-2e/chapter71/step1/html/globals_defs.html b/exploring-cpp-2e/chapter71/step1/html/globals_defs.html new file mode 100644 index 0000000..082efc7 --- /dev/null +++ b/exploring-cpp-2e/chapter71/step1/html/globals_defs.html @@ -0,0 +1,65 @@ + + + + + + +Calculator: File Members + + + + + + +
+
+ + + + + + +
+
Calculator +  Step 1 +
+
+
+ + + + + +
+
+
+ + + + diff --git a/exploring-cpp-2e/chapter71/step1/html/globals_func.html b/exploring-cpp-2e/chapter71/step1/html/globals_func.html new file mode 100644 index 0000000..f163ef6 --- /dev/null +++ b/exploring-cpp-2e/chapter71/step1/html/globals_func.html @@ -0,0 +1,72 @@ + + + + + + +Calculator: File Members + + + + + + +
+
+ + + + + + +
+
Calculator +  Step 1 +
+
+
+ + + + + +
+
+
+ + + + diff --git a/exploring-cpp-2e/chapter71/step1/html/hierarchy.html b/exploring-cpp-2e/chapter71/step1/html/hierarchy.html new file mode 100644 index 0000000..1520ea3 --- /dev/null +++ b/exploring-cpp-2e/chapter71/step1/html/hierarchy.html @@ -0,0 +1,66 @@ + + + + + + +Calculator: Class Hierarchy + + + + + + +
+
+ + + + + + +
+
Calculator +  Step 1 +
+
+
+ + + + +
+
+
+
Class Hierarchy
+
+
+
This inheritance list is sorted roughly, but not completely, alphabetically:
+
[detail level 12]
+ + + +
oCparser
\Cruntime_error
 \Cparse_error
+
+
+ + + + diff --git a/exploring-cpp-2e/chapter71/step1/html/index.html b/exploring-cpp-2e/chapter71/step1/html/index.html new file mode 100644 index 0000000..8d0c1f5 --- /dev/null +++ b/exploring-cpp-2e/chapter71/step1/html/index.html @@ -0,0 +1,53 @@ + + + + + + +Calculator: Main Page + + + + + + +
+
+ + + + + + +
+
Calculator +  Step 1 +
+
+
+ + + +
+
+
+
Calculator Documentation
+
+
+

This is step 1 of the calculator project in Exploration 68 of Exploring C++: The Programmer's Introduction to C++.

+

This version of the calculator implements simple arithmetic. It uses a recursive-descent parser and immediately evaluates expressions using double for all values.

+
+ + + + diff --git a/exploring-cpp-2e/chapter71/step1/html/jquery.js b/exploring-cpp-2e/chapter71/step1/html/jquery.js new file mode 100644 index 0000000..6aa2e4c --- /dev/null +++ b/exploring-cpp-2e/chapter71/step1/html/jquery.js @@ -0,0 +1,39 @@ +/*! + * jQuery JavaScript Library v1.7.1 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Mon Nov 21 21:11:03 2011 -0500 + */ +(function(bb,L){var av=bb.document,bu=bb.navigator,bl=bb.location;var b=(function(){var bF=function(b0,b1){return new bF.fn.init(b0,b1,bD)},bU=bb.jQuery,bH=bb.$,bD,bY=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,bM=/\S/,bI=/^\s+/,bE=/\s+$/,bA=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,bN=/^[\],:{}\s]*$/,bW=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,bP=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,bJ=/(?:^|:|,)(?:\s*\[)+/g,by=/(webkit)[ \/]([\w.]+)/,bR=/(opera)(?:.*version)?[ \/]([\w.]+)/,bQ=/(msie) ([\w.]+)/,bS=/(mozilla)(?:.*? rv:([\w.]+))?/,bB=/-([a-z]|[0-9])/ig,bZ=/^-ms-/,bT=function(b0,b1){return(b1+"").toUpperCase()},bX=bu.userAgent,bV,bC,e,bL=Object.prototype.toString,bG=Object.prototype.hasOwnProperty,bz=Array.prototype.push,bK=Array.prototype.slice,bO=String.prototype.trim,bv=Array.prototype.indexOf,bx={};bF.fn=bF.prototype={constructor:bF,init:function(b0,b4,b3){var b2,b5,b1,b6;if(!b0){return this}if(b0.nodeType){this.context=this[0]=b0;this.length=1;return this}if(b0==="body"&&!b4&&av.body){this.context=av;this[0]=av.body;this.selector=b0;this.length=1;return this}if(typeof b0==="string"){if(b0.charAt(0)==="<"&&b0.charAt(b0.length-1)===">"&&b0.length>=3){b2=[null,b0,null]}else{b2=bY.exec(b0)}if(b2&&(b2[1]||!b4)){if(b2[1]){b4=b4 instanceof bF?b4[0]:b4;b6=(b4?b4.ownerDocument||b4:av);b1=bA.exec(b0);if(b1){if(bF.isPlainObject(b4)){b0=[av.createElement(b1[1])];bF.fn.attr.call(b0,b4,true)}else{b0=[b6.createElement(b1[1])]}}else{b1=bF.buildFragment([b2[1]],[b6]);b0=(b1.cacheable?bF.clone(b1.fragment):b1.fragment).childNodes}return bF.merge(this,b0)}else{b5=av.getElementById(b2[2]);if(b5&&b5.parentNode){if(b5.id!==b2[2]){return b3.find(b0)}this.length=1;this[0]=b5}this.context=av;this.selector=b0;return this}}else{if(!b4||b4.jquery){return(b4||b3).find(b0)}else{return this.constructor(b4).find(b0)}}}else{if(bF.isFunction(b0)){return b3.ready(b0)}}if(b0.selector!==L){this.selector=b0.selector;this.context=b0.context}return bF.makeArray(b0,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return bK.call(this,0)},get:function(b0){return b0==null?this.toArray():(b0<0?this[this.length+b0]:this[b0])},pushStack:function(b1,b3,b0){var b2=this.constructor();if(bF.isArray(b1)){bz.apply(b2,b1)}else{bF.merge(b2,b1)}b2.prevObject=this;b2.context=this.context;if(b3==="find"){b2.selector=this.selector+(this.selector?" ":"")+b0}else{if(b3){b2.selector=this.selector+"."+b3+"("+b0+")"}}return b2},each:function(b1,b0){return bF.each(this,b1,b0)},ready:function(b0){bF.bindReady();bC.add(b0);return this},eq:function(b0){b0=+b0;return b0===-1?this.slice(b0):this.slice(b0,b0+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(bK.apply(this,arguments),"slice",bK.call(arguments).join(","))},map:function(b0){return this.pushStack(bF.map(this,function(b2,b1){return b0.call(b2,b1,b2)}))},end:function(){return this.prevObject||this.constructor(null)},push:bz,sort:[].sort,splice:[].splice};bF.fn.init.prototype=bF.fn;bF.extend=bF.fn.extend=function(){var b9,b2,b0,b1,b6,b7,b5=arguments[0]||{},b4=1,b3=arguments.length,b8=false;if(typeof b5==="boolean"){b8=b5;b5=arguments[1]||{};b4=2}if(typeof b5!=="object"&&!bF.isFunction(b5)){b5={}}if(b3===b4){b5=this;--b4}for(;b40){return}bC.fireWith(av,[bF]);if(bF.fn.trigger){bF(av).trigger("ready").off("ready")}}},bindReady:function(){if(bC){return}bC=bF.Callbacks("once memory");if(av.readyState==="complete"){return setTimeout(bF.ready,1)}if(av.addEventListener){av.addEventListener("DOMContentLoaded",e,false);bb.addEventListener("load",bF.ready,false)}else{if(av.attachEvent){av.attachEvent("onreadystatechange",e);bb.attachEvent("onload",bF.ready);var b0=false;try{b0=bb.frameElement==null}catch(b1){}if(av.documentElement.doScroll&&b0){bw()}}}},isFunction:function(b0){return bF.type(b0)==="function"},isArray:Array.isArray||function(b0){return bF.type(b0)==="array"},isWindow:function(b0){return b0&&typeof b0==="object"&&"setInterval" in b0},isNumeric:function(b0){return !isNaN(parseFloat(b0))&&isFinite(b0)},type:function(b0){return b0==null?String(b0):bx[bL.call(b0)]||"object"},isPlainObject:function(b2){if(!b2||bF.type(b2)!=="object"||b2.nodeType||bF.isWindow(b2)){return false}try{if(b2.constructor&&!bG.call(b2,"constructor")&&!bG.call(b2.constructor.prototype,"isPrototypeOf")){return false}}catch(b1){return false}var b0;for(b0 in b2){}return b0===L||bG.call(b2,b0)},isEmptyObject:function(b1){for(var b0 in b1){return false}return true},error:function(b0){throw new Error(b0)},parseJSON:function(b0){if(typeof b0!=="string"||!b0){return null}b0=bF.trim(b0);if(bb.JSON&&bb.JSON.parse){return bb.JSON.parse(b0)}if(bN.test(b0.replace(bW,"@").replace(bP,"]").replace(bJ,""))){return(new Function("return "+b0))()}bF.error("Invalid JSON: "+b0)},parseXML:function(b2){var b0,b1;try{if(bb.DOMParser){b1=new DOMParser();b0=b1.parseFromString(b2,"text/xml")}else{b0=new ActiveXObject("Microsoft.XMLDOM");b0.async="false";b0.loadXML(b2)}}catch(b3){b0=L}if(!b0||!b0.documentElement||b0.getElementsByTagName("parsererror").length){bF.error("Invalid XML: "+b2)}return b0},noop:function(){},globalEval:function(b0){if(b0&&bM.test(b0)){(bb.execScript||function(b1){bb["eval"].call(bb,b1)})(b0)}},camelCase:function(b0){return b0.replace(bZ,"ms-").replace(bB,bT)},nodeName:function(b1,b0){return b1.nodeName&&b1.nodeName.toUpperCase()===b0.toUpperCase()},each:function(b3,b6,b2){var b1,b4=0,b5=b3.length,b0=b5===L||bF.isFunction(b3);if(b2){if(b0){for(b1 in b3){if(b6.apply(b3[b1],b2)===false){break}}}else{for(;b40&&b0[0]&&b0[b1-1])||b1===0||bF.isArray(b0));if(b3){for(;b21?aJ.call(arguments,0):bG;if(!(--bw)){bC.resolveWith(bC,bx)}}}function bz(bF){return function(bG){bB[bF]=arguments.length>1?aJ.call(arguments,0):bG;bC.notifyWith(bE,bB)}}if(e>1){for(;bv
a";bI=bv.getElementsByTagName("*");bF=bv.getElementsByTagName("a")[0];if(!bI||!bI.length||!bF){return{}}bG=av.createElement("select");bx=bG.appendChild(av.createElement("option"));bE=bv.getElementsByTagName("input")[0];bJ={leadingWhitespace:(bv.firstChild.nodeType===3),tbody:!bv.getElementsByTagName("tbody").length,htmlSerialize:!!bv.getElementsByTagName("link").length,style:/top/.test(bF.getAttribute("style")),hrefNormalized:(bF.getAttribute("href")==="/a"),opacity:/^0.55/.test(bF.style.opacity),cssFloat:!!bF.style.cssFloat,checkOn:(bE.value==="on"),optSelected:bx.selected,getSetAttribute:bv.className!=="t",enctype:!!av.createElement("form").enctype,html5Clone:av.createElement("nav").cloneNode(true).outerHTML!=="<:nav>",submitBubbles:true,changeBubbles:true,focusinBubbles:false,deleteExpando:true,noCloneEvent:true,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableMarginRight:true};bE.checked=true;bJ.noCloneChecked=bE.cloneNode(true).checked;bG.disabled=true;bJ.optDisabled=!bx.disabled;try{delete bv.test}catch(bC){bJ.deleteExpando=false}if(!bv.addEventListener&&bv.attachEvent&&bv.fireEvent){bv.attachEvent("onclick",function(){bJ.noCloneEvent=false});bv.cloneNode(true).fireEvent("onclick")}bE=av.createElement("input");bE.value="t";bE.setAttribute("type","radio");bJ.radioValue=bE.value==="t";bE.setAttribute("checked","checked");bv.appendChild(bE);bD=av.createDocumentFragment();bD.appendChild(bv.lastChild);bJ.checkClone=bD.cloneNode(true).cloneNode(true).lastChild.checked;bJ.appendChecked=bE.checked;bD.removeChild(bE);bD.appendChild(bv);bv.innerHTML="";if(bb.getComputedStyle){bA=av.createElement("div");bA.style.width="0";bA.style.marginRight="0";bv.style.width="2px";bv.appendChild(bA);bJ.reliableMarginRight=(parseInt((bb.getComputedStyle(bA,null)||{marginRight:0}).marginRight,10)||0)===0}if(bv.attachEvent){for(by in {submit:1,change:1,focusin:1}){bB="on"+by;bw=(bB in bv);if(!bw){bv.setAttribute(bB,"return;");bw=(typeof bv[bB]==="function")}bJ[by+"Bubbles"]=bw}}bD.removeChild(bv);bD=bG=bx=bA=bv=bE=null;b(function(){var bM,bU,bV,bT,bN,bO,bL,bS,bR,e,bP,bQ=av.getElementsByTagName("body")[0];if(!bQ){return}bL=1;bS="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;";bR="visibility:hidden;border:0;";e="style='"+bS+"border:5px solid #000;padding:0;'";bP="
";bM=av.createElement("div");bM.style.cssText=bR+"width:0;height:0;position:static;top:0;margin-top:"+bL+"px";bQ.insertBefore(bM,bQ.firstChild);bv=av.createElement("div");bM.appendChild(bv);bv.innerHTML="
t
";bz=bv.getElementsByTagName("td");bw=(bz[0].offsetHeight===0);bz[0].style.display="";bz[1].style.display="none";bJ.reliableHiddenOffsets=bw&&(bz[0].offsetHeight===0);bv.innerHTML="";bv.style.width=bv.style.paddingLeft="1px";b.boxModel=bJ.boxModel=bv.offsetWidth===2;if(typeof bv.style.zoom!=="undefined"){bv.style.display="inline";bv.style.zoom=1;bJ.inlineBlockNeedsLayout=(bv.offsetWidth===2);bv.style.display="";bv.innerHTML="
";bJ.shrinkWrapBlocks=(bv.offsetWidth!==2)}bv.style.cssText=bS+bR;bv.innerHTML=bP;bU=bv.firstChild;bV=bU.firstChild;bN=bU.nextSibling.firstChild.firstChild;bO={doesNotAddBorder:(bV.offsetTop!==5),doesAddBorderForTableAndCells:(bN.offsetTop===5)};bV.style.position="fixed";bV.style.top="20px";bO.fixedPosition=(bV.offsetTop===20||bV.offsetTop===15);bV.style.position=bV.style.top="";bU.style.overflow="hidden";bU.style.position="relative";bO.subtractsBorderForOverflowNotVisible=(bV.offsetTop===-5);bO.doesNotIncludeMarginInBodyOffset=(bQ.offsetTop!==bL);bQ.removeChild(bM);bv=bM=null;b.extend(bJ,bO)});return bJ})();var aS=/^(?:\{.*\}|\[.*\])$/,aA=/([A-Z])/g;b.extend({cache:{},uuid:0,expando:"jQuery"+(b.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},hasData:function(e){e=e.nodeType?b.cache[e[b.expando]]:e[b.expando];return !!e&&!S(e)},data:function(bx,bv,bz,by){if(!b.acceptData(bx)){return}var bG,bA,bD,bE=b.expando,bC=typeof bv==="string",bF=bx.nodeType,e=bF?b.cache:bx,bw=bF?bx[bE]:bx[bE]&&bE,bB=bv==="events";if((!bw||!e[bw]||(!bB&&!by&&!e[bw].data))&&bC&&bz===L){return}if(!bw){if(bF){bx[bE]=bw=++b.uuid}else{bw=bE}}if(!e[bw]){e[bw]={};if(!bF){e[bw].toJSON=b.noop}}if(typeof bv==="object"||typeof bv==="function"){if(by){e[bw]=b.extend(e[bw],bv)}else{e[bw].data=b.extend(e[bw].data,bv)}}bG=bA=e[bw];if(!by){if(!bA.data){bA.data={}}bA=bA.data}if(bz!==L){bA[b.camelCase(bv)]=bz}if(bB&&!bA[bv]){return bG.events}if(bC){bD=bA[bv];if(bD==null){bD=bA[b.camelCase(bv)]}}else{bD=bA}return bD},removeData:function(bx,bv,by){if(!b.acceptData(bx)){return}var bB,bA,bz,bC=b.expando,bD=bx.nodeType,e=bD?b.cache:bx,bw=bD?bx[bC]:bC;if(!e[bw]){return}if(bv){bB=by?e[bw]:e[bw].data;if(bB){if(!b.isArray(bv)){if(bv in bB){bv=[bv]}else{bv=b.camelCase(bv);if(bv in bB){bv=[bv]}else{bv=bv.split(" ")}}}for(bA=0,bz=bv.length;bA-1){return true}}return false},val:function(bx){var e,bv,by,bw=this[0];if(!arguments.length){if(bw){e=b.valHooks[bw.nodeName.toLowerCase()]||b.valHooks[bw.type];if(e&&"get" in e&&(bv=e.get(bw,"value"))!==L){return bv}bv=bw.value;return typeof bv==="string"?bv.replace(aU,""):bv==null?"":bv}return}by=b.isFunction(bx);return this.each(function(bA){var bz=b(this),bB;if(this.nodeType!==1){return}if(by){bB=bx.call(this,bA,bz.val())}else{bB=bx}if(bB==null){bB=""}else{if(typeof bB==="number"){bB+=""}else{if(b.isArray(bB)){bB=b.map(bB,function(bC){return bC==null?"":bC+""})}}}e=b.valHooks[this.nodeName.toLowerCase()]||b.valHooks[this.type];if(!e||!("set" in e)||e.set(this,bB,"value")===L){this.value=bB}})}});b.extend({valHooks:{option:{get:function(e){var bv=e.attributes.value;return !bv||bv.specified?e.value:e.text}},select:{get:function(e){var bA,bv,bz,bx,by=e.selectedIndex,bB=[],bC=e.options,bw=e.type==="select-one";if(by<0){return null}bv=bw?by:0;bz=bw?by+1:bC.length;for(;bv=0});if(!e.length){bv.selectedIndex=-1}return e}}},attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(bA,bx,bB,bz){var bw,e,by,bv=bA.nodeType; +if(!bA||bv===3||bv===8||bv===2){return}if(bz&&bx in b.attrFn){return b(bA)[bx](bB)}if(typeof bA.getAttribute==="undefined"){return b.prop(bA,bx,bB)}by=bv!==1||!b.isXMLDoc(bA);if(by){bx=bx.toLowerCase();e=b.attrHooks[bx]||(ao.test(bx)?aY:be)}if(bB!==L){if(bB===null){b.removeAttr(bA,bx);return}else{if(e&&"set" in e&&by&&(bw=e.set(bA,bB,bx))!==L){return bw}else{bA.setAttribute(bx,""+bB);return bB}}}else{if(e&&"get" in e&&by&&(bw=e.get(bA,bx))!==null){return bw}else{bw=bA.getAttribute(bx);return bw===null?L:bw}}},removeAttr:function(bx,bz){var by,bA,bv,e,bw=0;if(bz&&bx.nodeType===1){bA=bz.toLowerCase().split(af);e=bA.length;for(;bw=0)}}})});var bd=/^(?:textarea|input|select)$/i,n=/^([^\.]*)?(?:\.(.+))?$/,J=/\bhover(\.\S+)?\b/,aO=/^key/,bf=/^(?:mouse|contextmenu)|click/,T=/^(?:focusinfocus|focusoutblur)$/,U=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,Y=function(e){var bv=U.exec(e);if(bv){bv[1]=(bv[1]||"").toLowerCase();bv[3]=bv[3]&&new RegExp("(?:^|\\s)"+bv[3]+"(?:\\s|$)")}return bv},j=function(bw,e){var bv=bw.attributes||{};return((!e[1]||bw.nodeName.toLowerCase()===e[1])&&(!e[2]||(bv.id||{}).value===e[2])&&(!e[3]||e[3].test((bv["class"]||{}).value)))},bt=function(e){return b.event.special.hover?e:e.replace(J,"mouseenter$1 mouseleave$1")};b.event={add:function(bx,bC,bJ,bA,by){var bD,bB,bK,bI,bH,bF,e,bG,bv,bz,bw,bE;if(bx.nodeType===3||bx.nodeType===8||!bC||!bJ||!(bD=b._data(bx))){return}if(bJ.handler){bv=bJ;bJ=bv.handler}if(!bJ.guid){bJ.guid=b.guid++}bK=bD.events;if(!bK){bD.events=bK={}}bB=bD.handle;if(!bB){bD.handle=bB=function(bL){return typeof b!=="undefined"&&(!bL||b.event.triggered!==bL.type)?b.event.dispatch.apply(bB.elem,arguments):L};bB.elem=bx}bC=b.trim(bt(bC)).split(" ");for(bI=0;bI=0){bG=bG.slice(0,-1);bw=true}if(bG.indexOf(".")>=0){bx=bG.split(".");bG=bx.shift();bx.sort()}if((!bA||b.event.customEvent[bG])&&!b.event.global[bG]){return}bv=typeof bv==="object"?bv[b.expando]?bv:new b.Event(bG,bv):new b.Event(bG);bv.type=bG;bv.isTrigger=true;bv.exclusive=bw;bv.namespace=bx.join(".");bv.namespace_re=bv.namespace?new RegExp("(^|\\.)"+bx.join("\\.(?:.*\\.)?")+"(\\.|$)"):null;by=bG.indexOf(":")<0?"on"+bG:"";if(!bA){e=b.cache;for(bC in e){if(e[bC].events&&e[bC].events[bG]){b.event.trigger(bv,bD,e[bC].handle.elem,true)}}return}bv.result=L;if(!bv.target){bv.target=bA}bD=bD!=null?b.makeArray(bD):[];bD.unshift(bv);bF=b.event.special[bG]||{};if(bF.trigger&&bF.trigger.apply(bA,bD)===false){return}bB=[[bA,bF.bindType||bG]];if(!bJ&&!bF.noBubble&&!b.isWindow(bA)){bI=bF.delegateType||bG;bH=T.test(bI+bG)?bA:bA.parentNode;bz=null;for(;bH;bH=bH.parentNode){bB.push([bH,bI]);bz=bH}if(bz&&bz===bA.ownerDocument){bB.push([bz.defaultView||bz.parentWindow||bb,bI])}}for(bC=0;bCbA){bH.push({elem:this,matches:bz.slice(bA)})}for(bC=0;bC0?this.on(e,null,bx,bw):this.trigger(e)};if(b.attrFn){b.attrFn[e]=true}if(aO.test(e)){b.event.fixHooks[e]=b.event.keyHooks}if(bf.test(e)){b.event.fixHooks[e]=b.event.mouseHooks}}); +/*! + * Sizzle CSS Selector Engine + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){var bH=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,bC="sizcache"+(Math.random()+"").replace(".",""),bI=0,bL=Object.prototype.toString,bB=false,bA=true,bK=/\\/g,bO=/\r\n/g,bQ=/\W/;[0,0].sort(function(){bA=false;return 0});var by=function(bV,e,bY,bZ){bY=bY||[];e=e||av;var b1=e;if(e.nodeType!==1&&e.nodeType!==9){return[]}if(!bV||typeof bV!=="string"){return bY}var bS,b3,b6,bR,b2,b5,b4,bX,bU=true,bT=by.isXML(e),bW=[],b0=bV;do{bH.exec("");bS=bH.exec(b0);if(bS){b0=bS[3];bW.push(bS[1]);if(bS[2]){bR=bS[3];break}}}while(bS);if(bW.length>1&&bD.exec(bV)){if(bW.length===2&&bE.relative[bW[0]]){b3=bM(bW[0]+bW[1],e,bZ)}else{b3=bE.relative[bW[0]]?[e]:by(bW.shift(),e);while(bW.length){bV=bW.shift();if(bE.relative[bV]){bV+=bW.shift()}b3=bM(bV,b3,bZ)}}}else{if(!bZ&&bW.length>1&&e.nodeType===9&&!bT&&bE.match.ID.test(bW[0])&&!bE.match.ID.test(bW[bW.length-1])){b2=by.find(bW.shift(),e,bT);e=b2.expr?by.filter(b2.expr,b2.set)[0]:b2.set[0]}if(e){b2=bZ?{expr:bW.pop(),set:bF(bZ)}:by.find(bW.pop(),bW.length===1&&(bW[0]==="~"||bW[0]==="+")&&e.parentNode?e.parentNode:e,bT);b3=b2.expr?by.filter(b2.expr,b2.set):b2.set;if(bW.length>0){b6=bF(b3)}else{bU=false}while(bW.length){b5=bW.pop();b4=b5;if(!bE.relative[b5]){b5=""}else{b4=bW.pop()}if(b4==null){b4=e}bE.relative[b5](b6,b4,bT)}}else{b6=bW=[]}}if(!b6){b6=b3}if(!b6){by.error(b5||bV)}if(bL.call(b6)==="[object Array]"){if(!bU){bY.push.apply(bY,b6)}else{if(e&&e.nodeType===1){for(bX=0;b6[bX]!=null;bX++){if(b6[bX]&&(b6[bX]===true||b6[bX].nodeType===1&&by.contains(e,b6[bX]))){bY.push(b3[bX])}}}else{for(bX=0;b6[bX]!=null;bX++){if(b6[bX]&&b6[bX].nodeType===1){bY.push(b3[bX])}}}}}else{bF(b6,bY)}if(bR){by(bR,b1,bY,bZ);by.uniqueSort(bY)}return bY};by.uniqueSort=function(bR){if(bJ){bB=bA;bR.sort(bJ);if(bB){for(var e=1;e0};by.find=function(bX,e,bY){var bW,bS,bU,bT,bV,bR;if(!bX){return[]}for(bS=0,bU=bE.order.length;bS":function(bW,bR){var bV,bU=typeof bR==="string",bS=0,e=bW.length;if(bU&&!bQ.test(bR)){bR=bR.toLowerCase();for(;bS=0)){if(!bS){e.push(bV)}}else{if(bS){bR[bU]=false}}}}return false},ID:function(e){return e[1].replace(bK,"")},TAG:function(bR,e){return bR[1].replace(bK,"").toLowerCase()},CHILD:function(e){if(e[1]==="nth"){if(!e[2]){by.error(e[0])}e[2]=e[2].replace(/^\+|\s*/g,"");var bR=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(e[2]==="even"&&"2n"||e[2]==="odd"&&"2n+1"||!/\D/.test(e[2])&&"0n+"+e[2]||e[2]);e[2]=(bR[1]+(bR[2]||1))-0;e[3]=bR[3]-0}else{if(e[2]){by.error(e[0])}}e[0]=bI++;return e},ATTR:function(bU,bR,bS,e,bV,bW){var bT=bU[1]=bU[1].replace(bK,"");if(!bW&&bE.attrMap[bT]){bU[1]=bE.attrMap[bT]}bU[4]=(bU[4]||bU[5]||"").replace(bK,"");if(bU[2]==="~="){bU[4]=" "+bU[4]+" "}return bU},PSEUDO:function(bU,bR,bS,e,bV){if(bU[1]==="not"){if((bH.exec(bU[3])||"").length>1||/^\w/.test(bU[3])){bU[3]=by(bU[3],null,null,bR)}else{var bT=by.filter(bU[3],bR,bS,true^bV);if(!bS){e.push.apply(e,bT)}return false}}else{if(bE.match.POS.test(bU[0])||bE.match.CHILD.test(bU[0])){return true}}return bU},POS:function(e){e.unshift(true);return e}},filters:{enabled:function(e){return e.disabled===false&&e.type!=="hidden"},disabled:function(e){return e.disabled===true},checked:function(e){return e.checked===true},selected:function(e){if(e.parentNode){e.parentNode.selectedIndex}return e.selected===true},parent:function(e){return !!e.firstChild},empty:function(e){return !e.firstChild},has:function(bS,bR,e){return !!by(e[3],bS).length},header:function(e){return(/h\d/i).test(e.nodeName)},text:function(bS){var e=bS.getAttribute("type"),bR=bS.type;return bS.nodeName.toLowerCase()==="input"&&"text"===bR&&(e===bR||e===null)},radio:function(e){return e.nodeName.toLowerCase()==="input"&&"radio"===e.type},checkbox:function(e){return e.nodeName.toLowerCase()==="input"&&"checkbox"===e.type},file:function(e){return e.nodeName.toLowerCase()==="input"&&"file"===e.type},password:function(e){return e.nodeName.toLowerCase()==="input"&&"password"===e.type},submit:function(bR){var e=bR.nodeName.toLowerCase();return(e==="input"||e==="button")&&"submit"===bR.type},image:function(e){return e.nodeName.toLowerCase()==="input"&&"image"===e.type},reset:function(bR){var e=bR.nodeName.toLowerCase();return(e==="input"||e==="button")&&"reset"===bR.type},button:function(bR){var e=bR.nodeName.toLowerCase();return e==="input"&&"button"===bR.type||e==="button"},input:function(e){return(/input|select|textarea|button/i).test(e.nodeName)},focus:function(e){return e===e.ownerDocument.activeElement}},setFilters:{first:function(bR,e){return e===0},last:function(bS,bR,e,bT){return bR===bT.length-1},even:function(bR,e){return e%2===0},odd:function(bR,e){return e%2===1 +},lt:function(bS,bR,e){return bRe[3]-0},nth:function(bS,bR,e){return e[3]-0===bR},eq:function(bS,bR,e){return e[3]-0===bR}},filter:{PSEUDO:function(bS,bX,bW,bY){var e=bX[1],bR=bE.filters[e];if(bR){return bR(bS,bW,bX,bY)}else{if(e==="contains"){return(bS.textContent||bS.innerText||bw([bS])||"").indexOf(bX[3])>=0}else{if(e==="not"){var bT=bX[3];for(var bV=0,bU=bT.length;bV=0)}}},ID:function(bR,e){return bR.nodeType===1&&bR.getAttribute("id")===e},TAG:function(bR,e){return(e==="*"&&bR.nodeType===1)||!!bR.nodeName&&bR.nodeName.toLowerCase()===e},CLASS:function(bR,e){return(" "+(bR.className||bR.getAttribute("class"))+" ").indexOf(e)>-1},ATTR:function(bV,bT){var bS=bT[1],e=by.attr?by.attr(bV,bS):bE.attrHandle[bS]?bE.attrHandle[bS](bV):bV[bS]!=null?bV[bS]:bV.getAttribute(bS),bW=e+"",bU=bT[2],bR=bT[4];return e==null?bU==="!=":!bU&&by.attr?e!=null:bU==="="?bW===bR:bU==="*="?bW.indexOf(bR)>=0:bU==="~="?(" "+bW+" ").indexOf(bR)>=0:!bR?bW&&e!==false:bU==="!="?bW!==bR:bU==="^="?bW.indexOf(bR)===0:bU==="$="?bW.substr(bW.length-bR.length)===bR:bU==="|="?bW===bR||bW.substr(0,bR.length+1)===bR+"-":false},POS:function(bU,bR,bS,bV){var e=bR[2],bT=bE.setFilters[e];if(bT){return bT(bU,bS,bR,bV)}}}};var bD=bE.match.POS,bx=function(bR,e){return"\\"+(e-0+1)};for(var bz in bE.match){bE.match[bz]=new RegExp(bE.match[bz].source+(/(?![^\[]*\])(?![^\(]*\))/.source));bE.leftMatch[bz]=new RegExp(/(^(?:.|\r|\n)*?)/.source+bE.match[bz].source.replace(/\\(\d+)/g,bx))}var bF=function(bR,e){bR=Array.prototype.slice.call(bR,0);if(e){e.push.apply(e,bR);return e}return bR};try{Array.prototype.slice.call(av.documentElement.childNodes,0)[0].nodeType}catch(bP){bF=function(bU,bT){var bS=0,bR=bT||[];if(bL.call(bU)==="[object Array]"){Array.prototype.push.apply(bR,bU)}else{if(typeof bU.length==="number"){for(var e=bU.length;bS";e.insertBefore(bR,e.firstChild);if(av.getElementById(bS)){bE.find.ID=function(bU,bV,bW){if(typeof bV.getElementById!=="undefined"&&!bW){var bT=bV.getElementById(bU[1]);return bT?bT.id===bU[1]||typeof bT.getAttributeNode!=="undefined"&&bT.getAttributeNode("id").nodeValue===bU[1]?[bT]:L:[]}};bE.filter.ID=function(bV,bT){var bU=typeof bV.getAttributeNode!=="undefined"&&bV.getAttributeNode("id");return bV.nodeType===1&&bU&&bU.nodeValue===bT}}e.removeChild(bR);e=bR=null})();(function(){var e=av.createElement("div");e.appendChild(av.createComment(""));if(e.getElementsByTagName("*").length>0){bE.find.TAG=function(bR,bV){var bU=bV.getElementsByTagName(bR[1]);if(bR[1]==="*"){var bT=[];for(var bS=0;bU[bS];bS++){if(bU[bS].nodeType===1){bT.push(bU[bS])}}bU=bT}return bU}}e.innerHTML="";if(e.firstChild&&typeof e.firstChild.getAttribute!=="undefined"&&e.firstChild.getAttribute("href")!=="#"){bE.attrHandle.href=function(bR){return bR.getAttribute("href",2)}}e=null})();if(av.querySelectorAll){(function(){var e=by,bT=av.createElement("div"),bS="__sizzle__";bT.innerHTML="

";if(bT.querySelectorAll&&bT.querySelectorAll(".TEST").length===0){return}by=function(b4,bV,bZ,b3){bV=bV||av;if(!b3&&!by.isXML(bV)){var b2=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b4);if(b2&&(bV.nodeType===1||bV.nodeType===9)){if(b2[1]){return bF(bV.getElementsByTagName(b4),bZ)}else{if(b2[2]&&bE.find.CLASS&&bV.getElementsByClassName){return bF(bV.getElementsByClassName(b2[2]),bZ)}}}if(bV.nodeType===9){if(b4==="body"&&bV.body){return bF([bV.body],bZ)}else{if(b2&&b2[3]){var bY=bV.getElementById(b2[3]);if(bY&&bY.parentNode){if(bY.id===b2[3]){return bF([bY],bZ)}}else{return bF([],bZ)}}}try{return bF(bV.querySelectorAll(b4),bZ)}catch(b0){}}else{if(bV.nodeType===1&&bV.nodeName.toLowerCase()!=="object"){var bW=bV,bX=bV.getAttribute("id"),bU=bX||bS,b6=bV.parentNode,b5=/^\s*[+~]/.test(b4);if(!bX){bV.setAttribute("id",bU)}else{bU=bU.replace(/'/g,"\\$&")}if(b5&&b6){bV=bV.parentNode}try{if(!b5||b6){return bF(bV.querySelectorAll("[id='"+bU+"'] "+b4),bZ)}}catch(b1){}finally{if(!bX){bW.removeAttribute("id")}}}}}return e(b4,bV,bZ,b3)};for(var bR in e){by[bR]=e[bR]}bT=null})()}(function(){var e=av.documentElement,bS=e.matchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.msMatchesSelector;if(bS){var bU=!bS.call(av.createElement("div"),"div"),bR=false;try{bS.call(av.documentElement,"[test!='']:sizzle")}catch(bT){bR=true}by.matchesSelector=function(bW,bY){bY=bY.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!by.isXML(bW)){try{if(bR||!bE.match.PSEUDO.test(bY)&&!/!=/.test(bY)){var bV=bS.call(bW,bY);if(bV||!bU||bW.document&&bW.document.nodeType!==11){return bV}}}catch(bX){}}return by(bY,null,null,[bW]).length>0}}})();(function(){var e=av.createElement("div");e.innerHTML="
";if(!e.getElementsByClassName||e.getElementsByClassName("e").length===0){return}e.lastChild.className="e";if(e.getElementsByClassName("e").length===1){return}bE.order.splice(1,0,"CLASS");bE.find.CLASS=function(bR,bS,bT){if(typeof bS.getElementsByClassName!=="undefined"&&!bT){return bS.getElementsByClassName(bR[1])}};e=null})();function bv(bR,bW,bV,bZ,bX,bY){for(var bT=0,bS=bZ.length;bT0){bU=e;break}}}e=e[bR]}bZ[bT]=bU}}}if(av.documentElement.contains){by.contains=function(bR,e){return bR!==e&&(bR.contains?bR.contains(e):true)}}else{if(av.documentElement.compareDocumentPosition){by.contains=function(bR,e){return !!(bR.compareDocumentPosition(e)&16)}}else{by.contains=function(){return false}}}by.isXML=function(e){var bR=(e?e.ownerDocument||e:0).documentElement;return bR?bR.nodeName!=="HTML":false};var bM=function(bS,e,bW){var bV,bX=[],bU="",bY=e.nodeType?[e]:e;while((bV=bE.match.PSEUDO.exec(bS))){bU+=bV[0];bS=bS.replace(bE.match.PSEUDO,"")}bS=bE.relative[bS]?bS+"*":bS;for(var bT=0,bR=bY.length;bT0){for(bB=bA;bB=0:b.filter(e,this).length>0:this.filter(e).length>0)},closest:function(by,bx){var bv=[],bw,e,bz=this[0];if(b.isArray(by)){var bB=1;while(bz&&bz.ownerDocument&&bz!==bx){for(bw=0;bw-1:b.find.matchesSelector(bz,by)){bv.push(bz);break}else{bz=bz.parentNode;if(!bz||!bz.ownerDocument||bz===bx||bz.nodeType===11){break}}}}bv=bv.length>1?b.unique(bv):bv;return this.pushStack(bv,"closest",by)},index:function(e){if(!e){return(this[0]&&this[0].parentNode)?this.prevAll().length:-1}if(typeof e==="string"){return b.inArray(this[0],b(e))}return b.inArray(e.jquery?e[0]:e,this)},add:function(e,bv){var bx=typeof e==="string"?b(e,bv):b.makeArray(e&&e.nodeType?[e]:e),bw=b.merge(this.get(),bx);return this.pushStack(C(bx[0])||C(bw[0])?bw:b.unique(bw))},andSelf:function(){return this.add(this.prevObject)}});function C(e){return !e||!e.parentNode||e.parentNode.nodeType===11}b.each({parent:function(bv){var e=bv.parentNode;return e&&e.nodeType!==11?e:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(bv,e,bw){return b.dir(bv,"parentNode",bw)},next:function(e){return b.nth(e,2,"nextSibling")},prev:function(e){return b.nth(e,2,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(bv,e,bw){return b.dir(bv,"nextSibling",bw)},prevUntil:function(bv,e,bw){return b.dir(bv,"previousSibling",bw)},siblings:function(e){return b.sibling(e.parentNode.firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:b.makeArray(e.childNodes)}},function(e,bv){b.fn[e]=function(by,bw){var bx=b.map(this,bv,by);if(!ab.test(e)){bw=by}if(bw&&typeof bw==="string"){bx=b.filter(bw,bx)}bx=this.length>1&&!ay[e]?b.unique(bx):bx;if((this.length>1||a9.test(bw))&&aq.test(e)){bx=bx.reverse()}return this.pushStack(bx,e,P.call(arguments).join(","))}});b.extend({filter:function(bw,e,bv){if(bv){bw=":not("+bw+")"}return e.length===1?b.find.matchesSelector(e[0],bw)?[e[0]]:[]:b.find.matches(bw,e)},dir:function(bw,bv,by){var e=[],bx=bw[bv];while(bx&&bx.nodeType!==9&&(by===L||bx.nodeType!==1||!b(bx).is(by))){if(bx.nodeType===1){e.push(bx)}bx=bx[bv]}return e},nth:function(by,e,bw,bx){e=e||1;var bv=0;for(;by;by=by[bw]){if(by.nodeType===1&&++bv===e){break}}return by},sibling:function(bw,bv){var e=[];for(;bw;bw=bw.nextSibling){if(bw.nodeType===1&&bw!==bv){e.push(bw)}}return e}});function aG(bx,bw,e){bw=bw||0;if(b.isFunction(bw)){return b.grep(bx,function(bz,by){var bA=!!bw.call(bz,by,bz);return bA===e})}else{if(bw.nodeType){return b.grep(bx,function(bz,by){return(bz===bw)===e})}else{if(typeof bw==="string"){var bv=b.grep(bx,function(by){return by.nodeType===1});if(bp.test(bw)){return b.filter(bw,bv,!e)}else{bw=b.filter(bw,bv)}}}}return b.grep(bx,function(bz,by){return(b.inArray(bz,bw)>=0)===e})}function a(e){var bw=aR.split("|"),bv=e.createDocumentFragment();if(bv.createElement){while(bw.length){bv.createElement(bw.pop())}}return bv}var aR="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",ag=/ jQuery\d+="(?:\d+|null)"/g,ar=/^\s+/,R=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,d=/<([\w:]+)/,w=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},ac=a(av); +ax.optgroup=ax.option;ax.tbody=ax.tfoot=ax.colgroup=ax.caption=ax.thead;ax.th=ax.td;if(!b.support.htmlSerialize){ax._default=[1,"div
","
"]}b.fn.extend({text:function(e){if(b.isFunction(e)){return this.each(function(bw){var bv=b(this);bv.text(e.call(this,bw,bv.text()))})}if(typeof e!=="object"&&e!==L){return this.empty().append((this[0]&&this[0].ownerDocument||av).createTextNode(e))}return b.text(this)},wrapAll:function(e){if(b.isFunction(e)){return this.each(function(bw){b(this).wrapAll(e.call(this,bw))})}if(this[0]){var bv=b(e,this[0].ownerDocument).eq(0).clone(true);if(this[0].parentNode){bv.insertBefore(this[0])}bv.map(function(){var bw=this;while(bw.firstChild&&bw.firstChild.nodeType===1){bw=bw.firstChild}return bw}).append(this)}return this},wrapInner:function(e){if(b.isFunction(e)){return this.each(function(bv){b(this).wrapInner(e.call(this,bv))})}return this.each(function(){var bv=b(this),bw=bv.contents();if(bw.length){bw.wrapAll(e)}else{bv.append(e)}})},wrap:function(e){var bv=b.isFunction(e);return this.each(function(bw){b(this).wrapAll(bv?e.call(this,bw):e)})},unwrap:function(){return this.parent().each(function(){if(!b.nodeName(this,"body")){b(this).replaceWith(this.childNodes)}}).end()},append:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.appendChild(e)}})},prepend:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.insertBefore(e,this.firstChild)}})},before:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bv){this.parentNode.insertBefore(bv,this)})}else{if(arguments.length){var e=b.clean(arguments);e.push.apply(e,this.toArray());return this.pushStack(e,"before",arguments)}}},after:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bv){this.parentNode.insertBefore(bv,this.nextSibling)})}else{if(arguments.length){var e=this.pushStack(this,"after",arguments);e.push.apply(e,b.clean(arguments));return e}}},remove:function(e,bx){for(var bv=0,bw;(bw=this[bv])!=null;bv++){if(!e||b.filter(e,[bw]).length){if(!bx&&bw.nodeType===1){b.cleanData(bw.getElementsByTagName("*"));b.cleanData([bw])}if(bw.parentNode){bw.parentNode.removeChild(bw)}}}return this},empty:function(){for(var e=0,bv;(bv=this[e])!=null;e++){if(bv.nodeType===1){b.cleanData(bv.getElementsByTagName("*"))}while(bv.firstChild){bv.removeChild(bv.firstChild)}}return this},clone:function(bv,e){bv=bv==null?false:bv;e=e==null?bv:e;return this.map(function(){return b.clone(this,bv,e)})},html:function(bx){if(bx===L){return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(ag,""):null}else{if(typeof bx==="string"&&!ae.test(bx)&&(b.support.leadingWhitespace||!ar.test(bx))&&!ax[(d.exec(bx)||["",""])[1].toLowerCase()]){bx=bx.replace(R,"<$1>");try{for(var bw=0,bv=this.length;bw1&&bw0?this.clone(true):this).get();b(bC[bA])[bv](by);bz=bz.concat(by)}return this.pushStack(bz,e,bC.selector)}}});function bg(e){if(typeof e.getElementsByTagName!=="undefined"){return e.getElementsByTagName("*")}else{if(typeof e.querySelectorAll!=="undefined"){return e.querySelectorAll("*")}else{return[]}}}function az(e){if(e.type==="checkbox"||e.type==="radio"){e.defaultChecked=e.checked}}function E(e){var bv=(e.nodeName||"").toLowerCase();if(bv==="input"){az(e)}else{if(bv!=="script"&&typeof e.getElementsByTagName!=="undefined"){b.grep(e.getElementsByTagName("input"),az)}}}function al(e){var bv=av.createElement("div");ac.appendChild(bv);bv.innerHTML=e.outerHTML;return bv.firstChild}b.extend({clone:function(by,bA,bw){var e,bv,bx,bz=b.support.html5Clone||!ah.test("<"+by.nodeName)?by.cloneNode(true):al(by);if((!b.support.noCloneEvent||!b.support.noCloneChecked)&&(by.nodeType===1||by.nodeType===11)&&!b.isXMLDoc(by)){ai(by,bz);e=bg(by);bv=bg(bz);for(bx=0;e[bx];++bx){if(bv[bx]){ai(e[bx],bv[bx])}}}if(bA){t(by,bz);if(bw){e=bg(by);bv=bg(bz);for(bx=0;e[bx];++bx){t(e[bx],bv[bx])}}}e=bv=null;return bz},clean:function(bw,by,bH,bA){var bF;by=by||av;if(typeof by.createElement==="undefined"){by=by.ownerDocument||by[0]&&by[0].ownerDocument||av}var bI=[],bB;for(var bE=0,bz;(bz=bw[bE])!=null;bE++){if(typeof bz==="number"){bz+=""}if(!bz){continue}if(typeof bz==="string"){if(!W.test(bz)){bz=by.createTextNode(bz)}else{bz=bz.replace(R,"<$1>");var bK=(d.exec(bz)||["",""])[1].toLowerCase(),bx=ax[bK]||ax._default,bD=bx[0],bv=by.createElement("div");if(by===av){ac.appendChild(bv)}else{a(by).appendChild(bv)}bv.innerHTML=bx[1]+bz+bx[2];while(bD--){bv=bv.lastChild}if(!b.support.tbody){var e=w.test(bz),bC=bK==="table"&&!e?bv.firstChild&&bv.firstChild.childNodes:bx[1]===""&&!e?bv.childNodes:[];for(bB=bC.length-1;bB>=0;--bB){if(b.nodeName(bC[bB],"tbody")&&!bC[bB].childNodes.length){bC[bB].parentNode.removeChild(bC[bB])}}}if(!b.support.leadingWhitespace&&ar.test(bz)){bv.insertBefore(by.createTextNode(ar.exec(bz)[0]),bv.firstChild)}bz=bv.childNodes}}var bG;if(!b.support.appendChecked){if(bz[0]&&typeof(bG=bz.length)==="number"){for(bB=0;bB=0){return bx+"px"}}else{return bx}}}});if(!b.support.opacity){b.cssHooks.opacity={get:function(bv,e){return au.test((e&&bv.currentStyle?bv.currentStyle.filter:bv.style.filter)||"")?(parseFloat(RegExp.$1)/100)+"":e?"1":""},set:function(by,bz){var bx=by.style,bv=by.currentStyle,e=b.isNumeric(bz)?"alpha(opacity="+bz*100+")":"",bw=bv&&bv.filter||bx.filter||"";bx.zoom=1;if(bz>=1&&b.trim(bw.replace(ak,""))===""){bx.removeAttribute("filter");if(bv&&!bv.filter){return}}bx.filter=ak.test(bw)?bw.replace(ak,e):bw+" "+e}}}b(function(){if(!b.support.reliableMarginRight){b.cssHooks.marginRight={get:function(bw,bv){var e;b.swap(bw,{display:"inline-block"},function(){if(bv){e=Z(bw,"margin-right","marginRight")}else{e=bw.style.marginRight}});return e}}}});if(av.defaultView&&av.defaultView.getComputedStyle){aI=function(by,bw){var bv,bx,e;bw=bw.replace(z,"-$1").toLowerCase();if((bx=by.ownerDocument.defaultView)&&(e=bx.getComputedStyle(by,null))){bv=e.getPropertyValue(bw);if(bv===""&&!b.contains(by.ownerDocument.documentElement,by)){bv=b.style(by,bw)}}return bv}}if(av.documentElement.currentStyle){aX=function(bz,bw){var bA,e,by,bv=bz.currentStyle&&bz.currentStyle[bw],bx=bz.style;if(bv===null&&bx&&(by=bx[bw])){bv=by}if(!bc.test(bv)&&bn.test(bv)){bA=bx.left;e=bz.runtimeStyle&&bz.runtimeStyle.left;if(e){bz.runtimeStyle.left=bz.currentStyle.left}bx.left=bw==="fontSize"?"1em":(bv||0);bv=bx.pixelLeft+"px";bx.left=bA;if(e){bz.runtimeStyle.left=e}}return bv===""?"auto":bv}}Z=aI||aX;function p(by,bw,bv){var bA=bw==="width"?by.offsetWidth:by.offsetHeight,bz=bw==="width"?an:a1,bx=0,e=bz.length; +if(bA>0){if(bv!=="border"){for(;bx)<[^<]*)*<\/script>/gi,q=/^(?:select|textarea)/i,h=/\s+/,br=/([?&])_=[^&]*/,K=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,A=b.fn.load,aa={},r={},aE,s,aV=["*/"]+["*"];try{aE=bl.href}catch(aw){aE=av.createElement("a");aE.href="";aE=aE.href}s=K.exec(aE.toLowerCase())||[];function f(e){return function(by,bA){if(typeof by!=="string"){bA=by;by="*"}if(b.isFunction(bA)){var bx=by.toLowerCase().split(h),bw=0,bz=bx.length,bv,bB,bC;for(;bw=0){var e=bw.slice(by,bw.length);bw=bw.slice(0,by)}var bx="GET";if(bz){if(b.isFunction(bz)){bA=bz;bz=L}else{if(typeof bz==="object"){bz=b.param(bz,b.ajaxSettings.traditional);bx="POST"}}}var bv=this;b.ajax({url:bw,type:bx,dataType:"html",data:bz,complete:function(bC,bB,bD){bD=bC.responseText;if(bC.isResolved()){bC.done(function(bE){bD=bE});bv.html(e?b("
").append(bD.replace(a6,"")).find(e):bD)}if(bA){bv.each(bA,[bD,bB,bC])}}});return this},serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?b.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||q.test(this.nodeName)||aZ.test(this.type))}).map(function(e,bv){var bw=b(this).val();return bw==null?null:b.isArray(bw)?b.map(bw,function(by,bx){return{name:bv.name,value:by.replace(bs,"\r\n")}}):{name:bv.name,value:bw.replace(bs,"\r\n")}}).get()}});b.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(e,bv){b.fn[bv]=function(bw){return this.on(bv,bw)}});b.each(["get","post"],function(e,bv){b[bv]=function(bw,by,bz,bx){if(b.isFunction(by)){bx=bx||bz;bz=by;by=L}return b.ajax({type:bv,url:bw,data:by,success:bz,dataType:bx})}});b.extend({getScript:function(e,bv){return b.get(e,L,bv,"script")},getJSON:function(e,bv,bw){return b.get(e,bv,bw,"json")},ajaxSetup:function(bv,e){if(e){am(bv,b.ajaxSettings)}else{e=bv;bv=b.ajaxSettings}am(bv,e);return bv},ajaxSettings:{url:aE,isLocal:aM.test(s[1]),global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":aV},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":bb.String,"text html":true,"text json":b.parseJSON,"text xml":b.parseXML},flatOptions:{context:true,url:true}},ajaxPrefilter:f(aa),ajaxTransport:f(r),ajax:function(bz,bx){if(typeof bz==="object"){bx=bz;bz=L}bx=bx||{};var bD=b.ajaxSetup({},bx),bS=bD.context||bD,bG=bS!==bD&&(bS.nodeType||bS instanceof b)?b(bS):b.event,bR=b.Deferred(),bN=b.Callbacks("once memory"),bB=bD.statusCode||{},bC,bH={},bO={},bQ,by,bL,bE,bI,bA=0,bw,bK,bJ={readyState:0,setRequestHeader:function(bT,bU){if(!bA){var e=bT.toLowerCase();bT=bO[e]=bO[e]||bT;bH[bT]=bU}return this},getAllResponseHeaders:function(){return bA===2?bQ:null},getResponseHeader:function(bT){var e;if(bA===2){if(!by){by={};while((e=aD.exec(bQ))){by[e[1].toLowerCase()]=e[2]}}e=by[bT.toLowerCase()]}return e===L?null:e},overrideMimeType:function(e){if(!bA){bD.mimeType=e}return this},abort:function(e){e=e||"abort";if(bL){bL.abort(e)}bF(0,e);return this}};function bF(bZ,bU,b0,bW){if(bA===2){return}bA=2;if(bE){clearTimeout(bE)}bL=L;bQ=bW||"";bJ.readyState=bZ>0?4:0;var bT,b4,b3,bX=bU,bY=b0?bj(bD,bJ,b0):L,bV,b2;if(bZ>=200&&bZ<300||bZ===304){if(bD.ifModified){if((bV=bJ.getResponseHeader("Last-Modified"))){b.lastModified[bC]=bV}if((b2=bJ.getResponseHeader("Etag"))){b.etag[bC]=b2}}if(bZ===304){bX="notmodified";bT=true}else{try{b4=G(bD,bY);bX="success";bT=true}catch(b1){bX="parsererror";b3=b1}}}else{b3=bX;if(!bX||bZ){bX="error";if(bZ<0){bZ=0}}}bJ.status=bZ;bJ.statusText=""+(bU||bX);if(bT){bR.resolveWith(bS,[b4,bX,bJ])}else{bR.rejectWith(bS,[bJ,bX,b3])}bJ.statusCode(bB);bB=L;if(bw){bG.trigger("ajax"+(bT?"Success":"Error"),[bJ,bD,bT?b4:b3])}bN.fireWith(bS,[bJ,bX]);if(bw){bG.trigger("ajaxComplete",[bJ,bD]);if(!(--b.active)){b.event.trigger("ajaxStop")}}}bR.promise(bJ);bJ.success=bJ.done;bJ.error=bJ.fail;bJ.complete=bN.add;bJ.statusCode=function(bT){if(bT){var e;if(bA<2){for(e in bT){bB[e]=[bB[e],bT[e]]}}else{e=bT[bJ.status];bJ.then(e,e)}}return this};bD.url=((bz||bD.url)+"").replace(bq,"").replace(c,s[1]+"//");bD.dataTypes=b.trim(bD.dataType||"*").toLowerCase().split(h);if(bD.crossDomain==null){bI=K.exec(bD.url.toLowerCase());bD.crossDomain=!!(bI&&(bI[1]!=s[1]||bI[2]!=s[2]||(bI[3]||(bI[1]==="http:"?80:443))!=(s[3]||(s[1]==="http:"?80:443))))}if(bD.data&&bD.processData&&typeof bD.data!=="string"){bD.data=b.param(bD.data,bD.traditional)}aW(aa,bD,bx,bJ);if(bA===2){return false}bw=bD.global;bD.type=bD.type.toUpperCase();bD.hasContent=!aQ.test(bD.type);if(bw&&b.active++===0){b.event.trigger("ajaxStart")}if(!bD.hasContent){if(bD.data){bD.url+=(M.test(bD.url)?"&":"?")+bD.data;delete bD.data}bC=bD.url;if(bD.cache===false){var bv=b.now(),bP=bD.url.replace(br,"$1_="+bv);bD.url=bP+((bP===bD.url)?(M.test(bD.url)?"&":"?")+"_="+bv:"")}}if(bD.data&&bD.hasContent&&bD.contentType!==false||bx.contentType){bJ.setRequestHeader("Content-Type",bD.contentType)}if(bD.ifModified){bC=bC||bD.url;if(b.lastModified[bC]){bJ.setRequestHeader("If-Modified-Since",b.lastModified[bC])}if(b.etag[bC]){bJ.setRequestHeader("If-None-Match",b.etag[bC])}}bJ.setRequestHeader("Accept",bD.dataTypes[0]&&bD.accepts[bD.dataTypes[0]]?bD.accepts[bD.dataTypes[0]]+(bD.dataTypes[0]!=="*"?", "+aV+"; q=0.01":""):bD.accepts["*"]);for(bK in bD.headers){bJ.setRequestHeader(bK,bD.headers[bK])}if(bD.beforeSend&&(bD.beforeSend.call(bS,bJ,bD)===false||bA===2)){bJ.abort();return false}for(bK in {success:1,error:1,complete:1}){bJ[bK](bD[bK])}bL=aW(r,bD,bx,bJ);if(!bL){bF(-1,"No Transport")}else{bJ.readyState=1;if(bw){bG.trigger("ajaxSend",[bJ,bD])}if(bD.async&&bD.timeout>0){bE=setTimeout(function(){bJ.abort("timeout")},bD.timeout)}try{bA=1;bL.send(bH,bF)}catch(bM){if(bA<2){bF(-1,bM)}else{throw bM}}}return bJ},param:function(e,bw){var bv=[],by=function(bz,bA){bA=b.isFunction(bA)?bA():bA;bv[bv.length]=encodeURIComponent(bz)+"="+encodeURIComponent(bA)};if(bw===L){bw=b.ajaxSettings.traditional}if(b.isArray(e)||(e.jquery&&!b.isPlainObject(e))){b.each(e,function(){by(this.name,this.value)})}else{for(var bx in e){v(bx,e[bx],bw,by)}}return bv.join("&").replace(k,"+")}});function v(bw,by,bv,bx){if(b.isArray(by)){b.each(by,function(bA,bz){if(bv||ap.test(bw)){bx(bw,bz)}else{v(bw+"["+(typeof bz==="object"||b.isArray(bz)?bA:"")+"]",bz,bv,bx)}})}else{if(!bv&&by!=null&&typeof by==="object"){for(var e in by){v(bw+"["+e+"]",by[e],bv,bx)}}else{bx(bw,by)}}}b.extend({active:0,lastModified:{},etag:{}});function bj(bD,bC,bz){var bv=bD.contents,bB=bD.dataTypes,bw=bD.responseFields,by,bA,bx,e;for(bA in bw){if(bA in bz){bC[bw[bA]]=bz[bA]}}while(bB[0]==="*"){bB.shift();if(by===L){by=bD.mimeType||bC.getResponseHeader("content-type")}}if(by){for(bA in bv){if(bv[bA]&&bv[bA].test(by)){bB.unshift(bA);break}}}if(bB[0] in bz){bx=bB[0]}else{for(bA in bz){if(!bB[0]||bD.converters[bA+" "+bB[0]]){bx=bA;break}if(!e){e=bA}}bx=bx||e}if(bx){if(bx!==bB[0]){bB.unshift(bx)}return bz[bx]}}function G(bH,bz){if(bH.dataFilter){bz=bH.dataFilter(bz,bH.dataType)}var bD=bH.dataTypes,bG={},bA,bE,bw=bD.length,bB,bC=bD[0],bx,by,bF,bv,e;for(bA=1;bA=bw.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();bw.animatedProperties[this.prop]=true;for(bA in bw.animatedProperties){if(bw.animatedProperties[bA]!==true){e=false}}if(e){if(bw.overflow!=null&&!b.support.shrinkWrapBlocks){b.each(["","X","Y"],function(bC,bD){bz.style["overflow"+bD]=bw.overflow[bC]})}if(bw.hide){b(bz).hide()}if(bw.hide||bw.show){for(bA in bw.animatedProperties){b.style(bz,bA,bw.orig[bA]);b.removeData(bz,"fxshow"+bA,true);b.removeData(bz,"toggle"+bA,true)}}bv=bw.complete;if(bv){bw.complete=false;bv.call(bz)}}return false}else{if(bw.duration==Infinity){this.now=bx}else{bB=bx-this.startTime;this.state=bB/bw.duration;this.pos=b.easing[bw.animatedProperties[this.prop]](this.state,bB,0,1,bw.duration);this.now=this.start+((this.end-this.start)*this.pos)}this.update()}return true}};b.extend(b.fx,{tick:function(){var bw,bv=b.timers,e=0;for(;e").appendTo(e),bw=bv.css("display");bv.remove();if(bw==="none"||bw===""){if(!a8){a8=av.createElement("iframe");a8.frameBorder=a8.width=a8.height=0}e.appendChild(a8);if(!m||!a8.createElement){m=(a8.contentWindow||a8.contentDocument).document;m.write((av.compatMode==="CSS1Compat"?"":"")+"");m.close()}bv=m.createElement(bx);m.body.appendChild(bv);bw=b.css(bv,"display");e.removeChild(a8)}Q[bx]=bw}return Q[bx]}var V=/^t(?:able|d|h)$/i,ad=/^(?:body|html)$/i;if("getBoundingClientRect" in av.documentElement){b.fn.offset=function(bI){var by=this[0],bB;if(bI){return this.each(function(e){b.offset.setOffset(this,bI,e)})}if(!by||!by.ownerDocument){return null}if(by===by.ownerDocument.body){return b.offset.bodyOffset(by)}try{bB=by.getBoundingClientRect()}catch(bF){}var bH=by.ownerDocument,bw=bH.documentElement;if(!bB||!b.contains(bw,by)){return bB?{top:bB.top,left:bB.left}:{top:0,left:0}}var bC=bH.body,bD=aK(bH),bA=bw.clientTop||bC.clientTop||0,bE=bw.clientLeft||bC.clientLeft||0,bv=bD.pageYOffset||b.support.boxModel&&bw.scrollTop||bC.scrollTop,bz=bD.pageXOffset||b.support.boxModel&&bw.scrollLeft||bC.scrollLeft,bG=bB.top+bv-bA,bx=bB.left+bz-bE;return{top:bG,left:bx}}}else{b.fn.offset=function(bF){var bz=this[0];if(bF){return this.each(function(bG){b.offset.setOffset(this,bF,bG)})}if(!bz||!bz.ownerDocument){return null}if(bz===bz.ownerDocument.body){return b.offset.bodyOffset(bz)}var bC,bw=bz.offsetParent,bv=bz,bE=bz.ownerDocument,bx=bE.documentElement,bA=bE.body,bB=bE.defaultView,e=bB?bB.getComputedStyle(bz,null):bz.currentStyle,bD=bz.offsetTop,by=bz.offsetLeft;while((bz=bz.parentNode)&&bz!==bA&&bz!==bx){if(b.support.fixedPosition&&e.position==="fixed"){break}bC=bB?bB.getComputedStyle(bz,null):bz.currentStyle;bD-=bz.scrollTop;by-=bz.scrollLeft;if(bz===bw){bD+=bz.offsetTop;by+=bz.offsetLeft;if(b.support.doesNotAddBorder&&!(b.support.doesAddBorderForTableAndCells&&V.test(bz.nodeName))){bD+=parseFloat(bC.borderTopWidth)||0;by+=parseFloat(bC.borderLeftWidth)||0}bv=bw;bw=bz.offsetParent}if(b.support.subtractsBorderForOverflowNotVisible&&bC.overflow!=="visible"){bD+=parseFloat(bC.borderTopWidth)||0;by+=parseFloat(bC.borderLeftWidth)||0}e=bC}if(e.position==="relative"||e.position==="static"){bD+=bA.offsetTop;by+=bA.offsetLeft}if(b.support.fixedPosition&&e.position==="fixed"){bD+=Math.max(bx.scrollTop,bA.scrollTop);by+=Math.max(bx.scrollLeft,bA.scrollLeft)}return{top:bD,left:by}}}b.offset={bodyOffset:function(e){var bw=e.offsetTop,bv=e.offsetLeft;if(b.support.doesNotIncludeMarginInBodyOffset){bw+=parseFloat(b.css(e,"marginTop"))||0;bv+=parseFloat(b.css(e,"marginLeft"))||0}return{top:bw,left:bv}},setOffset:function(bx,bG,bA){var bB=b.css(bx,"position");if(bB==="static"){bx.style.position="relative"}var bz=b(bx),bv=bz.offset(),e=b.css(bx,"top"),bE=b.css(bx,"left"),bF=(bB==="absolute"||bB==="fixed")&&b.inArray("auto",[e,bE])>-1,bD={},bC={},bw,by;if(bF){bC=bz.position();bw=bC.top;by=bC.left}else{bw=parseFloat(e)||0;by=parseFloat(bE)||0}if(b.isFunction(bG)){bG=bG.call(bx,bA,bv)}if(bG.top!=null){bD.top=(bG.top-bv.top)+bw}if(bG.left!=null){bD.left=(bG.left-bv.left)+by}if("using" in bG){bG.using.call(bx,bD)}else{bz.css(bD)}}};b.fn.extend({position:function(){if(!this[0]){return null}var bw=this[0],bv=this.offsetParent(),bx=this.offset(),e=ad.test(bv[0].nodeName)?{top:0,left:0}:bv.offset();bx.top-=parseFloat(b.css(bw,"marginTop"))||0;bx.left-=parseFloat(b.css(bw,"marginLeft"))||0;e.top+=parseFloat(b.css(bv[0],"borderTopWidth"))||0;e.left+=parseFloat(b.css(bv[0],"borderLeftWidth"))||0;return{top:bx.top-e.top,left:bx.left-e.left}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||av.body;while(e&&(!ad.test(e.nodeName)&&b.css(e,"position")==="static")){e=e.offsetParent}return e})}});b.each(["Left","Top"],function(bv,e){var bw="scroll"+e;b.fn[bw]=function(bz){var bx,by;if(bz===L){bx=this[0];if(!bx){return null}by=aK(bx);return by?("pageXOffset" in by)?by[bv?"pageYOffset":"pageXOffset"]:b.support.boxModel&&by.document.documentElement[bw]||by.document.body[bw]:bx[bw]}return this.each(function(){by=aK(this);if(by){by.scrollTo(!bv?bz:b(by).scrollLeft(),bv?bz:b(by).scrollTop())}else{this[bw]=bz}})}});function aK(e){return b.isWindow(e)?e:e.nodeType===9?e.defaultView||e.parentWindow:false}b.each(["Height","Width"],function(bv,e){var bw=e.toLowerCase();b.fn["inner"+e]=function(){var bx=this[0];return bx?bx.style?parseFloat(b.css(bx,bw,"padding")):this[bw]():null};b.fn["outer"+e]=function(by){var bx=this[0];return bx?bx.style?parseFloat(b.css(bx,bw,by?"margin":"border")):this[bw]():null};b.fn[bw]=function(bz){var bA=this[0];if(!bA){return bz==null?null:this}if(b.isFunction(bz)){return this.each(function(bE){var bD=b(this);bD[bw](bz.call(this,bE,bD[bw]()))})}if(b.isWindow(bA)){var bB=bA.document.documentElement["client"+e],bx=bA.document.body;return bA.document.compatMode==="CSS1Compat"&&bB||bx&&bx["client"+e]||bB}else{if(bA.nodeType===9){return Math.max(bA.documentElement["client"+e],bA.body["scroll"+e],bA.documentElement["scroll"+e],bA.body["offset"+e],bA.documentElement["offset"+e])}else{if(bz===L){var bC=b.css(bA,bw),by=parseFloat(bC);return b.isNumeric(by)?by:bC}else{return this.css(bw,typeof bz==="string"?bz:bz+"px")}}}}});bb.jQuery=bb.$=b;if(typeof define==="function"&&define.amd&&define.amd.jQuery){define("jquery",[],function(){return b +})}})(window); +/*! + PowerTip - v1.2.0 - 2013-04-03 + http://stevenbenner.github.com/jquery-powertip/ + Copyright (c) 2013 Steven Benner (http://stevenbenner.com/). + Released under MIT license. + https://raw.github.com/stevenbenner/jquery-powertip/master/LICENSE.txt +*/ +(function(a){if(typeof define==="function"&&define.amd){define(["jquery"],a)}else{a(jQuery)}}(function(k){var A=k(document),s=k(window),w=k("body");var n="displayController",e="hasActiveHover",d="forcedOpen",u="hasMouseMove",f="mouseOnToPopup",g="originalTitle",y="powertip",o="powertipjq",l="powertiptarget",E=180/Math.PI;var c={isTipOpen:false,isFixedTipOpen:false,isClosing:false,tipOpenImminent:false,activeHover:null,currentX:0,currentY:0,previousX:0,previousY:0,desyncTimeout:null,mouseTrackingActive:false,delayInProgress:false,windowWidth:0,windowHeight:0,scrollTop:0,scrollLeft:0};var p={none:0,top:1,bottom:2,left:4,right:8};k.fn.powerTip=function(F,N){if(!this.length){return this}if(k.type(F)==="string"&&k.powerTip[F]){return k.powerTip[F].call(this,this,N)}var O=k.extend({},k.fn.powerTip.defaults,F),G=new x(O);h();this.each(function M(){var R=k(this),Q=R.data(y),P=R.data(o),T=R.data(l),S;if(R.data(n)){k.powerTip.destroy(R)}S=R.attr("title");if(!Q&&!T&&!P&&S){R.data(y,S);R.data(g,S);R.removeAttr("title")}R.data(n,new t(R,O,G))});if(!O.manual){this.on({"mouseenter.powertip":function J(P){k.powerTip.show(this,P)},"mouseleave.powertip":function L(){k.powerTip.hide(this)},"focus.powertip":function K(){k.powerTip.show(this)},"blur.powertip":function H(){k.powerTip.hide(this,true)},"keydown.powertip":function I(P){if(P.keyCode===27){k.powerTip.hide(this,true)}}})}return this};k.fn.powerTip.defaults={fadeInTime:200,fadeOutTime:100,followMouse:false,popupId:"powerTip",intentSensitivity:7,intentPollInterval:100,closeDelay:100,placement:"n",smartPlacement:false,offset:10,mouseOnToPopup:false,manual:false};k.fn.powerTip.smartPlacementLists={n:["n","ne","nw","s"],e:["e","ne","se","w","nw","sw","n","s","e"],s:["s","se","sw","n"],w:["w","nw","sw","e","ne","se","n","s","w"],nw:["nw","w","sw","n","s","se","nw"],ne:["ne","e","se","n","s","sw","ne"],sw:["sw","w","nw","s","n","ne","sw"],se:["se","e","ne","s","n","nw","se"],"nw-alt":["nw-alt","n","ne-alt","sw-alt","s","se-alt","w","e"],"ne-alt":["ne-alt","n","nw-alt","se-alt","s","sw-alt","e","w"],"sw-alt":["sw-alt","s","se-alt","nw-alt","n","ne-alt","w","e"],"se-alt":["se-alt","s","sw-alt","ne-alt","n","nw-alt","e","w"]};k.powerTip={show:function z(F,G){if(G){i(G);c.previousX=G.pageX;c.previousY=G.pageY;k(F).data(n).show()}else{k(F).first().data(n).show(true,true)}return F},reposition:function r(F){k(F).first().data(n).resetPosition();return F},hide:function D(G,F){if(G){k(G).first().data(n).hide(F)}else{if(c.activeHover){c.activeHover.data(n).hide(true)}}return G},destroy:function C(G){k(G).off(".powertip").each(function F(){var I=k(this),H=[g,n,e,d];if(I.data(g)){I.attr("title",I.data(g));H.push(y)}I.removeData(H)});return G}};k.powerTip.showTip=k.powerTip.show;k.powerTip.closeTip=k.powerTip.hide;function b(){var F=this;F.top="auto";F.left="auto";F.right="auto";F.bottom="auto";F.set=function(H,G){if(k.isNumeric(G)){F[H]=Math.round(G)}}}function t(K,N,F){var J=null;function L(P,Q){M();if(!K.data(e)){if(!P){c.tipOpenImminent=true;J=setTimeout(function O(){J=null;I()},N.intentPollInterval)}else{if(Q){K.data(d,true)}F.showTip(K)}}}function G(P){M();c.tipOpenImminent=false;if(K.data(e)){K.data(d,false);if(!P){c.delayInProgress=true;J=setTimeout(function O(){J=null;F.hideTip(K);c.delayInProgress=false},N.closeDelay)}else{F.hideTip(K)}}}function I(){var Q=Math.abs(c.previousX-c.currentX),O=Math.abs(c.previousY-c.currentY),P=Q+O;if(P",{id:Q.popupId});if(w.length===0){w=k("body")}w.append(O)}if(Q.followMouse){if(!O.data(u)){A.on("mousemove",M);s.on("scroll",M);O.data(u,true)}}if(Q.mouseOnToPopup){O.on({mouseenter:function L(){if(O.data(f)){if(c.activeHover){c.activeHover.data(n).cancel()}}},mouseleave:function N(){if(c.activeHover){c.activeHover.data(n).hide()}}})}function I(S){S.data(e,true);O.queue(function R(T){H(S);T()})}function H(S){var U;if(!S.data(e)){return}if(c.isTipOpen){if(!c.isClosing){K(c.activeHover)}O.delay(100).queue(function R(V){H(S);V()});return}S.trigger("powerTipPreRender");U=B(S);if(U){O.empty().append(U)}else{return}S.trigger("powerTipRender");c.activeHover=S;c.isTipOpen=true;O.data(f,Q.mouseOnToPopup);if(!Q.followMouse){G(S);c.isFixedTipOpen=true}else{M()}O.fadeIn(Q.fadeInTime,function T(){if(!c.desyncTimeout){c.desyncTimeout=setInterval(J,500)}S.trigger("powerTipOpen")})}function K(R){c.isClosing=true;c.activeHover=null;c.isTipOpen=false;c.desyncTimeout=clearInterval(c.desyncTimeout);R.data(e,false);R.data(d,false);O.fadeOut(Q.fadeOutTime,function S(){var T=new b();c.isClosing=false;c.isFixedTipOpen=false;O.removeClass();T.set("top",c.currentY+Q.offset);T.set("left",c.currentX+Q.offset);O.css(T);R.trigger("powerTipClose")})}function M(){if(!c.isFixedTipOpen&&(c.isTipOpen||(c.tipOpenImminent&&O.data(u)))){var R=O.outerWidth(),V=O.outerHeight(),U=new b(),S,T;U.set("top",c.currentY+Q.offset);U.set("left",c.currentX+Q.offset);S=m(U,R,V);if(S!==p.none){T=a(S);if(T===1){if(S===p.right){U.set("left",c.windowWidth-R)}else{if(S===p.bottom){U.set("top",c.scrollTop+c.windowHeight-V)}}}else{U.set("left",c.currentX-R-Q.offset);U.set("top",c.currentY-V-Q.offset)}}O.css(U)}}function G(S){var R,T;if(Q.smartPlacement){R=k.fn.powerTip.smartPlacementLists[Q.placement];k.each(R,function(U,W){var V=m(F(S,W),O.outerWidth(),O.outerHeight());T=W;if(V===p.none){return false}})}else{F(S,Q.placement);T=Q.placement}O.addClass(T)}function F(U,T){var R=0,S,W,V=new b();V.set("top",0);V.set("left",0);O.css(V);do{S=O.outerWidth();W=O.outerHeight();V=P.compute(U,T,S,W,Q.offset);O.css(V)}while(++R<=5&&(S!==O.outerWidth()||W!==O.outerHeight()));return V}function J(){var R=false;if(c.isTipOpen&&!c.isClosing&&!c.delayInProgress){if(c.activeHover.data(e)===false||c.activeHover.is(":disabled")){R=true}else{if(!v(c.activeHover)&&!c.activeHover.is(":focus")&&!c.activeHover.data(d)){if(O.data(f)){if(!v(O)){R=true}}else{R=true}}}if(R){K(c.activeHover)}}}this.showTip=I;this.hideTip=K;this.resetPosition=G}function q(F){return window.SVGElement&&F[0] instanceof SVGElement}function h(){if(!c.mouseTrackingActive){c.mouseTrackingActive=true;k(function H(){c.scrollLeft=s.scrollLeft();c.scrollTop=s.scrollTop();c.windowWidth=s.width();c.windowHeight=s.height()});A.on("mousemove",i);s.on({resize:function G(){c.windowWidth=s.width();c.windowHeight=s.height()},scroll:function F(){var I=s.scrollLeft(),J=s.scrollTop();if(I!==c.scrollLeft){c.currentX+=I-c.scrollLeft;c.scrollLeft=I}if(J!==c.scrollTop){c.currentY+=J-c.scrollTop;c.scrollTop=J}}})}}function i(F){c.currentX=F.pageX;c.currentY=F.pageY}function v(F){var H=F.offset(),J=F[0].getBoundingClientRect(),I=J.right-J.left,G=J.bottom-J.top;return c.currentX>=H.left&&c.currentX<=H.left+I&&c.currentY>=H.top&&c.currentY<=H.top+G}function B(I){var G=I.data(y),F=I.data(o),K=I.data(l),H,J;if(G){if(k.isFunction(G)){G=G.call(I[0])}J=G}else{if(F){if(k.isFunction(F)){F=F.call(I[0])}if(F.length>0){J=F.clone(true,true)}}else{if(K){H=k("#"+K);if(H.length>0){J=H.html()}}}}return J}function m(M,L,K){var G=c.scrollTop,J=c.scrollLeft,I=G+c.windowHeight,F=J+c.windowWidth,H=p.none;if(M.topI||Math.abs(M.bottom-c.windowHeight)>I){H|=p.bottom}if(M.leftF){H|=p.left}if(M.left+L>F||M.right + + + + + +Calculator: parse.cpp File Reference + + + + + + +
+
+
+ + + + + +
+
Calculator +  Step 1 +
+
+ + + + + + +
+ +
+
parse.cpp File Reference
+
+
+
#include <sstream>
+#include <utility>
+#include "parse.hpp"
+
+

Go to the source code of this file.

+ + + + +

+Functions

void parse_loop (std::istream &input, std::ostream &output)
 
+

Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + +
void parse_loop (std::istream & input,
std::ostream & output 
)
+
+

Parse loop. Read expressions from input and print results to output.

+
Parameters
+ + + +
inputThe input stream.
outputThe output stream.
+
+
+ +

Definition at line 183 of file parse.cpp.

+ +

Referenced by BOOST_AUTO_TEST_CASE(), and main().

+
184 {
+
185  std::string line;
+
186  // No portable way to test whether the console is an interactive terminal
+
187  // vs. a non-interactive file. If you have a system-specific way to test,
+
188  // output the prompt only for the interactive case.
+
189  for (output << "> "; std::getline(input, line); output << "> ") {
+
190  std::istringstream input{std::move(line)};
+
191  parser p{input};
+
192  try {
+
193  double x{};
+
194  while (p.get_expr(x))
+
195  output << x << '\n';
+
196  } catch(parse_error const& ex) {
+
197  output << ex.what() << '\n';
+
198  } catch(std::exception const& ex) {
+
199  output << "exception: " << ex.what() << '\n';
+
200  }
+
201  }
+
202 }
+
Definition: parse.hpp:17
+ +
+
+
+
+ + + + diff --git a/exploring-cpp-2e/chapter71/step1/html/parse_8cpp_source.html b/exploring-cpp-2e/chapter71/step1/html/parse_8cpp_source.html new file mode 100644 index 0000000..fb8ba5b --- /dev/null +++ b/exploring-cpp-2e/chapter71/step1/html/parse_8cpp_source.html @@ -0,0 +1,270 @@ + + + + + + +Calculator: parse.cpp Source File + + + + + + +
+
+ + + + + + +
+
Calculator +  Step 1 +
+
+
+ + + + +
+
+
+
parse.cpp
+
+
+Go to the documentation of this file.
1 #include <sstream>
+
2 #include <utility>
+
3 
+
4 #include "parse.hpp"
+
5 
+
6 parser::parser(std::istream& input)
+
7 : input_(input),
+
8  ctype_(std::use_facet<std::ctype<char>>(input.getloc()))
+
9 {}
+
10 
+
11 std::string parser::charify(char c)
+
12 {
+
13  if (c == '\a') return R"('\a')";
+
14  if (c == '\b') return R"('\b')";
+
15  if (c == '\f') return R"('\f')";
+
16  if (c == '\n') return R"('\n')";
+
17  if (c == '\r') return R"('\r')";
+
18  if (c == '\t') return R"('\t')";
+
19  if (c == '\v') return R"('\v')";
+
20  if (c == '\'') return R"('\'')";
+
21  if (c == '\\') return R"('\\')";
+
22 
+
23  if (isprint(c))
+
24  return std::string{"\'"} + std::string(1,c) + "\'";
+
25  else {
+
26  std::ostringstream stream{};
+
27  stream << "'\\x" << std::hex;
+
28  stream.fill('0');
+
29  stream.width(2);
+
30  stream << (std::char_traits<char>::to_int_type(c) & 0xFF) << '\'';
+
31  return stream.str();
+
32  }
+
33 }
+
34 
+
35 /* Parse a floating point number.
+
36  * NUMBER ::= SIGN? DIGIT+ ('.' DIGITS+)? ('E' SIGN? DIGITS+)?
+
37  */
+
38 bool parser::get_number(double& result)
+
39 {
+
40  std::string token{};
+
41  char c{};
+
42  if (not input_.get(c))
+
43  return false;
+
44  if (c == '+' or c == '-') {
+
45  token += c;
+
46  if (not input_.get(c))
+
47  throw parse_error{"unterminated number: expected a digit after the sign"};
+
48  }
+
49  if (c < '0' or c > '9') {
+
50  input_.unget();
+
51  throw parse_error{"syntax error: expected digit, got " + charify(c)};
+
52  }
+
53  while (c >= '0' and c <= '9') {
+
54  token += c;
+
55  if (not input_.get(c)) {
+
56  std::istringstream tmp{std::move(token)};
+
57  // If the value overflows, return false.
+
58  return (tmp >> result);
+
59  }
+
60  }
+
61  if (c == '.') {
+
62  token += c;
+
63  if (not input_.get(c))
+
64  throw parse_error{"unterminated number: expected digit after the decimal point"};
+
65  if (c < '0' or c > '9') {
+
66  input_.unget();
+
67  throw parse_error{"syntax error: expected digit after decimal point, got " + charify(c)};
+
68  }
+
69  while (c >= '0' and c <= '9') {
+
70  token += c;
+
71  if (not input_.get(c)) {
+
72  std::istringstream tmp{std::move(token)};
+
73  // If the value overflows or is otherwise invalid, return false.
+
74  return (tmp >> result);
+
75  }
+
76  }
+
77  }
+
78  if (c == 'e' or c == 'E') {
+
79  token += c;
+
80  if (not input_.get(c))
+
81  throw parse_error{"unterminated number: expected digit in the exponent"};
+
82  if (c == '-' or c == '+') {
+
83  token += c;
+
84  if (not input_.get(c))
+
85  throw parse_error{"unterminated number: expected digit after sign in the exponent"};
+
86  }
+
87  if (c < '0' or c > '9') {
+
88  input_.unget();
+
89  throw parse_error{"syntax error: expected digit in the exponent, got " + charify(c)};
+
90  }
+
91  while (c >= '0' and c <= '9') {
+
92  token += c;
+
93  if (not input_.get(c)) {
+
94  std::istringstream tmp{std::move(token)};
+
95  // If the value overflows or is otherwise invalid, return false.
+
96  return (tmp >> result);
+
97  }
+
98  }
+
99  }
+
100  input_.unget();
+
101 
+
102  std::istringstream tmp{std::move(token)};
+
103  // If the value overflows or is otherwise invalid, return false.
+
104  return (tmp >> result);
+
105 }
+
106 
+
107 /* Parse an expression.
+
108  * EXPR ::= MULT_EXPR | EXPR + MULT_EXPR | EXPR - MULT_EXP
+
109  */
+
110 bool parser::get_expr(double& result)
+
111 {
+
112  if (not get_mult_expr(result))
+
113  return false;
+
114  char c{};
+
115  while (input_ >> c) {
+
116  if (c != '+' and c != '-') {
+
117  input_.unget();
+
118  return true;
+
119  } else {
+
120  double right{};
+
121  if (not get_mult_expr(right))
+
122  throw parse_error{"syntax error: unterminated expression. Expected a multiplicative-exprssion after " + std::string(c,1)};
+
123  if (c == '+')
+
124  result += right;
+
125  else
+
126  result -= right;
+
127  }
+
128  }
+
129  return true;
+
130 }
+
131 
+
132 /* Parse a multiplicative-expression.
+
133  * MULT_EXPR ::= PRIMARY | MULT_EXPR + PRIMARY | MULT_EXPR - PRIMARY
+
134  */
+
135 bool parser::get_mult_expr(double& result)
+
136 {
+
137  if (not get_primary(result))
+
138  return false;
+
139  char c{};
+
140  while (input_ >> c) {
+
141  if (c != '*' and c != '/') {
+
142  input_.unget();
+
143  return true;
+
144  } else {
+
145  double right{};
+
146  if (not get_primary(right))
+
147  throw parse_error{"syntax error: unterminated expression. Expected a primary after " + std::string(c,1)};
+
148  if (c == '*')
+
149  result *= right;
+
150  else if (right == 0.0)
+
151  throw parse_error{"division by zero"};
+
152  else
+
153  result /= right;
+
154  }
+
155  }
+
156  return true;
+
157 }
+
158 
+
159 /* Parse a primary.
+
160  * PRIMARY ::= NUMBER | '(' EXPR ')'
+
161  */
+
162 bool parser::get_primary(double& result)
+
163 {
+
164  char c{};
+
165  if (not (input_ >> c))
+
166  // Can't read one character, so must be end-of-file
+
167  return false;
+
168  else if (c == '(') {
+
169  if (not get_expr(result))
+
170  return false;
+
171  if (not (input_ >> c))
+
172  throw parse_error{"syntax error: EOF when expecting ')'"};
+
173  else if (c != ')')
+
174  throw parse_error{"syntax error: expected ')', but got " + charify(c)};
+
175  else
+
176  return true;
+
177  } else {
+
178  input_.unget();
+
179  return get_number(result);
+
180  }
+
181 }
+
182 
+
183 void parse_loop(std::istream& input, std::ostream& output)
+
184 {
+
185  std::string line;
+
186  // No portable way to test whether the console is an interactive terminal
+
187  // vs. a non-interactive file. If you have a system-specific way to test,
+
188  // output the prompt only for the interactive case.
+
189  for (output << "> "; std::getline(input, line); output << "> ") {
+
190  std::istringstream input{std::move(line)};
+
191  parser p{input};
+
192  try {
+
193  double x{};
+
194  while (p.get_expr(x))
+
195  output << x << '\n';
+
196  } catch(parse_error const& ex) {
+
197  output << ex.what() << '\n';
+
198  } catch(std::exception const& ex) {
+
199  output << "exception: " << ex.what() << '\n';
+
200  }
+
201  }
+
202 }
+
bool get_primary(double &result)
Definition: parse.cpp:162
+
void parse_loop(std::istream &input, std::ostream &output)
Definition: parse.cpp:183
+
parser(std::istream &input)
Definition: parse.cpp:6
+
std::string charify(char c)
Definition: parse.cpp:11
+
bool get_number(double &result)
Definition: parse.cpp:38
+
Definition: parse.hpp:17
+
bool get_expr(double &result)
Definition: parse.cpp:110
+ + +
std::istream & input_
Definition: parse.hpp:55
+
bool get_mult_expr(double &result)
Definition: parse.cpp:135
+
+ + + + diff --git a/exploring-cpp-2e/chapter71/step1/html/parse_8hpp.html b/exploring-cpp-2e/chapter71/step1/html/parse_8hpp.html new file mode 100644 index 0000000..83d1382 --- /dev/null +++ b/exploring-cpp-2e/chapter71/step1/html/parse_8hpp.html @@ -0,0 +1,140 @@ + + + + + + +Calculator: parse.hpp File Reference + + + + + + +
+
+ + + + + + +
+
Calculator +  Step 1 +
+
+
+ + + + +
+
+ +
+
parse.hpp File Reference
+
+
+
#include <istream>
+#include <locale>
+#include <ostream>
+#include <stdexcept>
+#include <string>
+
+

Go to the source code of this file.

+ + + + + + +

+Classes

class  parse_error
 
class  parser
 
+ + + +

+Functions

void parse_loop (std::istream &input, std::ostream &output)
 
+

Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + +
void parse_loop (std::istream & input,
std::ostream & output 
)
+
+

Parse loop. Read expressions from input and print results to output.

+
Parameters
+ + + +
inputThe input stream.
outputThe output stream.
+
+
+ +

Definition at line 183 of file parse.cpp.

+ +

Referenced by BOOST_AUTO_TEST_CASE(), and main().

+
184 {
+
185  std::string line;
+
186  // No portable way to test whether the console is an interactive terminal
+
187  // vs. a non-interactive file. If you have a system-specific way to test,
+
188  // output the prompt only for the interactive case.
+
189  for (output << "> "; std::getline(input, line); output << "> ") {
+
190  std::istringstream input{std::move(line)};
+
191  parser p{input};
+
192  try {
+
193  double x{};
+
194  while (p.get_expr(x))
+
195  output << x << '\n';
+
196  } catch(parse_error const& ex) {
+
197  output << ex.what() << '\n';
+
198  } catch(std::exception const& ex) {
+
199  output << "exception: " << ex.what() << '\n';
+
200  }
+
201  }
+
202 }
+
Definition: parse.hpp:17
+ +
+
+
+
+ + + + diff --git a/exploring-cpp-2e/chapter71/step1/html/parse_8hpp_source.html b/exploring-cpp-2e/chapter71/step1/html/parse_8hpp_source.html new file mode 100644 index 0000000..362e75b --- /dev/null +++ b/exploring-cpp-2e/chapter71/step1/html/parse_8hpp_source.html @@ -0,0 +1,103 @@ + + + + + + +Calculator: parse.hpp Source File + + + + + + +
+
+ + + + + + +
+
Calculator +  Step 1 +
+
+
+ + + + +
+
+
+
parse.hpp
+
+
+Go to the documentation of this file.
1 #ifndef PARSE_HPP_
+
2 #define PARSE_HPP_
+
3 
+
4 #include <istream>
+
5 #include <locale>
+
6 #include <ostream>
+
7 #include <stdexcept>
+
8 #include <string>
+
9 
+
11 class parse_error : public std::runtime_error {
+
12 public:
+
13  parse_error(std::string const& msg) : runtime_error{msg} {}
+
14 };
+
15 
+
17 class parser
+
18 {
+
19 public:
+
23  parser(std::istream& input);
+
24 
+
30  bool get_expr(double& result);
+
31 
+
32 private:
+
37  std::string charify(char c);
+
42  bool get_number(double& result);
+
48  bool get_primary(double& result);
+
53  bool get_mult_expr(double& result);
+
54 
+
55  std::istream& input_;
+
56  std::ctype<char> const& ctype_;
+
57 };
+
58 
+
64 void parse_loop(std::istream& input, std::ostream& output);
+
65 
+
66 #endif
+
bool get_primary(double &result)
Definition: parse.cpp:162
+
void parse_loop(std::istream &input, std::ostream &output)
Definition: parse.cpp:183
+
parser(std::istream &input)
Definition: parse.cpp:6
+
parse_error(std::string const &msg)
Definition: parse.hpp:13
+
std::string charify(char c)
Definition: parse.cpp:11
+
bool get_number(double &result)
Definition: parse.cpp:38
+
Definition: parse.hpp:17
+
bool get_expr(double &result)
Definition: parse.cpp:110
+ +
std::istream & input_
Definition: parse.hpp:55
+
std::ctype< char > const & ctype_
Definition: parse.hpp:56
+
bool get_mult_expr(double &result)
Definition: parse.cpp:135
+
+ + + + diff --git a/exploring-cpp-2e/chapter71/step1/html/sync_off.png b/exploring-cpp-2e/chapter71/step1/html/sync_off.png new file mode 100644 index 0000000..3b443fc Binary files /dev/null and b/exploring-cpp-2e/chapter71/step1/html/sync_off.png differ diff --git a/exploring-cpp-2e/chapter71/step1/html/sync_on.png b/exploring-cpp-2e/chapter71/step1/html/sync_on.png new file mode 100644 index 0000000..e08320f Binary files /dev/null and b/exploring-cpp-2e/chapter71/step1/html/sync_on.png differ diff --git a/exploring-cpp-2e/chapter71/step1/html/tab_a.png b/exploring-cpp-2e/chapter71/step1/html/tab_a.png new file mode 100644 index 0000000..3b725c4 Binary files /dev/null and b/exploring-cpp-2e/chapter71/step1/html/tab_a.png differ diff --git a/exploring-cpp-2e/chapter71/step1/html/tab_b.png b/exploring-cpp-2e/chapter71/step1/html/tab_b.png new file mode 100644 index 0000000..e2b4a86 Binary files /dev/null and b/exploring-cpp-2e/chapter71/step1/html/tab_b.png differ diff --git a/exploring-cpp-2e/chapter71/step1/html/tab_h.png b/exploring-cpp-2e/chapter71/step1/html/tab_h.png new file mode 100644 index 0000000..fd5cb70 Binary files /dev/null and b/exploring-cpp-2e/chapter71/step1/html/tab_h.png differ diff --git a/exploring-cpp-2e/chapter71/step1/html/tab_s.png b/exploring-cpp-2e/chapter71/step1/html/tab_s.png new file mode 100644 index 0000000..ab478c9 Binary files /dev/null and b/exploring-cpp-2e/chapter71/step1/html/tab_s.png differ diff --git a/exploring-cpp-2e/chapter71/step1/html/tabs.css b/exploring-cpp-2e/chapter71/step1/html/tabs.css new file mode 100644 index 0000000..9cf578f --- /dev/null +++ b/exploring-cpp-2e/chapter71/step1/html/tabs.css @@ -0,0 +1,60 @@ +.tabs, .tabs2, .tabs3 { + background-image: url('tab_b.png'); + width: 100%; + z-index: 101; + font-size: 13px; + font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; +} + +.tabs2 { + font-size: 10px; +} +.tabs3 { + font-size: 9px; +} + +.tablist { + margin: 0; + padding: 0; + display: table; +} + +.tablist li { + float: left; + display: table-cell; + background-image: url('tab_b.png'); + line-height: 36px; + list-style: none; +} + +.tablist a { + display: block; + padding: 0 20px; + font-weight: bold; + background-image:url('tab_s.png'); + background-repeat:no-repeat; + background-position:right; + color: #283A5D; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + text-decoration: none; + outline: none; +} + +.tabs3 .tablist a { + padding: 0 10px; +} + +.tablist a:hover { + background-image: url('tab_h.png'); + background-repeat:repeat-x; + color: #fff; + text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); + text-decoration: none; +} + +.tablist li.current a { + background-image: url('tab_a.png'); + background-repeat:repeat-x; + color: #fff; + text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); +} diff --git a/exploring-cpp-2e/chapter71/step1/html/test__main_8cpp.html b/exploring-cpp-2e/chapter71/step1/html/test__main_8cpp.html new file mode 100644 index 0000000..3b8abaa --- /dev/null +++ b/exploring-cpp-2e/chapter71/step1/html/test__main_8cpp.html @@ -0,0 +1,83 @@ + + + + + + +Calculator: test_main.cpp File Reference + + + + + + +
+
+ + + + + + +
+
Calculator +  Step 1 +
+
+
+ + + + +
+
+ +
+
test_main.cpp File Reference
+
+
+
#include <boost/test/included/unit_test.hpp>
+
+

Go to the source code of this file.

+ + + + +

+Macros

#define BOOST_TEST_MAIN
 
+

Macro Definition Documentation

+ +
+
+ + + + +
#define BOOST_TEST_MAIN
+
+ +

Definition at line 1 of file test_main.cpp.

+ +
+
+
+ + + + diff --git a/exploring-cpp-2e/chapter71/step1/html/test__main_8cpp_source.html b/exploring-cpp-2e/chapter71/step1/html/test__main_8cpp_source.html new file mode 100644 index 0000000..0a4ff3c --- /dev/null +++ b/exploring-cpp-2e/chapter71/step1/html/test__main_8cpp_source.html @@ -0,0 +1,59 @@ + + + + + + +Calculator: test_main.cpp Source File + + + + + + +
+
+ + + + + + +
+
Calculator +  Step 1 +
+
+
+ + + + +
+
+
+
test_main.cpp
+
+
+Go to the documentation of this file.
1 #define BOOST_TEST_MAIN
+
2 #include <boost/test/included/unit_test.hpp>
+
+ + + + diff --git a/exploring-cpp-2e/chapter71/step1/html/test__parse_8cpp.html b/exploring-cpp-2e/chapter71/step1/html/test__parse_8cpp.html new file mode 100644 index 0000000..71e346f --- /dev/null +++ b/exploring-cpp-2e/chapter71/step1/html/test__parse_8cpp.html @@ -0,0 +1,392 @@ + + + + + + +Calculator: test_parse.cpp File Reference + + + + + + +
+
+ + + + + + +
+
Calculator +  Step 1 +
+
+
+ + + + +
+
+ +
+
test_parse.cpp File Reference
+
+
+
#include <iostream>
+#include <istream>
+#include <ostream>
+#include <sstream>
+#include <string>
+#include <boost/test/auto_unit_test.hpp>
+#include "parse.hpp"
+
+

Go to the source code of this file.

+ + + + + + + + + + + + + + + + + + + + + + + + +

+Functions

 BOOST_AUTO_TEST_CASE (test_number)
 
 BOOST_AUTO_TEST_CASE (test_negative)
 
 BOOST_AUTO_TEST_CASE (test_add)
 
 BOOST_AUTO_TEST_CASE (test_subtract)
 
 BOOST_AUTO_TEST_CASE (test_multiply)
 
 BOOST_AUTO_TEST_CASE (test_divide)
 
 BOOST_AUTO_TEST_CASE (test_mix)
 
 BOOST_AUTO_TEST_CASE (test_error1)
 
 BOOST_AUTO_TEST_CASE (test_error2)
 
 BOOST_AUTO_TEST_CASE (test_error3)
 
 BOOST_AUTO_TEST_CASE (test_error4)
 
+

Function Documentation

+ +
+
+ + + + + + + + +
BOOST_AUTO_TEST_CASE (test_number )
+
+ +

Definition at line 11 of file test_parse.cpp.

+ +

References parse_loop().

+
12 {
+
13  std::istringstream in{"1\n3.14159\n1.23e45\n45.67e+8\n"};
+
14  std::ostringstream out{};
+
15  parse_loop(in, out);
+
16  BOOST_CHECK_EQUAL("> 1\n> 3.14159\n> 1.23e+45\n> 4.567e+09\n> ", out.str());
+
17 }
+
void parse_loop(std::istream &input, std::ostream &output)
Definition: parse.cpp:183
+
+
+
+ +
+
+ + + + + + + + +
BOOST_AUTO_TEST_CASE (test_negative )
+
+ +

Definition at line 19 of file test_parse.cpp.

+ +

References parse_loop().

+
20 {
+
21  std::istringstream in{"-1\n-3.14159\n-1.23e-45\n-34.56e-7\n"};
+
22  std::ostringstream out{};
+
23  parse_loop(in, out);
+
24  BOOST_CHECK_EQUAL("> -1\n> -3.14159\n> -1.23e-45\n> -3.456e-06\n> ", out.str());
+
25 }
+
void parse_loop(std::istream &input, std::ostream &output)
Definition: parse.cpp:183
+
+
+
+ +
+
+ + + + + + + + +
BOOST_AUTO_TEST_CASE (test_add )
+
+ +

Definition at line 27 of file test_parse.cpp.

+ +

References parse_loop().

+
28 {
+
29  std::istringstream in{"1 + 2\n1 + 2 + 3"};
+
30  std::ostringstream out{};
+
31  parse_loop(in, out);
+
32  BOOST_CHECK_EQUAL("> 3\n> 6\n> ", out.str());
+
33 }
+
void parse_loop(std::istream &input, std::ostream &output)
Definition: parse.cpp:183
+
+
+
+ +
+
+ + + + + + + + +
BOOST_AUTO_TEST_CASE (test_subtract )
+
+ +

Definition at line 35 of file test_parse.cpp.

+ +

References parse_loop().

+
36 {
+
37  std::istringstream in{"1 - 2\n5 - 1 - 2"};
+
38  std::ostringstream out{};
+
39  parse_loop(in, out);
+
40  BOOST_CHECK_EQUAL("> -1\n> 2\n> ", out.str());
+
41 }
+
void parse_loop(std::istream &input, std::ostream &output)
Definition: parse.cpp:183
+
+
+
+ +
+
+ + + + + + + + +
BOOST_AUTO_TEST_CASE (test_multiply )
+
+ +

Definition at line 43 of file test_parse.cpp.

+ +

References parse_loop().

+
44 {
+
45  std::istringstream in{"1 * 2\n5 * 2 * 1.5"};
+
46  std::ostringstream out{};
+
47  parse_loop(in, out);
+
48  BOOST_CHECK_EQUAL("> 2\n> 15\n> ", out.str());
+
49 }
+
void parse_loop(std::istream &input, std::ostream &output)
Definition: parse.cpp:183
+
+
+
+ +
+
+ + + + + + + + +
BOOST_AUTO_TEST_CASE (test_divide )
+
+ +

Definition at line 51 of file test_parse.cpp.

+ +

References parse_loop().

+
52 {
+
53  std::istringstream in{"1 / 2\n10 / 2 / 2"};
+
54  std::ostringstream out{};
+
55  parse_loop(in, out);
+
56  BOOST_CHECK_EQUAL("> 0.5\n> 2.5\n> ", out.str());
+
57 }
+
void parse_loop(std::istream &input, std::ostream &output)
Definition: parse.cpp:183
+
+
+
+ +
+
+ + + + + + + + +
BOOST_AUTO_TEST_CASE (test_mix )
+
+ +

Definition at line 59 of file test_parse.cpp.

+ +

References parse_loop().

+
60 {
+
61  std::istringstream in{" 1.5 * 2 + 3 / 1.5 - (10 - 3) + 2 * -1"};
+
62  std::ostringstream out{};
+
63  parse_loop(in, out);
+
64  BOOST_CHECK_EQUAL("> -4\n> ", out.str());
+
65 }
+
void parse_loop(std::istream &input, std::ostream &output)
Definition: parse.cpp:183
+
+
+
+ +
+
+ + + + + + + + +
BOOST_AUTO_TEST_CASE (test_error1 )
+
+ +

Definition at line 67 of file test_parse.cpp.

+ +

References parse_loop().

+
68 {
+
69  std::istringstream in{"1+++2"};
+
70  std::ostringstream out{};
+
71  parse_loop(in, out);
+
72  BOOST_CHECK_EQUAL("> syntax error: expected digit, got '+'\n> ", out.str());
+
73 }
+
void parse_loop(std::istream &input, std::ostream &output)
Definition: parse.cpp:183
+
+
+
+ +
+
+ + + + + + + + +
BOOST_AUTO_TEST_CASE (test_error2 )
+
+ +

Definition at line 75 of file test_parse.cpp.

+ +

References parse_loop().

+
76 {
+
77  std::istringstream in{"1..2"};
+
78  std::ostringstream out{};
+
79  parse_loop(in, out);
+
80  BOOST_CHECK_EQUAL("> syntax error: expected digit after decimal point, got '.'\n> ", out.str());
+
81 }
+
void parse_loop(std::istream &input, std::ostream &output)
Definition: parse.cpp:183
+
+
+
+ +
+
+ + + + + + + + +
BOOST_AUTO_TEST_CASE (test_error3 )
+
+ +

Definition at line 83 of file test_parse.cpp.

+ +

References parse_loop().

+
84 {
+
85  std::istringstream in{"1 @ 2"};
+
86  std::ostringstream out{};
+
87  parse_loop(in, out);
+
88  BOOST_CHECK_EQUAL("> 1\nsyntax error: expected digit, got '@'\n> ", out.str());
+
89 }
+
void parse_loop(std::istream &input, std::ostream &output)
Definition: parse.cpp:183
+
+
+
+ +
+
+ + + + + + + + +
BOOST_AUTO_TEST_CASE (test_error4 )
+
+ +

Definition at line 91 of file test_parse.cpp.

+ +

References parse_loop().

+
92 {
+
93  std::istringstream in{"(1 + 2"};
+
94  std::ostringstream out{};
+
95  parse_loop(in, out);
+
96  BOOST_CHECK_EQUAL("> syntax error: EOF when expecting ')'\n> ", out.str());
+
97 }
+
void parse_loop(std::istream &input, std::ostream &output)
Definition: parse.cpp:183
+
+
+
+
+ + + + diff --git a/exploring-cpp-2e/chapter71/step1/html/test__parse_8cpp_source.html b/exploring-cpp-2e/chapter71/step1/html/test__parse_8cpp_source.html new file mode 100644 index 0000000..1c5aef1 --- /dev/null +++ b/exploring-cpp-2e/chapter71/step1/html/test__parse_8cpp_source.html @@ -0,0 +1,158 @@ + + + + + + +Calculator: test_parse.cpp Source File + + + + + + +
+
+ + + + + + +
+
Calculator +  Step 1 +
+
+
+ + + + +
+
+
+
test_parse.cpp
+
+
+Go to the documentation of this file.
1 #include <iostream>
+
2 #include <istream>
+
3 #include <ostream>
+
4 #include <sstream>
+
5 #include <string>
+
6 
+
7 #include <boost/test/auto_unit_test.hpp>
+
8 
+
9 #include "parse.hpp"
+
10 
+ +
12 {
+
13  std::istringstream in{"1\n3.14159\n1.23e45\n45.67e+8\n"};
+
14  std::ostringstream out{};
+
15  parse_loop(in, out);
+
16  BOOST_CHECK_EQUAL("> 1\n> 3.14159\n> 1.23e+45\n> 4.567e+09\n> ", out.str());
+
17 }
+
18 
+
19 BOOST_AUTO_TEST_CASE(test_negative)
+
20 {
+
21  std::istringstream in{"-1\n-3.14159\n-1.23e-45\n-34.56e-7\n"};
+
22  std::ostringstream out{};
+
23  parse_loop(in, out);
+
24  BOOST_CHECK_EQUAL("> -1\n> -3.14159\n> -1.23e-45\n> -3.456e-06\n> ", out.str());
+
25 }
+
26 
+ +
28 {
+
29  std::istringstream in{"1 + 2\n1 + 2 + 3"};
+
30  std::ostringstream out{};
+
31  parse_loop(in, out);
+
32  BOOST_CHECK_EQUAL("> 3\n> 6\n> ", out.str());
+
33 }
+
34 
+
35 BOOST_AUTO_TEST_CASE(test_subtract)
+
36 {
+
37  std::istringstream in{"1 - 2\n5 - 1 - 2"};
+
38  std::ostringstream out{};
+
39  parse_loop(in, out);
+
40  BOOST_CHECK_EQUAL("> -1\n> 2\n> ", out.str());
+
41 }
+
42 
+
43 BOOST_AUTO_TEST_CASE(test_multiply)
+
44 {
+
45  std::istringstream in{"1 * 2\n5 * 2 * 1.5"};
+
46  std::ostringstream out{};
+
47  parse_loop(in, out);
+
48  BOOST_CHECK_EQUAL("> 2\n> 15\n> ", out.str());
+
49 }
+
50 
+ +
52 {
+
53  std::istringstream in{"1 / 2\n10 / 2 / 2"};
+
54  std::ostringstream out{};
+
55  parse_loop(in, out);
+
56  BOOST_CHECK_EQUAL("> 0.5\n> 2.5\n> ", out.str());
+
57 }
+
58 
+ +
60 {
+
61  std::istringstream in{" 1.5 * 2 + 3 / 1.5 - (10 - 3) + 2 * -1"};
+
62  std::ostringstream out{};
+
63  parse_loop(in, out);
+
64  BOOST_CHECK_EQUAL("> -4\n> ", out.str());
+
65 }
+
66 
+ +
68 {
+
69  std::istringstream in{"1+++2"};
+
70  std::ostringstream out{};
+
71  parse_loop(in, out);
+
72  BOOST_CHECK_EQUAL("> syntax error: expected digit, got '+'\n> ", out.str());
+
73 }
+
74 
+ +
76 {
+
77  std::istringstream in{"1..2"};
+
78  std::ostringstream out{};
+
79  parse_loop(in, out);
+
80  BOOST_CHECK_EQUAL("> syntax error: expected digit after decimal point, got '.'\n> ", out.str());
+
81 }
+
82 
+ +
84 {
+
85  std::istringstream in{"1 @ 2"};
+
86  std::ostringstream out{};
+
87  parse_loop(in, out);
+
88  BOOST_CHECK_EQUAL("> 1\nsyntax error: expected digit, got '@'\n> ", out.str());
+
89 }
+
90 
+ +
92 {
+
93  std::istringstream in{"(1 + 2"};
+
94  std::ostringstream out{};
+
95  parse_loop(in, out);
+
96  BOOST_CHECK_EQUAL("> syntax error: EOF when expecting ')'\n> ", out.str());
+
97 }
+
98 
+
void parse_loop(std::istream &input, std::ostream &output)
Definition: parse.cpp:183
+ +
BOOST_AUTO_TEST_CASE(test_number)
Definition: test_parse.cpp:11
+
+ + + + diff --git a/exploring-cpp-2e/chapter71/step1/parse.cpp b/exploring-cpp-2e/chapter71/step1/parse.cpp new file mode 100644 index 0000000..69a9b24 --- /dev/null +++ b/exploring-cpp-2e/chapter71/step1/parse.cpp @@ -0,0 +1,202 @@ +#include +#include + +#include "parse.hpp" + +parser::parser(std::istream& input) +: input_(input), + ctype_(std::use_facet>(input.getloc())) +{} + +std::string parser::charify(char c) +{ + if (c == '\a') return R"('\a')"; + if (c == '\b') return R"('\b')"; + if (c == '\f') return R"('\f')"; + if (c == '\n') return R"('\n')"; + if (c == '\r') return R"('\r')"; + if (c == '\t') return R"('\t')"; + if (c == '\v') return R"('\v')"; + if (c == '\'') return R"('\'')"; + if (c == '\\') return R"('\\')"; + + if (isprint(c)) + return std::string{"\'"} + std::string(1,c) + "\'"; + else { + std::ostringstream stream{}; + stream << "'\\x" << std::hex; + stream.fill('0'); + stream.width(2); + stream << (std::char_traits::to_int_type(c) & 0xFF) << '\''; + return stream.str(); + } +} + +/* Parse a floating point number. + * NUMBER ::= SIGN? DIGIT+ ('.' DIGITS+)? ('E' SIGN? DIGITS+)? + */ +bool parser::get_number(double& result) +{ + std::string token{}; + char c{}; + if (not input_.get(c)) + return false; + if (c == '+' or c == '-') { + token += c; + if (not input_.get(c)) + throw parse_error{"unterminated number: expected a digit after the sign"}; + } + if (c < '0' or c > '9') { + input_.unget(); + throw parse_error{"syntax error: expected digit, got " + charify(c)}; + } + while (c >= '0' and c <= '9') { + token += c; + if (not input_.get(c)) { + std::istringstream tmp{std::move(token)}; + // If the value overflows, return false. + return (tmp >> result); + } + } + if (c == '.') { + token += c; + if (not input_.get(c)) + throw parse_error{"unterminated number: expected digit after the decimal point"}; + if (c < '0' or c > '9') { + input_.unget(); + throw parse_error{"syntax error: expected digit after decimal point, got " + charify(c)}; + } + while (c >= '0' and c <= '9') { + token += c; + if (not input_.get(c)) { + std::istringstream tmp{std::move(token)}; + // If the value overflows or is otherwise invalid, return false. + return (tmp >> result); + } + } + } + if (c == 'e' or c == 'E') { + token += c; + if (not input_.get(c)) + throw parse_error{"unterminated number: expected digit in the exponent"}; + if (c == '-' or c == '+') { + token += c; + if (not input_.get(c)) + throw parse_error{"unterminated number: expected digit after sign in the exponent"}; + } + if (c < '0' or c > '9') { + input_.unget(); + throw parse_error{"syntax error: expected digit in the exponent, got " + charify(c)}; + } + while (c >= '0' and c <= '9') { + token += c; + if (not input_.get(c)) { + std::istringstream tmp{std::move(token)}; + // If the value overflows or is otherwise invalid, return false. + return (tmp >> result); + } + } + } + input_.unget(); + + std::istringstream tmp{std::move(token)}; + // If the value overflows or is otherwise invalid, return false. + return (tmp >> result); +} + +/* Parse an expression. + * EXPR ::= MULT_EXPR | EXPR + MULT_EXPR | EXPR - MULT_EXP + */ +bool parser::get_expr(double& result) +{ + if (not get_mult_expr(result)) + return false; + char c{}; + while (input_ >> c) { + if (c != '+' and c != '-') { + input_.unget(); + return true; + } else { + double right{}; + if (not get_mult_expr(right)) + throw parse_error{"syntax error: unterminated expression. Expected a multiplicative-exprssion after " + std::string(c,1)}; + if (c == '+') + result += right; + else + result -= right; + } + } + return true; +} + +/* Parse a multiplicative-expression. + * MULT_EXPR ::= PRIMARY | MULT_EXPR + PRIMARY | MULT_EXPR - PRIMARY + */ +bool parser::get_mult_expr(double& result) +{ + if (not get_primary(result)) + return false; + char c{}; + while (input_ >> c) { + if (c != '*' and c != '/') { + input_.unget(); + return true; + } else { + double right{}; + if (not get_primary(right)) + throw parse_error{"syntax error: unterminated expression. Expected a primary after " + std::string(c,1)}; + if (c == '*') + result *= right; + else if (right == 0.0) + throw parse_error{"division by zero"}; + else + result /= right; + } + } + return true; +} + +/* Parse a primary. + * PRIMARY ::= NUMBER | '(' EXPR ')' + */ +bool parser::get_primary(double& result) +{ + char c{}; + if (not (input_ >> c)) + // Can't read one character, so must be end-of-file + return false; + else if (c == '(') { + if (not get_expr(result)) + return false; + if (not (input_ >> c)) + throw parse_error{"syntax error: EOF when expecting ')'"}; + else if (c != ')') + throw parse_error{"syntax error: expected ')', but got " + charify(c)}; + else + return true; + } else { + input_.unget(); + return get_number(result); + } +} + +void parse_loop(std::istream& input, std::ostream& output) +{ + std::string line; + // No portable way to test whether the console is an interactive terminal + // vs. a non-interactive file. If you have a system-specific way to test, + // output the prompt only for the interactive case. + for (output << "> "; std::getline(input, line); output << "> ") { + std::istringstream input{std::move(line)}; + parser p{input}; + try { + double x{}; + while (p.get_expr(x)) + output << x << '\n'; + } catch(parse_error const& ex) { + output << ex.what() << '\n'; + } catch(std::exception const& ex) { + output << "exception: " << ex.what() << '\n'; + } + } +} diff --git a/exploring-cpp-2e/chapter71/step1/parse.hpp b/exploring-cpp-2e/chapter71/step1/parse.hpp new file mode 100644 index 0000000..886fb95 --- /dev/null +++ b/exploring-cpp-2e/chapter71/step1/parse.hpp @@ -0,0 +1,66 @@ +#ifndef PARSE_HPP_ +#define PARSE_HPP_ + +#include +#include +#include +#include +#include + +/** Exception class for parser errors, usually syntax errors. */ +class parse_error : public std::runtime_error { +public: + parse_error(std::string const& msg) : runtime_error{msg} {} +}; + +/** Parser class template. */ +class parser +{ +public: + /** Constructor. Save the @p input stream. + * @param input The input stream + */ + parser(std::istream& input); + + /** Read one expression and store the result in @p result. + * @param result Where to store the result of the expression. + * @return true to continue or false to end the loop + * @throw parse_error for various syntax and other errors + */ + bool get_expr(double& result); + +private: + /** Convert a characer to a readable form. + * @param c The character + * @return A C++-style character literal that ensures @p c is readable. + */ + std::string charify(char c); + /** Parse a number. + * @param result Store the number here + * @return true to continue parsing or false to stop (end of file or error) + */ + bool get_number(double& result); + /** Parse a primary expression. + * A primary is a parenthesized expression or a numeric literal. + * @param result Store the number here + * @return true to continue parsing or false to stop (end of file or error) + */ + bool get_primary(double& result); + /** Parse a multiplicative expression. + * @param result Store the number here + * @return true to continue parsing or false to stop (end of file or error) + */ + bool get_mult_expr(double& result); + + std::istream& input_; + std::ctype const& ctype_; +}; + +/** Parse loop. + * Read expressions from @p input and print results to @p output. + * @param input The input stream. + * @param output The output stream. + */ +void parse_loop(std::istream& input, std::ostream& output); + +#endif diff --git a/exploring-cpp-2e/chapter71/step1/test_main.cpp b/exploring-cpp-2e/chapter71/step1/test_main.cpp new file mode 100644 index 0000000..de7e8d7 --- /dev/null +++ b/exploring-cpp-2e/chapter71/step1/test_main.cpp @@ -0,0 +1,2 @@ +#define BOOST_TEST_MAIN +#include diff --git a/exploring-cpp-2e/chapter71/step1/test_parse.cpp b/exploring-cpp-2e/chapter71/step1/test_parse.cpp new file mode 100644 index 0000000..983ac2d --- /dev/null +++ b/exploring-cpp-2e/chapter71/step1/test_parse.cpp @@ -0,0 +1,98 @@ +#include +#include +#include +#include +#include + +#include + +#include "parse.hpp" + +BOOST_AUTO_TEST_CASE(test_number) +{ + std::istringstream in{"1\n3.14159\n1.23e45\n45.67e+8\n"}; + std::ostringstream out{}; + parse_loop(in, out); + BOOST_CHECK_EQUAL("> 1\n> 3.14159\n> 1.23e+45\n> 4.567e+09\n> ", out.str()); +} + +BOOST_AUTO_TEST_CASE(test_negative) +{ + std::istringstream in{"-1\n-3.14159\n-1.23e-45\n-34.56e-7\n"}; + std::ostringstream out{}; + parse_loop(in, out); + BOOST_CHECK_EQUAL("> -1\n> -3.14159\n> -1.23e-45\n> -3.456e-06\n> ", out.str()); +} + +BOOST_AUTO_TEST_CASE(test_add) +{ + std::istringstream in{"1 + 2\n1 + 2 + 3"}; + std::ostringstream out{}; + parse_loop(in, out); + BOOST_CHECK_EQUAL("> 3\n> 6\n> ", out.str()); +} + +BOOST_AUTO_TEST_CASE(test_subtract) +{ + std::istringstream in{"1 - 2\n5 - 1 - 2"}; + std::ostringstream out{}; + parse_loop(in, out); + BOOST_CHECK_EQUAL("> -1\n> 2\n> ", out.str()); +} + +BOOST_AUTO_TEST_CASE(test_multiply) +{ + std::istringstream in{"1 * 2\n5 * 2 * 1.5"}; + std::ostringstream out{}; + parse_loop(in, out); + BOOST_CHECK_EQUAL("> 2\n> 15\n> ", out.str()); +} + +BOOST_AUTO_TEST_CASE(test_divide) +{ + std::istringstream in{"1 / 2\n10 / 2 / 2"}; + std::ostringstream out{}; + parse_loop(in, out); + BOOST_CHECK_EQUAL("> 0.5\n> 2.5\n> ", out.str()); +} + +BOOST_AUTO_TEST_CASE(test_mix) +{ + std::istringstream in{" 1.5 * 2 + 3 / 1.5 - (10 - 3) + 2 * -1"}; + std::ostringstream out{}; + parse_loop(in, out); + BOOST_CHECK_EQUAL("> -4\n> ", out.str()); +} + +BOOST_AUTO_TEST_CASE(test_error1) +{ + std::istringstream in{"1+++2"}; + std::ostringstream out{}; + parse_loop(in, out); + BOOST_CHECK_EQUAL("> syntax error: expected digit, got '+'\n> ", out.str()); +} + +BOOST_AUTO_TEST_CASE(test_error2) +{ + std::istringstream in{"1..2"}; + std::ostringstream out{}; + parse_loop(in, out); + BOOST_CHECK_EQUAL("> syntax error: expected digit after decimal point, got '.'\n> ", out.str()); +} + +BOOST_AUTO_TEST_CASE(test_error3) +{ + std::istringstream in{"1 @ 2"}; + std::ostringstream out{}; + parse_loop(in, out); + BOOST_CHECK_EQUAL("> 1\nsyntax error: expected digit, got '@'\n> ", out.str()); +} + +BOOST_AUTO_TEST_CASE(test_error4) +{ + std::istringstream in{"(1 + 2"}; + std::ostringstream out{}; + parse_loop(in, out); + BOOST_CHECK_EQUAL("> syntax error: EOF when expecting ')'\n> ", out.str()); +} + diff --git a/exploring-cpp-2e/chapter71/step2/Doxyfile b/exploring-cpp-2e/chapter71/step2/Doxyfile new file mode 100644 index 0000000..6d9886a --- /dev/null +++ b/exploring-cpp-2e/chapter71/step2/Doxyfile @@ -0,0 +1,2280 @@ +# Doxyfile 1.8.5 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = "Calculator" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = "Step 2" + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is included in +# the documentation. The maximum height of the logo should not exceed 55 pixels +# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo +# to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese- +# Traditional, Croatian, Czech, Danish, Dutch, English, Esperanto, Farsi, +# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en, +# Korean, Korean-en, Latvian, Norwegian, Macedonian, Persian, Polish, +# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, +# Turkish, Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a +# new page for each member. If set to NO, the documentation of a member will be +# part of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. +# +# Note For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by by putting a % sign in front of the word +# or globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO these classes will be included in the various overviews. This option has +# no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the +# todo list. This list is created by putting \todo commands in the +# documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the +# test list. This list is created by putting \test commands in the +# documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES the list +# will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. Do not use file names with spaces, bibtex cannot handle them. See +# also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO doxygen will only warn about wrong or incomplete parameter +# documentation, but not about the absence of documentation. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. +# Note: If this tag is empty the current directory is searched. + +INPUT = + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank the +# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, +# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, +# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, +# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, +# *.qsf, *.as and *.js. + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER ) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = YES + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES, then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 1 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user- +# defined cascading style sheet that is included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefor more robust against future updates. +# Doxygen will copy the style sheet file to the output directory. For an example +# see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the stylesheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to NO can help when comparing the output of multiple runs. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = NO + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler ( hhc.exe). If non-empty +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated ( +# YES) or that it should be included in the master .chm file ( NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated ( +# YES) or a normal table of contents ( NO) in the .chm file. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using prerendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /