diff --git a/cs142/final/Makefile b/cs142/final/Makefile new file mode 100644 index 0000000..e4e80f9 --- /dev/null +++ b/cs142/final/Makefile @@ -0,0 +1,31 @@ +CXXFLAGS= -Wall -g +OBJECTS=main.o employee.o hourly.o salaried.o administrator.o faculty.o util.o campus.o +EXE=main + +all: $(EXE) + + +$(EXE): main.o + $(CXX) $(CXXFLAGS) $(OBJECTS) -o $@ + +main.o: main.cpp employee.o hourly.o salaried.o administrator.o faculty.o util.o campus.o +employee.o: employee.h employee.cpp +hourly.o: hourly.cpp hourly.h employee.h +salaried.o: salaried.h salaried.cpp employee.h +administrator.o: administrator.cpp administrator.h employee.h +faculty.o: faculty.cpp faculty.h employee.h +util.o: util.h util.cpp +campus.o: campus.cpp campus.h + +run: $(EXE) + @./$(EXE) + +clean: + @rm -vf *.o + @rm -vf $(EXE) + +debug: $(EXE) + gdb ./$(EXE) + +valgrind: $(EXE) + valgrind --tool=memcheck --leak-check=yes ./$(EXE) diff --git a/cs142/final/administrator.cpp b/cs142/final/administrator.cpp new file mode 100644 index 0000000..102595d --- /dev/null +++ b/cs142/final/administrator.cpp @@ -0,0 +1,14 @@ +#include "administrator.h" +#include "employee.h" + +using namespace std; + +administrator::administrator(string name, double pay_rate, int hours, string type) : + employee(name, pay_rate, hours, type) {} + +int administrator::get_salary() { + if(hours > 170) { + pay_rate += pay_rate * .1; + } + return pay_rate; +} diff --git a/cs142/final/administrator.h b/cs142/final/administrator.h new file mode 100644 index 0000000..e714ff2 --- /dev/null +++ b/cs142/final/administrator.h @@ -0,0 +1,15 @@ +#ifndef __ADMINISTRATOR_H__ +#define __ADMINISTRATOR_H__ + +#include +#include "employee.h" + +using namespace std; + +class administrator : public employee { + public: + administrator(string name, double pay_rate, int hours, string type); + int get_salary(); +}; + +#endif diff --git a/cs142/final/campus.cpp b/cs142/final/campus.cpp new file mode 100644 index 0000000..61d4221 --- /dev/null +++ b/cs142/final/campus.cpp @@ -0,0 +1,263 @@ +#include "campus.h" +#include "salaried.h" +#include "hourly.h" +#include "faculty.h" +#include "administrator.h" +#include "util.h" +#include +#include +#include +#include + +bool campus::contains(string name) { //function used to verify if the string is already included + employee * f = NULL; + for(unsigned int i = 0; i < workers.size(); i++) { + f = dynamic_cast(workers[i]); + if(f->get_name() == name) { + return true; + } + } + return false; +} + +void campus::add_worker_from_parse(string name, string type, double pay_rate) { //add worker for parsed input + bool passed = false; + employee * h = NULL; + int hours = 0; + if(type == "H") { + h = new hourly(name, pay_rate, hours, type); + passed = true; + } + else if(type == "S") { + h = new salaried(name, pay_rate, hours, type); + passed = true; + } + else if(type == "F") { + h = new faculty(name, pay_rate, hours, type); + passed = true; + } + else if(type == "A") { + h = new administrator(name, pay_rate, hours, type); + passed = true; + } + if(passed == true) { + workers.push_back(h); + } +} + +void campus::add_worker() { //general add worker function which it gets the input + employee * h = NULL; + bool passed; + string info; + string name, type; + int hours = 0; + double pay_rate = 0; + cout << "Enter info in following format" << endl; + cout << "type pay_rate name" << endl;; + getline(cin, info); + passed = parse_n_load(info, name, type, pay_rate); + if(contains(name) == true) { + cout << "already exists" << endl; + return; + } + if(passed == false) { + cout << "incorrect entry" << endl; + } + if(info[0] == ' ') { + cout << "incorrect entry" << endl; + passed = false; + } + else if(type == "H") { + h = new hourly(name, pay_rate, hours, type); + } + else if(type == "S") { + h = new salaried(name, pay_rate, hours, type); + } + else if(type == "F") { + h = new faculty(name, pay_rate, hours, type); + } + else if(type == "A") { + h = new administrator(name, pay_rate, hours, type); + } + if(passed == true) { + workers.push_back(h); + } +} +void campus::delete_worker() { + string name; + employee * h = NULL; + cout << "Enter name of worker to delete" << endl; + getline(cin, name); + for(unsigned int i = 0; i < workers.size(); i++) { + h = dynamic_cast(workers[i]); + if(h->get_name() == name) { + delete h; + workers.erase(workers.begin() + i); + } + } +} + +void campus::display_worker() { //allows for display of all employees or selected + string input; + employee * h = NULL; + cout << "(a)ll workers or (o)ne worker?" << endl; + cin >> input; + cin.ignore(); + cout << "type // payrate // name // hours // salary" << endl; + if(input == "a") { + for(unsigned int i = 0; i < workers.size(); i++){ + h = dynamic_cast(workers[i]); + cout << *workers[i] << " $" << h->get_salary() << endl; + } + } + if(input == "o") { + cout << "name: "; + employee * h = NULL; + getline(cin, input); + for(unsigned int i = 0; i < workers.size(); i++) { + h = dynamic_cast(workers[i]); + if(h->get_name() == input) { + cout << *h << " $" << h->get_salary() << endl; + } + } + + } +} + +void campus::sort_name() { + bool ready = true; + employee * h = NULL; + employee * j = NULL; + while(ready) { + for(unsigned int i = 0; i < workers.size() -1; i++) { + h = dynamic_cast(workers[i]); + j = dynamic_cast(workers[i+1]); + ready = false; + if(h->get_name() > j->get_name()) { + workers.push_back(workers[i]); + workers[i] = workers[i+1]; + workers[i+1] = workers[workers.size()-1]; + workers.pop_back(); + ready = true; + } + } + } +} + +void campus::sort_pay() { + bool ready = true; + employee * h = NULL; + employee * j = NULL; + while(ready) { + for(unsigned int i = 0; i < workers.size() -1; i++) { + h = dynamic_cast(workers[i]); + j = dynamic_cast(workers[i+1]); + ready = false; + if(h->get_payrate() > j->get_payrate()) { + workers.push_back(workers[i]); + workers[i] = workers[i+1]; + workers[i+1] = workers[workers.size()-1]; + workers.pop_back(); + ready = true; + } + } + } +} + +void campus::sort_worker() { //allows for either sort by name or by pay + string input; + cout << "sort by (n)ame or by (p)ay?" << endl; + cin >> input; + if(input == "n") { + sort_name(); + } + if(input == "p") { + sort_pay(); + } +} + +void campus::advance_month() { + employee * h = NULL; + for(unsigned int i = 0; i < workers.size(); i++) { + h = dynamic_cast(workers[i]); + h->reset_hours(); + } +} + +void campus::set_hours() { + string name; + employee * h = NULL; + cout << "enter name of employee" << endl; + getline(cin, name); + for(unsigned int i = 0; i < workers.size(); i++) { + h = dynamic_cast(workers[i]); + if(h->get_name() == name) { + int input; + cout << "enter hours" << endl; + cin >> input; + cin.ignore(); + h->set_hours(input); + } + } +} + +void campus::add_files(campus c) { //function for i/o. can either write to a file or take a file in + string add_or_write; + cout << "(a)dd or (w)rite to file?" << endl; + cin >> add_or_write; + cin.ignore(); + if(add_or_write == "a") { + bool file_correct = false; + string input, input_file_name; + while(!file_correct) { + cout << "please enter file name: "; + getline(cin, input); + ifstream inputs(input.c_str()); + if(inputs.good()) { + input_file_name = input; + file_correct = true; + string lineread; + while(getline(inputs, lineread)) { + bool worked; + string name, type; + double pay_rate; + worked = parse_n_load(lineread, name, type, pay_rate); + if(worked == true) { + add_worker_from_parse(name, type, pay_rate); + } + lineread = ""; + } + } + else { + cerr << "incorrect file name" << endl; + } + } + } + if(add_or_write == "w") { + bool file_correct = false; + string input, input_file_name; + string output_file_name; + file_correct = false; + while(!file_correct) { + cout << "please enter file name: "; + getline(cin, output_file_name); + ofstream out(output_file_name.c_str()); + if(out.good()) { + out << c; + file_correct = true; + } + else { + cerr << "incorrect file name" << endl; + } + } + } +} + +ostream & operator<<(ostream & os, campus & t) { //makes writing out to files much easier + employee * h = NULL; + for(unsigned int i = 0; i < t.workers.size(); i++) { + h = dynamic_cast(t.workers[i]); + os << h->get_type() << " " << h->get_payrate() << " " << h->get_name() << "\n"; + } + return os; +} diff --git a/cs142/final/campus.h b/cs142/final/campus.h new file mode 100644 index 0000000..9d1349f --- /dev/null +++ b/cs142/final/campus.h @@ -0,0 +1,27 @@ +#ifndef __CAMPUS_H__ +#define __CAMPUS_H__ + +#include "employee.h" +#include + +using namespace std; + +class campus { + private: + vector workers; + public: + void add_worker(); + void add_worker_from_parse(string name, string type, double pay_rate); + void delete_worker(); + void display_worker(); + void sort_worker(); + void advance_month(); + void set_hours(); + void add_files(campus c); + void sort_name(); + void sort_pay(); + bool contains(string name); + friend ostream & operator<<(ostream & os, campus & t); +}; + +#endif diff --git a/cs142/final/employee.cpp b/cs142/final/employee.cpp new file mode 100644 index 0000000..ea102aa --- /dev/null +++ b/cs142/final/employee.cpp @@ -0,0 +1,35 @@ +#include "employee.h" +#include +using namespace std; + +employee::employee(string name, double pay_rate, int hours, string type) : + name(name), pay_rate(pay_rate), hours(hours), type(type) {} + +string employee::get_name(){ + return name; +} + +double employee::get_payrate() { + return pay_rate; +} + +int employee::get_hours() { + return hours; +} + +string employee::get_type() { + return type; +} + +void employee::reset_hours() { + hours = 0; +} + +void employee::set_hours(int input) { + hours += input; +} + +ostream & operator<<(ostream & os, employee & t){ //makes printing out employee easy + os << t.type << " " << t.pay_rate << " " << t.name << " " << t.hours; + return os; +} diff --git a/cs142/final/employee.h b/cs142/final/employee.h new file mode 100644 index 0000000..1617b27 --- /dev/null +++ b/cs142/final/employee.h @@ -0,0 +1,27 @@ +#ifndef __EMPLOYEE_H__ +#define __EMPLOYEE_H__ + +#include + +using namespace std; + +class employee { + private: + string name; + protected: + string type; + double pay_rate; + int hours; + public: + employee(string name, double pay_rate, int hours, string type); + string get_name(); + double get_payrate(); + string get_type(); + int get_hours(); + void set_hours(int input); + void reset_hours(); + virtual int get_salary() = 0; + friend ostream & operator<<(ostream & os, employee & t); +}; + +#endif diff --git a/cs142/final/faculty.cpp b/cs142/final/faculty.cpp new file mode 100644 index 0000000..95cbcbc --- /dev/null +++ b/cs142/final/faculty.cpp @@ -0,0 +1,32 @@ +#include "faculty.h" +#include "employee.h" +#include +#include + +using namespace std; + +faculty::faculty(string name, double pay_rate, int hours, string type) : employee(name, pay_rate, hours, type), + grad_students(set_grad_students()) {} + +int faculty::get_salary() { + double pay_rate_return = 0; + if(grad_students > 0){ + double percent; + pay_rate_return = pay_rate; + for(int i = 0; i < grad_students; i++){ + percent += 0.05; + } + pay_rate_return += pay_rate*percent; + return pay_rate_return; + } + return pay_rate; +} + +int faculty::get_grad_students() { + return grad_students; +} +int faculty::set_grad_students() { //gets random number of grad students for faculty + srand(time(NULL)); + int students = rand() % 5; + return students; +} diff --git a/cs142/final/faculty.h b/cs142/final/faculty.h new file mode 100644 index 0000000..b2ae7e3 --- /dev/null +++ b/cs142/final/faculty.h @@ -0,0 +1,19 @@ +#ifndef __FACULTY_H__ +#define __FACULTY_H__ + +#include +#include "employee.h" + +using namespace std; + +class faculty : public employee { + private: + int grad_students; + public: + faculty(string name, double pay_rate, int hours, string type); + int get_grad_students(); + int set_grad_students(); + int get_salary(); +}; + +#endif diff --git a/cs142/final/hourly.cpp b/cs142/final/hourly.cpp new file mode 100644 index 0000000..5b82196 --- /dev/null +++ b/cs142/final/hourly.cpp @@ -0,0 +1,19 @@ +#include "hourly.h" +#include "employee.h" + +using namespace std; + +hourly::hourly(string name, double pay_rate, int hours, string type) : employee(name, pay_rate, hours, type) {} + +int hourly::get_salary() { + int salary; + int overtime; + if((hours - 170) > 0) { + overtime = (hours - 170); + salary = 170 * pay_rate; + salary += overtime * (pay_rate * 1.5); + return salary; + } + salary = hours * pay_rate; + return salary; +} diff --git a/cs142/final/hourly.h b/cs142/final/hourly.h new file mode 100644 index 0000000..e13c1dd --- /dev/null +++ b/cs142/final/hourly.h @@ -0,0 +1,15 @@ +#ifndef __HOURLY_H__ +#define __HOURLY_H__ + +#include +#include "employee.h" + +using namespace std; + +class hourly : public employee { + public: + hourly(string name, double pay_rate, int hours, string type); + int get_salary(); +}; + +#endif diff --git a/cs142/final/main.cpp b/cs142/final/main.cpp new file mode 100644 index 0000000..0183aa3 --- /dev/null +++ b/cs142/final/main.cpp @@ -0,0 +1,48 @@ +#include +#include +#include "employee.h" +#include "salaried.h" +#include "hourly.h" +#include "faculty.h" +#include "administrator.h" +#include "util.h" +#include "campus.h" + +using namespace std; + + +int main() { //driver for program + campus c = campus(); + bool keep_going = true; + while(keep_going) { + string input; + cout << "(a)dd worker, (r)emove worker, (d)isplay worker, add (h)ours, \n"; + cout << " (s)ort workers, advance (m)onth, add (f)ile, (q)uit" << endl; + cin >> input; + cin.ignore(); + if(input == "a") { + c.add_worker(); + } + if(input == "r") { + c.delete_worker(); + } + if(input == "h") { + c.set_hours(); + } + if(input == "d") { + c.display_worker(); + } + if(input == "s") { + c.sort_worker(); + } + if(input == "m") { + c.advance_month(); + } + if(input == "f") { + c.add_files(c); //will either take in a file or write out to one + } + if(input == "q") { + keep_going = false; + } + } +} diff --git a/cs142/final/salaried.cpp b/cs142/final/salaried.cpp new file mode 100644 index 0000000..ad6ebb5 --- /dev/null +++ b/cs142/final/salaried.cpp @@ -0,0 +1,13 @@ +#include "salaried.h" +#include "employee.h" + +using namespace std; + +salaried::salaried(string name, double pay_rate, int hours, string type) : employee(name, pay_rate, hours, type) {} + +int salaried::get_salary() { + if(hours > 170/2) { + return pay_rate; + } + return 0; +} diff --git a/cs142/final/salaried.h b/cs142/final/salaried.h new file mode 100644 index 0000000..8f51a21 --- /dev/null +++ b/cs142/final/salaried.h @@ -0,0 +1,15 @@ +#ifndef __SALARIED_H__ +#define __SALARIED_H__ + +#include +#include "employee.h" + +using namespace std; + +class salaried : public employee { + public: + salaried(string name, double pay_rate, int hours, string type); + int get_salary(); +}; + +#endif diff --git a/cs142/final/tags b/cs142/final/tags new file mode 100644 index 0000000..db3b643 --- /dev/null +++ b/cs142/final/tags @@ -0,0 +1,46 @@ +!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/ +!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/ +!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/ +!_TAG_PROGRAM_NAME Exuberant Ctags // +!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/ +!_TAG_PROGRAM_VERSION 5.9~svn20110310 // +CXXFLAGS Makefile /^CXXFLAGS= -Wall -g$/;" m +EXE Makefile /^EXE=main$/;" m +OBJECTS Makefile /^OBJECTS=main.o employee.o hourly.o salaried.o administrator.o faculty.o util.o$/;" m +__ADMINISTRATOR_H__ administrator.h 2;" d +__EMPLOYEE_H__ employee.h 2;" d +__FACULTY_H__ faculty.h 2;" d +__HOURLY_H__ hourly.h 2;" d +__SALARIED_H__ salaried.h 2;" d +__UTIL_H__ util.h 2;" d +administrator administrator.cpp /^administrator::administrator(string name, double pay_rate, int hours) : employee(name, pay_rate, hours) {}$/;" f class:administrator +administrator administrator.h /^class administrator : public employee {$/;" c +employee employee.cpp /^employee::employee(string name, double pay_rate, int hours) :$/;" f class:employee +employee employee.h /^class employee {$/;" c +faculty faculty.cpp /^faculty::faculty(string name, double pay_rate, int hours) : employee(name, pay_rate, hours),$/;" f class:faculty +faculty faculty.h /^class faculty : public employee {$/;" c +get_grad_students faculty.cpp /^int faculty::get_grad_students() {$/;" f class:faculty +get_hours employee.cpp /^int employee::get_hours() {$/;" f class:employee +get_name employee.cpp /^string employee::get_name(){$/;" f class:employee +get_payrate employee.cpp /^double employee::get_payrate() {$/;" f class:employee +get_salary administrator.cpp /^int administrator::get_salary() {$/;" f class:administrator +get_salary faculty.cpp /^int faculty::get_salary() {$/;" f class:faculty +get_salary hourly.cpp /^int hourly::get_salary() {$/;" f class:hourly +get_salary salaried.cpp /^int salaried::get_salary() {$/;" f class:salaried +grad_students faculty.h /^ int grad_students;$/;" m class:faculty +hourly hourly.cpp /^hourly::hourly(string name, double pay_rate, int hours) : employee(name, pay_rate, hours) {}$/;" f class:hourly +hourly hourly.h /^class hourly : public employee {$/;" c +hours employee.h /^ int hours;$/;" m class:employee +main main.cpp /^int main() {$/;" f +name employee.h /^ string name;$/;" m class:employee +parse_n_load util.cpp /^bool parse_n_load(const string & input, string & name, string & type,$/;" f +pay_rate employee.h /^ double pay_rate;$/;" m class:employee +salaried salaried.cpp /^salaried::salaried(string name, double pay_rate, int hours) : employee(name, pay_rate, hours) {}$/;" f class:salaried +salaried salaried.h /^class salaried : public employee {$/;" c +set_grad_students faculty.cpp /^int faculty::set_grad_students() {$/;" f class:faculty +test_admin main.cpp /^void test_admin() {$/;" f +test_faculty main.cpp /^void test_faculty() {$/;" f +test_hourly main.cpp /^void test_hourly() {$/;" f +test_salaried main.cpp /^void test_salaried() {$/;" f +test_util main.cpp /^void test_util() {$/;" f +tokenize util.cpp /^vector tokenize(const string & str, const string & delimiters) {$/;" f diff --git a/cs142/final/test.txt b/cs142/final/test.txt new file mode 100644 index 0000000..8a1c5e0 --- /dev/null +++ b/cs142/final/test.txt @@ -0,0 +1,4 @@ +A 10.5 zombie +alka alkjsa +F 152 stephen is awesome +H 15.243 cremeballs. creame diff --git a/cs142/final/util.cpp b/cs142/final/util.cpp new file mode 100644 index 0000000..c518a49 --- /dev/null +++ b/cs142/final/util.cpp @@ -0,0 +1,46 @@ +#include +#include +using namespace std; +#include +#include "util.h" +#include + +vector tokenize(const string & str, const string & delimiters) { + //tokenizes a string by the delimiter passed in + vector tokens; + string::size_type lastPos = str.find_first_not_of(delimiters, 0); + string::size_type pos = str.find_first_of(delimiters, lastPos); + while (string::npos != pos or string::npos != lastPos) + { + tokens.push_back(str.substr(lastPos, pos - lastPos)); + lastPos = str.find_first_not_of(delimiters, pos); + pos = str.find_first_of(delimiters, lastPos); + } + return tokens; +} + +bool parse_n_load(const string & input, string & name, string & type, + double & pay_rate) { + vector tokens = tokenize(input); + if(tokens.size() == 0) { + return false; + } + type = tokens[0]; + if (not ( type == "A" + or type == "F" + or type == "H" + or type == "S")) { + return false; + } + pay_rate = atof(tokens[1].c_str()); + if(pay_rate == 0) { + return false; + } + for(unsigned int i = 2; i < tokens.size(); i++) { + name += tokens[i]; + if(i < tokens.size() - 1) { + name += " "; + } + } + return true; +} diff --git a/cs142/final/util.h b/cs142/final/util.h new file mode 100644 index 0000000..18e19f3 --- /dev/null +++ b/cs142/final/util.h @@ -0,0 +1,14 @@ +#ifndef __UTIL_H__ +#define __UTIL_H__ + +#include +#include + +using namespace std; + +void print(const string & in); +vector tokenize(const string & str, const string & delimiters=" "); +bool parse_n_load(const string & input, string & name, string & type, + double & pay_rate); + +#endif diff --git a/cs142/lab00/Makefile b/cs142/lab00/Makefile new file mode 100644 index 0000000..4342ace --- /dev/null +++ b/cs142/lab00/Makefile @@ -0,0 +1,6 @@ +CPPFLAGS=-Wall -g -std=c++0x + +all: hello_world + +clean: + rm -rv hello_world diff --git a/cs142/lab00/hello_world.cpp b/cs142/lab00/hello_world.cpp new file mode 100644 index 0000000..003be76 --- /dev/null +++ b/cs142/lab00/hello_world.cpp @@ -0,0 +1,10 @@ +#include + +using namespace std; + +int main() { + + cout << "Hello, world! My name is Derek McQuay."<< endl; + cin.get(); + return 0; +} diff --git a/cs142/lab01/byu.cpp b/cs142/lab01/byu.cpp new file mode 100644 index 0000000..2b6275e --- /dev/null +++ b/cs142/lab01/byu.cpp @@ -0,0 +1,17 @@ +#include + +using namespace std; + +int main() { + + + cout << " Basic BYU Trivia\n" << endl; + cout << " Questions Answers \n" << endl; + cout << "What was the original name of BYU? Brigham Young Academy" << endl; + cout << "When was BYA established? 1875" << endl; + cout << "Who was the first \"permanent\" principal of BYA? Karl G. Maeser" << endl; + cout << "When did BYA become BYU? 1903" << endl; + cout << "To what sports conference do we belong? Mountain West Conference(MWC)" << endl; + cout << "When did BYU win the national football title? 1984" << endl; + cout << "Who won the Heisman Trophy in 1990? Ty Detmer" << endl; +} diff --git a/cs142/lab01/quiz.txt b/cs142/lab01/quiz.txt new file mode 100644 index 0000000..4db9d1d --- /dev/null +++ b/cs142/lab01/quiz.txt @@ -0,0 +1,22 @@ +A +D +B +A +B +C +B +B +B +B +D +B +B +C +A +C +D +A,C +B +B +A,B,C,D +so we can learn by doing rather than let someone else learn. diff --git a/cs142/lab02/Makefile b/cs142/lab02/Makefile new file mode 100644 index 0000000..c749661 --- /dev/null +++ b/cs142/lab02/Makefile @@ -0,0 +1,10 @@ +CPPFLAGS=-Wall -g -std=c++0x + +all: timer temperature binary + +binary: binary.cpp +temperature: temperature.cpp +timer: timer.cpp + +clean: + rm -rv timer temperature binary diff --git a/cs142/lab02/binary.cpp b/cs142/lab02/binary.cpp new file mode 100644 index 0000000..1639e69 --- /dev/null +++ b/cs142/lab02/binary.cpp @@ -0,0 +1,57 @@ +#include +#include + +using namespace std; + +int main() { + + int value; + int first, second, third, fourth, fifth; + vector final; + + cout << "please insert your number between 0 and 31" << endl; + cin >> value; + int prin = value%2; + value = value/2; + if(prin >=1) + first = 1; + else + first = 0; + final.push_back(first); + prin = value%2; + value = value/2; + if(prin >=1) + second = 1; + else + second = 0; + final.push_back(second); + prin = value%2; + value = value/2; + if(prin >= 1) + third = 1; + else + third = 0; + final.push_back(third); + prin = value%2; + value = value/2; + if(prin >= 1) + fourth = 1; + else + fourth = 0; + final.push_back(fourth); + prin = value%2; + value = value/2; + if(prin >= 1) + fifth = 1; + else + fifth = 0; + final.push_back(fifth); + + cout < + +using namespace std; + +int main() { + + double temperature; + cout << "please enter a temperature in degress Fahrenheit:" << endl; + cin >> temperature; + double celsius = (temperature-32) * 5/9; + cout << "This is Fahrenheit as an int:" << endl; + cout << (int) temperature << endl; + cout << "This is Celsius as a double:" << endl; + cout << celsius << endl; + cout << "This is Celsius as an int:" << endl; + cout << (int) celsius << endl; + + + +} diff --git a/cs142/lab02/timer.cpp b/cs142/lab02/timer.cpp new file mode 100644 index 0000000..87543d4 --- /dev/null +++ b/cs142/lab02/timer.cpp @@ -0,0 +1,30 @@ +#include +#include + +using namespace std; + +void calculate (int a) { + + int hours, minutes, seconds; + + hours = (a / 3600); + minutes = (a / 60) - (hours * 60); + seconds = a % 60; + + cout << "hours: " << hours << " minutes: " << minutes << " seconds: " << seconds << endl; + +}; + + +int main() { + + int time; + cout << "please enter a number of seconds" << endl; + cin >> time; + cout << time << endl; + cout << "absolute value of input " << abs (time) << endl; + calculate(time); + cout << "now with sqrt: " << endl; + calculate(sqrt(time)); +} + diff --git a/cs142/lab03/Makefile b/cs142/lab03/Makefile new file mode 100644 index 0000000..0921d49 --- /dev/null +++ b/cs142/lab03/Makefile @@ -0,0 +1,4 @@ +CXXFLAGS=-Wall -g -std=c++0x +all: grade +clean: + rm -vf grade diff --git a/cs142/lab03/class/main.cpp b/cs142/lab03/class/main.cpp new file mode 100644 index 0000000..2850424 --- /dev/null +++ b/cs142/lab03/class/main.cpp @@ -0,0 +1,13 @@ +#include + +using namespace std; + +#include "person.h" + +#pragma once + +int main(int argc, char * argv[]) { + + person p; + p.get_grades(); +} diff --git a/cs142/lab03/class/person.cpp b/cs142/lab03/class/person.cpp new file mode 100644 index 0000000..72cb456 --- /dev/null +++ b/cs142/lab03/class/person.cpp @@ -0,0 +1,60 @@ +using namespace std; + +#include "person.h" + +#pragma once + +void person::get_latedays() { + + cout << "Please enter if it was turned in earlier or late (earlier with a negative number): " << endl; + cin >> late_days; + total_latedays = total_latedays + late_days; +} + +void person::get_exam_latedays(){ + cout << "Please enter if it was turned in in late (number of late days): " << endl; + cin >> late_days_exam; + late_days_exam = abs(late_days_exam); + total_latedays_exam = total_latedays_exam + late_days_exam; +} + +void person::calculate_grade() { + + grade = lab1 + lab2 + lab3 + lab4 + lab5 + lab6 + lab7 + lab8 + lab9 + lab10 + lab11 + exam1 + exam2 + final; +} + + +void person::get_grades(){ + + cout << "please enter the name of the student: " << endl; + cout << "now we are going to enter the following grades for the student: " << endl; + cout << "Grade for lab 01: " << endl; + cin >> lab1; + cout << "Grade for lab 02; " << endl; + cin >> lab2; + cout << "Grade for lab 03; " << endl; + cin >> lab3; + cout << "Grade for lab 04; " << endl; + cin >> lab4; + cout << "Grade for lab 05; " << endl; + cin >> lab5; + cout << "Grade for lab 06; " << endl; + cin >> lab6; + cout << "Grade for lab 07; " << endl; + cin >> lab7; + cout << "Grade for lab 08; " << endl; + cin >> lab8; + cout << "Grade for lab 09; " << endl; + cin >> lab9; + cout << "Grade for lab 10; " << endl; + cin >> lab10; + cout << "Grade for lab 11; " << endl; + cin >> lab11; + cout << "Grade for exam 1: " << endl; + cin >> exam1; + cout << "Grade for exam 2: " << endl; + cin >> exam2; + cout << "Grade for final: " << endl; + cin >> final; + cout << "Please enter how many days late the final was: " << endl; +} diff --git a/cs142/lab03/class/person.h b/cs142/lab03/class/person.h new file mode 100644 index 0000000..fb64fc9 --- /dev/null +++ b/cs142/lab03/class/person.h @@ -0,0 +1,24 @@ +#include +#include + +using namespace std; + +class person +{ + + + private: + string person_name; + int lab1, lab2, lab3, lab4, lab5, lab6, lab7, lab8, lab9, lab10, lab11, exam1, exam2, final; + int late_days, total_latedays, late_days_exam, total_latedays_exam; + int grade; + + public: + + person(){}; + void get_latedays(); + void get_exam_latedays(); + void calculate_grade(); + void get_grades(); + +}; diff --git a/cs142/lab03/grade.cpp b/cs142/lab03/grade.cpp new file mode 100644 index 0000000..123d028 --- /dev/null +++ b/cs142/lab03/grade.cpp @@ -0,0 +1,304 @@ +#include +#include +#include + +using namespace std; + +struct student { + string name; + int grade; + string letter_grade; + +}; + +int main() { + // this is incorrect: typedef struct student1; + struct student student1; + struct student student2; + int lab1, lab2, lab3, lab4, lab5, lab6, lab7, lab8, lab9, lab10, lab11; + int exam1, exam2, final; + int late_days; + int late_daytotal = 0; + int exam_late_days; + int exam_late_days_total = 0; + string name; + + for(int i = 1; i<3; i++){ + cout << "Please enter name of student: " << endl; + cin >> name; + cout << "Please enter grade for lab 1: " << endl; + cin >> lab1; + if(lab1 >20 or lab1 < 0){ + cout << "This is not in the range!" << endl; + return 0; + } + cout << "Were there late days/early days?: (indicate early days by negative number, late days by positive" << endl; + cin >> late_days; + if(late_days <-2 or late_days > 2){ + cout << "This is not in the range!" << endl; + return 0; + } + late_daytotal = late_daytotal + late_days; + cout << "Please enter grade for lab 2: " << endl; + cin >> lab2; + if(lab2 >20 or lab2 < 0){ + cout << "This is not in the range!" << endl; + return 0; + } + cout << "Were there late days/early days?: (indicate early days by negative number, late days by positive" << endl; + cin >> late_days; + if(late_days <-2 or late_days > 2){ + cout << "This is not in the range!" << endl; + return 0; + } + late_daytotal = late_daytotal + late_days; + cout << "Please enter grade for lab 3: " << endl; + cin >> lab3; + if(lab3 >30 or lab3 < 0){ + cout << "This is not in the range!" << endl; + return 0; + } + cout << "Were there late days/early days?: (indicate early days by negative number, late days by positive" << endl; + cin >> late_days; + if(late_days <-3 or late_days > 3){ + cout << "This is not in the range!" << endl; + return 0; + } + late_daytotal = late_daytotal + late_days; + cout << "Please enter grade for lab 4: " << endl; + cin >> lab4; + if(lab4 >30 or lab4 < 0){ + cout << "This is not in the range!" << endl; + return 0; + } + cout << "Were there late days/early days?: (indicate early days by negative number, late days by positive" << endl; + cin >> late_days; + if(late_days <-3 or late_days > 3){ + cout << "This is not in the range!" << endl; + return 0; + } + late_daytotal = late_daytotal + late_days; + cout << "Please enter grade for lab 5: " << endl; + cin >> lab5; + if(lab5 >30 or lab5 < 0){ + cout << "This is not in the range!" << endl; + return 0; + } + cout << "Were there late days/early days?: (indicate early days by negative number, late days by positive" << endl; + cin >> late_days; + if(late_days <-3 or late_days > 3){ + cout << "This is not in the range!" << endl; + return 0; + } + late_daytotal = late_daytotal + late_days; + cout << "Please enter grade for lab 6: " << endl; + cin >> lab6; + if(lab6 >30 or lab6 < 0){ + cout << "This is not in the range!" << endl; + return 0; + } + cout << "Were there late days/early days?: (indicate early days by negative number, late days by positive" << endl; + cin >> late_days; + if(late_days <-3 or late_days > 3){ + cout << "This is not in the range!" << endl; + return 0; + } + late_daytotal = late_daytotal + late_days; + cout << "Please enter grade for lab 7: " << endl; + cin >> lab7; + if(lab7 >30 or lab7 < 0){ + cout << "This is not in the range!" << endl; + return 0; + } + cout << "Were there late days/early days?: (indicate early days by negative number, late days by positive" << endl; + cin >> late_days; + if(late_days <-3 or late_days > 3){ + cout << "This is not in the range!" << endl; + return 0; + } + late_daytotal = late_daytotal + late_days; + cout << "Please enter grade for lab 8: " << endl; + cin >> lab8; + if(lab8 >30 or lab8 < 0){ + cout << "This is not in the range!" << endl; + return 0; + } + cout << "Were there late days/early days?: (indicate early days by negative number, late days by positive" << endl; + cin >> late_days; + if(late_days <-3 or late_days > 3){ + cout << "This is not in the range!" << endl; + return 0; + } + late_daytotal = late_daytotal + late_days; + cout << "Please enter grade for lab 9: " << endl; + cin >> lab9; + if(lab9 >20 or lab9 < 0){ + cout << "This is not in the range!" << endl; + return 0; + } + cout << "Were there late days/early days?: (indicate early days by negative number, late days by positive" << endl; + cin >> late_days; + if(late_days <-2 or late_days > 2){ + cout << "This is not in the range!" << endl; + return 0; + } + late_daytotal = late_daytotal + late_days; + cout << "Please enter grade for lab 10: " << endl; + cin >> lab10; + if(lab10 >20 or lab10 < 0){ + cout << "This is not in the range!" << endl; + return 0; + } + cout << "Were there late days/early days?: (indicate early days by negative number, late days by positive" << endl; + cin >> late_days; + if(late_days <-2 or late_days > 2){ + cout << "This is not in the range!" << endl; + return 0; + } + late_daytotal = late_daytotal + late_days; + cout << "Please enter grade for lab 11: " << endl; + cin >> lab11; + if(lab11 >40 or lab11 < 0){ + cout << "This is not in the range!" << endl; + return 0; + } + cout << "Were there late days/early days?: (indicate early days by negative number, late days by positive" << endl; + cin >> late_days; + if(late_days <-4 or late_days > 4){ + cout << "This is not in the range!" << endl; + return 0; + } + late_daytotal = late_daytotal + late_days; + cout << "Please enter exam 1 score: " << endl; + cin >> exam1; + if(exam1 < 0 or exam1 > 100){ + cout << "This is not in the range!" << endl; + return 0; + } + cout << "Were there late days/early days?" << endl; + cin >> exam_late_days; + if(exam_late_days < 0 or exam_late_days > 3){ + cout << "This is not in the range!" << endl; + return 0; + } + exam_late_days_total = exam_late_days_total + exam_late_days; + cout << "Please enter exam 2 score: " << endl; + cin >> exam2; + if(exam2 < 0 or exam2 > 100){ + cout << "This is not in the range!" << endl; + return 0; + } + cout << "Were there late days/early days?" << endl; + cin >> exam_late_days; + if(exam_late_days < 0 or exam_late_days > 3){ + cout << "This is not in the range!" << endl; + return 0; + } + exam_late_days_total = exam_late_days_total + exam_late_days; + cout << "Please enter final score: " << endl; + cin >> final; + if(final < 0 or final > 100){ + cout << "This is not in the range!" << endl; + return 0; + } + cout << "Were there late days/early days?" << endl; + cin >> exam_late_days; + if(exam_late_days < 0 or exam_late_days > 3){ + cout << "This is not in the range!" << endl; + return 0; + } + exam_late_days_total = exam_late_days_total + exam_late_days; + + int total_labs = lab1+lab2+lab3+lab4+lab5+lab6+lab7+lab8+lab9+lab10+lab11; + int total_exam = exam1 + exam2 + final; + int final_grade = total_labs + total_exam; + if(late_daytotal < 0){ + final_grade = final_grade + abs(late_daytotal); + } + else{ + final_grade = final_grade - late_daytotal; + } + final_grade = final_grade - exam_late_days_total*20; + string letter_grade; + if(final_grade >= 570) + letter_grade = "A"; + if(final_grade <570 && final_grade >=540) + letter_grade = "A-"; + if(final_grade < 540 && final_grade >= 522) + letter_grade = "B+"; + if(final_grade < 522 && final_grade >= 498) + letter_grade = "B"; + if(final_grade < 498 && final_grade >= 480) + letter_grade = "B-"; + if(final_grade < 480 && final_grade >= 462) + letter_grade = "C+"; + if(final_grade < 462 && final_grade >= 438) + letter_grade = "C"; + if(final_grade < 438 && final_grade >= 420) + letter_grade = "C-"; + if(final_grade < 420 && final_grade >= 402) + letter_grade = "D+"; + if(final_grade < 402 && final_grade >= 378) + letter_grade = "D"; + if(final_grade < 378 && final_grade >= 360) + letter_grade = "D-"; + if(final_grade < 360) + letter_grade = "E"; + + // something looks iffy here: (check your warnings (read all the words (even 'assignment'))) + if (i == 1) { + student1.name = name; + student1.grade = final_grade; + student1.letter_grade = letter_grade; + } + else { + student2.name = name; + student2.grade = final_grade; + student2.letter_grade = letter_grade; + } + } + int order = 0; + cout << "Please enter what order you want to see the students: " << endl; + cout << "enter 1 for alphabetical or 2 for highest score first: " << endl; + cin >> order; + if(order > 2 or order < 1) { + cout << "out of range" < student2.grade){ + cout << "name " << student1.name << endl; + cout << "points " << student1.grade << endl; + cout << "letter grade " << student1.letter_grade << endl; + cout << "name " << student2.name << endl; + cout << "points " << student2.grade << endl; + cout << "letter grade " << student2.letter_grade << endl; + } + else { + cout << "name " << student2.name << endl; + cout << "points " << student2.grade << endl; + cout << "letter grade " << student2.letter_grade << endl; + cout << "name " << student1.name << endl; + cout << "points " << student1.grade << endl; + cout << "letter grade " << student1.letter_grade << endl; + } + } +} diff --git a/cs142/lab03/quick.cpp b/cs142/lab03/quick.cpp new file mode 100644 index 0000000..f45d84c --- /dev/null +++ b/cs142/lab03/quick.cpp @@ -0,0 +1,16 @@ +#include +#include + +using namespace std; + +int main () { + + string a, b; + cin >> a; + cin >> b; + + if(a +#include +#include +#include +#include +#include +#include + +using namespace std; + +int bit2dec(string s); + +vector get_numbers(int pow, int compliment) { + string store; + vector numbers; + int constant = compliment; + for(int i = 0; i < 2; i++){ + for(int j = 0; j < 2; j++){ + for(int k = 0; k < 2; k++){ + for(int l = 0; l < 2; l++){ + ostringstream stream; + if(pow == 0){ + stream << i << j << k << l << constant; + } + else if(pow == 1){ + stream << i << j << k << constant << l; + } + else if(pow == 2){ + stream << i << j << constant << k << l; + } + else if(pow == 3){ + stream << i << constant << j << k << l; + } + else if(pow == 4){ + stream << constant << i << j << k << l; + } + store = stream.str(); + numbers.push_back(bit2dec(store)); + } + } + } + } + return numbers; +} + + +ostream & operator<<(ostream & os, const vector & nums) { + for(unsigned int i = 0; i < nums.size(); i++){ + if(i % 4 == 0){ + os << endl; + } + os << nums[i] << " "; + } + return os; +} + +int bit2dec(string s) { + + int total = 0; + int power = 0; + for(int i = s.size() - 1; i >= 0; i--) { + if(s[i] == '1') { + total += pow(2,power); + } + power++; + } + return total; +} + + +int main() { + + srand (time(NULL)); + int keep_playing = 0; + while(keep_playing == 0){ + ostringstream answer; + for(unsigned int i = 0; i < 5 ; i++) { + int switcher = rand() % 2; + string check; + cout << "Is your number in this list? enter y for yes n for no" << endl; + cout << get_numbers(i, switcher) << endl; + cin >> check; + if(switcher == 0){ + if(check == "y") { + answer << '0'; + } + else { + answer << '1'; + } + } + if(switcher == 1) { + if(check == "y") { + answer << '1'; + } + else { + answer << '0'; + } + } + } + string final = answer.str(); + reverse (final.begin(), final.end()); + cout << bit2dec(final) << endl; + cout << "Do you want to keep playing? enter y for yes, n for no" << endl; + string check; + cin >> check; + if(check == "n"){ + keep_playing++; + } + } + return 0; +} diff --git a/cs142/lab04/quick.cpp b/cs142/lab04/quick.cpp new file mode 100644 index 0000000..a8a20c5 --- /dev/null +++ b/cs142/lab04/quick.cpp @@ -0,0 +1,17 @@ +#include +#include + +using namespace std; + +int main() { + + vector numbers; + + numbers.push_back(0); + numbers.push_back(1); + numbers.push_back(0); + numbers.push_back(1); + numbers.push_back(0); + + cout << numbers[0] << numbers[1]<< numbers[2]< +#include + +using namespace std; + +struct property { + string name; + int value; +} +void create_board(vector & board) { + board.push_back(property{"mediterranean Avenue", 60} +} + +int main() { + vector board; + cout << board.name << endl; + +} diff --git a/cs142/lab05/game/monopoly.cpp b/cs142/lab05/game/monopoly.cpp new file mode 100644 index 0000000..1730b23 --- /dev/null +++ b/cs142/lab05/game/monopoly.cpp @@ -0,0 +1,175 @@ +#include +#include +#include +#include + +using namespace std; + + +struct property{ + string name; + int value; +}; + +void roll_the_dice() { + srand(time(NULL)); + int roll = rand() % 6 +1; + int roll2 = rand() % 6 +1; + cout << roll << " + "<< roll2 << " equals " << roll +roll2 << endl; +} + +void report_current_money(int & current_money) { + cout << "this is your current money" << endl; + cout << current_money << endl; +} + +void add_money(int & current_money) { + cout << "how much money would you like to add? " << endl; + int add; + cin >> add; + if(add < 0){ + cout << "please enter a positive number" << endl; + add_money(current_money); + } + else { + current_money += add; + cout << current_money << endl; + } +} + +void spend_money(int & current_money) { + cout << "how much money would you like to spend? " << endl; + int minus; + cin >> minus; + if(current_money - minus < 0) { + cout << "This would result in a negative number!" << endl; + } + else { + current_money -= minus; + cout << current_money << endl; + } +} + +void pass_go(int & current_money) { + cout << "you passed go, collect 200 dollars!" << endl; + current_money += 200; +} + +bool has_property(vector & props, string name) { + bool has_prop = false; + for(unsigned int i = 0; i < props.size(); i++) { + if(name == props[i].name) { + has_prop = true; + } + } + return has_prop; +} + +void buy_property(vector & properties, int & current_money) { + bool success = false; + int property_value = 0; + string input_name; + + + while(!success) { + cout << "please enter property name: "; + cin >> input_name; + if (not has_property(properties, input_name) ){ + cout << "What is the value of your property?" << endl; + cin >> property_value; + while(property_value < 0) { + cout << "incorrect property value. Please try again." << endl; + cin >> property_value; + } + if(current_money - property_value < 0) { + cout << "you dont have enough money to purchase this." << endl; + break; + } + current_money -= property_value; + properties.push_back(property{input_name, property_value}); + success = true; + } + else { + cerr << "you already have that property" << endl; + break; + } + } + +} + +void sell_property(vector & properties, int & current_money) { + string property_to_sell; + cout << "please enter the property name you would like to sell: " << endl; + cin >> property_to_sell; + if(has_property(properties, property_to_sell)) { + for(unsigned int i = 0; i < properties.size(); i++) { + if(properties[i].name == property_to_sell) { + current_money += properties[i].value; + properties.erase(properties.begin()+i); + } + } + } + else { + cout << "you dont own that property to be able to sell it" << endl; + } +} + +void quit_game() { + cout << "thanks for playing!" << endl; + exit (0); +} + +ostream & operator<<(ostream & os, const property & prop) { + os << "{name: '" << prop.name + << "', value: " << prop.value + << "}"; + return os; +} + +void display_properties(vector & properties) { + cout << "found the following " + << properties.size() << " properties:" << endl; + for(unsigned int i = 0; i < properties.size(); i++) { + cout << properties[i] << endl; + } +} + +void play_game(vector & properties, int & current_money) { + + bool keep_playing = true; + while(keep_playing){ + int choice; + cout << "Welcome to Monopoly" << endl; + cout << "please enter a number correspoding to what function you would like to run" << endl; + cout << "1) Roll the dice\n2) Report the player's current money\n3) Add money\n4) Spend money" << endl; + cout << "5) Pass GO\n6) Buy Property\n7)Sell Property\n8)Display owned properties\n9) Quit the program" << endl; + cin >> choice; + if(choice == 1) + roll_the_dice(); + else if(choice == 2) + report_current_money(current_money); + else if(choice == 3) + add_money(current_money); + else if(choice == 4) + spend_money(current_money); + else if(choice == 5) + pass_go(current_money); + else if(choice == 6) + buy_property(properties, current_money); + else if(choice == 7) + sell_property(properties, current_money); + else if(choice == 8) + display_properties(properties); + else if(choice == 9) + quit_game(); + } + +} + +int main() { + int current_money = 1500; + vector properties; + play_game(properties, current_money); + + return 0; +} diff --git a/cs142/lab05/game/properties/properties_in_order.txt b/cs142/lab05/game/properties/properties_in_order.txt new file mode 100644 index 0000000..a12270e --- /dev/null +++ b/cs142/lab05/game/properties/properties_in_order.txt @@ -0,0 +1,40 @@ +Mediterranean Avenue -60 +Community Chest +Baltic Avenue - 60 +Income Tax +Reading Railroad - 200 +Oriental Avenue - 100 +Chance +Vermont Avenue - 100 +Connecticut Avenue - 120 +Jail +St. Charles Place - 140 +Electric Company - 150 +States Avenue - 140 +Virginia Avenue - 160 +Pennsylvania Railroad - 200 +St. James Place - 180 +Community Chest +Tennessee Avenue - 180 +New York Avenue - 200 +Free parking +Kentucky Avenue - 220 +Chance +Indiana Avenue - 220 +Illinois Avenue - 240 +B&O Railroad - 200 +Atlantic Avenue - 260 +Ventnor Avenue - 260 +Water Works - 150 +Marvin Gardens - 280 +Go to jail +Pacific avenue - 300 +North Carolina Avenue - 300 +Community chest +Pennsylvania Avenue - 320 +Short line - 200 +Chance +Park Place - 350 +Luxury tax +Boardwalk - 400 +Go diff --git a/cs142/lab05/monopoly.cpp b/cs142/lab05/monopoly.cpp new file mode 100644 index 0000000..1f56356 --- /dev/null +++ b/cs142/lab05/monopoly.cpp @@ -0,0 +1,182 @@ +#include +#include +#include + +using namespace std; + + +struct property{ + string name; + int value; +}; + +void roll_the_dice() { + srand(time(NULL)); + int roll = rand() % 6 +1; + int roll2 = rand() % 6 +1; + cout << roll << " + "<< roll2 << " equals " << roll +roll2 << endl; +} + +void report_current_money(int & current_money) { + cout << "this is your current money" << endl; + cout << current_money << endl; +} + +void add_money(int & current_money) { + cout << "how much money would you like to add? " << endl; + int add; + cin >> add; + if(add < 0){ + cout << "please enter a positive number" << endl; + add_money(current_money); + } + else { + current_money += add; + cout << current_money << endl; + } +} + +void spend_money(int & current_money) { + cout << "how much money would you like to spend? " << endl; + int minus; + cin >> minus; + if(current_money - minus < 0) { + cout << "This would result in a negative number!" << endl; + } + else { + current_money -= minus; + cout << current_money << endl; + } +} + +void pass_go(int & current_money) { + cout << "you passed go, collect 200 dollars!" << endl; + current_money += 200; +} + +bool has_property(vector & props, string name) { + bool has_prop = false; + for(unsigned int i = 0; i < props.size(); i++) { + if(name == props[i].name) { + has_prop = true; + } + } + return has_prop; +} + +void buy_property(vector & properties, int & current_money) { + bool success = false; + int property_value = 0; + string input_name; + + + while(!success) { + cout << "please enter property name: "; + cin >> input_name; + if (not has_property(properties, input_name) ){ + cout << "What is the value of your property?" << endl; + cin >> property_value; + while(property_value < 0) { + cout << "incorrect property value. Please try again." << endl; + cin >> property_value; + } + if(current_money - property_value < 0) { + cout << "you dont have enough money to purchase this." << endl; + break; + } + current_money -= property_value; + properties.push_back(property{input_name, property_value}); + success = true; + } + else { + cerr << "you already have that property" << endl; + break; + } + } + +} + +void sell_property(vector & properties, int & current_money) { + string property_to_sell; + cout << "please enter the property name you would like to sell: " << endl; + cin >> property_to_sell; + if(has_property(properties, property_to_sell)) { + for(unsigned int i = 0; i < properties.size(); i++) { + if(properties[i].name == property_to_sell) { + cout << "enter value for sale" << endl; + int sale; + cin >> sale; + if(sale < 0){ + cout << "can't be nagative" << endl; + break; + } + properties[i].value = sale; + current_money += properties[i].value; + properties.erase(properties.begin()+i); + } + } + } + else { + cout << "you dont own that property to be able to sell it" << endl; + } +} + +void quit_game() { + cout << "thanks for playing!" << endl; + exit (0); +} + +ostream & operator<<(ostream & os, const property & prop) { + os << "{name: '" << prop.name + << "', value: " << prop.value + << "}"; + return os; +} + +void display_properties(vector & properties) { + cout << "found the following " + << properties.size() << " properties:" << endl; + for(unsigned int i = 0; i < properties.size(); i++) { + cout << properties[i] << endl; + } +} + +void play_game(vector & properties, int & current_money) { + + bool keep_playing = true; + while(keep_playing){ + int choice; + cout << "Welcome to Monopoly" << endl; + cout << "please enter a number correspoding to what function you would like to run" << endl; + cout << "1) Roll the dice\n2) Report the player's current money\n3) Add money\n4) Spend money" << endl; + cout << "5) Pass GO\n6) Buy Property\n7)Sell Property\n8)Display owned properties\n9) Quit the program" << endl; + cin >> choice; + if(choice == 1) + roll_the_dice(); + else if(choice == 2) + report_current_money(current_money); + else if(choice == 3) + add_money(current_money); + else if(choice == 4) + spend_money(current_money); + else if(choice == 5) + pass_go(current_money); + else if(choice == 6) + buy_property(properties, current_money); + else if(choice == 7) + sell_property(properties, current_money); + else if(choice == 8) + display_properties(properties); + else if(choice == 9) + quit_game(); + } + +} + +int main() { + int current_money = 1500; + vector properties; + play_game(properties, current_money); + + return 0; +} diff --git a/cs142/lab06/Makefile b/cs142/lab06/Makefile new file mode 100644 index 0000000..55b5755 --- /dev/null +++ b/cs142/lab06/Makefile @@ -0,0 +1,6 @@ +CXXFLAGS=-Wall -g -std=c++0x +all: add-display +clean: + rm -vf add-display +test: all + ./add-display diff --git a/cs142/lab06/add-display.cpp b/cs142/lab06/add-display.cpp new file mode 100644 index 0000000..c897590 --- /dev/null +++ b/cs142/lab06/add-display.cpp @@ -0,0 +1,211 @@ +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +void display_all_restaurants(array & restaurants, int & current_size) { + for(int i = 0; i <= current_size - 1; i++) { + if(i == current_size - 1) { + cout << i << "-" << restaurants[i] << endl; + } + else { + cout << i << "-" << restaurants[i] << ", "; + } + } +} + +void add_a_restaurant(array & restaurants, int & current_size) { + string name; + bool correct_entry = true; + cout << "please enter name of restaurant: " << endl; + cin.ignore(); + getline(cin, name); + if(current_size >= 16) { + cout << "The array already has 16 restaurants and you can't add anymore." << endl; + } + else { + for(int i = 0; i <= current_size - 1; i++) { + if(restaurants[i] == name) { + correct_entry = false; + } + } + if(correct_entry == true) { + restaurants[current_size] = name; + current_size++; + cout << "you added the restaurant " << name << endl; + } + else { + cout << "this restaurant is already existant" << endl; + } + } +} + +void remove_a_restaurant(array & restaurants, int & current_size) { + string name; + bool correct_entry = false; + cout << "Please enter name of restaurant you would like to remove: " << endl; + cin.ignore(); + getline(cin, name); + for(int i = 0; i <= current_size -1; i++) { + if(i == current_size && restaurants[i] == name) { + current_size--; + cout << name << " has been removed" << endl; + } + if(restaurants[i] == name) { + restaurants[i] = restaurants[current_size -1]; + current_size--; + correct_entry = true; + cout << name << " has been removed" << endl; + } + } + if(correct_entry == false) { + cout << "restaurant does not exist" << endl; + } +} + +void shuffle_array(array & restaurants, int current_size) { + random_shuffle (&restaurants[0], &restaurants[current_size]); +} + +int round_counter(int current_size) { + int round; + if(current_size == 16) { + round = 4; + } + else if(current_size == 8) { + round = 3; + } + else if(current_size == 4) { + round = 2; + } + else if(current_size == 2) { + round =1; + } + return round; +} + +int match_counter(int current_size) { + int match; + if(current_size == 16) { + match = 8; + } + else if(current_size == 8) { + match = 4; + } + else if(current_size == 4) { + match = 2; + } + else if(current_size == 2) { + match =1; + } + return match; +} + +void begin_tournament(array & restaurants, int & current_size) { + bool temp_bool = true; + bool tourn_running = true; + cin.ignore(); + string name; + int match = match_counter(current_size); + int round = round_counter(current_size); + int current_round = 1; + array temp_array; + while(tourn_running == true) { + int current_match = 1; + int place = 0; + temp_bool = true; + cin.ignore(); + for(int i = 0; i < current_size; i += 2) { + while(temp_bool == true) { + cout << "which restaurant: " << restaurants[i] << " or " << restaurants[i + 1] << endl; + cout << "match " << current_match << "/" << match << " Round " + << current_round << "/" << round << endl; + getline(cin, name); + if(name == restaurants[i] or name == restaurants[i + 1]) { + if(name == restaurants[i]) { + temp_array[place] = name; + } + else { + temp_array[place] = name; + } + place ++; + temp_bool = false; + current_match++; + } + else { + cout << "invalid response " << name << endl; + } + } + temp_bool = true; + } + while(temp_bool == true) { + for(int i = 0; i < place; i++) { + restaurants[i] = temp_array[i]; + } + current_size = current_size/2; + if(current_size == 1) { + cout << "this is the winner " << restaurants[0] << endl; + exit(0); + } + else { + cout << "next round of tournament" << endl; + temp_bool = false; + } + } + match = match/2; + current_round++; + } +} + +void test_size(array & restaurants, int & current_size) { + if(current_size ==2 or current_size ==4 or current_size ==8 or current_size == 16) { + cout << "you have 2^n" << endl; + begin_tournament(restaurants, current_size); + } + else { + cout << "you dont have 2^n number of restaurants, please remove or enter more" << endl; + } +} + +int main() { + array restaurants = {{ + "cafe rio", + "india palace", + "panda express", + "subway", + "quiznos", + "olive garden", + "jimmy johns", + "cougareat", + }}; + bool temp = true; + int current_size = 8; + srand(time(NULL)); + while(temp == true) { + int input; + cout << "pick a function" << endl; + cout << "1)Display all restaurants\n2)Add a restaurant\n3)Remove a restaurant" << endl; + cout << "4)Shufflle the array\n5)Begin the tournament" << endl; + cin >> input; + if(input == 1){ + display_all_restaurants(restaurants, current_size); + } + if(input == 2){ + add_a_restaurant(restaurants, current_size); + } + if(input == 3){ + remove_a_restaurant(restaurants, current_size); + } + if(input == 4){ + shuffle_array(restaurants, current_size); + } + if(input == 5){ + test_size(restaurants, current_size); + } + } +} diff --git a/cs142/lab06/array.cpp b/cs142/lab06/array.cpp new file mode 100644 index 0000000..ce8d477 --- /dev/null +++ b/cs142/lab06/array.cpp @@ -0,0 +1,42 @@ +#include +#include + +using namespace std; + +int main() { + array test; + for(unsigned int i = 0; i < test.size(); i++) { + string a; + cout << i << " enter name" << endl; + cin >> a; + test[i] = a; + + } + int a = 0; + cout << "i++" << endl; + for(unsigned int i = 0; i < test.size(); i++) { + cout << test[i] << "-" << i << " /"; + } + cout << "" << endl; + cout << "i--" << endl; + for(unsigned int i = 15; i > 0; i--) { + cout << test[i] << "-" << i << " /"; + } + cout << "" << endl; + cout << test.size() << " size of thing" << endl; + cout << "" << endl; + for(unsigned int i = 0; i < test.size(); i++) { + if(test[i] == "derek") { + a = i; + } + } + for(a; a < test.size(); a++) { + int b = a; + test[a] = test[b++]; + } + cout << "something happening here" << a << " is where derek is" << endl; + for(unsigned int i = 0; i < test.size(); i++) { + cout << test[i] << "-" << i << " /"; + } + cout << "" << endl; +} diff --git a/cs142/lab06/test.txt b/cs142/lab06/test.txt new file mode 100644 index 0000000..0bad2fb --- /dev/null +++ b/cs142/lab06/test.txt @@ -0,0 +1,10 @@ +derek +colleen +adeline +sylas +emmett +stephen +vanessa +mardson +4 +1 diff --git a/cs142/lab07/Makefile b/cs142/lab07/Makefile new file mode 100644 index 0000000..396f81c --- /dev/null +++ b/cs142/lab07/Makefile @@ -0,0 +1,29 @@ +CXX=g++ +CPPFLAGS=-Wall -g -std=c++0x +SOURCES=cookies.cpp +OBJECTS=$(SOURCES:.cpp=.o) +EXE=cookie + +all: $(EXE) + +$(EXE): $(OBJECTS) + $(CXX) $(LDFLAGS) $(OBJECTS) -o $@ + + +clean: + @rm -vf *.o + @rm -rvf *.dSYM + @rm -vf $(EXE) + + +run: $(EXE) + ./$(EXE) + +debug: $(EXE) + gdb $(EXE) + +valgrind: $(EXE) + valgrind --tool=memcheck --leak-check=yes ./$(EXE) + +autov: $(EXE) + valgrind --tool=memcheck --leak-check=yes ./$(EXE) < test.txt diff --git a/cs142/lab07/cookies.cpp b/cs142/lab07/cookies.cpp new file mode 100644 index 0000000..81e87b3 --- /dev/null +++ b/cs142/lab07/cookies.cpp @@ -0,0 +1,250 @@ +#include +#include + +using namespace std; + +//------------------------------------------------------------------------------------- +string * findOrder(string * cookies[], int * size, string name); +void addOrder(string * cookies[], int * size, string new_name); +int deliverOrder(string * cookies[], int * size, string name); +bool modifyOrder(string * cookies[], int * size, string original_name, string new_name); +string displayOrders(string * cookies[], int * size); +//------------------------------------------------------------------------------------- +/* + findOrder + + Returns a memory address found in the given array that references a string with the same data + as the given string. Returns null if no such string is found. + + It is recommended that you use this function within your other functions. If you do not, you + must still complete this function as described above. +*/ +string * findOrder(string * cookies[], int * size, string name) +{ + string * r = NULL; + for(int i = 0; i < *size; i++) { + if(*cookies[i] == name) { + r = cookies[i]; + break; + } + } + return r; +} +//------------------------------------------------------------------------------------- +/* + addOrder + + Adds the memory address of a new string to the given array. The new string should have the + same data as that of the given string. + + A string may already exist containing the same data as the given string (ie, the string + passed to this function as a parameter) and whose memory address is already stored within + the given array. In this situation, add to the array the memory address of the string that + already exists rather than creating a new string. + + Update the reference of size appropriately. +*/ +void addOrder(string * cookies[], int * size, string new_name) { + string * found = findOrder(cookies, size, new_name); + if(found == NULL) { + cookies[*size] = new string(new_name); + } + else { + cookies[*size] = found; + } + (*size)++; +} +//------------------------------------------------------------------------------------- +/* + deliverOrder + + Removes all references to strings containing the same data as the given string and reports + the number of string references removed. The overall order of the list is unchanged. + + Update the reference of size appropriately. +*/ +int deliverOrder(string * cookies[], int * size, string name) +{ + int removes = 0; + for(int i = 0; i < *size; i++) { + if(*cookies[i] == name) { + for(int j = i; j < *size; j++) { + cookies[j] = cookies[j+1]; + } + *size = *size -1; + removes++; + i--; + } + } + return removes; +} +//------------------------------------------------------------------------------------- +/* + modifyOrder + + Searches the given array for a memory address to a string that contains the same data as the + first given string. + + If found, the data of the found string is changed to match the data of the second given string, + and the function returns true. If not found, the function returns false. +*/ +bool modifyOrder(string * cookies[], int * size, string original_name, string new_name) +{ + bool result = false; + for(int i = 0; i < *size; i++) { + if(*cookies[i] == original_name) { + *cookies[i] = new_name; + result = true; + } + } + return result; +} +//------------------------------------------------------------------------------------- +/* + displayOrders + + Returns a string containing a list of names referred to in the given array. + Each index in the array represents a particular box of cookies, and there may be more than + one box for each customer. Therefore, this function's output may include the same name + multiple times. +*/ +string displayOrders(string * cookies[], int * size) +{ + string r = ""; + for(int i = 0; i < *size; i++) { + r += *cookies[i] + ", "; + } + return r; +} +//------------------------------------------------------------------------------------- + + + + + + +//------------------------------------------------------------------------------------- +int getOption(int range); +string getName(string message); +//------------------------------------------------------------------------------------- +int main() +{ + const int MAXIMUM_SIZE = 10; + string * cookies [MAXIMUM_SIZE] = {}; + int x = 0; + int * size = &(x); + + bool done = false; + while(!done) + { + //Get menu option + cout << "MENU:" << endl; + cout << "\t1. Add an order\n\t2. Deliver an order\n\t3. Modify an order\n\t4. Quit\n" << endl; + int option = getOption(4); + + //Adding + if(option==1) + { + if((*size) >= MAXIMUM_SIZE) + { + cout << "The car is full; cannot add more orders" << endl; + } + else + { + string new_name = getName("Please enter the customer's name for the new order:"); + addOrder(cookies, size, new_name); + cout << "Cookies added for costumer [" << new_name << "]" << endl; + } + } + + //Delivering + else if(option==2) + { + string name = getName("Please enter the customer's name for the delivery:"); + int delivered = deliverOrder(cookies, size, name); + cout << "Delivered " << delivered << " boxes of cookies to [" << name << "]" << endl; + } + + //Modifying + else if(option==3) + { + string original_name = getName("Please enter the original customer's name:"); + string new_name = getName("Please enter the new customer's name:"); + bool changed = modifyOrder(cookies,size,original_name,new_name); + if(changed) + { + cout << "Changed name from [" << original_name << "] to [" << new_name << "]" << endl; + } + else + { + cout << "Could not find a customer with the name: [" << original_name << "]" << endl; + } + } + + //Quitting + else if(option==4) + { + done = true; + } + + + cout << displayOrders(cookies, size) << endl; + } + + cout << "Thank you for using the cookie tracker!" << endl; + //The following line may not work on all systems; therefore, you may change this line as needed + // system("pause"); + return 0; +} +//------------------------------------------------------------------------------------- +int getOption(int range) +{ + int input = 0; + bool done = false; + while(!done) + { + cout << "Please select an option:" << endl; + input = 0; + cin >> input; + cin.ignore(1000,'\n'); + if(cin.fail()) + { + cin.clear(); + cin.ignore(1000,'\n'); + cout << "Error: Invalid option" << endl; + } + else if(input < 1 || input > range) + { + cout << "Error: Invalid option number" << endl; + } + else + { + done = true; + } + } + return input; +} +//------------------------------------------------------------------------------------- +string getName(string message) +{ + string input = ""; + bool done = false; + while(!done) + { + cout << message << endl; + input = ""; + getline(cin, input); + if(cin.fail()) + { + cin.clear(); + cin.ignore(1000,'\n'); + cout << "Error: Invalid name" << endl; + } + else + { + done = true; + } + } + return input; +} +//------------------------------------------------------------------------------------- diff --git a/cs142/lab07/test.txt b/cs142/lab07/test.txt new file mode 100644 index 0000000..f31fd44 --- /dev/null +++ b/cs142/lab07/test.txt @@ -0,0 +1,18 @@ +1 +stephen +1 +michael +1 +michael +1 +stephen +1 +derek +3 +stephen +Stephen Mardson McQuay +2 +michael +2 +derek +4 diff --git a/cs142/lab08/Makefile b/cs142/lab08/Makefile new file mode 100644 index 0000000..d892d54 --- /dev/null +++ b/cs142/lab08/Makefile @@ -0,0 +1,18 @@ +CXX=g++ +CPPFLAGS=-Wall -g -std=c++0x + +all: people + +people: main.o person.o + g++ $(CPPFLAGS) person.o main.o -o people + +main.o: main.cpp person.o person.h +person.o: person.cpp person.h +test: people + ./people < test.txt + +clean: + rm -fv people *.o + +debug: people + gdb people diff --git a/cs142/lab08/main.cpp b/cs142/lab08/main.cpp new file mode 100644 index 0000000..a089e15 --- /dev/null +++ b/cs142/lab08/main.cpp @@ -0,0 +1,106 @@ +#include +#include + +using namespace std; + +#include "person.h" + +void display_list_of_friends(vector & p) { + for(unsigned int i = 0; i < p.size(); i++) { + cout << p[i].name << endl; + cout << "\t" << p[i].fav_food << endl; + cout << "\tlist of friends: " << endl; + for(unsigned int j = 0; j < p[i].friends.size(); j++) { + cout << "\t\t" << p[i].friends[j] << endl;; + } + } +} + + +int get_person(vector & p, string name) { + int position = -1; + for(unsigned int i = 0; i < p.size(); i++) { + if(p[i].name == name) { + position = i; + break; + } + } + return position; +} + +int main() { + vector people; + string selection; + while(1) { + cout << "1)add person\n2)display all people\n3)add friend\n4)remove friend" << endl; + cout << "5)modify food\n6)display friends/food" << endl; + cin >> selection; + if(selection[0] == '1') { //optimized + string name, food; + cout << "what is the persons name followed by favorite food on a new line " << endl; + cin.ignore(); + getline(cin, name); + getline(cin, food); + person p = person(name, food); + int p1 = get_person(people, p.name); + if(p1 == -1) { + people.push_back(p); + } + } + else if(selection[0] == '2') { //optimized + display_list_of_friends(people); + } + else if(selection[0] == '3') { //optimized + cout << "which relationship do you want to start (enter two names, seperated by newlines)?" << endl; + string first, second; + cin.ignore(); + getline(cin, first); + getline(cin, second); + int p1 = get_person(people, first); + int p2 = get_person(people, second); + if(p1 != -1 and p2 != -1 and first!= second) { + people[p1].add_friend(second); + people[p2].add_friend(first); + } + } + else if(selection[0] == '4') { //optimized + cout << "which relationship do you want to end (enter two names, seperated by newlines)?" << endl; + string first, second; + cin.ignore(); + getline(cin, first); + getline(cin, second); + int p1 = get_person(people, first); + int p2 = get_person(people, second); + if (p1 != -1 and p2 != -1) { + people[p1].delete_friend(people[p2].name); + people[p2].delete_friend(people[p1].name); + } + } + else if(selection[0] == '5') { //optimized + string name; + cout << "what is the name of the person to whom you would like to modify fav food?" << endl; + cin.ignore(); + getline(cin, name); + int p1 = get_person(people, name); + if(p1 != -1) { + string new_food; + cout << "what food do you want to add?" << endl; + getline(cin, new_food); + people[p1].modify_food(new_food); + } + } + else if(selection[0] == '6') { + cout << "What is the name of the person to whom you would like to view friends with same food?" << endl; + string name; + cin.ignore(); + getline(cin, name); + int p1 = get_person(people, name); + if(p1 != -1) { + people[p1].display_person(people); + } + } + else if(selection[0] == 'q') { + break; + } + } +} diff --git a/cs142/lab08/person.cpp b/cs142/lab08/person.cpp new file mode 100644 index 0000000..a604d17 --- /dev/null +++ b/cs142/lab08/person.cpp @@ -0,0 +1,47 @@ +#include +#include + +using namespace std; + +#include "person.h" + +void person::modify_food(string new_food) { + fav_food = new_food; +} + +void person::display_person(vector & p) { + for(unsigned int i = 0; i < friends.size(); i++) { + for(unsigned int j = 0; j < p.size(); j++) { + if(p[j].name == friends[i] and p[j].fav_food == fav_food) { + cout << p[j].name << " also likes " << fav_food << endl; + } + } + } +} + +void person::add_friend(string name) { + if(not already_friends(name)) { + friends.push_back(name); + } +} + +bool person::already_friends(string name) { + for(unsigned int i = 0; i < friends.size(); i++) { + if(friends[i] == name) { + return true; + } + } + return false; +} + +void person::delete_friend(string name) { + for(unsigned int i = 0; i < friends.size(); i++) { + if(friends[i] == name) { + friends.erase((friends.begin())+i); + break; + } + else { + cerr << "this person does not exist" << endl; + } + } +} diff --git a/cs142/lab08/person.h b/cs142/lab08/person.h new file mode 100644 index 0000000..59e15de --- /dev/null +++ b/cs142/lab08/person.h @@ -0,0 +1,24 @@ +#ifndef __PERSON_H__ +#define __PERSON_H__ +#include +#include + +using namespace std; + +class person { + public: + string name; + string fav_food; + vector friends; + person(string new_name, string food) { + name = new_name; + fav_food = food; + }; + void modify_food(string new_food); + void display_person(vector & p); + void add_friend(string name); + bool already_friends(string name); + void delete_friend(string name); +}; + +#endif diff --git a/cs142/lab08/test.cc b/cs142/lab08/test.cc new file mode 100644 index 0000000..c94ddc2 --- /dev/null +++ b/cs142/lab08/test.cc @@ -0,0 +1,43 @@ +#include +#include +#include + +using namespace std; + +ostream & operator<<(ostream & os, vector & v) { + os << "["; + for(auto &i: v) { + os << i << ", "; + } + os << "]"; + return os; +} + + +int main() { + vector people = { + "bilbo", + "frodo", + "samwise", + "gandalf", + "aragorn", + "aowen", + "gollum", + "gimli", + "legalos", + }; + + cout << people << endl; + vector::iterator it = find(people.begin(), people.end(), "gandalf"); + if(it != people.end()) + people.erase(it); + cout << people << endl; + it = find(people.begin(), people.end(), "frodo"); + if(it != people.end()) + people.erase(it); + cout << people << endl; + it = find(people.begin(), people.end(), "Lord Voldemort"); + if(it != people.end()) + people.erase(it); + cout << people << endl; +} diff --git a/cs142/lab08/test.txt b/cs142/lab08/test.txt new file mode 100644 index 0000000..ab6ff15 --- /dev/null +++ b/cs142/lab08/test.txt @@ -0,0 +1,21 @@ +2 +1 +stephen +apples +1 +derek +panda +2 +3 +stephen +derek +2 +1 +colleen +bananna +2 +3 +colleen +derek +2 +q diff --git a/cs142/lab09/Makefile b/cs142/lab09/Makefile new file mode 100644 index 0000000..0a72923 --- /dev/null +++ b/cs142/lab09/Makefile @@ -0,0 +1,29 @@ +CXXFLAGS=-Wall -g -std=c++0x -Ijsoncpp -DJSON_IS_AMALGAMATION +all: app iotest + +app: main.o tournament.o restaurant.o json.o io.o + $(CXX) $(CXXFLAGS) main.o restaurant.o tournament.o io.o json.o -o $@ + +main.o: main.cpp +restaurant.o: restaurant.cpp restaurant.h +tournament.o: tournament.cpp tournament.h +io.o: io.h io.cpp +json.o: jsoncpp/jsoncpp.cpp + $(CXX) $(CXXFLAGS) $< -c -o $@ + +iotest: iotest.cpp io.o json.o restaurant.o + +clean: + @rm -vf *.o + @rm -vf app + @rm -vf iotest + @rm -rvf *.dSYM + +test: all + @./app + +io: iotest + @./iotest restaurants.db + +debug: all + gdb rest diff --git a/cs142/lab09/io.cpp b/cs142/lab09/io.cpp new file mode 100644 index 0000000..a942d51 --- /dev/null +++ b/cs142/lab09/io.cpp @@ -0,0 +1,30 @@ +#include +#include +#include +#include +using namespace std; + +#include "jsoncpp/json/json.h" +#include "io.h" +#include "restaurant.h" + +vector parse_file(string filename) { + vector restaurants; + ifstream infile(filename.c_str()); + string file_contents((istreambuf_iterator(infile)), + istreambuf_iterator()); + Json::Value root; + Json::Reader reader; + bool good_parse = reader.parse(file_contents, root); + if(not good_parse) { + throw runtime_error(reader.getFormattedErrorMessages()); + } + for(unsigned int i = 0; i < root.size(); i++) { + string name = root[i]["name"].asString(); + int score = root[i]["score"].asInt(); + restaurant r(name, score); + restaurants.push_back(r); + } + + return restaurants; +} diff --git a/cs142/lab09/io.h b/cs142/lab09/io.h new file mode 100644 index 0000000..9859190 --- /dev/null +++ b/cs142/lab09/io.h @@ -0,0 +1,11 @@ +#ifndef __IO_H__ +#define __IO_H__ + +#include +#include +using namespace std; +#include "restaurant.h" + +vector parse_file(string filename); + +#endif diff --git a/cs142/lab09/iotest.cpp b/cs142/lab09/iotest.cpp new file mode 100644 index 0000000..3d7f7aa --- /dev/null +++ b/cs142/lab09/iotest.cpp @@ -0,0 +1,27 @@ +#include +#include +#include + +using namespace std; + +#include "io.h" +#include "restaurant.h" + +const string usage = "usage: iotest "; + +int main(int argc, char * argv[]) { + if (argc != 2) { + cerr << usage << endl; + return 1; + } + try { + vector v = parse_file(argv[1]); + for(auto r: v) { + cout << r << endl; + } + } + catch(runtime_error e) { + cerr << e.what() << endl; + } + return 0; +} diff --git a/cs142/lab09/jsoncpp/json/json-forwards.h b/cs142/lab09/jsoncpp/json/json-forwards.h new file mode 100644 index 0000000..28a6ad7 --- /dev/null +++ b/cs142/lab09/jsoncpp/json/json-forwards.h @@ -0,0 +1,249 @@ +/// Json-cpp amalgated forward header (http://jsoncpp.sourceforge.net/). +/// It is intented to be used with #include +/// This header provides forward declaration for all JsonCpp types. + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + +/* +The JsonCpp library's source code, including accompanying documentation, +tests and demonstration applications, are licensed under the following +conditions... + +The author (Baptiste Lepilleur) explicitly disclaims copyright in all +jurisdictions which recognize such a disclaimer. In such jurisdictions, +this software is released into the Public Domain. + +In jurisdictions which do not recognize Public Domain property (e.g. Germany as of +2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is +released under the terms of the MIT License (see below). + +In jurisdictions which recognize Public Domain property, the user of this +software may choose to accept it either as 1) Public Domain, 2) under the +conditions of the MIT License (see below), or 3) under the terms of dual +Public Domain/MIT License conditions described here, as they choose. + +The MIT License is about as close to Public Domain as a license can get, and is +described in clear, concise terms at: + + http://en.wikipedia.org/wiki/MIT_License + +The full text of the MIT License follows: + +======================================================================== +Copyright (c) 2007-2010 Baptiste Lepilleur + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, copy, +modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall 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 +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. +======================================================================== +(END LICENSE TEXT) + +The MIT license is compatible with both the GPL and commercial +software, affording one all of the rights of Public Domain with the +minor nuisance of being required to keep the above copyright notice +and license text in the source code. Note also that by accepting the +Public Domain "license" you can re-license your copy using whatever +license you like. + +*/ + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + + + + + +#ifndef JSON_FORWARD_AMALGATED_H_INCLUDED +# define JSON_FORWARD_AMALGATED_H_INCLUDED +/// If defined, indicates that the source file is amalgated +/// to prevent private header inclusion. +#define JSON_IS_AMALGATED + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/config.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_CONFIG_H_INCLUDED +# define JSON_CONFIG_H_INCLUDED + +/// If defined, indicates that json library is embedded in CppTL library. +//# define JSON_IN_CPPTL 1 + +/// If defined, indicates that json may leverage CppTL library +//# define JSON_USE_CPPTL 1 +/// If defined, indicates that cpptl vector based map should be used instead of std::map +/// as Value container. +//# define JSON_USE_CPPTL_SMALLMAP 1 +/// If defined, indicates that Json specific container should be used +/// (hash table & simple deque container with customizable allocator). +/// THIS FEATURE IS STILL EXPERIMENTAL! There is know bugs: See #3177332 +//# define JSON_VALUE_USE_INTERNAL_MAP 1 +/// Force usage of standard new/malloc based allocator instead of memory pool based allocator. +/// The memory pools allocator used optimization (initializing Value and ValueInternalLink +/// as if it was a POD) that may cause some validation tool to report errors. +/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined. +//# define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1 + +/// If defined, indicates that Json use exception to report invalid type manipulation +/// instead of C assert macro. +# define JSON_USE_EXCEPTION 1 + +/// If defined, indicates that the source file is amalgated +/// to prevent private header inclusion. +/// Remarks: it is automatically defined in the generated amalgated header. +// #define JSON_IS_AMALGAMATION + + +# ifdef JSON_IN_CPPTL +# include +# ifndef JSON_USE_CPPTL +# define JSON_USE_CPPTL 1 +# endif +# endif + +# ifdef JSON_IN_CPPTL +# define JSON_API CPPTL_API +# elif defined(JSON_DLL_BUILD) +# define JSON_API __declspec(dllexport) +# elif defined(JSON_DLL) +# define JSON_API __declspec(dllimport) +# else +# define JSON_API +# endif + +// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for integer +// Storages, and 64 bits integer support is disabled. +// #define JSON_NO_INT64 1 + +#if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6 +// Microsoft Visual Studio 6 only support conversion from __int64 to double +// (no conversion from unsigned __int64). +#define JSON_USE_INT64_DOUBLE_CONVERSION 1 +#endif // if defined(_MSC_VER) && _MSC_VER < 1200 // MSVC 6 + +#if defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008 +/// Indicates that the following function is deprecated. +# define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) +#endif + +#if !defined(JSONCPP_DEPRECATED) +# define JSONCPP_DEPRECATED(message) +#endif // if !defined(JSONCPP_DEPRECATED) + +namespace Json { + typedef int Int; + typedef unsigned int UInt; +# if defined(JSON_NO_INT64) + typedef int LargestInt; + typedef unsigned int LargestUInt; +# undef JSON_HAS_INT64 +# else // if defined(JSON_NO_INT64) + // For Microsoft Visual use specific types as long long is not supported +# if defined(_MSC_VER) // Microsoft Visual Studio + typedef __int64 Int64; + typedef unsigned __int64 UInt64; +# else // if defined(_MSC_VER) // Other platforms, use long long + typedef long long int Int64; + typedef unsigned long long int UInt64; +# endif // if defined(_MSC_VER) + typedef Int64 LargestInt; + typedef UInt64 LargestUInt; +# define JSON_HAS_INT64 +# endif // if defined(JSON_NO_INT64) +} // end namespace Json + + +#endif // JSON_CONFIG_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/config.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/forwards.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_FORWARDS_H_INCLUDED +# define JSON_FORWARDS_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +# include "config.h" +#endif // if !defined(JSON_IS_AMALGAMATION) + +namespace Json { + + // writer.h + class FastWriter; + class StyledWriter; + + // reader.h + class Reader; + + // features.h + class Features; + + // value.h + typedef unsigned int ArrayIndex; + class StaticString; + class Path; + class PathArgument; + class Value; + class ValueIteratorBase; + class ValueIterator; + class ValueConstIterator; +#ifdef JSON_VALUE_USE_INTERNAL_MAP + class ValueMapAllocator; + class ValueInternalLink; + class ValueInternalArray; + class ValueInternalMap; +#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP + +} // namespace Json + + +#endif // JSON_FORWARDS_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/forwards.h +// ////////////////////////////////////////////////////////////////////// + + + + + +#endif //ifndef JSON_FORWARD_AMALGATED_H_INCLUDED diff --git a/cs142/lab09/jsoncpp/json/json.h b/cs142/lab09/jsoncpp/json/json.h new file mode 100644 index 0000000..6969ca1 --- /dev/null +++ b/cs142/lab09/jsoncpp/json/json.h @@ -0,0 +1,1855 @@ +/// Json-cpp amalgated header (http://jsoncpp.sourceforge.net/). +/// It is intented to be used with #include + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + +/* +The JsonCpp library's source code, including accompanying documentation, +tests and demonstration applications, are licensed under the following +conditions... + +The author (Baptiste Lepilleur) explicitly disclaims copyright in all +jurisdictions which recognize such a disclaimer. In such jurisdictions, +this software is released into the Public Domain. + +In jurisdictions which do not recognize Public Domain property (e.g. Germany as of +2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is +released under the terms of the MIT License (see below). + +In jurisdictions which recognize Public Domain property, the user of this +software may choose to accept it either as 1) Public Domain, 2) under the +conditions of the MIT License (see below), or 3) under the terms of dual +Public Domain/MIT License conditions described here, as they choose. + +The MIT License is about as close to Public Domain as a license can get, and is +described in clear, concise terms at: + + http://en.wikipedia.org/wiki/MIT_License + +The full text of the MIT License follows: + +======================================================================== +Copyright (c) 2007-2010 Baptiste Lepilleur + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, copy, +modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall 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 +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. +======================================================================== +(END LICENSE TEXT) + +The MIT license is compatible with both the GPL and commercial +software, affording one all of the rights of Public Domain with the +minor nuisance of being required to keep the above copyright notice +and license text in the source code. Note also that by accepting the +Public Domain "license" you can re-license your copy using whatever +license you like. + +*/ + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + + + + + +#ifndef JSON_AMALGATED_H_INCLUDED +# define JSON_AMALGATED_H_INCLUDED +/// If defined, indicates that the source file is amalgated +/// to prevent private header inclusion. +#define JSON_IS_AMALGATED + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/config.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_CONFIG_H_INCLUDED +# define JSON_CONFIG_H_INCLUDED + +/// If defined, indicates that json library is embedded in CppTL library. +//# define JSON_IN_CPPTL 1 + +/// If defined, indicates that json may leverage CppTL library +//# define JSON_USE_CPPTL 1 +/// If defined, indicates that cpptl vector based map should be used instead of std::map +/// as Value container. +//# define JSON_USE_CPPTL_SMALLMAP 1 +/// If defined, indicates that Json specific container should be used +/// (hash table & simple deque container with customizable allocator). +/// THIS FEATURE IS STILL EXPERIMENTAL! There is know bugs: See #3177332 +//# define JSON_VALUE_USE_INTERNAL_MAP 1 +/// Force usage of standard new/malloc based allocator instead of memory pool based allocator. +/// The memory pools allocator used optimization (initializing Value and ValueInternalLink +/// as if it was a POD) that may cause some validation tool to report errors. +/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined. +//# define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1 + +/// If defined, indicates that Json use exception to report invalid type manipulation +/// instead of C assert macro. +# define JSON_USE_EXCEPTION 1 + +/// If defined, indicates that the source file is amalgated +/// to prevent private header inclusion. +/// Remarks: it is automatically defined in the generated amalgated header. +// #define JSON_IS_AMALGAMATION + + +# ifdef JSON_IN_CPPTL +# include +# ifndef JSON_USE_CPPTL +# define JSON_USE_CPPTL 1 +# endif +# endif + +# ifdef JSON_IN_CPPTL +# define JSON_API CPPTL_API +# elif defined(JSON_DLL_BUILD) +# define JSON_API __declspec(dllexport) +# elif defined(JSON_DLL) +# define JSON_API __declspec(dllimport) +# else +# define JSON_API +# endif + +// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for integer +// Storages, and 64 bits integer support is disabled. +// #define JSON_NO_INT64 1 + +#if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6 +// Microsoft Visual Studio 6 only support conversion from __int64 to double +// (no conversion from unsigned __int64). +#define JSON_USE_INT64_DOUBLE_CONVERSION 1 +#endif // if defined(_MSC_VER) && _MSC_VER < 1200 // MSVC 6 + +#if defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008 +/// Indicates that the following function is deprecated. +# define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) +#endif + +#if !defined(JSONCPP_DEPRECATED) +# define JSONCPP_DEPRECATED(message) +#endif // if !defined(JSONCPP_DEPRECATED) + +namespace Json { + typedef int Int; + typedef unsigned int UInt; +# if defined(JSON_NO_INT64) + typedef int LargestInt; + typedef unsigned int LargestUInt; +# undef JSON_HAS_INT64 +# else // if defined(JSON_NO_INT64) + // For Microsoft Visual use specific types as long long is not supported +# if defined(_MSC_VER) // Microsoft Visual Studio + typedef __int64 Int64; + typedef unsigned __int64 UInt64; +# else // if defined(_MSC_VER) // Other platforms, use long long + typedef long long int Int64; + typedef unsigned long long int UInt64; +# endif // if defined(_MSC_VER) + typedef Int64 LargestInt; + typedef UInt64 LargestUInt; +# define JSON_HAS_INT64 +# endif // if defined(JSON_NO_INT64) +} // end namespace Json + + +#endif // JSON_CONFIG_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/config.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/forwards.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_FORWARDS_H_INCLUDED +# define JSON_FORWARDS_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +# include "config.h" +#endif // if !defined(JSON_IS_AMALGAMATION) + +namespace Json { + + // writer.h + class FastWriter; + class StyledWriter; + + // reader.h + class Reader; + + // features.h + class Features; + + // value.h + typedef unsigned int ArrayIndex; + class StaticString; + class Path; + class PathArgument; + class Value; + class ValueIteratorBase; + class ValueIterator; + class ValueConstIterator; +#ifdef JSON_VALUE_USE_INTERNAL_MAP + class ValueMapAllocator; + class ValueInternalLink; + class ValueInternalArray; + class ValueInternalMap; +#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP + +} // namespace Json + + +#endif // JSON_FORWARDS_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/forwards.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/features.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef CPPTL_JSON_FEATURES_H_INCLUDED +# define CPPTL_JSON_FEATURES_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +# include "forwards.h" +#endif // if !defined(JSON_IS_AMALGAMATION) + +namespace Json { + + /** \brief Configuration passed to reader and writer. + * This configuration object can be used to force the Reader or Writer + * to behave in a standard conforming way. + */ + class JSON_API Features + { + public: + /** \brief A configuration that allows all features and assumes all strings are UTF-8. + * - C & C++ comments are allowed + * - Root object can be any JSON value + * - Assumes Value strings are encoded in UTF-8 + */ + static Features all(); + + /** \brief A configuration that is strictly compatible with the JSON specification. + * - Comments are forbidden. + * - Root object must be either an array or an object value. + * - Assumes Value strings are encoded in UTF-8 + */ + static Features strictMode(); + + /** \brief Initialize the configuration like JsonConfig::allFeatures; + */ + Features(); + + /// \c true if comments are allowed. Default: \c true. + bool allowComments_; + + /// \c true if root must be either an array or an object value. Default: \c false. + bool strictRoot_; + }; + +} // namespace Json + +#endif // CPPTL_JSON_FEATURES_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/features.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/value.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef CPPTL_JSON_H_INCLUDED +# define CPPTL_JSON_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +# include "forwards.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +# include +# include + +# ifndef JSON_USE_CPPTL_SMALLMAP +# include +# else +# include +# endif +# ifdef JSON_USE_CPPTL +# include +# endif + +/** \brief JSON (JavaScript Object Notation). + */ +namespace Json { + + /** \brief Type of the value held by a Value object. + */ + enum ValueType + { + nullValue = 0, ///< 'null' value + intValue, ///< signed integer value + uintValue, ///< unsigned integer value + realValue, ///< double value + stringValue, ///< UTF-8 string value + booleanValue, ///< bool value + arrayValue, ///< array value (ordered list) + objectValue ///< object value (collection of name/value pairs). + }; + + enum CommentPlacement + { + commentBefore = 0, ///< a comment placed on the line before a value + commentAfterOnSameLine, ///< a comment just after a value on the same line + commentAfter, ///< a comment on the line after a value (only make sense for root value) + numberOfCommentPlacement + }; + +//# ifdef JSON_USE_CPPTL +// typedef CppTL::AnyEnumerator EnumMemberNames; +// typedef CppTL::AnyEnumerator EnumValues; +//# endif + + /** \brief Lightweight wrapper to tag static string. + * + * Value constructor and objectValue member assignement takes advantage of the + * StaticString and avoid the cost of string duplication when storing the + * string or the member name. + * + * Example of usage: + * \code + * Json::Value aValue( StaticString("some text") ); + * Json::Value object; + * static const StaticString code("code"); + * object[code] = 1234; + * \endcode + */ + class JSON_API StaticString + { + public: + explicit StaticString( const char *czstring ) + : str_( czstring ) + { + } + + operator const char *() const + { + return str_; + } + + const char *c_str() const + { + return str_; + } + + private: + const char *str_; + }; + + /** \brief Represents a JSON value. + * + * This class is a discriminated union wrapper that can represents a: + * - signed integer [range: Value::minInt - Value::maxInt] + * - unsigned integer (range: 0 - Value::maxUInt) + * - double + * - UTF-8 string + * - boolean + * - 'null' + * - an ordered list of Value + * - collection of name/value pairs (javascript object) + * + * The type of the held value is represented by a #ValueType and + * can be obtained using type(). + * + * values of an #objectValue or #arrayValue can be accessed using operator[]() methods. + * Non const methods will automatically create the a #nullValue element + * if it does not exist. + * The sequence of an #arrayValue will be automatically resize and initialized + * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue. + * + * The get() methods can be used to obtanis default value in the case the required element + * does not exist. + * + * It is possible to iterate over the list of a #objectValue values using + * the getMemberNames() method. + */ + class JSON_API Value + { + friend class ValueIteratorBase; +# ifdef JSON_VALUE_USE_INTERNAL_MAP + friend class ValueInternalLink; + friend class ValueInternalMap; +# endif + public: + typedef std::vector Members; + typedef ValueIterator iterator; + typedef ValueConstIterator const_iterator; + typedef Json::UInt UInt; + typedef Json::Int Int; +# if defined(JSON_HAS_INT64) + typedef Json::UInt64 UInt64; + typedef Json::Int64 Int64; +#endif // defined(JSON_HAS_INT64) + typedef Json::LargestInt LargestInt; + typedef Json::LargestUInt LargestUInt; + typedef Json::ArrayIndex ArrayIndex; + + static const Value null; + /// Minimum signed integer value that can be stored in a Json::Value. + static const LargestInt minLargestInt; + /// Maximum signed integer value that can be stored in a Json::Value. + static const LargestInt maxLargestInt; + /// Maximum unsigned integer value that can be stored in a Json::Value. + static const LargestUInt maxLargestUInt; + + /// Minimum signed int value that can be stored in a Json::Value. + static const Int minInt; + /// Maximum signed int value that can be stored in a Json::Value. + static const Int maxInt; + /// Maximum unsigned int value that can be stored in a Json::Value. + static const UInt maxUInt; + + /// Minimum signed 64 bits int value that can be stored in a Json::Value. + static const Int64 minInt64; + /// Maximum signed 64 bits int value that can be stored in a Json::Value. + static const Int64 maxInt64; + /// Maximum unsigned 64 bits int value that can be stored in a Json::Value. + static const UInt64 maxUInt64; + + private: +#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION +# ifndef JSON_VALUE_USE_INTERNAL_MAP + class CZString + { + public: + enum DuplicationPolicy + { + noDuplication = 0, + duplicate, + duplicateOnCopy + }; + CZString( ArrayIndex index ); + CZString( const char *cstr, DuplicationPolicy allocate ); + CZString( const CZString &other ); + ~CZString(); + CZString &operator =( const CZString &other ); + bool operator<( const CZString &other ) const; + bool operator==( const CZString &other ) const; + ArrayIndex index() const; + const char *c_str() const; + bool isStaticString() const; + private: + void swap( CZString &other ); + const char *cstr_; + ArrayIndex index_; + }; + + public: +# ifndef JSON_USE_CPPTL_SMALLMAP + typedef std::map ObjectValues; +# else + typedef CppTL::SmallMap ObjectValues; +# endif // ifndef JSON_USE_CPPTL_SMALLMAP +# endif // ifndef JSON_VALUE_USE_INTERNAL_MAP +#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION + + public: + /** \brief Create a default Value of the given type. + + This is a very useful constructor. + To create an empty array, pass arrayValue. + To create an empty object, pass objectValue. + Another Value can then be set to this one by assignment. + This is useful since clear() and resize() will not alter types. + + Examples: + \code + Json::Value null_value; // null + Json::Value arr_value(Json::arrayValue); // [] + Json::Value obj_value(Json::objectValue); // {} + \endcode + */ + Value( ValueType type = nullValue ); + Value( Int value ); + Value( UInt value ); +#if defined(JSON_HAS_INT64) + Value( Int64 value ); + Value( UInt64 value ); +#endif // if defined(JSON_HAS_INT64) + Value( double value ); + Value( const char *value ); + Value( const char *beginValue, const char *endValue ); + /** \brief Constructs a value from a static string. + + * Like other value string constructor but do not duplicate the string for + * internal storage. The given string must remain alive after the call to this + * constructor. + * Example of usage: + * \code + * Json::Value aValue( StaticString("some text") ); + * \endcode + */ + Value( const StaticString &value ); + Value( const std::string &value ); +# ifdef JSON_USE_CPPTL + Value( const CppTL::ConstString &value ); +# endif + Value( bool value ); + Value( const Value &other ); + ~Value(); + + Value &operator=( const Value &other ); + /// Swap values. + /// \note Currently, comments are intentionally not swapped, for + /// both logic and efficiency. + void swap( Value &other ); + + ValueType type() const; + + bool operator <( const Value &other ) const; + bool operator <=( const Value &other ) const; + bool operator >=( const Value &other ) const; + bool operator >( const Value &other ) const; + + bool operator ==( const Value &other ) const; + bool operator !=( const Value &other ) const; + + int compare( const Value &other ) const; + + const char *asCString() const; + std::string asString() const; +# ifdef JSON_USE_CPPTL + CppTL::ConstString asConstString() const; +# endif + Int asInt() const; + UInt asUInt() const; + Int64 asInt64() const; + UInt64 asUInt64() const; + LargestInt asLargestInt() const; + LargestUInt asLargestUInt() const; + float asFloat() const; + double asDouble() const; + bool asBool() const; + + bool isNull() const; + bool isBool() const; + bool isInt() const; + bool isUInt() const; + bool isIntegral() const; + bool isDouble() const; + bool isNumeric() const; + bool isString() const; + bool isArray() const; + bool isObject() const; + + bool isConvertibleTo( ValueType other ) const; + + /// Number of values in array or object + ArrayIndex size() const; + + /// \brief Return true if empty array, empty object, or null; + /// otherwise, false. + bool empty() const; + + /// Return isNull() + bool operator!() const; + + /// Remove all object members and array elements. + /// \pre type() is arrayValue, objectValue, or nullValue + /// \post type() is unchanged + void clear(); + + /// Resize the array to size elements. + /// New elements are initialized to null. + /// May only be called on nullValue or arrayValue. + /// \pre type() is arrayValue or nullValue + /// \post type() is arrayValue + void resize( ArrayIndex size ); + + /// Access an array element (zero based index ). + /// If the array contains less than index element, then null value are inserted + /// in the array so that its size is index+1. + /// (You may need to say 'value[0u]' to get your compiler to distinguish + /// this from the operator[] which takes a string.) + Value &operator[]( ArrayIndex index ); + + /// Access an array element (zero based index ). + /// If the array contains less than index element, then null value are inserted + /// in the array so that its size is index+1. + /// (You may need to say 'value[0u]' to get your compiler to distinguish + /// this from the operator[] which takes a string.) + Value &operator[]( int index ); + + /// Access an array element (zero based index ) + /// (You may need to say 'value[0u]' to get your compiler to distinguish + /// this from the operator[] which takes a string.) + const Value &operator[]( ArrayIndex index ) const; + + /// Access an array element (zero based index ) + /// (You may need to say 'value[0u]' to get your compiler to distinguish + /// this from the operator[] which takes a string.) + const Value &operator[]( int index ) const; + + /// If the array contains at least index+1 elements, returns the element value, + /// otherwise returns defaultValue. + Value get( ArrayIndex index, + const Value &defaultValue ) const; + /// Return true if index < size(). + bool isValidIndex( ArrayIndex index ) const; + /// \brief Append value to array at the end. + /// + /// Equivalent to jsonvalue[jsonvalue.size()] = value; + Value &append( const Value &value ); + + /// Access an object value by name, create a null member if it does not exist. + Value &operator[]( const char *key ); + /// Access an object value by name, returns null if there is no member with that name. + const Value &operator[]( const char *key ) const; + /// Access an object value by name, create a null member if it does not exist. + Value &operator[]( const std::string &key ); + /// Access an object value by name, returns null if there is no member with that name. + const Value &operator[]( const std::string &key ) const; + /** \brief Access an object value by name, create a null member if it does not exist. + + * If the object as no entry for that name, then the member name used to store + * the new entry is not duplicated. + * Example of use: + * \code + * Json::Value object; + * static const StaticString code("code"); + * object[code] = 1234; + * \endcode + */ + Value &operator[]( const StaticString &key ); +# ifdef JSON_USE_CPPTL + /// Access an object value by name, create a null member if it does not exist. + Value &operator[]( const CppTL::ConstString &key ); + /// Access an object value by name, returns null if there is no member with that name. + const Value &operator[]( const CppTL::ConstString &key ) const; +# endif + /// Return the member named key if it exist, defaultValue otherwise. + Value get( const char *key, + const Value &defaultValue ) const; + /// Return the member named key if it exist, defaultValue otherwise. + Value get( const std::string &key, + const Value &defaultValue ) const; +# ifdef JSON_USE_CPPTL + /// Return the member named key if it exist, defaultValue otherwise. + Value get( const CppTL::ConstString &key, + const Value &defaultValue ) const; +# endif + /// \brief Remove and return the named member. + /// + /// Do nothing if it did not exist. + /// \return the removed Value, or null. + /// \pre type() is objectValue or nullValue + /// \post type() is unchanged + Value removeMember( const char* key ); + /// Same as removeMember(const char*) + Value removeMember( const std::string &key ); + + /// Return true if the object has a member named key. + bool isMember( const char *key ) const; + /// Return true if the object has a member named key. + bool isMember( const std::string &key ) const; +# ifdef JSON_USE_CPPTL + /// Return true if the object has a member named key. + bool isMember( const CppTL::ConstString &key ) const; +# endif + + /// \brief Return a list of the member names. + /// + /// If null, return an empty list. + /// \pre type() is objectValue or nullValue + /// \post if type() was nullValue, it remains nullValue + Members getMemberNames() const; + +//# ifdef JSON_USE_CPPTL +// EnumMemberNames enumMemberNames() const; +// EnumValues enumValues() const; +//# endif + + /// Comments must be //... or /* ... */ + void setComment( const char *comment, + CommentPlacement placement ); + /// Comments must be //... or /* ... */ + void setComment( const std::string &comment, + CommentPlacement placement ); + bool hasComment( CommentPlacement placement ) const; + /// Include delimiters and embedded newlines. + std::string getComment( CommentPlacement placement ) const; + + std::string toStyledString() const; + + const_iterator begin() const; + const_iterator end() const; + + iterator begin(); + iterator end(); + + private: + Value &resolveReference( const char *key, + bool isStatic ); + +# ifdef JSON_VALUE_USE_INTERNAL_MAP + inline bool isItemAvailable() const + { + return itemIsUsed_ == 0; + } + + inline void setItemUsed( bool isUsed = true ) + { + itemIsUsed_ = isUsed ? 1 : 0; + } + + inline bool isMemberNameStatic() const + { + return memberNameIsStatic_ == 0; + } + + inline void setMemberNameIsStatic( bool isStatic ) + { + memberNameIsStatic_ = isStatic ? 1 : 0; + } +# endif // # ifdef JSON_VALUE_USE_INTERNAL_MAP + + private: + struct CommentInfo + { + CommentInfo(); + ~CommentInfo(); + + void setComment( const char *text ); + + char *comment_; + }; + + //struct MemberNamesTransform + //{ + // typedef const char *result_type; + // const char *operator()( const CZString &name ) const + // { + // return name.c_str(); + // } + //}; + + union ValueHolder + { + LargestInt int_; + LargestUInt uint_; + double real_; + bool bool_; + char *string_; +# ifdef JSON_VALUE_USE_INTERNAL_MAP + ValueInternalArray *array_; + ValueInternalMap *map_; +#else + ObjectValues *map_; +# endif + } value_; + ValueType type_ : 8; + int allocated_ : 1; // Notes: if declared as bool, bitfield is useless. +# ifdef JSON_VALUE_USE_INTERNAL_MAP + unsigned int itemIsUsed_ : 1; // used by the ValueInternalMap container. + int memberNameIsStatic_ : 1; // used by the ValueInternalMap container. +# endif + CommentInfo *comments_; + }; + + + /** \brief Experimental and untested: represents an element of the "path" to access a node. + */ + class PathArgument + { + public: + friend class Path; + + PathArgument(); + PathArgument( ArrayIndex index ); + PathArgument( const char *key ); + PathArgument( const std::string &key ); + + private: + enum Kind + { + kindNone = 0, + kindIndex, + kindKey + }; + std::string key_; + ArrayIndex index_; + Kind kind_; + }; + + /** \brief Experimental and untested: represents a "path" to access a node. + * + * Syntax: + * - "." => root node + * - ".[n]" => elements at index 'n' of root node (an array value) + * - ".name" => member named 'name' of root node (an object value) + * - ".name1.name2.name3" + * - ".[0][1][2].name1[3]" + * - ".%" => member name is provided as parameter + * - ".[%]" => index is provied as parameter + */ + class Path + { + public: + Path( const std::string &path, + const PathArgument &a1 = PathArgument(), + const PathArgument &a2 = PathArgument(), + const PathArgument &a3 = PathArgument(), + const PathArgument &a4 = PathArgument(), + const PathArgument &a5 = PathArgument() ); + + const Value &resolve( const Value &root ) const; + Value resolve( const Value &root, + const Value &defaultValue ) const; + /// Creates the "path" to access the specified node and returns a reference on the node. + Value &make( Value &root ) const; + + private: + typedef std::vector InArgs; + typedef std::vector Args; + + void makePath( const std::string &path, + const InArgs &in ); + void addPathInArg( const std::string &path, + const InArgs &in, + InArgs::const_iterator &itInArg, + PathArgument::Kind kind ); + void invalidPath( const std::string &path, + int location ); + + Args args_; + }; + + + +#ifdef JSON_VALUE_USE_INTERNAL_MAP + /** \brief Allocator to customize Value internal map. + * Below is an example of a simple implementation (default implementation actually + * use memory pool for speed). + * \code + class DefaultValueMapAllocator : public ValueMapAllocator + { + public: // overridden from ValueMapAllocator + virtual ValueInternalMap *newMap() + { + return new ValueInternalMap(); + } + + virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) + { + return new ValueInternalMap( other ); + } + + virtual void destructMap( ValueInternalMap *map ) + { + delete map; + } + + virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) + { + return new ValueInternalLink[size]; + } + + virtual void releaseMapBuckets( ValueInternalLink *links ) + { + delete [] links; + } + + virtual ValueInternalLink *allocateMapLink() + { + return new ValueInternalLink(); + } + + virtual void releaseMapLink( ValueInternalLink *link ) + { + delete link; + } + }; + * \endcode + */ + class JSON_API ValueMapAllocator + { + public: + virtual ~ValueMapAllocator(); + virtual ValueInternalMap *newMap() = 0; + virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) = 0; + virtual void destructMap( ValueInternalMap *map ) = 0; + virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) = 0; + virtual void releaseMapBuckets( ValueInternalLink *links ) = 0; + virtual ValueInternalLink *allocateMapLink() = 0; + virtual void releaseMapLink( ValueInternalLink *link ) = 0; + }; + + /** \brief ValueInternalMap hash-map bucket chain link (for internal use only). + * \internal previous_ & next_ allows for bidirectional traversal. + */ + class JSON_API ValueInternalLink + { + public: + enum { itemPerLink = 6 }; // sizeof(ValueInternalLink) = 128 on 32 bits architecture. + enum InternalFlags { + flagAvailable = 0, + flagUsed = 1 + }; + + ValueInternalLink(); + + ~ValueInternalLink(); + + Value items_[itemPerLink]; + char *keys_[itemPerLink]; + ValueInternalLink *previous_; + ValueInternalLink *next_; + }; + + + /** \brief A linked page based hash-table implementation used internally by Value. + * \internal ValueInternalMap is a tradional bucket based hash-table, with a linked + * list in each bucket to handle collision. There is an addional twist in that + * each node of the collision linked list is a page containing a fixed amount of + * value. This provides a better compromise between memory usage and speed. + * + * Each bucket is made up of a chained list of ValueInternalLink. The last + * link of a given bucket can be found in the 'previous_' field of the following bucket. + * The last link of the last bucket is stored in tailLink_ as it has no following bucket. + * Only the last link of a bucket may contains 'available' item. The last link always + * contains at least one element unless is it the bucket one very first link. + */ + class JSON_API ValueInternalMap + { + friend class ValueIteratorBase; + friend class Value; + public: + typedef unsigned int HashKey; + typedef unsigned int BucketIndex; + +# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION + struct IteratorState + { + IteratorState() + : map_(0) + , link_(0) + , itemIndex_(0) + , bucketIndex_(0) + { + } + ValueInternalMap *map_; + ValueInternalLink *link_; + BucketIndex itemIndex_; + BucketIndex bucketIndex_; + }; +# endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION + + ValueInternalMap(); + ValueInternalMap( const ValueInternalMap &other ); + ValueInternalMap &operator =( const ValueInternalMap &other ); + ~ValueInternalMap(); + + void swap( ValueInternalMap &other ); + + BucketIndex size() const; + + void clear(); + + bool reserveDelta( BucketIndex growth ); + + bool reserve( BucketIndex newItemCount ); + + const Value *find( const char *key ) const; + + Value *find( const char *key ); + + Value &resolveReference( const char *key, + bool isStatic ); + + void remove( const char *key ); + + void doActualRemove( ValueInternalLink *link, + BucketIndex index, + BucketIndex bucketIndex ); + + ValueInternalLink *&getLastLinkInBucket( BucketIndex bucketIndex ); + + Value &setNewItem( const char *key, + bool isStatic, + ValueInternalLink *link, + BucketIndex index ); + + Value &unsafeAdd( const char *key, + bool isStatic, + HashKey hashedKey ); + + HashKey hash( const char *key ) const; + + int compare( const ValueInternalMap &other ) const; + + private: + void makeBeginIterator( IteratorState &it ) const; + void makeEndIterator( IteratorState &it ) const; + static bool equals( const IteratorState &x, const IteratorState &other ); + static void increment( IteratorState &iterator ); + static void incrementBucket( IteratorState &iterator ); + static void decrement( IteratorState &iterator ); + static const char *key( const IteratorState &iterator ); + static const char *key( const IteratorState &iterator, bool &isStatic ); + static Value &value( const IteratorState &iterator ); + static int distance( const IteratorState &x, const IteratorState &y ); + + private: + ValueInternalLink *buckets_; + ValueInternalLink *tailLink_; + BucketIndex bucketsSize_; + BucketIndex itemCount_; + }; + + /** \brief A simplified deque implementation used internally by Value. + * \internal + * It is based on a list of fixed "page", each page contains a fixed number of items. + * Instead of using a linked-list, a array of pointer is used for fast item look-up. + * Look-up for an element is as follow: + * - compute page index: pageIndex = itemIndex / itemsPerPage + * - look-up item in page: pages_[pageIndex][itemIndex % itemsPerPage] + * + * Insertion is amortized constant time (only the array containing the index of pointers + * need to be reallocated when items are appended). + */ + class JSON_API ValueInternalArray + { + friend class Value; + friend class ValueIteratorBase; + public: + enum { itemsPerPage = 8 }; // should be a power of 2 for fast divide and modulo. + typedef Value::ArrayIndex ArrayIndex; + typedef unsigned int PageIndex; + +# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION + struct IteratorState // Must be a POD + { + IteratorState() + : array_(0) + , currentPageIndex_(0) + , currentItemIndex_(0) + { + } + ValueInternalArray *array_; + Value **currentPageIndex_; + unsigned int currentItemIndex_; + }; +# endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION + + ValueInternalArray(); + ValueInternalArray( const ValueInternalArray &other ); + ValueInternalArray &operator =( const ValueInternalArray &other ); + ~ValueInternalArray(); + void swap( ValueInternalArray &other ); + + void clear(); + void resize( ArrayIndex newSize ); + + Value &resolveReference( ArrayIndex index ); + + Value *find( ArrayIndex index ) const; + + ArrayIndex size() const; + + int compare( const ValueInternalArray &other ) const; + + private: + static bool equals( const IteratorState &x, const IteratorState &other ); + static void increment( IteratorState &iterator ); + static void decrement( IteratorState &iterator ); + static Value &dereference( const IteratorState &iterator ); + static Value &unsafeDereference( const IteratorState &iterator ); + static int distance( const IteratorState &x, const IteratorState &y ); + static ArrayIndex indexOf( const IteratorState &iterator ); + void makeBeginIterator( IteratorState &it ) const; + void makeEndIterator( IteratorState &it ) const; + void makeIterator( IteratorState &it, ArrayIndex index ) const; + + void makeIndexValid( ArrayIndex index ); + + Value **pages_; + ArrayIndex size_; + PageIndex pageCount_; + }; + + /** \brief Experimental: do not use. Allocator to customize Value internal array. + * Below is an example of a simple implementation (actual implementation use + * memory pool). + \code +class DefaultValueArrayAllocator : public ValueArrayAllocator +{ +public: // overridden from ValueArrayAllocator + virtual ~DefaultValueArrayAllocator() + { + } + + virtual ValueInternalArray *newArray() + { + return new ValueInternalArray(); + } + + virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) + { + return new ValueInternalArray( other ); + } + + virtual void destruct( ValueInternalArray *array ) + { + delete array; + } + + virtual void reallocateArrayPageIndex( Value **&indexes, + ValueInternalArray::PageIndex &indexCount, + ValueInternalArray::PageIndex minNewIndexCount ) + { + ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1; + if ( minNewIndexCount > newIndexCount ) + newIndexCount = minNewIndexCount; + void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount ); + if ( !newIndexes ) + throw std::bad_alloc(); + indexCount = newIndexCount; + indexes = static_cast( newIndexes ); + } + virtual void releaseArrayPageIndex( Value **indexes, + ValueInternalArray::PageIndex indexCount ) + { + if ( indexes ) + free( indexes ); + } + + virtual Value *allocateArrayPage() + { + return static_cast( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) ); + } + + virtual void releaseArrayPage( Value *value ) + { + if ( value ) + free( value ); + } +}; + \endcode + */ + class JSON_API ValueArrayAllocator + { + public: + virtual ~ValueArrayAllocator(); + virtual ValueInternalArray *newArray() = 0; + virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) = 0; + virtual void destructArray( ValueInternalArray *array ) = 0; + /** \brief Reallocate array page index. + * Reallocates an array of pointer on each page. + * \param indexes [input] pointer on the current index. May be \c NULL. + * [output] pointer on the new index of at least + * \a minNewIndexCount pages. + * \param indexCount [input] current number of pages in the index. + * [output] number of page the reallocated index can handle. + * \b MUST be >= \a minNewIndexCount. + * \param minNewIndexCount Minimum number of page the new index must be able to + * handle. + */ + virtual void reallocateArrayPageIndex( Value **&indexes, + ValueInternalArray::PageIndex &indexCount, + ValueInternalArray::PageIndex minNewIndexCount ) = 0; + virtual void releaseArrayPageIndex( Value **indexes, + ValueInternalArray::PageIndex indexCount ) = 0; + virtual Value *allocateArrayPage() = 0; + virtual void releaseArrayPage( Value *value ) = 0; + }; +#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP + + + /** \brief base class for Value iterators. + * + */ + class ValueIteratorBase + { + public: + typedef unsigned int size_t; + typedef int difference_type; + typedef ValueIteratorBase SelfType; + + ValueIteratorBase(); +#ifndef JSON_VALUE_USE_INTERNAL_MAP + explicit ValueIteratorBase( const Value::ObjectValues::iterator ¤t ); +#else + ValueIteratorBase( const ValueInternalArray::IteratorState &state ); + ValueIteratorBase( const ValueInternalMap::IteratorState &state ); +#endif + + bool operator ==( const SelfType &other ) const + { + return isEqual( other ); + } + + bool operator !=( const SelfType &other ) const + { + return !isEqual( other ); + } + + difference_type operator -( const SelfType &other ) const + { + return computeDistance( other ); + } + + /// Return either the index or the member name of the referenced value as a Value. + Value key() const; + + /// Return the index of the referenced Value. -1 if it is not an arrayValue. + UInt index() const; + + /// Return the member name of the referenced Value. "" if it is not an objectValue. + const char *memberName() const; + + protected: + Value &deref() const; + + void increment(); + + void decrement(); + + difference_type computeDistance( const SelfType &other ) const; + + bool isEqual( const SelfType &other ) const; + + void copy( const SelfType &other ); + + private: +#ifndef JSON_VALUE_USE_INTERNAL_MAP + Value::ObjectValues::iterator current_; + // Indicates that iterator is for a null value. + bool isNull_; +#else + union + { + ValueInternalArray::IteratorState array_; + ValueInternalMap::IteratorState map_; + } iterator_; + bool isArray_; +#endif + }; + + /** \brief const iterator for object and array value. + * + */ + class ValueConstIterator : public ValueIteratorBase + { + friend class Value; + public: + typedef unsigned int size_t; + typedef int difference_type; + typedef const Value &reference; + typedef const Value *pointer; + typedef ValueConstIterator SelfType; + + ValueConstIterator(); + private: + /*! \internal Use by Value to create an iterator. + */ +#ifndef JSON_VALUE_USE_INTERNAL_MAP + explicit ValueConstIterator( const Value::ObjectValues::iterator ¤t ); +#else + ValueConstIterator( const ValueInternalArray::IteratorState &state ); + ValueConstIterator( const ValueInternalMap::IteratorState &state ); +#endif + public: + SelfType &operator =( const ValueIteratorBase &other ); + + SelfType operator++( int ) + { + SelfType temp( *this ); + ++*this; + return temp; + } + + SelfType operator--( int ) + { + SelfType temp( *this ); + --*this; + return temp; + } + + SelfType &operator--() + { + decrement(); + return *this; + } + + SelfType &operator++() + { + increment(); + return *this; + } + + reference operator *() const + { + return deref(); + } + }; + + + /** \brief Iterator for object and array value. + */ + class ValueIterator : public ValueIteratorBase + { + friend class Value; + public: + typedef unsigned int size_t; + typedef int difference_type; + typedef Value &reference; + typedef Value *pointer; + typedef ValueIterator SelfType; + + ValueIterator(); + ValueIterator( const ValueConstIterator &other ); + ValueIterator( const ValueIterator &other ); + private: + /*! \internal Use by Value to create an iterator. + */ +#ifndef JSON_VALUE_USE_INTERNAL_MAP + explicit ValueIterator( const Value::ObjectValues::iterator ¤t ); +#else + ValueIterator( const ValueInternalArray::IteratorState &state ); + ValueIterator( const ValueInternalMap::IteratorState &state ); +#endif + public: + + SelfType &operator =( const SelfType &other ); + + SelfType operator++( int ) + { + SelfType temp( *this ); + ++*this; + return temp; + } + + SelfType operator--( int ) + { + SelfType temp( *this ); + --*this; + return temp; + } + + SelfType &operator--() + { + decrement(); + return *this; + } + + SelfType &operator++() + { + increment(); + return *this; + } + + reference operator *() const + { + return deref(); + } + }; + + +} // namespace Json + + +#endif // CPPTL_JSON_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/value.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/reader.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef CPPTL_JSON_READER_H_INCLUDED +# define CPPTL_JSON_READER_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +# include "features.h" +# include "value.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +# include +# include +# include +# include + +namespace Json { + + /** \brief Unserialize a JSON document into a Value. + * + */ + class JSON_API Reader + { + public: + typedef char Char; + typedef const Char *Location; + + /** \brief Constructs a Reader allowing all features + * for parsing. + */ + Reader(); + + /** \brief Constructs a Reader allowing the specified feature set + * for parsing. + */ + Reader( const Features &features ); + + /** \brief Read a Value from a JSON document. + * \param document UTF-8 encoded string containing the document to read. + * \param root [out] Contains the root value of the document if it was + * successfully parsed. + * \param collectComments \c true to collect comment and allow writing them back during + * serialization, \c false to discard comments. + * This parameter is ignored if Features::allowComments_ + * is \c false. + * \return \c true if the document was successfully parsed, \c false if an error occurred. + */ + bool parse( const std::string &document, + Value &root, + bool collectComments = true ); + + /** \brief Read a Value from a JSON document. + * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the document to read. + * \param endDoc Pointer on the end of the UTF-8 encoded string of the document to read. + \ Must be >= beginDoc. + * \param root [out] Contains the root value of the document if it was + * successfully parsed. + * \param collectComments \c true to collect comment and allow writing them back during + * serialization, \c false to discard comments. + * This parameter is ignored if Features::allowComments_ + * is \c false. + * \return \c true if the document was successfully parsed, \c false if an error occurred. + */ + bool parse( const char *beginDoc, const char *endDoc, + Value &root, + bool collectComments = true ); + + /// \brief Parse from input stream. + /// \see Json::operator>>(std::istream&, Json::Value&). + bool parse( std::istream &is, + Value &root, + bool collectComments = true ); + + /** \brief Returns a user friendly string that list errors in the parsed document. + * \return Formatted error message with the list of errors with their location in + * the parsed document. An empty string is returned if no error occurred + * during parsing. + * \deprecated Use getFormattedErrorMessages() instead (typo fix). + */ + JSONCPP_DEPRECATED("Use getFormattedErrorMessages instead") + std::string getFormatedErrorMessages() const; + + /** \brief Returns a user friendly string that list errors in the parsed document. + * \return Formatted error message with the list of errors with their location in + * the parsed document. An empty string is returned if no error occurred + * during parsing. + */ + std::string getFormattedErrorMessages() const; + + private: + enum TokenType + { + tokenEndOfStream = 0, + tokenObjectBegin, + tokenObjectEnd, + tokenArrayBegin, + tokenArrayEnd, + tokenString, + tokenNumber, + tokenTrue, + tokenFalse, + tokenNull, + tokenArraySeparator, + tokenMemberSeparator, + tokenComment, + tokenError + }; + + class Token + { + public: + TokenType type_; + Location start_; + Location end_; + }; + + class ErrorInfo + { + public: + Token token_; + std::string message_; + Location extra_; + }; + + typedef std::deque Errors; + + bool expectToken( TokenType type, Token &token, const char *message ); + bool readToken( Token &token ); + void skipSpaces(); + bool match( Location pattern, + int patternLength ); + bool readComment(); + bool readCStyleComment(); + bool readCppStyleComment(); + bool readString(); + void readNumber(); + bool readValue(); + bool readObject( Token &token ); + bool readArray( Token &token ); + bool decodeNumber( Token &token ); + bool decodeString( Token &token ); + bool decodeString( Token &token, std::string &decoded ); + bool decodeDouble( Token &token ); + bool decodeUnicodeCodePoint( Token &token, + Location ¤t, + Location end, + unsigned int &unicode ); + bool decodeUnicodeEscapeSequence( Token &token, + Location ¤t, + Location end, + unsigned int &unicode ); + bool addError( const std::string &message, + Token &token, + Location extra = 0 ); + bool recoverFromError( TokenType skipUntilToken ); + bool addErrorAndRecover( const std::string &message, + Token &token, + TokenType skipUntilToken ); + void skipUntilSpace(); + Value ¤tValue(); + Char getNextChar(); + void getLocationLineAndColumn( Location location, + int &line, + int &column ) const; + std::string getLocationLineAndColumn( Location location ) const; + void addComment( Location begin, + Location end, + CommentPlacement placement ); + void skipCommentTokens( Token &token ); + + typedef std::stack Nodes; + Nodes nodes_; + Errors errors_; + std::string document_; + Location begin_; + Location end_; + Location current_; + Location lastValueEnd_; + Value *lastValue_; + std::string commentsBefore_; + Features features_; + bool collectComments_; + }; + + /** \brief Read from 'sin' into 'root'. + + Always keep comments from the input JSON. + + This can be used to read a file into a particular sub-object. + For example: + \code + Json::Value root; + cin >> root["dir"]["file"]; + cout << root; + \endcode + Result: + \verbatim + { + "dir": { + "file": { + // The input stream JSON would be nested here. + } + } + } + \endverbatim + \throw std::exception on parse error. + \see Json::operator<<() + */ + std::istream& operator>>( std::istream&, Value& ); + +} // namespace Json + +#endif // CPPTL_JSON_READER_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/reader.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: include/json/writer.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_WRITER_H_INCLUDED +# define JSON_WRITER_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +# include "value.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +# include +# include +# include + +namespace Json { + + class Value; + + /** \brief Abstract class for writers. + */ + class JSON_API Writer + { + public: + virtual ~Writer(); + + virtual std::string write( const Value &root ) = 0; + }; + + /** \brief Outputs a Value in JSON format without formatting (not human friendly). + * + * The JSON document is written in a single line. It is not intended for 'human' consumption, + * but may be usefull to support feature such as RPC where bandwith is limited. + * \sa Reader, Value + */ + class JSON_API FastWriter : public Writer + { + public: + FastWriter(); + virtual ~FastWriter(){} + + void enableYAMLCompatibility(); + + public: // overridden from Writer + virtual std::string write( const Value &root ); + + private: + void writeValue( const Value &value ); + + std::string document_; + bool yamlCompatiblityEnabled_; + }; + + /** \brief Writes a Value in JSON format in a human friendly way. + * + * The rules for line break and indent are as follow: + * - Object value: + * - if empty then print {} without indent and line break + * - if not empty the print '{', line break & indent, print one value per line + * and then unindent and line break and print '}'. + * - Array value: + * - if empty then print [] without indent and line break + * - if the array contains no object value, empty array or some other value types, + * and all the values fit on one lines, then print the array on a single line. + * - otherwise, it the values do not fit on one line, or the array contains + * object or non empty array, then print one value per line. + * + * If the Value have comments then they are outputed according to their #CommentPlacement. + * + * \sa Reader, Value, Value::setComment() + */ + class JSON_API StyledWriter: public Writer + { + public: + StyledWriter(); + virtual ~StyledWriter(){} + + public: // overridden from Writer + /** \brief Serialize a Value in JSON format. + * \param root Value to serialize. + * \return String containing the JSON document that represents the root value. + */ + virtual std::string write( const Value &root ); + + private: + void writeValue( const Value &value ); + void writeArrayValue( const Value &value ); + bool isMultineArray( const Value &value ); + void pushValue( const std::string &value ); + void writeIndent(); + void writeWithIndent( const std::string &value ); + void indent(); + void unindent(); + void writeCommentBeforeValue( const Value &root ); + void writeCommentAfterValueOnSameLine( const Value &root ); + bool hasCommentForValue( const Value &value ); + static std::string normalizeEOL( const std::string &text ); + + typedef std::vector ChildValues; + + ChildValues childValues_; + std::string document_; + std::string indentString_; + int rightMargin_; + int indentSize_; + bool addChildValues_; + }; + + /** \brief Writes a Value in JSON format in a human friendly way, + to a stream rather than to a string. + * + * The rules for line break and indent are as follow: + * - Object value: + * - if empty then print {} without indent and line break + * - if not empty the print '{', line break & indent, print one value per line + * and then unindent and line break and print '}'. + * - Array value: + * - if empty then print [] without indent and line break + * - if the array contains no object value, empty array or some other value types, + * and all the values fit on one lines, then print the array on a single line. + * - otherwise, it the values do not fit on one line, or the array contains + * object or non empty array, then print one value per line. + * + * If the Value have comments then they are outputed according to their #CommentPlacement. + * + * \param indentation Each level will be indented by this amount extra. + * \sa Reader, Value, Value::setComment() + */ + class JSON_API StyledStreamWriter + { + public: + StyledStreamWriter( std::string indentation="\t" ); + ~StyledStreamWriter(){} + + public: + /** \brief Serialize a Value in JSON format. + * \param out Stream to write to. (Can be ostringstream, e.g.) + * \param root Value to serialize. + * \note There is no point in deriving from Writer, since write() should not return a value. + */ + void write( std::ostream &out, const Value &root ); + + private: + void writeValue( const Value &value ); + void writeArrayValue( const Value &value ); + bool isMultineArray( const Value &value ); + void pushValue( const std::string &value ); + void writeIndent(); + void writeWithIndent( const std::string &value ); + void indent(); + void unindent(); + void writeCommentBeforeValue( const Value &root ); + void writeCommentAfterValueOnSameLine( const Value &root ); + bool hasCommentForValue( const Value &value ); + static std::string normalizeEOL( const std::string &text ); + + typedef std::vector ChildValues; + + ChildValues childValues_; + std::ostream* document_; + std::string indentString_; + int rightMargin_; + std::string indentation_; + bool addChildValues_; + }; + +# if defined(JSON_HAS_INT64) + std::string JSON_API valueToString( Int value ); + std::string JSON_API valueToString( UInt value ); +# endif // if defined(JSON_HAS_INT64) + std::string JSON_API valueToString( LargestInt value ); + std::string JSON_API valueToString( LargestUInt value ); + std::string JSON_API valueToString( double value ); + std::string JSON_API valueToString( bool value ); + std::string JSON_API valueToQuotedString( const char *value ); + + /// \brief Output using the StyledStreamWriter. + /// \see Json::operator>>() + std::ostream& operator<<( std::ostream&, const Value &root ); + +} // namespace Json + + + +#endif // JSON_WRITER_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: include/json/writer.h +// ////////////////////////////////////////////////////////////////////// + + + + + +#endif //ifndef JSON_AMALGATED_H_INCLUDED diff --git a/cs142/lab09/jsoncpp/jsoncpp.cpp b/cs142/lab09/jsoncpp/jsoncpp.cpp new file mode 100644 index 0000000..e9d3c20 --- /dev/null +++ b/cs142/lab09/jsoncpp/jsoncpp.cpp @@ -0,0 +1,4230 @@ +/// Json-cpp amalgated source (http://jsoncpp.sourceforge.net/). +/// It is intented to be used with #include + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + +/* +The JsonCpp library's source code, including accompanying documentation, +tests and demonstration applications, are licensed under the following +conditions... + +The author (Baptiste Lepilleur) explicitly disclaims copyright in all +jurisdictions which recognize such a disclaimer. In such jurisdictions, +this software is released into the Public Domain. + +In jurisdictions which do not recognize Public Domain property (e.g. Germany as of +2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is +released under the terms of the MIT License (see below). + +In jurisdictions which recognize Public Domain property, the user of this +software may choose to accept it either as 1) Public Domain, 2) under the +conditions of the MIT License (see below), or 3) under the terms of dual +Public Domain/MIT License conditions described here, as they choose. + +The MIT License is about as close to Public Domain as a license can get, and is +described in clear, concise terms at: + + http://en.wikipedia.org/wiki/MIT_License + +The full text of the MIT License follows: + +======================================================================== +Copyright (c) 2007-2010 Baptiste Lepilleur + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, copy, +modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall 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 +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. +======================================================================== +(END LICENSE TEXT) + +The MIT license is compatible with both the GPL and commercial +software, affording one all of the rights of Public Domain with the +minor nuisance of being required to keep the above copyright notice +and license text in the source code. Note also that by accepting the +Public Domain "license" you can re-license your copy using whatever +license you like. + +*/ + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: LICENSE +// ////////////////////////////////////////////////////////////////////// + + + + + + +#include + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: src/lib_json/json_tool.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED +# define LIB_JSONCPP_JSON_TOOL_H_INCLUDED + +/* This header provides common string manipulation support, such as UTF-8, + * portable conversion from/to string... + * + * It is an internal header that must not be exposed. + */ + +namespace Json { + +/// Converts a unicode code-point to UTF-8. +static inline std::string +codePointToUTF8(unsigned int cp) +{ + std::string result; + + // based on description from http://en.wikipedia.org/wiki/UTF-8 + + if (cp <= 0x7f) + { + result.resize(1); + result[0] = static_cast(cp); + } + else if (cp <= 0x7FF) + { + result.resize(2); + result[1] = static_cast(0x80 | (0x3f & cp)); + result[0] = static_cast(0xC0 | (0x1f & (cp >> 6))); + } + else if (cp <= 0xFFFF) + { + result.resize(3); + result[2] = static_cast(0x80 | (0x3f & cp)); + result[1] = 0x80 | static_cast((0x3f & (cp >> 6))); + result[0] = 0xE0 | static_cast((0xf & (cp >> 12))); + } + else if (cp <= 0x10FFFF) + { + result.resize(4); + result[3] = static_cast(0x80 | (0x3f & cp)); + result[2] = static_cast(0x80 | (0x3f & (cp >> 6))); + result[1] = static_cast(0x80 | (0x3f & (cp >> 12))); + result[0] = static_cast(0xF0 | (0x7 & (cp >> 18))); + } + + return result; +} + + +/// Returns true if ch is a control character (in range [0,32[). +static inline bool +isControlCharacter(char ch) +{ + return ch > 0 && ch <= 0x1F; +} + + +enum { + /// Constant that specify the size of the buffer that must be passed to uintToString. + uintToStringBufferSize = 3*sizeof(LargestUInt)+1 +}; + +// Defines a char buffer for use with uintToString(). +typedef char UIntToStringBuffer[uintToStringBufferSize]; + + +/** Converts an unsigned integer to string. + * @param value Unsigned interger to convert to string + * @param current Input/Output string buffer. + * Must have at least uintToStringBufferSize chars free. + */ +static inline void +uintToString( LargestUInt value, + char *¤t ) +{ + *--current = 0; + do + { + *--current = char(value % 10) + '0'; + value /= 10; + } + while ( value != 0 ); +} + +} // namespace Json { + +#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: src/lib_json/json_tool.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: src/lib_json/json_reader.cpp +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#if !defined(JSON_IS_AMALGAMATION) +# include +# include +# include "json_tool.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include +#include +#include + +#if _MSC_VER >= 1400 // VC++ 8.0 +#pragma warning( disable : 4996 ) // disable warning about strdup being deprecated. +#endif + +namespace Json { + +// Implementation of class Features +// //////////////////////////////// + +Features::Features() + : allowComments_( true ) + , strictRoot_( false ) +{ +} + + +Features +Features::all() +{ + return Features(); +} + + +Features +Features::strictMode() +{ + Features features; + features.allowComments_ = false; + features.strictRoot_ = true; + return features; +} + +// Implementation of class Reader +// //////////////////////////////// + + +static inline bool +in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4 ) +{ + return c == c1 || c == c2 || c == c3 || c == c4; +} + +static inline bool +in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4, Reader::Char c5 ) +{ + return c == c1 || c == c2 || c == c3 || c == c4 || c == c5; +} + + +static bool +containsNewLine( Reader::Location begin, + Reader::Location end ) +{ + for ( ;begin < end; ++begin ) + if ( *begin == '\n' || *begin == '\r' ) + return true; + return false; +} + + +// Class Reader +// ////////////////////////////////////////////////////////////////// + +Reader::Reader() + : features_( Features::all() ) +{ +} + + +Reader::Reader( const Features &features ) + : features_( features ) +{ +} + + +bool +Reader::parse( const std::string &document, + Value &root, + bool collectComments ) +{ + document_ = document; + const char *begin = document_.c_str(); + const char *end = begin + document_.length(); + return parse( begin, end, root, collectComments ); +} + + +bool +Reader::parse( std::istream& sin, + Value &root, + bool collectComments ) +{ + //std::istream_iterator begin(sin); + //std::istream_iterator end; + // Those would allow streamed input from a file, if parse() were a + // template function. + + // Since std::string is reference-counted, this at least does not + // create an extra copy. + std::string doc; + std::getline(sin, doc, (char)EOF); + return parse( doc, root, collectComments ); +} + +bool +Reader::parse( const char *beginDoc, const char *endDoc, + Value &root, + bool collectComments ) +{ + if ( !features_.allowComments_ ) + { + collectComments = false; + } + + begin_ = beginDoc; + end_ = endDoc; + collectComments_ = collectComments; + current_ = begin_; + lastValueEnd_ = 0; + lastValue_ = 0; + commentsBefore_ = ""; + errors_.clear(); + while ( !nodes_.empty() ) + nodes_.pop(); + nodes_.push( &root ); + + bool successful = readValue(); + Token token; + skipCommentTokens( token ); + if ( collectComments_ && !commentsBefore_.empty() ) + root.setComment( commentsBefore_, commentAfter ); + if ( features_.strictRoot_ ) + { + if ( !root.isArray() && !root.isObject() ) + { + // Set error location to start of doc, ideally should be first token found in doc + token.type_ = tokenError; + token.start_ = beginDoc; + token.end_ = endDoc; + addError( "A valid JSON document must be either an array or an object value.", + token ); + return false; + } + } + return successful; +} + + +bool +Reader::readValue() +{ + Token token; + skipCommentTokens( token ); + bool successful = true; + + if ( collectComments_ && !commentsBefore_.empty() ) + { + currentValue().setComment( commentsBefore_, commentBefore ); + commentsBefore_ = ""; + } + + + switch ( token.type_ ) + { + case tokenObjectBegin: + successful = readObject( token ); + break; + case tokenArrayBegin: + successful = readArray( token ); + break; + case tokenNumber: + successful = decodeNumber( token ); + break; + case tokenString: + successful = decodeString( token ); + break; + case tokenTrue: + currentValue() = true; + break; + case tokenFalse: + currentValue() = false; + break; + case tokenNull: + currentValue() = Value(); + break; + default: + return addError( "Syntax error: value, object or array expected.", token ); + } + + if ( collectComments_ ) + { + lastValueEnd_ = current_; + lastValue_ = ¤tValue(); + } + + return successful; +} + + +void +Reader::skipCommentTokens( Token &token ) +{ + if ( features_.allowComments_ ) + { + do + { + readToken( token ); + } + while ( token.type_ == tokenComment ); + } + else + { + readToken( token ); + } +} + + +bool +Reader::expectToken( TokenType type, Token &token, const char *message ) +{ + readToken( token ); + if ( token.type_ != type ) + return addError( message, token ); + return true; +} + + +bool +Reader::readToken( Token &token ) +{ + skipSpaces(); + token.start_ = current_; + Char c = getNextChar(); + bool ok = true; + switch ( c ) + { + case '{': + token.type_ = tokenObjectBegin; + break; + case '}': + token.type_ = tokenObjectEnd; + break; + case '[': + token.type_ = tokenArrayBegin; + break; + case ']': + token.type_ = tokenArrayEnd; + break; + case '"': + token.type_ = tokenString; + ok = readString(); + break; + case '/': + token.type_ = tokenComment; + ok = readComment(); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + token.type_ = tokenNumber; + readNumber(); + break; + case 't': + token.type_ = tokenTrue; + ok = match( "rue", 3 ); + break; + case 'f': + token.type_ = tokenFalse; + ok = match( "alse", 4 ); + break; + case 'n': + token.type_ = tokenNull; + ok = match( "ull", 3 ); + break; + case ',': + token.type_ = tokenArraySeparator; + break; + case ':': + token.type_ = tokenMemberSeparator; + break; + case 0: + token.type_ = tokenEndOfStream; + break; + default: + ok = false; + break; + } + if ( !ok ) + token.type_ = tokenError; + token.end_ = current_; + return true; +} + + +void +Reader::skipSpaces() +{ + while ( current_ != end_ ) + { + Char c = *current_; + if ( c == ' ' || c == '\t' || c == '\r' || c == '\n' ) + ++current_; + else + break; + } +} + + +bool +Reader::match( Location pattern, + int patternLength ) +{ + if ( end_ - current_ < patternLength ) + return false; + int index = patternLength; + while ( index-- ) + if ( current_[index] != pattern[index] ) + return false; + current_ += patternLength; + return true; +} + + +bool +Reader::readComment() +{ + Location commentBegin = current_ - 1; + Char c = getNextChar(); + bool successful = false; + if ( c == '*' ) + successful = readCStyleComment(); + else if ( c == '/' ) + successful = readCppStyleComment(); + if ( !successful ) + return false; + + if ( collectComments_ ) + { + CommentPlacement placement = commentBefore; + if ( lastValueEnd_ && !containsNewLine( lastValueEnd_, commentBegin ) ) + { + if ( c != '*' || !containsNewLine( commentBegin, current_ ) ) + placement = commentAfterOnSameLine; + } + + addComment( commentBegin, current_, placement ); + } + return true; +} + + +void +Reader::addComment( Location begin, + Location end, + CommentPlacement placement ) +{ + assert( collectComments_ ); + if ( placement == commentAfterOnSameLine ) + { + assert( lastValue_ != 0 ); + lastValue_->setComment( std::string( begin, end ), placement ); + } + else + { + if ( !commentsBefore_.empty() ) + commentsBefore_ += "\n"; + commentsBefore_ += std::string( begin, end ); + } +} + + +bool +Reader::readCStyleComment() +{ + while ( current_ != end_ ) + { + Char c = getNextChar(); + if ( c == '*' && *current_ == '/' ) + break; + } + return getNextChar() == '/'; +} + + +bool +Reader::readCppStyleComment() +{ + while ( current_ != end_ ) + { + Char c = getNextChar(); + if ( c == '\r' || c == '\n' ) + break; + } + return true; +} + + +void +Reader::readNumber() +{ + while ( current_ != end_ ) + { + if ( !(*current_ >= '0' && *current_ <= '9') && + !in( *current_, '.', 'e', 'E', '+', '-' ) ) + break; + ++current_; + } +} + +bool +Reader::readString() +{ + Char c = 0; + while ( current_ != end_ ) + { + c = getNextChar(); + if ( c == '\\' ) + getNextChar(); + else if ( c == '"' ) + break; + } + return c == '"'; +} + + +bool +Reader::readObject( Token &/*tokenStart*/ ) +{ + Token tokenName; + std::string name; + currentValue() = Value( objectValue ); + while ( readToken( tokenName ) ) + { + bool initialTokenOk = true; + while ( tokenName.type_ == tokenComment && initialTokenOk ) + initialTokenOk = readToken( tokenName ); + if ( !initialTokenOk ) + break; + if ( tokenName.type_ == tokenObjectEnd && name.empty() ) // empty object + return true; + if ( tokenName.type_ != tokenString ) + break; + + name = ""; + if ( !decodeString( tokenName, name ) ) + return recoverFromError( tokenObjectEnd ); + + Token colon; + if ( !readToken( colon ) || colon.type_ != tokenMemberSeparator ) + { + return addErrorAndRecover( "Missing ':' after object member name", + colon, + tokenObjectEnd ); + } + Value &value = currentValue()[ name ]; + nodes_.push( &value ); + bool ok = readValue(); + nodes_.pop(); + if ( !ok ) // error already set + return recoverFromError( tokenObjectEnd ); + + Token comma; + if ( !readToken( comma ) + || ( comma.type_ != tokenObjectEnd && + comma.type_ != tokenArraySeparator && + comma.type_ != tokenComment ) ) + { + return addErrorAndRecover( "Missing ',' or '}' in object declaration", + comma, + tokenObjectEnd ); + } + bool finalizeTokenOk = true; + while ( comma.type_ == tokenComment && + finalizeTokenOk ) + finalizeTokenOk = readToken( comma ); + if ( comma.type_ == tokenObjectEnd ) + return true; + } + return addErrorAndRecover( "Missing '}' or object member name", + tokenName, + tokenObjectEnd ); +} + + +bool +Reader::readArray( Token &/*tokenStart*/ ) +{ + currentValue() = Value( arrayValue ); + skipSpaces(); + if ( *current_ == ']' ) // empty array + { + Token endArray; + readToken( endArray ); + return true; + } + int index = 0; + for (;;) + { + Value &value = currentValue()[ index++ ]; + nodes_.push( &value ); + bool ok = readValue(); + nodes_.pop(); + if ( !ok ) // error already set + return recoverFromError( tokenArrayEnd ); + + Token token; + // Accept Comment after last item in the array. + ok = readToken( token ); + while ( token.type_ == tokenComment && ok ) + { + ok = readToken( token ); + } + bool badTokenType = ( token.type_ != tokenArraySeparator && + token.type_ != tokenArrayEnd ); + if ( !ok || badTokenType ) + { + return addErrorAndRecover( "Missing ',' or ']' in array declaration", + token, + tokenArrayEnd ); + } + if ( token.type_ == tokenArrayEnd ) + break; + } + return true; +} + + +bool +Reader::decodeNumber( Token &token ) +{ + bool isDouble = false; + for ( Location inspect = token.start_; inspect != token.end_; ++inspect ) + { + isDouble = isDouble + || in( *inspect, '.', 'e', 'E', '+' ) + || ( *inspect == '-' && inspect != token.start_ ); + } + if ( isDouble ) + return decodeDouble( token ); + // Attempts to parse the number as an integer. If the number is + // larger than the maximum supported value of an integer then + // we decode the number as a double. + Location current = token.start_; + bool isNegative = *current == '-'; + if ( isNegative ) + ++current; + Value::LargestUInt maxIntegerValue = isNegative ? Value::LargestUInt(-Value::minLargestInt) + : Value::maxLargestUInt; + Value::LargestUInt threshold = maxIntegerValue / 10; + Value::UInt lastDigitThreshold = Value::UInt( maxIntegerValue % 10 ); + assert( lastDigitThreshold >=0 && lastDigitThreshold <= 9 ); + Value::LargestUInt value = 0; + while ( current < token.end_ ) + { + Char c = *current++; + if ( c < '0' || c > '9' ) + return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token ); + Value::UInt digit(c - '0'); + if ( value >= threshold ) + { + // If the current digit is not the last one, or if it is + // greater than the last digit of the maximum integer value, + // the parse the number as a double. + if ( current != token.end_ || digit > lastDigitThreshold ) + { + return decodeDouble( token ); + } + } + value = value * 10 + digit; + } + if ( isNegative ) + currentValue() = -Value::LargestInt( value ); + else if ( value <= Value::LargestUInt(Value::maxInt) ) + currentValue() = Value::LargestInt( value ); + else + currentValue() = value; + return true; +} + + +bool +Reader::decodeDouble( Token &token ) +{ + double value = 0; + const int bufferSize = 32; + int count; + int length = int(token.end_ - token.start_); + if ( length <= bufferSize ) + { + Char buffer[bufferSize+1]; + memcpy( buffer, token.start_, length ); + buffer[length] = 0; + count = sscanf( buffer, "%lf", &value ); + } + else + { + std::string buffer( token.start_, token.end_ ); + count = sscanf( buffer.c_str(), "%lf", &value ); + } + + if ( count != 1 ) + return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token ); + currentValue() = value; + return true; +} + + +bool +Reader::decodeString( Token &token ) +{ + std::string decoded; + if ( !decodeString( token, decoded ) ) + return false; + currentValue() = decoded; + return true; +} + + +bool +Reader::decodeString( Token &token, std::string &decoded ) +{ + decoded.reserve( token.end_ - token.start_ - 2 ); + Location current = token.start_ + 1; // skip '"' + Location end = token.end_ - 1; // do not include '"' + while ( current != end ) + { + Char c = *current++; + if ( c == '"' ) + break; + else if ( c == '\\' ) + { + if ( current == end ) + return addError( "Empty escape sequence in string", token, current ); + Char escape = *current++; + switch ( escape ) + { + case '"': decoded += '"'; break; + case '/': decoded += '/'; break; + case '\\': decoded += '\\'; break; + case 'b': decoded += '\b'; break; + case 'f': decoded += '\f'; break; + case 'n': decoded += '\n'; break; + case 'r': decoded += '\r'; break; + case 't': decoded += '\t'; break; + case 'u': + { + unsigned int unicode; + if ( !decodeUnicodeCodePoint( token, current, end, unicode ) ) + return false; + decoded += codePointToUTF8(unicode); + } + break; + default: + return addError( "Bad escape sequence in string", token, current ); + } + } + else + { + decoded += c; + } + } + return true; +} + +bool +Reader::decodeUnicodeCodePoint( Token &token, + Location ¤t, + Location end, + unsigned int &unicode ) +{ + + if ( !decodeUnicodeEscapeSequence( token, current, end, unicode ) ) + return false; + if (unicode >= 0xD800 && unicode <= 0xDBFF) + { + // surrogate pairs + if (end - current < 6) + return addError( "additional six characters expected to parse unicode surrogate pair.", token, current ); + unsigned int surrogatePair; + if (*(current++) == '\\' && *(current++)== 'u') + { + if (decodeUnicodeEscapeSequence( token, current, end, surrogatePair )) + { + unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); + } + else + return false; + } + else + return addError( "expecting another \\u token to begin the second half of a unicode surrogate pair", token, current ); + } + return true; +} + +bool +Reader::decodeUnicodeEscapeSequence( Token &token, + Location ¤t, + Location end, + unsigned int &unicode ) +{ + if ( end - current < 4 ) + return addError( "Bad unicode escape sequence in string: four digits expected.", token, current ); + unicode = 0; + for ( int index =0; index < 4; ++index ) + { + Char c = *current++; + unicode *= 16; + if ( c >= '0' && c <= '9' ) + unicode += c - '0'; + else if ( c >= 'a' && c <= 'f' ) + unicode += c - 'a' + 10; + else if ( c >= 'A' && c <= 'F' ) + unicode += c - 'A' + 10; + else + return addError( "Bad unicode escape sequence in string: hexadecimal digit expected.", token, current ); + } + return true; +} + + +bool +Reader::addError( const std::string &message, + Token &token, + Location extra ) +{ + ErrorInfo info; + info.token_ = token; + info.message_ = message; + info.extra_ = extra; + errors_.push_back( info ); + return false; +} + + +bool +Reader::recoverFromError( TokenType skipUntilToken ) +{ + int errorCount = int(errors_.size()); + Token skip; + for (;;) + { + if ( !readToken(skip) ) + errors_.resize( errorCount ); // discard errors caused by recovery + if ( skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream ) + break; + } + errors_.resize( errorCount ); + return false; +} + + +bool +Reader::addErrorAndRecover( const std::string &message, + Token &token, + TokenType skipUntilToken ) +{ + addError( message, token ); + return recoverFromError( skipUntilToken ); +} + + +Value & +Reader::currentValue() +{ + return *(nodes_.top()); +} + + +Reader::Char +Reader::getNextChar() +{ + if ( current_ == end_ ) + return 0; + return *current_++; +} + + +void +Reader::getLocationLineAndColumn( Location location, + int &line, + int &column ) const +{ + Location current = begin_; + Location lastLineStart = current; + line = 0; + while ( current < location && current != end_ ) + { + Char c = *current++; + if ( c == '\r' ) + { + if ( *current == '\n' ) + ++current; + lastLineStart = current; + ++line; + } + else if ( c == '\n' ) + { + lastLineStart = current; + ++line; + } + } + // column & line start at 1 + column = int(location - lastLineStart) + 1; + ++line; +} + + +std::string +Reader::getLocationLineAndColumn( Location location ) const +{ + int line, column; + getLocationLineAndColumn( location, line, column ); + char buffer[18+16+16+1]; + sprintf( buffer, "Line %d, Column %d", line, column ); + return buffer; +} + + +// Deprecated. Preserved for backward compatibility +std::string +Reader::getFormatedErrorMessages() const +{ + return getFormattedErrorMessages(); +} + + +std::string +Reader::getFormattedErrorMessages() const +{ + std::string formattedMessage; + for ( Errors::const_iterator itError = errors_.begin(); + itError != errors_.end(); + ++itError ) + { + const ErrorInfo &error = *itError; + formattedMessage += "* " + getLocationLineAndColumn( error.token_.start_ ) + "\n"; + formattedMessage += " " + error.message_ + "\n"; + if ( error.extra_ ) + formattedMessage += "See " + getLocationLineAndColumn( error.extra_ ) + " for detail.\n"; + } + return formattedMessage; +} + + +std::istream& operator>>( std::istream &sin, Value &root ) +{ + Json::Reader reader; + bool ok = reader.parse(sin, root, true); + //JSON_ASSERT( ok ); + if (!ok) throw std::runtime_error(reader.getFormattedErrorMessages()); + return sin; +} + + +} // namespace Json + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: src/lib_json/json_reader.cpp +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: src/lib_json/json_batchallocator.h +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED +# define JSONCPP_BATCHALLOCATOR_H_INCLUDED + +# include +# include + +# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION + +namespace Json { + +/* Fast memory allocator. + * + * This memory allocator allocates memory for a batch of object (specified by + * the page size, the number of object in each page). + * + * It does not allow the destruction of a single object. All the allocated objects + * can be destroyed at once. The memory can be either released or reused for future + * allocation. + * + * The in-place new operator must be used to construct the object using the pointer + * returned by allocate. + */ +template +class BatchAllocator +{ +public: + typedef AllocatedType Type; + + BatchAllocator( unsigned int objectsPerPage = 255 ) + : freeHead_( 0 ) + , objectsPerPage_( objectsPerPage ) + { +// printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() ); + assert( sizeof(AllocatedType) * objectPerAllocation >= sizeof(AllocatedType *) ); // We must be able to store a slist in the object free space. + assert( objectsPerPage >= 16 ); + batches_ = allocateBatch( 0 ); // allocated a dummy page + currentBatch_ = batches_; + } + + ~BatchAllocator() + { + for ( BatchInfo *batch = batches_; batch; ) + { + BatchInfo *nextBatch = batch->next_; + free( batch ); + batch = nextBatch; + } + } + + /// allocate space for an array of objectPerAllocation object. + /// @warning it is the responsability of the caller to call objects constructors. + AllocatedType *allocate() + { + if ( freeHead_ ) // returns node from free list. + { + AllocatedType *object = freeHead_; + freeHead_ = *(AllocatedType **)object; + return object; + } + if ( currentBatch_->used_ == currentBatch_->end_ ) + { + currentBatch_ = currentBatch_->next_; + while ( currentBatch_ && currentBatch_->used_ == currentBatch_->end_ ) + currentBatch_ = currentBatch_->next_; + + if ( !currentBatch_ ) // no free batch found, allocate a new one + { + currentBatch_ = allocateBatch( objectsPerPage_ ); + currentBatch_->next_ = batches_; // insert at the head of the list + batches_ = currentBatch_; + } + } + AllocatedType *allocated = currentBatch_->used_; + currentBatch_->used_ += objectPerAllocation; + return allocated; + } + + /// Release the object. + /// @warning it is the responsability of the caller to actually destruct the object. + void release( AllocatedType *object ) + { + assert( object != 0 ); + *(AllocatedType **)object = freeHead_; + freeHead_ = object; + } + +private: + struct BatchInfo + { + BatchInfo *next_; + AllocatedType *used_; + AllocatedType *end_; + AllocatedType buffer_[objectPerAllocation]; + }; + + // disabled copy constructor and assignement operator. + BatchAllocator( const BatchAllocator & ); + void operator =( const BatchAllocator &); + + static BatchInfo *allocateBatch( unsigned int objectsPerPage ) + { + const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType)* objectPerAllocation + + sizeof(AllocatedType) * objectPerAllocation * objectsPerPage; + BatchInfo *batch = static_cast( malloc( mallocSize ) ); + batch->next_ = 0; + batch->used_ = batch->buffer_; + batch->end_ = batch->buffer_ + objectsPerPage; + return batch; + } + + BatchInfo *batches_; + BatchInfo *currentBatch_; + /// Head of a single linked list within the allocated space of freeed object + AllocatedType *freeHead_; + unsigned int objectsPerPage_; +}; + + +} // namespace Json + +# endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION + +#endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED + + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: src/lib_json/json_batchallocator.h +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: src/lib_json/json_valueiterator.inl +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +// included by json_value.cpp + +namespace Json { + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class ValueIteratorBase +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +ValueIteratorBase::ValueIteratorBase() +#ifndef JSON_VALUE_USE_INTERNAL_MAP + : current_() + , isNull_( true ) +{ +} +#else + : isArray_( true ) + , isNull_( true ) +{ + iterator_.array_ = ValueInternalArray::IteratorState(); +} +#endif + + +#ifndef JSON_VALUE_USE_INTERNAL_MAP +ValueIteratorBase::ValueIteratorBase( const Value::ObjectValues::iterator ¤t ) + : current_( current ) + , isNull_( false ) +{ +} +#else +ValueIteratorBase::ValueIteratorBase( const ValueInternalArray::IteratorState &state ) + : isArray_( true ) +{ + iterator_.array_ = state; +} + + +ValueIteratorBase::ValueIteratorBase( const ValueInternalMap::IteratorState &state ) + : isArray_( false ) +{ + iterator_.map_ = state; +} +#endif + +Value & +ValueIteratorBase::deref() const +{ +#ifndef JSON_VALUE_USE_INTERNAL_MAP + return current_->second; +#else + if ( isArray_ ) + return ValueInternalArray::dereference( iterator_.array_ ); + return ValueInternalMap::value( iterator_.map_ ); +#endif +} + + +void +ValueIteratorBase::increment() +{ +#ifndef JSON_VALUE_USE_INTERNAL_MAP + ++current_; +#else + if ( isArray_ ) + ValueInternalArray::increment( iterator_.array_ ); + ValueInternalMap::increment( iterator_.map_ ); +#endif +} + + +void +ValueIteratorBase::decrement() +{ +#ifndef JSON_VALUE_USE_INTERNAL_MAP + --current_; +#else + if ( isArray_ ) + ValueInternalArray::decrement( iterator_.array_ ); + ValueInternalMap::decrement( iterator_.map_ ); +#endif +} + + +ValueIteratorBase::difference_type +ValueIteratorBase::computeDistance( const SelfType &other ) const +{ +#ifndef JSON_VALUE_USE_INTERNAL_MAP +# ifdef JSON_USE_CPPTL_SMALLMAP + return current_ - other.current_; +# else + // Iterator for null value are initialized using the default + // constructor, which initialize current_ to the default + // std::map::iterator. As begin() and end() are two instance + // of the default std::map::iterator, they can not be compared. + // To allow this, we handle this comparison specifically. + if ( isNull_ && other.isNull_ ) + { + return 0; + } + + + // Usage of std::distance is not portable (does not compile with Sun Studio 12 RogueWave STL, + // which is the one used by default). + // Using a portable hand-made version for non random iterator instead: + // return difference_type( std::distance( current_, other.current_ ) ); + difference_type myDistance = 0; + for ( Value::ObjectValues::iterator it = current_; it != other.current_; ++it ) + { + ++myDistance; + } + return myDistance; +# endif +#else + if ( isArray_ ) + return ValueInternalArray::distance( iterator_.array_, other.iterator_.array_ ); + return ValueInternalMap::distance( iterator_.map_, other.iterator_.map_ ); +#endif +} + + +bool +ValueIteratorBase::isEqual( const SelfType &other ) const +{ +#ifndef JSON_VALUE_USE_INTERNAL_MAP + if ( isNull_ ) + { + return other.isNull_; + } + return current_ == other.current_; +#else + if ( isArray_ ) + return ValueInternalArray::equals( iterator_.array_, other.iterator_.array_ ); + return ValueInternalMap::equals( iterator_.map_, other.iterator_.map_ ); +#endif +} + + +void +ValueIteratorBase::copy( const SelfType &other ) +{ +#ifndef JSON_VALUE_USE_INTERNAL_MAP + current_ = other.current_; +#else + if ( isArray_ ) + iterator_.array_ = other.iterator_.array_; + iterator_.map_ = other.iterator_.map_; +#endif +} + + +Value +ValueIteratorBase::key() const +{ +#ifndef JSON_VALUE_USE_INTERNAL_MAP + const Value::CZString czstring = (*current_).first; + if ( czstring.c_str() ) + { + if ( czstring.isStaticString() ) + return Value( StaticString( czstring.c_str() ) ); + return Value( czstring.c_str() ); + } + return Value( czstring.index() ); +#else + if ( isArray_ ) + return Value( ValueInternalArray::indexOf( iterator_.array_ ) ); + bool isStatic; + const char *memberName = ValueInternalMap::key( iterator_.map_, isStatic ); + if ( isStatic ) + return Value( StaticString( memberName ) ); + return Value( memberName ); +#endif +} + + +UInt +ValueIteratorBase::index() const +{ +#ifndef JSON_VALUE_USE_INTERNAL_MAP + const Value::CZString czstring = (*current_).first; + if ( !czstring.c_str() ) + return czstring.index(); + return Value::UInt( -1 ); +#else + if ( isArray_ ) + return Value::UInt( ValueInternalArray::indexOf( iterator_.array_ ) ); + return Value::UInt( -1 ); +#endif +} + + +const char * +ValueIteratorBase::memberName() const +{ +#ifndef JSON_VALUE_USE_INTERNAL_MAP + const char *name = (*current_).first.c_str(); + return name ? name : ""; +#else + if ( !isArray_ ) + return ValueInternalMap::key( iterator_.map_ ); + return ""; +#endif +} + + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class ValueConstIterator +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +ValueConstIterator::ValueConstIterator() +{ +} + + +#ifndef JSON_VALUE_USE_INTERNAL_MAP +ValueConstIterator::ValueConstIterator( const Value::ObjectValues::iterator ¤t ) + : ValueIteratorBase( current ) +{ +} +#else +ValueConstIterator::ValueConstIterator( const ValueInternalArray::IteratorState &state ) + : ValueIteratorBase( state ) +{ +} + +ValueConstIterator::ValueConstIterator( const ValueInternalMap::IteratorState &state ) + : ValueIteratorBase( state ) +{ +} +#endif + +ValueConstIterator & +ValueConstIterator::operator =( const ValueIteratorBase &other ) +{ + copy( other ); + return *this; +} + + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class ValueIterator +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +ValueIterator::ValueIterator() +{ +} + + +#ifndef JSON_VALUE_USE_INTERNAL_MAP +ValueIterator::ValueIterator( const Value::ObjectValues::iterator ¤t ) + : ValueIteratorBase( current ) +{ +} +#else +ValueIterator::ValueIterator( const ValueInternalArray::IteratorState &state ) + : ValueIteratorBase( state ) +{ +} + +ValueIterator::ValueIterator( const ValueInternalMap::IteratorState &state ) + : ValueIteratorBase( state ) +{ +} +#endif + +ValueIterator::ValueIterator( const ValueConstIterator &other ) + : ValueIteratorBase( other ) +{ +} + +ValueIterator::ValueIterator( const ValueIterator &other ) + : ValueIteratorBase( other ) +{ +} + +ValueIterator & +ValueIterator::operator =( const SelfType &other ) +{ + copy( other ); + return *this; +} + +} // namespace Json + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: src/lib_json/json_valueiterator.inl +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: src/lib_json/json_value.cpp +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#if !defined(JSON_IS_AMALGAMATION) +# include +# include +# ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR +# include "json_batchallocator.h" +# endif // #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include +#include +#ifdef JSON_USE_CPPTL +# include +#endif +#include // size_t + +#define JSON_ASSERT_UNREACHABLE assert( false ) +#define JSON_ASSERT( condition ) assert( condition ); // @todo <= change this into an exception throw +#define JSON_FAIL_MESSAGE( message ) throw std::runtime_error( message ); +#define JSON_ASSERT_MESSAGE( condition, message ) if (!( condition )) JSON_FAIL_MESSAGE( message ) + +namespace Json { + +const Value Value::null; +const Int Value::minInt = Int( ~(UInt(-1)/2) ); +const Int Value::maxInt = Int( UInt(-1)/2 ); +const UInt Value::maxUInt = UInt(-1); +const Int64 Value::minInt64 = Int64( ~(UInt64(-1)/2) ); +const Int64 Value::maxInt64 = Int64( UInt64(-1)/2 ); +const UInt64 Value::maxUInt64 = UInt64(-1); +const LargestInt Value::minLargestInt = LargestInt( ~(LargestUInt(-1)/2) ); +const LargestInt Value::maxLargestInt = LargestInt( LargestUInt(-1)/2 ); +const LargestUInt Value::maxLargestUInt = LargestUInt(-1); + + +/// Unknown size marker +static const unsigned int unknown = (unsigned)-1; + + +/** Duplicates the specified string value. + * @param value Pointer to the string to duplicate. Must be zero-terminated if + * length is "unknown". + * @param length Length of the value. if equals to unknown, then it will be + * computed using strlen(value). + * @return Pointer on the duplicate instance of string. + */ +static inline char * +duplicateStringValue( const char *value, + unsigned int length = unknown ) +{ + if ( length == unknown ) + length = (unsigned int)strlen(value); + char *newString = static_cast( malloc( length + 1 ) ); + JSON_ASSERT_MESSAGE( newString != 0, "Failed to allocate string value buffer" ); + memcpy( newString, value, length ); + newString[length] = 0; + return newString; +} + + +/** Free the string duplicated by duplicateStringValue(). + */ +static inline void +releaseStringValue( char *value ) +{ + if ( value ) + free( value ); +} + +} // namespace Json + + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ValueInternals... +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +#if !defined(JSON_IS_AMALGAMATION) +# ifdef JSON_VALUE_USE_INTERNAL_MAP +# include "json_internalarray.inl" +# include "json_internalmap.inl" +# endif // JSON_VALUE_USE_INTERNAL_MAP + +# include "json_valueiterator.inl" +#endif // if !defined(JSON_IS_AMALGAMATION) + +namespace Json { + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class Value::CommentInfo +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + + +Value::CommentInfo::CommentInfo() + : comment_( 0 ) +{ +} + +Value::CommentInfo::~CommentInfo() +{ + if ( comment_ ) + releaseStringValue( comment_ ); +} + + +void +Value::CommentInfo::setComment( const char *text ) +{ + if ( comment_ ) + releaseStringValue( comment_ ); + JSON_ASSERT( text != 0 ); + JSON_ASSERT_MESSAGE( text[0]=='\0' || text[0]=='/', "Comments must start with /"); + // It seems that /**/ style comments are acceptable as well. + comment_ = duplicateStringValue( text ); +} + + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class Value::CZString +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +# ifndef JSON_VALUE_USE_INTERNAL_MAP + +// Notes: index_ indicates if the string was allocated when +// a string is stored. + +Value::CZString::CZString( ArrayIndex index ) + : cstr_( 0 ) + , index_( index ) +{ +} + +Value::CZString::CZString( const char *cstr, DuplicationPolicy allocate ) + : cstr_( allocate == duplicate ? duplicateStringValue(cstr) + : cstr ) + , index_( allocate ) +{ +} + +Value::CZString::CZString( const CZString &other ) +: cstr_( other.index_ != noDuplication && other.cstr_ != 0 + ? duplicateStringValue( other.cstr_ ) + : other.cstr_ ) + , index_( other.cstr_ ? (other.index_ == noDuplication ? noDuplication : duplicate) + : other.index_ ) +{ +} + +Value::CZString::~CZString() +{ + if ( cstr_ && index_ == duplicate ) + releaseStringValue( const_cast( cstr_ ) ); +} + +void +Value::CZString::swap( CZString &other ) +{ + std::swap( cstr_, other.cstr_ ); + std::swap( index_, other.index_ ); +} + +Value::CZString & +Value::CZString::operator =( const CZString &other ) +{ + CZString temp( other ); + swap( temp ); + return *this; +} + +bool +Value::CZString::operator<( const CZString &other ) const +{ + if ( cstr_ ) + return strcmp( cstr_, other.cstr_ ) < 0; + return index_ < other.index_; +} + +bool +Value::CZString::operator==( const CZString &other ) const +{ + if ( cstr_ ) + return strcmp( cstr_, other.cstr_ ) == 0; + return index_ == other.index_; +} + + +ArrayIndex +Value::CZString::index() const +{ + return index_; +} + + +const char * +Value::CZString::c_str() const +{ + return cstr_; +} + +bool +Value::CZString::isStaticString() const +{ + return index_ == noDuplication; +} + +#endif // ifndef JSON_VALUE_USE_INTERNAL_MAP + + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class Value::Value +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +/*! \internal Default constructor initialization must be equivalent to: + * memset( this, 0, sizeof(Value) ) + * This optimization is used in ValueInternalMap fast allocator. + */ +Value::Value( ValueType type ) + : type_( type ) + , allocated_( 0 ) + , comments_( 0 ) +# ifdef JSON_VALUE_USE_INTERNAL_MAP + , itemIsUsed_( 0 ) +#endif +{ + switch ( type ) + { + case nullValue: + break; + case intValue: + case uintValue: + value_.int_ = 0; + break; + case realValue: + value_.real_ = 0.0; + break; + case stringValue: + value_.string_ = 0; + break; +#ifndef JSON_VALUE_USE_INTERNAL_MAP + case arrayValue: + case objectValue: + value_.map_ = new ObjectValues(); + break; +#else + case arrayValue: + value_.array_ = arrayAllocator()->newArray(); + break; + case objectValue: + value_.map_ = mapAllocator()->newMap(); + break; +#endif + case booleanValue: + value_.bool_ = false; + break; + default: + JSON_ASSERT_UNREACHABLE; + } +} + + +#if defined(JSON_HAS_INT64) +Value::Value( UInt value ) + : type_( uintValue ) + , comments_( 0 ) +# ifdef JSON_VALUE_USE_INTERNAL_MAP + , itemIsUsed_( 0 ) +#endif +{ + value_.uint_ = value; +} + +Value::Value( Int value ) + : type_( intValue ) + , comments_( 0 ) +# ifdef JSON_VALUE_USE_INTERNAL_MAP + , itemIsUsed_( 0 ) +#endif +{ + value_.int_ = value; +} + +#endif // if defined(JSON_HAS_INT64) + + +Value::Value( Int64 value ) + : type_( intValue ) + , comments_( 0 ) +# ifdef JSON_VALUE_USE_INTERNAL_MAP + , itemIsUsed_( 0 ) +#endif +{ + value_.int_ = value; +} + + +Value::Value( UInt64 value ) + : type_( uintValue ) + , comments_( 0 ) +# ifdef JSON_VALUE_USE_INTERNAL_MAP + , itemIsUsed_( 0 ) +#endif +{ + value_.uint_ = value; +} + +Value::Value( double value ) + : type_( realValue ) + , comments_( 0 ) +# ifdef JSON_VALUE_USE_INTERNAL_MAP + , itemIsUsed_( 0 ) +#endif +{ + value_.real_ = value; +} + +Value::Value( const char *value ) + : type_( stringValue ) + , allocated_( true ) + , comments_( 0 ) +# ifdef JSON_VALUE_USE_INTERNAL_MAP + , itemIsUsed_( 0 ) +#endif +{ + value_.string_ = duplicateStringValue( value ); +} + + +Value::Value( const char *beginValue, + const char *endValue ) + : type_( stringValue ) + , allocated_( true ) + , comments_( 0 ) +# ifdef JSON_VALUE_USE_INTERNAL_MAP + , itemIsUsed_( 0 ) +#endif +{ + value_.string_ = duplicateStringValue( beginValue, + (unsigned int)(endValue - beginValue) ); +} + + +Value::Value( const std::string &value ) + : type_( stringValue ) + , allocated_( true ) + , comments_( 0 ) +# ifdef JSON_VALUE_USE_INTERNAL_MAP + , itemIsUsed_( 0 ) +#endif +{ + value_.string_ = duplicateStringValue( value.c_str(), + (unsigned int)value.length() ); + +} + +Value::Value( const StaticString &value ) + : type_( stringValue ) + , allocated_( false ) + , comments_( 0 ) +# ifdef JSON_VALUE_USE_INTERNAL_MAP + , itemIsUsed_( 0 ) +#endif +{ + value_.string_ = const_cast( value.c_str() ); +} + + +# ifdef JSON_USE_CPPTL +Value::Value( const CppTL::ConstString &value ) + : type_( stringValue ) + , allocated_( true ) + , comments_( 0 ) +# ifdef JSON_VALUE_USE_INTERNAL_MAP + , itemIsUsed_( 0 ) +#endif +{ + value_.string_ = duplicateStringValue( value, value.length() ); +} +# endif + +Value::Value( bool value ) + : type_( booleanValue ) + , comments_( 0 ) +# ifdef JSON_VALUE_USE_INTERNAL_MAP + , itemIsUsed_( 0 ) +#endif +{ + value_.bool_ = value; +} + + +Value::Value( const Value &other ) + : type_( other.type_ ) + , comments_( 0 ) +# ifdef JSON_VALUE_USE_INTERNAL_MAP + , itemIsUsed_( 0 ) +#endif +{ + switch ( type_ ) + { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + value_ = other.value_; + break; + case stringValue: + if ( other.value_.string_ ) + { + value_.string_ = duplicateStringValue( other.value_.string_ ); + allocated_ = true; + } + else + value_.string_ = 0; + break; +#ifndef JSON_VALUE_USE_INTERNAL_MAP + case arrayValue: + case objectValue: + value_.map_ = new ObjectValues( *other.value_.map_ ); + break; +#else + case arrayValue: + value_.array_ = arrayAllocator()->newArrayCopy( *other.value_.array_ ); + break; + case objectValue: + value_.map_ = mapAllocator()->newMapCopy( *other.value_.map_ ); + break; +#endif + default: + JSON_ASSERT_UNREACHABLE; + } + if ( other.comments_ ) + { + comments_ = new CommentInfo[numberOfCommentPlacement]; + for ( int comment =0; comment < numberOfCommentPlacement; ++comment ) + { + const CommentInfo &otherComment = other.comments_[comment]; + if ( otherComment.comment_ ) + comments_[comment].setComment( otherComment.comment_ ); + } + } +} + + +Value::~Value() +{ + switch ( type_ ) + { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + break; + case stringValue: + if ( allocated_ ) + releaseStringValue( value_.string_ ); + break; +#ifndef JSON_VALUE_USE_INTERNAL_MAP + case arrayValue: + case objectValue: + delete value_.map_; + break; +#else + case arrayValue: + arrayAllocator()->destructArray( value_.array_ ); + break; + case objectValue: + mapAllocator()->destructMap( value_.map_ ); + break; +#endif + default: + JSON_ASSERT_UNREACHABLE; + } + + if ( comments_ ) + delete[] comments_; +} + +Value & +Value::operator=( const Value &other ) +{ + Value temp( other ); + swap( temp ); + return *this; +} + +void +Value::swap( Value &other ) +{ + ValueType temp = type_; + type_ = other.type_; + other.type_ = temp; + std::swap( value_, other.value_ ); + int temp2 = allocated_; + allocated_ = other.allocated_; + other.allocated_ = temp2; +} + +ValueType +Value::type() const +{ + return type_; +} + + +int +Value::compare( const Value &other ) const +{ + if ( *this < other ) + return -1; + if ( *this > other ) + return 1; + return 0; +} + + +bool +Value::operator <( const Value &other ) const +{ + int typeDelta = type_ - other.type_; + if ( typeDelta ) + return typeDelta < 0 ? true : false; + switch ( type_ ) + { + case nullValue: + return false; + case intValue: + return value_.int_ < other.value_.int_; + case uintValue: + return value_.uint_ < other.value_.uint_; + case realValue: + return value_.real_ < other.value_.real_; + case booleanValue: + return value_.bool_ < other.value_.bool_; + case stringValue: + return ( value_.string_ == 0 && other.value_.string_ ) + || ( other.value_.string_ + && value_.string_ + && strcmp( value_.string_, other.value_.string_ ) < 0 ); +#ifndef JSON_VALUE_USE_INTERNAL_MAP + case arrayValue: + case objectValue: + { + int delta = int( value_.map_->size() - other.value_.map_->size() ); + if ( delta ) + return delta < 0; + return (*value_.map_) < (*other.value_.map_); + } +#else + case arrayValue: + return value_.array_->compare( *(other.value_.array_) ) < 0; + case objectValue: + return value_.map_->compare( *(other.value_.map_) ) < 0; +#endif + default: + JSON_ASSERT_UNREACHABLE; + } + return false; // unreachable +} + +bool +Value::operator <=( const Value &other ) const +{ + return !(other < *this); +} + +bool +Value::operator >=( const Value &other ) const +{ + return !(*this < other); +} + +bool +Value::operator >( const Value &other ) const +{ + return other < *this; +} + +bool +Value::operator ==( const Value &other ) const +{ + //if ( type_ != other.type_ ) + // GCC 2.95.3 says: + // attempt to take address of bit-field structure member `Json::Value::type_' + // Beats me, but a temp solves the problem. + int temp = other.type_; + if ( type_ != temp ) + return false; + switch ( type_ ) + { + case nullValue: + return true; + case intValue: + return value_.int_ == other.value_.int_; + case uintValue: + return value_.uint_ == other.value_.uint_; + case realValue: + return value_.real_ == other.value_.real_; + case booleanValue: + return value_.bool_ == other.value_.bool_; + case stringValue: + return ( value_.string_ == other.value_.string_ ) + || ( other.value_.string_ + && value_.string_ + && strcmp( value_.string_, other.value_.string_ ) == 0 ); +#ifndef JSON_VALUE_USE_INTERNAL_MAP + case arrayValue: + case objectValue: + return value_.map_->size() == other.value_.map_->size() + && (*value_.map_) == (*other.value_.map_); +#else + case arrayValue: + return value_.array_->compare( *(other.value_.array_) ) == 0; + case objectValue: + return value_.map_->compare( *(other.value_.map_) ) == 0; +#endif + default: + JSON_ASSERT_UNREACHABLE; + } + return false; // unreachable +} + +bool +Value::operator !=( const Value &other ) const +{ + return !( *this == other ); +} + +const char * +Value::asCString() const +{ + JSON_ASSERT( type_ == stringValue ); + return value_.string_; +} + + +std::string +Value::asString() const +{ + switch ( type_ ) + { + case nullValue: + return ""; + case stringValue: + return value_.string_ ? value_.string_ : ""; + case booleanValue: + return value_.bool_ ? "true" : "false"; + case intValue: + case uintValue: + case realValue: + case arrayValue: + case objectValue: + JSON_FAIL_MESSAGE( "Type is not convertible to string" ); + default: + JSON_ASSERT_UNREACHABLE; + } + return ""; // unreachable +} + +# ifdef JSON_USE_CPPTL +CppTL::ConstString +Value::asConstString() const +{ + return CppTL::ConstString( asString().c_str() ); +} +# endif + + +Value::Int +Value::asInt() const +{ + switch ( type_ ) + { + case nullValue: + return 0; + case intValue: + JSON_ASSERT_MESSAGE( value_.int_ >= minInt && value_.int_ <= maxInt, "unsigned integer out of signed int range" ); + return Int(value_.int_); + case uintValue: + JSON_ASSERT_MESSAGE( value_.uint_ <= UInt(maxInt), "unsigned integer out of signed int range" ); + return Int(value_.uint_); + case realValue: + JSON_ASSERT_MESSAGE( value_.real_ >= minInt && value_.real_ <= maxInt, "Real out of signed integer range" ); + return Int( value_.real_ ); + case booleanValue: + return value_.bool_ ? 1 : 0; + case stringValue: + case arrayValue: + case objectValue: + JSON_FAIL_MESSAGE( "Type is not convertible to int" ); + default: + JSON_ASSERT_UNREACHABLE; + } + return 0; // unreachable; +} + + +Value::UInt +Value::asUInt() const +{ + switch ( type_ ) + { + case nullValue: + return 0; + case intValue: + JSON_ASSERT_MESSAGE( value_.int_ >= 0, "Negative integer can not be converted to unsigned integer" ); + JSON_ASSERT_MESSAGE( value_.int_ <= maxUInt, "signed integer out of UInt range" ); + return UInt(value_.int_); + case uintValue: + JSON_ASSERT_MESSAGE( value_.uint_ <= maxUInt, "unsigned integer out of UInt range" ); + return UInt(value_.uint_); + case realValue: + JSON_ASSERT_MESSAGE( value_.real_ >= 0 && value_.real_ <= maxUInt, "Real out of unsigned integer range" ); + return UInt( value_.real_ ); + case booleanValue: + return value_.bool_ ? 1 : 0; + case stringValue: + case arrayValue: + case objectValue: + JSON_FAIL_MESSAGE( "Type is not convertible to uint" ); + default: + JSON_ASSERT_UNREACHABLE; + } + return 0; // unreachable; +} + + +# if defined(JSON_HAS_INT64) + +Value::Int64 +Value::asInt64() const +{ + switch ( type_ ) + { + case nullValue: + return 0; + case intValue: + return value_.int_; + case uintValue: + JSON_ASSERT_MESSAGE( value_.uint_ <= UInt64(maxInt64), "unsigned integer out of Int64 range" ); + return value_.uint_; + case realValue: + JSON_ASSERT_MESSAGE( value_.real_ >= minInt64 && value_.real_ <= maxInt64, "Real out of Int64 range" ); + return Int( value_.real_ ); + case booleanValue: + return value_.bool_ ? 1 : 0; + case stringValue: + case arrayValue: + case objectValue: + JSON_FAIL_MESSAGE( "Type is not convertible to Int64" ); + default: + JSON_ASSERT_UNREACHABLE; + } + return 0; // unreachable; +} + + +Value::UInt64 +Value::asUInt64() const +{ + switch ( type_ ) + { + case nullValue: + return 0; + case intValue: + JSON_ASSERT_MESSAGE( value_.int_ >= 0, "Negative integer can not be converted to UInt64" ); + return value_.int_; + case uintValue: + return value_.uint_; + case realValue: + JSON_ASSERT_MESSAGE( value_.real_ >= 0 && value_.real_ <= maxUInt64, "Real out of UInt64 range" ); + return UInt( value_.real_ ); + case booleanValue: + return value_.bool_ ? 1 : 0; + case stringValue: + case arrayValue: + case objectValue: + JSON_FAIL_MESSAGE( "Type is not convertible to UInt64" ); + default: + JSON_ASSERT_UNREACHABLE; + } + return 0; // unreachable; +} +# endif // if defined(JSON_HAS_INT64) + + +LargestInt +Value::asLargestInt() const +{ +#if defined(JSON_NO_INT64) + return asInt(); +#else + return asInt64(); +#endif +} + + +LargestUInt +Value::asLargestUInt() const +{ +#if defined(JSON_NO_INT64) + return asUInt(); +#else + return asUInt64(); +#endif +} + + +double +Value::asDouble() const +{ + switch ( type_ ) + { + case nullValue: + return 0.0; + case intValue: + return static_cast( value_.int_ ); + case uintValue: +#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + return static_cast( value_.uint_ ); +#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + return static_cast( Int(value_.uint_/2) ) * 2 + Int(value_.uint_ & 1); +#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + case realValue: + return value_.real_; + case booleanValue: + return value_.bool_ ? 1.0 : 0.0; + case stringValue: + case arrayValue: + case objectValue: + JSON_FAIL_MESSAGE( "Type is not convertible to double" ); + default: + JSON_ASSERT_UNREACHABLE; + } + return 0; // unreachable; +} + +float +Value::asFloat() const +{ + switch ( type_ ) + { + case nullValue: + return 0.0f; + case intValue: + return static_cast( value_.int_ ); + case uintValue: +#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + return static_cast( value_.uint_ ); +#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + return static_cast( Int(value_.uint_/2) ) * 2 + Int(value_.uint_ & 1); +#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + case realValue: + return static_cast( value_.real_ ); + case booleanValue: + return value_.bool_ ? 1.0f : 0.0f; + case stringValue: + case arrayValue: + case objectValue: + JSON_FAIL_MESSAGE( "Type is not convertible to float" ); + default: + JSON_ASSERT_UNREACHABLE; + } + return 0.0f; // unreachable; +} + +bool +Value::asBool() const +{ + switch ( type_ ) + { + case nullValue: + return false; + case intValue: + case uintValue: + return value_.int_ != 0; + case realValue: + return value_.real_ != 0.0; + case booleanValue: + return value_.bool_; + case stringValue: + return value_.string_ && value_.string_[0] != 0; + case arrayValue: + case objectValue: + return value_.map_->size() != 0; + default: + JSON_ASSERT_UNREACHABLE; + } + return false; // unreachable; +} + + +bool +Value::isConvertibleTo( ValueType other ) const +{ + switch ( type_ ) + { + case nullValue: + return true; + case intValue: + return ( other == nullValue && value_.int_ == 0 ) + || other == intValue + || ( other == uintValue && value_.int_ >= 0 ) + || other == realValue + || other == stringValue + || other == booleanValue; + case uintValue: + return ( other == nullValue && value_.uint_ == 0 ) + || ( other == intValue && value_.uint_ <= (unsigned)maxInt ) + || other == uintValue + || other == realValue + || other == stringValue + || other == booleanValue; + case realValue: + return ( other == nullValue && value_.real_ == 0.0 ) + || ( other == intValue && value_.real_ >= minInt && value_.real_ <= maxInt ) + || ( other == uintValue && value_.real_ >= 0 && value_.real_ <= maxUInt ) + || other == realValue + || other == stringValue + || other == booleanValue; + case booleanValue: + return ( other == nullValue && value_.bool_ == false ) + || other == intValue + || other == uintValue + || other == realValue + || other == stringValue + || other == booleanValue; + case stringValue: + return other == stringValue + || ( other == nullValue && (!value_.string_ || value_.string_[0] == 0) ); + case arrayValue: + return other == arrayValue + || ( other == nullValue && value_.map_->size() == 0 ); + case objectValue: + return other == objectValue + || ( other == nullValue && value_.map_->size() == 0 ); + default: + JSON_ASSERT_UNREACHABLE; + } + return false; // unreachable; +} + + +/// Number of values in array or object +ArrayIndex +Value::size() const +{ + switch ( type_ ) + { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + case stringValue: + return 0; +#ifndef JSON_VALUE_USE_INTERNAL_MAP + case arrayValue: // size of the array is highest index + 1 + if ( !value_.map_->empty() ) + { + ObjectValues::const_iterator itLast = value_.map_->end(); + --itLast; + return (*itLast).first.index()+1; + } + return 0; + case objectValue: + return ArrayIndex( value_.map_->size() ); +#else + case arrayValue: + return Int( value_.array_->size() ); + case objectValue: + return Int( value_.map_->size() ); +#endif + default: + JSON_ASSERT_UNREACHABLE; + } + return 0; // unreachable; +} + + +bool +Value::empty() const +{ + if ( isNull() || isArray() || isObject() ) + return size() == 0u; + else + return false; +} + + +bool +Value::operator!() const +{ + return isNull(); +} + + +void +Value::clear() +{ + JSON_ASSERT( type_ == nullValue || type_ == arrayValue || type_ == objectValue ); + + switch ( type_ ) + { +#ifndef JSON_VALUE_USE_INTERNAL_MAP + case arrayValue: + case objectValue: + value_.map_->clear(); + break; +#else + case arrayValue: + value_.array_->clear(); + break; + case objectValue: + value_.map_->clear(); + break; +#endif + default: + break; + } +} + +void +Value::resize( ArrayIndex newSize ) +{ + JSON_ASSERT( type_ == nullValue || type_ == arrayValue ); + if ( type_ == nullValue ) + *this = Value( arrayValue ); +#ifndef JSON_VALUE_USE_INTERNAL_MAP + ArrayIndex oldSize = size(); + if ( newSize == 0 ) + clear(); + else if ( newSize > oldSize ) + (*this)[ newSize - 1 ]; + else + { + for ( ArrayIndex index = newSize; index < oldSize; ++index ) + { + value_.map_->erase( index ); + } + assert( size() == newSize ); + } +#else + value_.array_->resize( newSize ); +#endif +} + + +Value & +Value::operator[]( ArrayIndex index ) +{ + JSON_ASSERT( type_ == nullValue || type_ == arrayValue ); + if ( type_ == nullValue ) + *this = Value( arrayValue ); +#ifndef JSON_VALUE_USE_INTERNAL_MAP + CZString key( index ); + ObjectValues::iterator it = value_.map_->lower_bound( key ); + if ( it != value_.map_->end() && (*it).first == key ) + return (*it).second; + + ObjectValues::value_type defaultValue( key, null ); + it = value_.map_->insert( it, defaultValue ); + return (*it).second; +#else + return value_.array_->resolveReference( index ); +#endif +} + + +Value & +Value::operator[]( int index ) +{ + JSON_ASSERT( index >= 0 ); + return (*this)[ ArrayIndex(index) ]; +} + + +const Value & +Value::operator[]( ArrayIndex index ) const +{ + JSON_ASSERT( type_ == nullValue || type_ == arrayValue ); + if ( type_ == nullValue ) + return null; +#ifndef JSON_VALUE_USE_INTERNAL_MAP + CZString key( index ); + ObjectValues::const_iterator it = value_.map_->find( key ); + if ( it == value_.map_->end() ) + return null; + return (*it).second; +#else + Value *value = value_.array_->find( index ); + return value ? *value : null; +#endif +} + + +const Value & +Value::operator[]( int index ) const +{ + JSON_ASSERT( index >= 0 ); + return (*this)[ ArrayIndex(index) ]; +} + + +Value & +Value::operator[]( const char *key ) +{ + return resolveReference( key, false ); +} + + +Value & +Value::resolveReference( const char *key, + bool isStatic ) +{ + JSON_ASSERT( type_ == nullValue || type_ == objectValue ); + if ( type_ == nullValue ) + *this = Value( objectValue ); +#ifndef JSON_VALUE_USE_INTERNAL_MAP + CZString actualKey( key, isStatic ? CZString::noDuplication + : CZString::duplicateOnCopy ); + ObjectValues::iterator it = value_.map_->lower_bound( actualKey ); + if ( it != value_.map_->end() && (*it).first == actualKey ) + return (*it).second; + + ObjectValues::value_type defaultValue( actualKey, null ); + it = value_.map_->insert( it, defaultValue ); + Value &value = (*it).second; + return value; +#else + return value_.map_->resolveReference( key, isStatic ); +#endif +} + + +Value +Value::get( ArrayIndex index, + const Value &defaultValue ) const +{ + const Value *value = &((*this)[index]); + return value == &null ? defaultValue : *value; +} + + +bool +Value::isValidIndex( ArrayIndex index ) const +{ + return index < size(); +} + + + +const Value & +Value::operator[]( const char *key ) const +{ + JSON_ASSERT( type_ == nullValue || type_ == objectValue ); + if ( type_ == nullValue ) + return null; +#ifndef JSON_VALUE_USE_INTERNAL_MAP + CZString actualKey( key, CZString::noDuplication ); + ObjectValues::const_iterator it = value_.map_->find( actualKey ); + if ( it == value_.map_->end() ) + return null; + return (*it).second; +#else + const Value *value = value_.map_->find( key ); + return value ? *value : null; +#endif +} + + +Value & +Value::operator[]( const std::string &key ) +{ + return (*this)[ key.c_str() ]; +} + + +const Value & +Value::operator[]( const std::string &key ) const +{ + return (*this)[ key.c_str() ]; +} + +Value & +Value::operator[]( const StaticString &key ) +{ + return resolveReference( key, true ); +} + + +# ifdef JSON_USE_CPPTL +Value & +Value::operator[]( const CppTL::ConstString &key ) +{ + return (*this)[ key.c_str() ]; +} + + +const Value & +Value::operator[]( const CppTL::ConstString &key ) const +{ + return (*this)[ key.c_str() ]; +} +# endif + + +Value & +Value::append( const Value &value ) +{ + return (*this)[size()] = value; +} + + +Value +Value::get( const char *key, + const Value &defaultValue ) const +{ + const Value *value = &((*this)[key]); + return value == &null ? defaultValue : *value; +} + + +Value +Value::get( const std::string &key, + const Value &defaultValue ) const +{ + return get( key.c_str(), defaultValue ); +} + +Value +Value::removeMember( const char* key ) +{ + JSON_ASSERT( type_ == nullValue || type_ == objectValue ); + if ( type_ == nullValue ) + return null; +#ifndef JSON_VALUE_USE_INTERNAL_MAP + CZString actualKey( key, CZString::noDuplication ); + ObjectValues::iterator it = value_.map_->find( actualKey ); + if ( it == value_.map_->end() ) + return null; + Value old(it->second); + value_.map_->erase(it); + return old; +#else + Value *value = value_.map_->find( key ); + if (value){ + Value old(*value); + value_.map_.remove( key ); + return old; + } else { + return null; + } +#endif +} + +Value +Value::removeMember( const std::string &key ) +{ + return removeMember( key.c_str() ); +} + +# ifdef JSON_USE_CPPTL +Value +Value::get( const CppTL::ConstString &key, + const Value &defaultValue ) const +{ + return get( key.c_str(), defaultValue ); +} +# endif + +bool +Value::isMember( const char *key ) const +{ + const Value *value = &((*this)[key]); + return value != &null; +} + + +bool +Value::isMember( const std::string &key ) const +{ + return isMember( key.c_str() ); +} + + +# ifdef JSON_USE_CPPTL +bool +Value::isMember( const CppTL::ConstString &key ) const +{ + return isMember( key.c_str() ); +} +#endif + +Value::Members +Value::getMemberNames() const +{ + JSON_ASSERT( type_ == nullValue || type_ == objectValue ); + if ( type_ == nullValue ) + return Value::Members(); + Members members; + members.reserve( value_.map_->size() ); +#ifndef JSON_VALUE_USE_INTERNAL_MAP + ObjectValues::const_iterator it = value_.map_->begin(); + ObjectValues::const_iterator itEnd = value_.map_->end(); + for ( ; it != itEnd; ++it ) + members.push_back( std::string( (*it).first.c_str() ) ); +#else + ValueInternalMap::IteratorState it; + ValueInternalMap::IteratorState itEnd; + value_.map_->makeBeginIterator( it ); + value_.map_->makeEndIterator( itEnd ); + for ( ; !ValueInternalMap::equals( it, itEnd ); ValueInternalMap::increment(it) ) + members.push_back( std::string( ValueInternalMap::key( it ) ) ); +#endif + return members; +} +// +//# ifdef JSON_USE_CPPTL +//EnumMemberNames +//Value::enumMemberNames() const +//{ +// if ( type_ == objectValue ) +// { +// return CppTL::Enum::any( CppTL::Enum::transform( +// CppTL::Enum::keys( *(value_.map_), CppTL::Type() ), +// MemberNamesTransform() ) ); +// } +// return EnumMemberNames(); +//} +// +// +//EnumValues +//Value::enumValues() const +//{ +// if ( type_ == objectValue || type_ == arrayValue ) +// return CppTL::Enum::anyValues( *(value_.map_), +// CppTL::Type() ); +// return EnumValues(); +//} +// +//# endif + + +bool +Value::isNull() const +{ + return type_ == nullValue; +} + + +bool +Value::isBool() const +{ + return type_ == booleanValue; +} + + +bool +Value::isInt() const +{ + return type_ == intValue; +} + + +bool +Value::isUInt() const +{ + return type_ == uintValue; +} + + +bool +Value::isIntegral() const +{ + return type_ == intValue + || type_ == uintValue + || type_ == booleanValue; +} + + +bool +Value::isDouble() const +{ + return type_ == realValue; +} + + +bool +Value::isNumeric() const +{ + return isIntegral() || isDouble(); +} + + +bool +Value::isString() const +{ + return type_ == stringValue; +} + + +bool +Value::isArray() const +{ + return type_ == nullValue || type_ == arrayValue; +} + + +bool +Value::isObject() const +{ + return type_ == nullValue || type_ == objectValue; +} + + +void +Value::setComment( const char *comment, + CommentPlacement placement ) +{ + if ( !comments_ ) + comments_ = new CommentInfo[numberOfCommentPlacement]; + comments_[placement].setComment( comment ); +} + + +void +Value::setComment( const std::string &comment, + CommentPlacement placement ) +{ + setComment( comment.c_str(), placement ); +} + + +bool +Value::hasComment( CommentPlacement placement ) const +{ + return comments_ != 0 && comments_[placement].comment_ != 0; +} + +std::string +Value::getComment( CommentPlacement placement ) const +{ + if ( hasComment(placement) ) + return comments_[placement].comment_; + return ""; +} + + +std::string +Value::toStyledString() const +{ + StyledWriter writer; + return writer.write( *this ); +} + + +Value::const_iterator +Value::begin() const +{ + switch ( type_ ) + { +#ifdef JSON_VALUE_USE_INTERNAL_MAP + case arrayValue: + if ( value_.array_ ) + { + ValueInternalArray::IteratorState it; + value_.array_->makeBeginIterator( it ); + return const_iterator( it ); + } + break; + case objectValue: + if ( value_.map_ ) + { + ValueInternalMap::IteratorState it; + value_.map_->makeBeginIterator( it ); + return const_iterator( it ); + } + break; +#else + case arrayValue: + case objectValue: + if ( value_.map_ ) + return const_iterator( value_.map_->begin() ); + break; +#endif + default: + break; + } + return const_iterator(); +} + +Value::const_iterator +Value::end() const +{ + switch ( type_ ) + { +#ifdef JSON_VALUE_USE_INTERNAL_MAP + case arrayValue: + if ( value_.array_ ) + { + ValueInternalArray::IteratorState it; + value_.array_->makeEndIterator( it ); + return const_iterator( it ); + } + break; + case objectValue: + if ( value_.map_ ) + { + ValueInternalMap::IteratorState it; + value_.map_->makeEndIterator( it ); + return const_iterator( it ); + } + break; +#else + case arrayValue: + case objectValue: + if ( value_.map_ ) + return const_iterator( value_.map_->end() ); + break; +#endif + default: + break; + } + return const_iterator(); +} + + +Value::iterator +Value::begin() +{ + switch ( type_ ) + { +#ifdef JSON_VALUE_USE_INTERNAL_MAP + case arrayValue: + if ( value_.array_ ) + { + ValueInternalArray::IteratorState it; + value_.array_->makeBeginIterator( it ); + return iterator( it ); + } + break; + case objectValue: + if ( value_.map_ ) + { + ValueInternalMap::IteratorState it; + value_.map_->makeBeginIterator( it ); + return iterator( it ); + } + break; +#else + case arrayValue: + case objectValue: + if ( value_.map_ ) + return iterator( value_.map_->begin() ); + break; +#endif + default: + break; + } + return iterator(); +} + +Value::iterator +Value::end() +{ + switch ( type_ ) + { +#ifdef JSON_VALUE_USE_INTERNAL_MAP + case arrayValue: + if ( value_.array_ ) + { + ValueInternalArray::IteratorState it; + value_.array_->makeEndIterator( it ); + return iterator( it ); + } + break; + case objectValue: + if ( value_.map_ ) + { + ValueInternalMap::IteratorState it; + value_.map_->makeEndIterator( it ); + return iterator( it ); + } + break; +#else + case arrayValue: + case objectValue: + if ( value_.map_ ) + return iterator( value_.map_->end() ); + break; +#endif + default: + break; + } + return iterator(); +} + + +// class PathArgument +// ////////////////////////////////////////////////////////////////// + +PathArgument::PathArgument() + : kind_( kindNone ) +{ +} + + +PathArgument::PathArgument( ArrayIndex index ) + : index_( index ) + , kind_( kindIndex ) +{ +} + + +PathArgument::PathArgument( const char *key ) + : key_( key ) + , kind_( kindKey ) +{ +} + + +PathArgument::PathArgument( const std::string &key ) + : key_( key.c_str() ) + , kind_( kindKey ) +{ +} + +// class Path +// ////////////////////////////////////////////////////////////////// + +Path::Path( const std::string &path, + const PathArgument &a1, + const PathArgument &a2, + const PathArgument &a3, + const PathArgument &a4, + const PathArgument &a5 ) +{ + InArgs in; + in.push_back( &a1 ); + in.push_back( &a2 ); + in.push_back( &a3 ); + in.push_back( &a4 ); + in.push_back( &a5 ); + makePath( path, in ); +} + + +void +Path::makePath( const std::string &path, + const InArgs &in ) +{ + const char *current = path.c_str(); + const char *end = current + path.length(); + InArgs::const_iterator itInArg = in.begin(); + while ( current != end ) + { + if ( *current == '[' ) + { + ++current; + if ( *current == '%' ) + addPathInArg( path, in, itInArg, PathArgument::kindIndex ); + else + { + ArrayIndex index = 0; + for ( ; current != end && *current >= '0' && *current <= '9'; ++current ) + index = index * 10 + ArrayIndex(*current - '0'); + args_.push_back( index ); + } + if ( current == end || *current++ != ']' ) + invalidPath( path, int(current - path.c_str()) ); + } + else if ( *current == '%' ) + { + addPathInArg( path, in, itInArg, PathArgument::kindKey ); + ++current; + } + else if ( *current == '.' ) + { + ++current; + } + else + { + const char *beginName = current; + while ( current != end && !strchr( "[.", *current ) ) + ++current; + args_.push_back( std::string( beginName, current ) ); + } + } +} + + +void +Path::addPathInArg( const std::string &path, + const InArgs &in, + InArgs::const_iterator &itInArg, + PathArgument::Kind kind ) +{ + if ( itInArg == in.end() ) + { + // Error: missing argument %d + } + else if ( (*itInArg)->kind_ != kind ) + { + // Error: bad argument type + } + else + { + args_.push_back( **itInArg ); + } +} + + +void +Path::invalidPath( const std::string &path, + int location ) +{ + // Error: invalid path. +} + + +const Value & +Path::resolve( const Value &root ) const +{ + const Value *node = &root; + for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it ) + { + const PathArgument &arg = *it; + if ( arg.kind_ == PathArgument::kindIndex ) + { + if ( !node->isArray() || node->isValidIndex( arg.index_ ) ) + { + // Error: unable to resolve path (array value expected at position... + } + node = &((*node)[arg.index_]); + } + else if ( arg.kind_ == PathArgument::kindKey ) + { + if ( !node->isObject() ) + { + // Error: unable to resolve path (object value expected at position...) + } + node = &((*node)[arg.key_]); + if ( node == &Value::null ) + { + // Error: unable to resolve path (object has no member named '' at position...) + } + } + } + return *node; +} + + +Value +Path::resolve( const Value &root, + const Value &defaultValue ) const +{ + const Value *node = &root; + for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it ) + { + const PathArgument &arg = *it; + if ( arg.kind_ == PathArgument::kindIndex ) + { + if ( !node->isArray() || node->isValidIndex( arg.index_ ) ) + return defaultValue; + node = &((*node)[arg.index_]); + } + else if ( arg.kind_ == PathArgument::kindKey ) + { + if ( !node->isObject() ) + return defaultValue; + node = &((*node)[arg.key_]); + if ( node == &Value::null ) + return defaultValue; + } + } + return *node; +} + + +Value & +Path::make( Value &root ) const +{ + Value *node = &root; + for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it ) + { + const PathArgument &arg = *it; + if ( arg.kind_ == PathArgument::kindIndex ) + { + if ( !node->isArray() ) + { + // Error: node is not an array at position ... + } + node = &((*node)[arg.index_]); + } + else if ( arg.kind_ == PathArgument::kindKey ) + { + if ( !node->isObject() ) + { + // Error: node is not an object at position... + } + node = &((*node)[arg.key_]); + } + } + return *node; +} + + +} // namespace Json + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: src/lib_json/json_value.cpp +// ////////////////////////////////////////////////////////////////////// + + + + + + +// ////////////////////////////////////////////////////////////////////// +// Beginning of content of file: src/lib_json/json_writer.cpp +// ////////////////////////////////////////////////////////////////////// + +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#if !defined(JSON_IS_AMALGAMATION) +# include +# include "json_tool.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include +#include +#include +#include + +#if _MSC_VER >= 1400 // VC++ 8.0 +#pragma warning( disable : 4996 ) // disable warning about strdup being deprecated. +#endif + +namespace Json { + +static bool containsControlCharacter( const char* str ) +{ + while ( *str ) + { + if ( isControlCharacter( *(str++) ) ) + return true; + } + return false; +} + + +std::string valueToString( LargestInt value ) +{ + UIntToStringBuffer buffer; + char *current = buffer + sizeof(buffer); + bool isNegative = value < 0; + if ( isNegative ) + value = -value; + uintToString( LargestUInt(value), current ); + if ( isNegative ) + *--current = '-'; + assert( current >= buffer ); + return current; +} + + +std::string valueToString( LargestUInt value ) +{ + UIntToStringBuffer buffer; + char *current = buffer + sizeof(buffer); + uintToString( value, current ); + assert( current >= buffer ); + return current; +} + +#if defined(JSON_HAS_INT64) + +std::string valueToString( Int value ) +{ + return valueToString( LargestInt(value) ); +} + + +std::string valueToString( UInt value ) +{ + return valueToString( LargestUInt(value) ); +} + +#endif // # if defined(JSON_HAS_INT64) + + +std::string valueToString( double value ) +{ + char buffer[32]; +#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with visual studio 2005 to avoid warning. + sprintf_s(buffer, sizeof(buffer), "%#.16g", value); +#else + sprintf(buffer, "%#.16g", value); +#endif + char* ch = buffer + strlen(buffer) - 1; + if (*ch != '0') return buffer; // nothing to truncate, so save time + while(ch > buffer && *ch == '0'){ + --ch; + } + char* last_nonzero = ch; + while(ch >= buffer){ + switch(*ch){ + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + --ch; + continue; + case '.': + // Truncate zeroes to save bytes in output, but keep one. + *(last_nonzero+2) = '\0'; + return buffer; + default: + return buffer; + } + } + return buffer; +} + + +std::string valueToString( bool value ) +{ + return value ? "true" : "false"; +} + +std::string valueToQuotedString( const char *value ) +{ + // Not sure how to handle unicode... + if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL && !containsControlCharacter( value )) + return std::string("\"") + value + "\""; + // We have to walk value and escape any special characters. + // Appending to std::string is not efficient, but this should be rare. + // (Note: forward slashes are *not* rare, but I am not escaping them.) + std::string::size_type maxsize = strlen(value)*2 + 3; // allescaped+quotes+NULL + std::string result; + result.reserve(maxsize); // to avoid lots of mallocs + result += "\""; + for (const char* c=value; *c != 0; ++c) + { + switch(*c) + { + case '\"': + result += "\\\""; + break; + case '\\': + result += "\\\\"; + break; + case '\b': + result += "\\b"; + break; + case '\f': + result += "\\f"; + break; + case '\n': + result += "\\n"; + break; + case '\r': + result += "\\r"; + break; + case '\t': + result += "\\t"; + break; + //case '/': + // Even though \/ is considered a legal escape in JSON, a bare + // slash is also legal, so I see no reason to escape it. + // (I hope I am not misunderstanding something. + // blep notes: actually escaping \/ may be useful in javascript to avoid (*c); + result += oss.str(); + } + else + { + result += *c; + } + break; + } + } + result += "\""; + return result; +} + +// Class Writer +// ////////////////////////////////////////////////////////////////// +Writer::~Writer() +{ +} + + +// Class FastWriter +// ////////////////////////////////////////////////////////////////// + +FastWriter::FastWriter() + : yamlCompatiblityEnabled_( false ) +{ +} + + +void +FastWriter::enableYAMLCompatibility() +{ + yamlCompatiblityEnabled_ = true; +} + + +std::string +FastWriter::write( const Value &root ) +{ + document_ = ""; + writeValue( root ); + document_ += "\n"; + return document_; +} + + +void +FastWriter::writeValue( const Value &value ) +{ + switch ( value.type() ) + { + case nullValue: + document_ += "null"; + break; + case intValue: + document_ += valueToString( value.asLargestInt() ); + break; + case uintValue: + document_ += valueToString( value.asLargestUInt() ); + break; + case realValue: + document_ += valueToString( value.asDouble() ); + break; + case stringValue: + document_ += valueToQuotedString( value.asCString() ); + break; + case booleanValue: + document_ += valueToString( value.asBool() ); + break; + case arrayValue: + { + document_ += "["; + int size = value.size(); + for ( int index =0; index < size; ++index ) + { + if ( index > 0 ) + document_ += ","; + writeValue( value[index] ); + } + document_ += "]"; + } + break; + case objectValue: + { + Value::Members members( value.getMemberNames() ); + document_ += "{"; + for ( Value::Members::iterator it = members.begin(); + it != members.end(); + ++it ) + { + const std::string &name = *it; + if ( it != members.begin() ) + document_ += ","; + document_ += valueToQuotedString( name.c_str() ); + document_ += yamlCompatiblityEnabled_ ? ": " + : ":"; + writeValue( value[name] ); + } + document_ += "}"; + } + break; + } +} + + +// Class StyledWriter +// ////////////////////////////////////////////////////////////////// + +StyledWriter::StyledWriter() + : rightMargin_( 74 ) + , indentSize_( 3 ) +{ +} + + +std::string +StyledWriter::write( const Value &root ) +{ + document_ = ""; + addChildValues_ = false; + indentString_ = ""; + writeCommentBeforeValue( root ); + writeValue( root ); + writeCommentAfterValueOnSameLine( root ); + document_ += "\n"; + return document_; +} + + +void +StyledWriter::writeValue( const Value &value ) +{ + switch ( value.type() ) + { + case nullValue: + pushValue( "null" ); + break; + case intValue: + pushValue( valueToString( value.asLargestInt() ) ); + break; + case uintValue: + pushValue( valueToString( value.asLargestUInt() ) ); + break; + case realValue: + pushValue( valueToString( value.asDouble() ) ); + break; + case stringValue: + pushValue( valueToQuotedString( value.asCString() ) ); + break; + case booleanValue: + pushValue( valueToString( value.asBool() ) ); + break; + case arrayValue: + writeArrayValue( value); + break; + case objectValue: + { + Value::Members members( value.getMemberNames() ); + if ( members.empty() ) + pushValue( "{}" ); + else + { + writeWithIndent( "{" ); + indent(); + Value::Members::iterator it = members.begin(); + for (;;) + { + const std::string &name = *it; + const Value &childValue = value[name]; + writeCommentBeforeValue( childValue ); + writeWithIndent( valueToQuotedString( name.c_str() ) ); + document_ += " : "; + writeValue( childValue ); + if ( ++it == members.end() ) + { + writeCommentAfterValueOnSameLine( childValue ); + break; + } + document_ += ","; + writeCommentAfterValueOnSameLine( childValue ); + } + unindent(); + writeWithIndent( "}" ); + } + } + break; + } +} + + +void +StyledWriter::writeArrayValue( const Value &value ) +{ + unsigned size = value.size(); + if ( size == 0 ) + pushValue( "[]" ); + else + { + bool isArrayMultiLine = isMultineArray( value ); + if ( isArrayMultiLine ) + { + writeWithIndent( "[" ); + indent(); + bool hasChildValue = !childValues_.empty(); + unsigned index =0; + for (;;) + { + const Value &childValue = value[index]; + writeCommentBeforeValue( childValue ); + if ( hasChildValue ) + writeWithIndent( childValues_[index] ); + else + { + writeIndent(); + writeValue( childValue ); + } + if ( ++index == size ) + { + writeCommentAfterValueOnSameLine( childValue ); + break; + } + document_ += ","; + writeCommentAfterValueOnSameLine( childValue ); + } + unindent(); + writeWithIndent( "]" ); + } + else // output on a single line + { + assert( childValues_.size() == size ); + document_ += "[ "; + for ( unsigned index =0; index < size; ++index ) + { + if ( index > 0 ) + document_ += ", "; + document_ += childValues_[index]; + } + document_ += " ]"; + } + } +} + + +bool +StyledWriter::isMultineArray( const Value &value ) +{ + int size = value.size(); + bool isMultiLine = size*3 >= rightMargin_ ; + childValues_.clear(); + for ( int index =0; index < size && !isMultiLine; ++index ) + { + const Value &childValue = value[index]; + isMultiLine = isMultiLine || + ( (childValue.isArray() || childValue.isObject()) && + childValue.size() > 0 ); + } + if ( !isMultiLine ) // check if line length > max line length + { + childValues_.reserve( size ); + addChildValues_ = true; + int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]' + for ( int index =0; index < size && !isMultiLine; ++index ) + { + writeValue( value[index] ); + lineLength += int( childValues_[index].length() ); + isMultiLine = isMultiLine && hasCommentForValue( value[index] ); + } + addChildValues_ = false; + isMultiLine = isMultiLine || lineLength >= rightMargin_; + } + return isMultiLine; +} + + +void +StyledWriter::pushValue( const std::string &value ) +{ + if ( addChildValues_ ) + childValues_.push_back( value ); + else + document_ += value; +} + + +void +StyledWriter::writeIndent() +{ + if ( !document_.empty() ) + { + char last = document_[document_.length()-1]; + if ( last == ' ' ) // already indented + return; + if ( last != '\n' ) // Comments may add new-line + document_ += '\n'; + } + document_ += indentString_; +} + + +void +StyledWriter::writeWithIndent( const std::string &value ) +{ + writeIndent(); + document_ += value; +} + + +void +StyledWriter::indent() +{ + indentString_ += std::string( indentSize_, ' ' ); +} + + +void +StyledWriter::unindent() +{ + assert( int(indentString_.size()) >= indentSize_ ); + indentString_.resize( indentString_.size() - indentSize_ ); +} + + +void +StyledWriter::writeCommentBeforeValue( const Value &root ) +{ + if ( !root.hasComment( commentBefore ) ) + return; + document_ += normalizeEOL( root.getComment( commentBefore ) ); + document_ += "\n"; +} + + +void +StyledWriter::writeCommentAfterValueOnSameLine( const Value &root ) +{ + if ( root.hasComment( commentAfterOnSameLine ) ) + document_ += " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) ); + + if ( root.hasComment( commentAfter ) ) + { + document_ += "\n"; + document_ += normalizeEOL( root.getComment( commentAfter ) ); + document_ += "\n"; + } +} + + +bool +StyledWriter::hasCommentForValue( const Value &value ) +{ + return value.hasComment( commentBefore ) + || value.hasComment( commentAfterOnSameLine ) + || value.hasComment( commentAfter ); +} + + +std::string +StyledWriter::normalizeEOL( const std::string &text ) +{ + std::string normalized; + normalized.reserve( text.length() ); + const char *begin = text.c_str(); + const char *end = begin + text.length(); + const char *current = begin; + while ( current != end ) + { + char c = *current++; + if ( c == '\r' ) // mac or dos EOL + { + if ( *current == '\n' ) // convert dos EOL + ++current; + normalized += '\n'; + } + else // handle unix EOL & other char + normalized += c; + } + return normalized; +} + + +// Class StyledStreamWriter +// ////////////////////////////////////////////////////////////////// + +StyledStreamWriter::StyledStreamWriter( std::string indentation ) + : document_(NULL) + , rightMargin_( 74 ) + , indentation_( indentation ) +{ +} + + +void +StyledStreamWriter::write( std::ostream &out, const Value &root ) +{ + document_ = &out; + addChildValues_ = false; + indentString_ = ""; + writeCommentBeforeValue( root ); + writeValue( root ); + writeCommentAfterValueOnSameLine( root ); + *document_ << "\n"; + document_ = NULL; // Forget the stream, for safety. +} + + +void +StyledStreamWriter::writeValue( const Value &value ) +{ + switch ( value.type() ) + { + case nullValue: + pushValue( "null" ); + break; + case intValue: + pushValue( valueToString( value.asLargestInt() ) ); + break; + case uintValue: + pushValue( valueToString( value.asLargestUInt() ) ); + break; + case realValue: + pushValue( valueToString( value.asDouble() ) ); + break; + case stringValue: + pushValue( valueToQuotedString( value.asCString() ) ); + break; + case booleanValue: + pushValue( valueToString( value.asBool() ) ); + break; + case arrayValue: + writeArrayValue( value); + break; + case objectValue: + { + Value::Members members( value.getMemberNames() ); + if ( members.empty() ) + pushValue( "{}" ); + else + { + writeWithIndent( "{" ); + indent(); + Value::Members::iterator it = members.begin(); + for (;;) + { + const std::string &name = *it; + const Value &childValue = value[name]; + writeCommentBeforeValue( childValue ); + writeWithIndent( valueToQuotedString( name.c_str() ) ); + *document_ << " : "; + writeValue( childValue ); + if ( ++it == members.end() ) + { + writeCommentAfterValueOnSameLine( childValue ); + break; + } + *document_ << ","; + writeCommentAfterValueOnSameLine( childValue ); + } + unindent(); + writeWithIndent( "}" ); + } + } + break; + } +} + + +void +StyledStreamWriter::writeArrayValue( const Value &value ) +{ + unsigned size = value.size(); + if ( size == 0 ) + pushValue( "[]" ); + else + { + bool isArrayMultiLine = isMultineArray( value ); + if ( isArrayMultiLine ) + { + writeWithIndent( "[" ); + indent(); + bool hasChildValue = !childValues_.empty(); + unsigned index =0; + for (;;) + { + const Value &childValue = value[index]; + writeCommentBeforeValue( childValue ); + if ( hasChildValue ) + writeWithIndent( childValues_[index] ); + else + { + writeIndent(); + writeValue( childValue ); + } + if ( ++index == size ) + { + writeCommentAfterValueOnSameLine( childValue ); + break; + } + *document_ << ","; + writeCommentAfterValueOnSameLine( childValue ); + } + unindent(); + writeWithIndent( "]" ); + } + else // output on a single line + { + assert( childValues_.size() == size ); + *document_ << "[ "; + for ( unsigned index =0; index < size; ++index ) + { + if ( index > 0 ) + *document_ << ", "; + *document_ << childValues_[index]; + } + *document_ << " ]"; + } + } +} + + +bool +StyledStreamWriter::isMultineArray( const Value &value ) +{ + int size = value.size(); + bool isMultiLine = size*3 >= rightMargin_ ; + childValues_.clear(); + for ( int index =0; index < size && !isMultiLine; ++index ) + { + const Value &childValue = value[index]; + isMultiLine = isMultiLine || + ( (childValue.isArray() || childValue.isObject()) && + childValue.size() > 0 ); + } + if ( !isMultiLine ) // check if line length > max line length + { + childValues_.reserve( size ); + addChildValues_ = true; + int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]' + for ( int index =0; index < size && !isMultiLine; ++index ) + { + writeValue( value[index] ); + lineLength += int( childValues_[index].length() ); + isMultiLine = isMultiLine && hasCommentForValue( value[index] ); + } + addChildValues_ = false; + isMultiLine = isMultiLine || lineLength >= rightMargin_; + } + return isMultiLine; +} + + +void +StyledStreamWriter::pushValue( const std::string &value ) +{ + if ( addChildValues_ ) + childValues_.push_back( value ); + else + *document_ << value; +} + + +void +StyledStreamWriter::writeIndent() +{ + /* + Some comments in this method would have been nice. ;-) + + if ( !document_.empty() ) + { + char last = document_[document_.length()-1]; + if ( last == ' ' ) // already indented + return; + if ( last != '\n' ) // Comments may add new-line + *document_ << '\n'; + } + */ + *document_ << '\n' << indentString_; +} + + +void +StyledStreamWriter::writeWithIndent( const std::string &value ) +{ + writeIndent(); + *document_ << value; +} + + +void +StyledStreamWriter::indent() +{ + indentString_ += indentation_; +} + + +void +StyledStreamWriter::unindent() +{ + assert( indentString_.size() >= indentation_.size() ); + indentString_.resize( indentString_.size() - indentation_.size() ); +} + + +void +StyledStreamWriter::writeCommentBeforeValue( const Value &root ) +{ + if ( !root.hasComment( commentBefore ) ) + return; + *document_ << normalizeEOL( root.getComment( commentBefore ) ); + *document_ << "\n"; +} + + +void +StyledStreamWriter::writeCommentAfterValueOnSameLine( const Value &root ) +{ + if ( root.hasComment( commentAfterOnSameLine ) ) + *document_ << " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) ); + + if ( root.hasComment( commentAfter ) ) + { + *document_ << "\n"; + *document_ << normalizeEOL( root.getComment( commentAfter ) ); + *document_ << "\n"; + } +} + + +bool +StyledStreamWriter::hasCommentForValue( const Value &value ) +{ + return value.hasComment( commentBefore ) + || value.hasComment( commentAfterOnSameLine ) + || value.hasComment( commentAfter ); +} + + +std::string +StyledStreamWriter::normalizeEOL( const std::string &text ) +{ + std::string normalized; + normalized.reserve( text.length() ); + const char *begin = text.c_str(); + const char *end = begin + text.length(); + const char *current = begin; + while ( current != end ) + { + char c = *current++; + if ( c == '\r' ) // mac or dos EOL + { + if ( *current == '\n' ) // convert dos EOL + ++current; + normalized += '\n'; + } + else // handle unix EOL & other char + normalized += c; + } + return normalized; +} + + +std::ostream& operator<<( std::ostream &sout, const Value &root ) +{ + Json::StyledStreamWriter writer; + writer.write(sout, root); + return sout; +} + + +} // namespace Json + +// ////////////////////////////////////////////////////////////////////// +// End of content of file: src/lib_json/json_writer.cpp +// ////////////////////////////////////////////////////////////////////// + + + + + diff --git a/cs142/lab09/main.cpp b/cs142/lab09/main.cpp new file mode 100644 index 0000000..049214b --- /dev/null +++ b/cs142/lab09/main.cpp @@ -0,0 +1,75 @@ +#include +#include +#include +#include + +using namespace std; + +#include "restaurant.h" +#include "tournament.h" +#include "io.h" + +int main() { + tournament t; + bool keep_going = true; + bool file_correct = false; + string input, input_file_name; + const string usage = "usage: iotest "; + while(!file_correct) { + cout << "please enter file name: "; + getline(cin, input); + ifstream inputs(input.c_str()); + if(inputs.good()) { + input_file_name = input; + file_correct = true; + } + else { + cerr << "incorrect file name" << endl; + } + } + t.populate_restaurants(input_file_name); + bool succeful_pop = false; + while(keep_going) { + cout << "1)Display all restaurants\n2)Add a restaurant\n3)Remove a restaurant" << endl; + cout << "4)Shufflle the array\n5)Begin the tournament" << endl; + cin >> input; + if(input[0] == '1'){ + cout << t << endl; + } + else if(input[0] == '2'){ + t.add_restaurants(); + } + else if(input[0] == '3'){ + t.remove_restaurants(); + } + else if(input[0] == '4'){ + t.shuffle(); + } + else if(input[0] == '5'){ + if(t.verify_size()) { + keep_going = false; + succeful_pop = true; + } + } + else if(input[0] == '0'){ + keep_going = false; + } + } + if(succeful_pop) { + t.start_tournament(); + string output_file_name; + file_correct = false; + while(!file_correct) { + cout << "please enter file name: "; + getline(cin, output_file_name); + ofstream out(output_file_name.c_str()); + if(out.good()) { + out << t; + file_correct = true; + } + else { + cerr << "incorrect file name" << endl; + } + } + } +} diff --git a/cs142/lab09/restaurant.cpp b/cs142/lab09/restaurant.cpp new file mode 100644 index 0000000..e36ae24 --- /dev/null +++ b/cs142/lab09/restaurant.cpp @@ -0,0 +1,8 @@ +#include "restaurant.h" + +using namespace std; + +ostream & operator<<(ostream & os, restaurant & r) { + os << "{\"name\": \"" << r.name << "\", \"score\": " << r.score << "}"; + return os; +} diff --git a/cs142/lab09/restaurant.h b/cs142/lab09/restaurant.h new file mode 100644 index 0000000..149dc3a --- /dev/null +++ b/cs142/lab09/restaurant.h @@ -0,0 +1,16 @@ +#ifndef __RESTAURANT_H__ +#define __RESTAURANT_H__ + +#include +#include + +using namespace std; + +class restaurant { + public: + string name; + int score; + restaurant(string name, int score): name(name), score(score) {} + friend ostream & operator<<(ostream & os, restaurant & r); +}; +#endif diff --git a/cs142/lab09/test.json b/cs142/lab09/test.json new file mode 100644 index 0000000..ece0ced --- /dev/null +++ b/cs142/lab09/test.json @@ -0,0 +1,5 @@ +[ + {"name": "Italian Stallion", "score": 0}, + {"name": "Pizza Planet", "score": 20}, + {"name": "Gousteau's", "score": 500} +] diff --git a/cs142/lab09/tournament.cpp b/cs142/lab09/tournament.cpp new file mode 100644 index 0000000..ae2625f --- /dev/null +++ b/cs142/lab09/tournament.cpp @@ -0,0 +1,196 @@ +#include +#include +#include +#include + +using namespace std; + +#include "tournament.h" +#include "restaurant.h" +#include "io.h" + +ostream & operator<<(ostream & os, vector & v) { + for(auto i: v) { + os << i << endl; + } + return os; +} + +ostream & operator<<(ostream & os, tournament & t){ + os << "["; + for(unsigned int i = 0; i < t.restaurants.size(); i++) { + if(i == t.restaurants.size() - 1) { + os << t.restaurants[i]; + } + else { + os << t.restaurants[i]<< " ,"; + } + } + os << "]"; + return os; +} + +bool tournament::populate_restaurants(string filename) { + try { + restaurants = parse_file(filename); + return true; + } + catch(runtime_error e) { + cerr << e.what() << endl; + return false; + } +} + +bool tournament::already_in(string name) { + for(unsigned int i = 0; i < restaurants.size(); i++) { + if(restaurants[i].name == name) { + return true; + } + } + return false; +} + +void tournament::add_restaurants() { + string name; + int score = 0; + cout << "name" << endl; + cin.ignore(); + getline(cin, name); + if(not already_in(name)) { + restaurants.push_back(restaurant(name, score)); + } +} + +void tournament::remove_restaurants() { + string name; + cout << "name" << endl; + cin.ignore(); + getline(cin, name); + if(already_in(name)) { + for(unsigned int i = 0; i < restaurants.size(); i++) { + if(restaurants[i].name == name){ + restaurants.erase(restaurants.begin() + i); + } + } + } +} + +void tournament::shuffle() { + random_shuffle(restaurants.begin(), restaurants.end()); +} + +int round_counter(int current_size) { + int round; + if(current_size == 32) { + round = 5; + } + if(current_size == 16) { + round = 4; + } + else if(current_size == 8) { + round = 3; + } + else if(current_size == 4) { + round = 2; + } + else if(current_size == 2) { + round =1; + } + return round; +} + +int match_counter(int current_size) { + int match; + if(current_size == 32) { + match = 16; + } + if(current_size == 16) { + match = 8; + } + else if(current_size == 8) { + match = 4; + } + else if(current_size == 4) { + match = 2; + } + else if(current_size == 2) { + match =1; + } + return match; +} + +bool tournament::start_tournament(){ + if(not verify_size()) { + cout << "not 2^n" << endl; + return false; + } + bool temp_bool = true; + bool tourn_running = true; + cin.ignore(); + string name; + int match = match_counter(restaurants.size()); + int round = round_counter(restaurants.size()); + int current_round = 1; + vector temp_array; + while(tourn_running == true) { + int current_match = 1; + temp_bool = true; + cin.ignore(); + for(unsigned int i = 0; i < restaurants.size(); i += 2) { + while(temp_bool == true) { + cout << "which restaurant: " << restaurants[i] << " or " << restaurants[i + 1] << endl; + cout << "match " << current_match << "/" << match << " Round " + << current_round << "/" << round << endl; + getline(cin, name); + if(name == restaurants[i].name or name == restaurants[i + 1].name) { + if(name == restaurants[i].name) { + restaurants[i].score++; + temp_array.push_back(restaurants[i]); + losers.push_back(restaurants[i+1]); + } + else { + restaurants[i+1].score++; + temp_array.push_back(restaurants[i + 1]); + losers.push_back(restaurants[i]); + } + temp_bool = false; + current_match++; + } + else { + cout << "invalid response " << name << endl; + } + } + temp_bool = true; + } + while(temp_bool == true) { + for(unsigned int i = 0; i < temp_array.size(); i++) { + restaurants[i] = temp_array[i]; + } + for(unsigned int i = 0; i < temp_array.size(); i++){ + restaurants.pop_back(); + } + if(restaurants.size() == 1) { + losers.push_back(restaurants[0]); + cout << "this is the winner " << restaurants[0] << endl; + restaurants = losers; + return true; + } + else { + cout << "next round of tournament" << endl; + temp_bool = false; + } + } + temp_array.clear(); + match = match/2; + current_round++; + } + return false; +} + +bool tournament::verify_size() { + int r = restaurants.size(); + if(r == 2 or r == 4 or r == 8 or r == 16 or r == 32 or r == 64) { + return true; + } + return false; +} diff --git a/cs142/lab09/tournament.h b/cs142/lab09/tournament.h new file mode 100644 index 0000000..da18fd2 --- /dev/null +++ b/cs142/lab09/tournament.h @@ -0,0 +1,25 @@ +#ifndef __TOURNAMENT_H__ +#define __TOURNAMENT_H__ +#include +#include "restaurant.h" + +using namespace std; + +class tournament { + private: + vector restaurants; + vector losers; + public: + tournament(){}; + void display_restaurant(); + bool populate_restaurants(string filename); + bool already_in(string name); + void add_restaurants(); + void remove_restaurants(); + void shuffle(); + bool start_tournament(); + bool verify_size(); + friend ostream & operator<<(ostream & os, tournament & t); +}; + +#endif diff --git a/cs142/lab10/ArenaInterface.h b/cs142/lab10/ArenaInterface.h new file mode 100644 index 0000000..2e2f576 --- /dev/null +++ b/cs142/lab10/ArenaInterface.h @@ -0,0 +1,56 @@ +#pragma once +#include +#include +#include +#include "FighterInterface.h" +using namespace std; + +/* + WARNING: It is expressly forbidden to modify any part of this document, including its name +*/ +class ArenaInterface +{ + public: + ArenaInterface(){} + virtual ~ArenaInterface(){} + + /* + addFighter(string) + + Adds a new fighter to the collection of fighters in the arena. Do not allow + duplicate names. Reject any string that does not adhere to the format + outlined in the lab specs. + + Return true if a new fighter was added; false otherwise. + */ + virtual bool addFighter(string info) = 0; + + /* + removeFighter(string) + + Removes the fighter whose name is equal to the given name. Does nothing if + no fighter is found with the given name. + + Return true if a fighter is removed; false otherwise. + */ + virtual bool removeFighter(string name) = 0; + + /* + getFighter(string) + + Returns the memory address of a fighter whose name is equal to the given + name. Returns NULL if no fighter is found with the given name. + + Return a memory address if a fighter is found; NULL otherwise. + */ + virtual FighterInterface* getFighter(string name) = 0; + + /* + getSize() + + Returns the number of fighters in the arena. + + Return a non-negative integer. + */ + virtual int getSize() = 0; +}; diff --git a/cs142/lab10/Battle.h b/cs142/lab10/Battle.h new file mode 100644 index 0000000..5b30f0d --- /dev/null +++ b/cs142/lab10/Battle.h @@ -0,0 +1,176 @@ +#include +#include +#include +#include +#include "FighterInterface.h" +using namespace std; + +/* + WARNING: It is expressly forbidden to modify any part of this document, including its name +*/ +//======================================================================================= +FighterInterface* fight(FighterInterface*, FighterInterface*, bool); +void takeTurn(FighterInterface*, FighterInterface*, bool); +void speak(string); +//======================================================================================= +/* + fight(FighterInterface, FighterInterface, bool) + + Runs through the fighting algorithm for the two given fighters. + + Each fighter takes a turn using its special ability, attacking, and regenerating. If + the other fighter's current hit points falls to or drops below 0, then the other + fighter has lost. This process repeats until one fighter has fallen or 100 rounds + have occurred with neither fighter falling. + + If the given bool is true, this function will print a great deal of information + during the battle. This can be useful for testing. + + Returns the winner of the fight; null if the fight ends in a draw. +*/ +FighterInterface* fight(FighterInterface* c1, FighterInterface* c2, bool verbose) +{ + if(verbose) + { + stringstream stream; + stream << "----------"; + stream << c1->getName(); + stream << " vs "; + stream << c2->getName(); + stream << "----------"; + speak(stream.str()); + } + + c1->reset(); + c2->reset(); + + for(int i=0; i<100; i++) + { + //C1's turn + takeTurn(c1, c2, verbose); + if(c2->getCurrentHP() <= 0) + { + if(verbose) + { + stringstream stream; + stream << c1->getName(); + stream << " wins! ("; + stream << c1->getCurrentHP(); + stream << "/"; + stream << c1->getMaximumHP(); + stream << " HP left)"; + speak(stream.str()); + } + return c1; + } + + //C2's turn + takeTurn(c2, c1, verbose); + if(c1->getCurrentHP() <= 0) + { + if(verbose) + { + stringstream stream; + stream << c2->getName(); + stream << " wins! ("; + stream << c2->getCurrentHP(); + stream << "/"; + stream << c2->getMaximumHP(); + stream << " HP left)"; + speak(stream.str()); + } + return c2; + } + } + if(verbose) + { + speak("After 100 rounds, neither fighter has fallen. It's a draw!"); + } + return NULL; +} +//======================================================================================= +/* + takeTurn(FighterInterface*, FighterInterface*, bool) + + Runs through a single turn for [attacker] attacking [defender]. Each turn consists of + [attacker] trying to use its special ability, attacking [defender], and regenerating. +*/ +void takeTurn(FighterInterface* attacker, FighterInterface* defender, bool verbose) +{ + //Header + if(verbose) + { + stringstream stream; + stream << "It's "; + stream << attacker->getName(); + stream << "'s turn! ("; + stream << attacker->getCurrentHP(); + stream << "/"; + stream << attacker->getMaximumHP(); + stream << " HP)."; + speak(stream.str()); + } + + //Use Ability + if(!attacker->isSimplified()) + { + bool ability = attacker->useAbility(); + if(ability && verbose) + { + stringstream stream; + stream << "\t"; + stream << attacker->getName(); + stream << " uses a special ability!"; + speak(stream.str()); + } + } + + //Attack + int damage = attacker->getDamage(); + int before_attack = defender->getCurrentHP(); + defender->takeDamage(damage); + int after_attack = defender->getCurrentHP(); + if(verbose) + { + stringstream stream; + stream << "\t"; + stream << attacker->getName(); + stream << " attacks with "; + stream << damage; + stream << " damage, and "; + stream << defender->getName(); + stream << " takes "; + stream << (before_attack-after_attack); + stream << " damage."; + speak(stream.str()); + } + + //Regenerate + if(!attacker->isSimplified()) + { + int before_regen = attacker->getCurrentHP(); + attacker->regenerate(); + int after_regen = attacker->getCurrentHP(); + if(verbose) + { + stringstream stream; + stream << "\t"; + stream << attacker->getName(); + stream << " regenerates "; + stream << (after_regen-before_regen); + stream << " HP."; + speak(stream.str()); + } + } +} +//======================================================================================= +/* + speak(string) + + Displays a given message. +*/ +void speak(string message) +{ + printf("%s\n", message.c_str()); +} +//======================================================================================= diff --git a/cs142/lab10/Factory.cpp b/cs142/lab10/Factory.cpp new file mode 100644 index 0000000..cc446c6 --- /dev/null +++ b/cs142/lab10/Factory.cpp @@ -0,0 +1,7 @@ +#include "Factory.h" +#include "arena.h" + +ArenaInterface* Factory::createArena() +{ + return new arena(); +} diff --git a/cs142/lab10/Factory.h b/cs142/lab10/Factory.h new file mode 100644 index 0000000..5adcc45 --- /dev/null +++ b/cs142/lab10/Factory.h @@ -0,0 +1,21 @@ +#pragma once +#include "ArenaInterface.h" +/* + WARNING: It is expressly forbidden to modify any part of this document, including its name +*/ +//======================================================================================= +/* + createArena() + + Creates and returns an object whose class extends ArenaInterface. + This should be an object of a class you have created. + + Example: If you made a class called "Arena", you might say, "return new Arena();". +*/ +class Factory +{ +public: + static ArenaInterface* createArena(); +}; + +//======================================================================================= diff --git a/cs142/lab10/FighterInterface.h b/cs142/lab10/FighterInterface.h new file mode 100644 index 0000000..6197b97 --- /dev/null +++ b/cs142/lab10/FighterInterface.h @@ -0,0 +1,200 @@ +#pragma once +#include +#include +using namespace std; + +/* + WARNING: It is expressly forbidden to modify any part of this document, including its name +*/ + +/* + This class specifies the methods for a fighter. + + All fighters have the following attributes: + Name - The fighter's name. + Hit Points - The amount of health the fighter has, with a specified maximum. Reaching 0 is equivalent to death. + Strength - Physical power, used to determine hit point regeneration. + Speed - Dexterity and physical movement, used to reduce damage when being attacked. + Magic - Magical prowess, used for some special abilities. + + The three fighter types have unique abilities: + Robot - Relies on strength to deal damage. Also can use stored electricity to temporarily increase damage (max electricity equal to 2*magic). + Archer - Relies on speed to deal damage. Also can increase its speed for the remainder of the battle (no max bonus speed). + Cleric - Relies on magic to deal damage. Also can heal itself using mana, restoring hit points (max mana equal to 5*magic). + + More details about how stats are used and how abilities work can be found in the comments below. +*/ + +/* + ROBOT_ABILITY_COST + The amount of energy a Robot needs to perform its special ability. +*/ +const int ROBOT_ABILITY_COST = 5; + +/* + CLERIC_ABILITY_COST + The amount of mana a Cleric needs to perform its special ability. +*/ +const int CLERIC_ABILITY_COST = 25; + +class FighterInterface +{ + public: + FighterInterface(){} + virtual ~FighterInterface(){} + + /* + getName() + + Returns the name of this fighter. + */ + virtual string getName() = 0; + + /* + getMaximumHP() + + Returns the maximum hit points of this fighter. + */ + virtual int getMaximumHP() = 0; + + /* + getCurrentHP() + + Returns the current hit points of this fighter. + */ + virtual int getCurrentHP() = 0; + + /* + getStrength() + + Returns the strength stat of this fighter. + */ + virtual int getStrength() = 0; + + /* + getSpeed() + + Returns the speed stat of this fighter. + */ + virtual int getSpeed() = 0; + + /* + getMagic() + + Returns the magic stat of this fighter. + */ + virtual int getMagic() = 0; + + /* + getDamage() + + Returns the amount of damage a fighter will deal. + + Robot: + This value is equal to the Robot's strength plus any additional damage added for having just used its special ability. + + Archer: + This value is equal to the Archer's speed. + + Cleric: + This value is equal to the Cleric's magic. + */ + virtual int getDamage() = 0; + + /* + takeDamage(int) + + Reduces the fighter's current hit points by an amount equal to the given + damage minus one fourth of the fighter's speed. This method must reduce + the fighter's current hit points by at least one. It is acceptable for + this method to give the fighter negative current hit points. + + Examples: + damage=10, speed=7 => damage_taken=9 + damage=10, speed=9 => damage_taken=8 + damage=10, speed=50 => damage_taken=1 + */ + virtual void takeDamage(int damage) = 0; + + /* + reset() + + Restores a fighter's current hit points to its maximum hit points. + + Robot: + Also restores a Robot's current energy to its maximum value (which is 2 times its magic). + Also resets a Robot's bonus damage to 0. + + Archer: + Also resets an Archer's current speed to its original value. + + Cleric: + Also restores a Cleric's current mana to its maximum value (which is 5 times its magic). + */ + virtual void reset() = 0; + + /* + regenerate() + + Increases the fighter's current hit points by an amount equal to one sixth of + the fighter's strength. This method must increase the fighter's current hit + points by at least one. Do not allow the current hit points to exceed the + maximum hit points. + + Cleric: + Also increases a Cleric's current mana by an amount equal to one fifth of the + Cleric's magic. This method must increase the Cleric's current mana by at + least one. Do not allow the current mana to exceed the maximum mana. + */ + virtual void regenerate() = 0; + + /* + useAbility() + + Attempts to perform a special ability based on the type of fighter. The + fighter will attempt to use this special ability just prior to attacking + every turn. + + Robot: Shockwave Punch + Adds bonus damage to the Robot's next attack (and only its next attack) equal to (strength * ((current_energy/maximum_energy)^4)). + Can only be used if the Robot has at least [ROBOT_ABILITY_COST] energy. + Decreases the Robot's current energy by [ROBOT_ABILITY_COST] (after calculating the additional damage) when used. + Examples: + strength=20, current_energy=20, maximum_energy=20 => bonus_damage=20 + strength=20, current_energy=15, maximum_energy=20 => bonus_damage=6 + strength=20, current_energy=10, maximum_energy=20 => bonus_damage=1 + strength=20, current_energy=5, maximum_energy=20 => bonus_damage=0 + Robot Note: + The bonus damage formula should be computed using double arithmetic, and only + the final result should be cast into an integer. + + Archer: Quickstep + Increases the Archer's speed by one point each time the ability is used. + This bonus lasts until the reset() method is used. + This ability always works; there is no maximum bonus speed. + + Cleric: Healing Light + Increases the Cleric's current hit points by an amount equal to one third of its magic. + Can only be used if the Cleric has at least [CLERIC_ABILITY_COST] mana. + Will be used even if the Cleric's current HP is equal to their maximum HP + Decreases the Cleric's current mana by [CLERIC_ABILITY_COST] when used. + Cleric Note: + This ability, when successful, must increase the Cleric's current hit points + by at least one. Do not allow the current hit points to exceed the maximum + hit points. + + Return true if the ability was used; false otherwise. + */ + virtual bool useAbility() = 0; + + /* + isSimplified() + + Returns true if you have not completed the useAbility() and/or the regenerate() + methods for this type of fighter. This allows the test driver to award points + for Part 3 even if Part 4 is incomplete. + + Return true if the testing is to be simplified; false otherwise. + */ + virtual bool isSimplified() = 0; +}; diff --git a/cs142/lab10/Makefile b/cs142/lab10/Makefile new file mode 100644 index 0000000..2dc9463 --- /dev/null +++ b/cs142/lab10/Makefile @@ -0,0 +1,33 @@ +CXXFLAGS= -Wall -g +OBJECTS=main.o arena.o Factory.o archer.o fighter.o util.o cleric.o robot.o +EXE=main + +all: $(EXE) + + +$(EXE): main.o + $(CXX) $(CXXFLAGS) $(OBJECTS) -o $@ + +main.o: main.cpp Factory.o arena.o fighter.o archer.o util.o cleric.o robot.o + +Factory.o: Factory.cpp Factory.h + +arena.o: arena.cpp arena.h +fighter.o: fighter.cpp fighter.h +archer.o: archer.cpp archer.h fighter.h +cleric.o: cleric.cpp cleric.h fighter.h +robot.o: robot.cpp robot.h fighter.h +util.o: util.cpp util.h + +run: $(EXE) + @./$(EXE) + +clean: + @rm -vf *.o + @rm -vf $(EXE) + +debug: $(EXE) + gdb ./$(EXE) + +valgrind: $(EXE) + valgrind --tool=memcheck --leak-check=yes ./$(EXE) diff --git a/cs142/lab10/archer.cpp b/cs142/lab10/archer.cpp new file mode 100644 index 0000000..eafd492 --- /dev/null +++ b/cs142/lab10/archer.cpp @@ -0,0 +1,21 @@ +#include "archer.h" +archer::archer(string name, int max_hp, int strength, int speed, int magic) : + fighter(name, max_hp, strength, speed, magic), original_speed(speed) {} + +int archer::getDamage() { + return speed; +} + +void archer::reset() { + hp = max_hp; + speed = original_speed; +} + +bool archer::useAbility() { + speed++; + return true; +} + +int archer::get_original_speed() { + return original_speed; +} diff --git a/cs142/lab10/archer.h b/cs142/lab10/archer.h new file mode 100644 index 0000000..b5c85a0 --- /dev/null +++ b/cs142/lab10/archer.h @@ -0,0 +1,21 @@ +#ifndef __ARCHER_H__ +#define __ARCHER_H__ + +#include "fighter.h" + +class archer : public fighter { + private: + int original_speed; + public: + archer(string, int, int, int, int); + + string get_type() { return "A"; }; + + int getDamage(); + void reset(); + bool useAbility(); + + int get_original_speed(); +}; + +#endif diff --git a/cs142/lab10/arena.cpp b/cs142/lab10/arena.cpp new file mode 100644 index 0000000..a6cc0b5 --- /dev/null +++ b/cs142/lab10/arena.cpp @@ -0,0 +1,111 @@ +#include +using namespace std; + +#include "arena.h" +#include "fighter.h" +#include "archer.h" +#include "cleric.h" +#include "robot.h" +#include "util.h" + +arena::~arena() { + fighter * f = NULL; + for(vector::iterator it = fighters.begin(); + it != fighters.end(); + it++) { + f = dynamic_cast(*it); + delete f; + } +} + +bool arena::contains(string name) { + fighter * f = NULL; + for(unsigned int i = 0; i < fighters.size(); i++) { + f = dynamic_cast(fighters[i]); + if(f->getName() == name) { + return true; + } + } + return false; +} + +bool arena::addFighter(string info) { + fighter * f = NULL; + + string name; + string type; + int max_hp; + int strength; + int speed; + int magic; + + bool worked; + worked = parse_n_load(info, name, type, max_hp, strength, speed, magic); + if(not worked) { + return false; + } + + if(contains(name)) { + return false; + } + + if(type == "A") { + f = new archer(name, max_hp, strength, speed, magic); + } + else if(type == "C") { + f = new cleric(name, max_hp, strength, speed, magic); + } + else if(type == "R") { + f = new robot(name, max_hp, strength, speed, magic); + } + + fighters.push_back(f); + + return true; +} + +bool arena::removeFighter(string name) { + fighter * f = NULL; + for(vector::iterator it = fighters.begin(); + it != fighters.end(); + it++) { + f = dynamic_cast(*it); + if(f->getName() == name) { + delete f; + fighters.erase(it); + return true; + } + } + return false; +} + +FighterInterface * arena::getFighter(string name) { + fighter * f = NULL; + for(vector::iterator it = fighters.begin(); + it != fighters.end(); + it++) { + f = dynamic_cast(*it); + if(f->getName() == name) { + return dynamic_cast(f); + } + } + return NULL; +} + +int arena::getSize() { + return fighters.size(); +} + +ostream & operator<<(ostream & os, arena & a) { + os << "["; + for(vector::iterator it = a.fighters.begin(); + it != a.fighters.end(); + it++) { + os << *(dynamic_cast( *it)); + if (it != a.fighters.end() - 1) { + os << ", "; + } + } + os << "]"; + return os; +} diff --git a/cs142/lab10/arena.h b/cs142/lab10/arena.h new file mode 100644 index 0000000..47fb557 --- /dev/null +++ b/cs142/lab10/arena.h @@ -0,0 +1,23 @@ +#ifndef __ARENA_H__ +#define __ARENA_H__ + +#include +#include "ArenaInterface.h" + +class arena : public ArenaInterface { + private: + std::vector fighters; + bool contains(string name); + public: + arena(){} + ~arena(); + bool addFighter(string info); + bool removeFighter(string name); + FighterInterface * getFighter(string name); + int getSize(); + + friend ostream & operator<<(ostream &, arena &); +}; + + +#endif diff --git a/cs142/lab10/cleric.cpp b/cs142/lab10/cleric.cpp new file mode 100644 index 0000000..81df65a --- /dev/null +++ b/cs142/lab10/cleric.cpp @@ -0,0 +1,59 @@ +#include "FighterInterface.h" +#include "cleric.h" + +cleric::cleric(string name, int max_hp, int strength, int speed, int magic) : + fighter(name, max_hp, strength, speed, magic), mana(5*magic) {} + +int cleric::getDamage() { + return magic; +} + +void cleric::reset() { + hp = max_hp; + mana = 5 * magic; +} + +void cleric::regenerate() { + fighter::regenerate(); + + int increase = magic / 5; + + if(increase < 0) { + increase = 0; + } + else if(increase == 0) { + increase = 1; + } + if(mana + increase < magic * 5) { + mana += increase; + } + else { + mana = 5 * magic; + } +} + +bool cleric::useAbility() { + // a.k.a. Healing light + if(mana - CLERIC_ABILITY_COST >= 0) { + int increase = magic / 3; + if(increase < 0) { + increase = 0; + } + else if(increase == 0) { + increase = 1; + } + if(hp + increase < max_hp) { + hp += increase; + } + else { + hp = max_hp; + } + mana -= CLERIC_ABILITY_COST; + return true; + } + return false; +} + +int cleric::get_mana() { + return mana; +} diff --git a/cs142/lab10/cleric.h b/cs142/lab10/cleric.h new file mode 100644 index 0000000..ebf037c --- /dev/null +++ b/cs142/lab10/cleric.h @@ -0,0 +1,24 @@ +#ifndef __CLERIC_H__ +#define __CLERIC_H__ + +#include "fighter.h" + +class cleric : public fighter { + private: + int original_speed; + int mana; + public: + cleric(string, int, int, int, int); + + string get_type() { return "A"; }; + + int getDamage(); + void reset(); + bool useAbility(); + void regenerate(); + + int get_original_speed(); + int get_mana(); +}; + +#endif diff --git a/cs142/lab10/fighter.cpp b/cs142/lab10/fighter.cpp new file mode 100644 index 0000000..6841a76 --- /dev/null +++ b/cs142/lab10/fighter.cpp @@ -0,0 +1,72 @@ +#include "fighter.h" + +fighter::fighter(string name, int max_hp, int strength, int speed, int magic) : + name(name), max_hp(max_hp), hp(max_hp), strength(strength), + speed(speed), magic(magic) {} + +string fighter::getName() { + return name; +} + +int fighter::getMaximumHP() { + return max_hp; +} + +int fighter::getCurrentHP() { + return hp; +} + +int fighter::getStrength() { + return strength; +} + +int fighter::getSpeed() { + return speed; +} + +int fighter::getMagic() { + return magic; +} + +void fighter::regenerate() { + int increase = strength / 6; + + if(increase < 0) { + increase = 0; + } + else if(increase == 0) { + increase = 1; + } + + if(hp + increase <= max_hp) { + hp += increase; + } + else { + hp = max_hp; + } +} + +void fighter::takeDamage(int damage) { + int hurt = damage - (speed / 4); + if (hurt <= 0) { + hurt = 1; + } + hp -= hurt; +} + +bool fighter::isSimplified() { + return false; +} + +ostream & operator<<(ostream & os, fighter & f) { + os << "{\n" + << " \"name\": \"" << f.name << "\",\n" + << " \"type\": \"" << f.get_type() << "\",\n" + << " \"hp\": " << f.hp << ",\n" + << " \"max hp\": " << f.max_hp << ",\n" + << " \"strength\": " << f.strength << ",\n" + << " \"speed\": " << f.speed << ",\n" + << " \"magic\": " << f.magic << ",\n" + << "}"; + return os; +} diff --git a/cs142/lab10/fighter.h b/cs142/lab10/fighter.h new file mode 100644 index 0000000..63789c5 --- /dev/null +++ b/cs142/lab10/fighter.h @@ -0,0 +1,44 @@ +#ifndef __FIGHTER_H__ +#define __FIGHTER_H__ + +#include +#include "FighterInterface.h" + +class fighter : public FighterInterface +{ + private: + string name; + + protected: + int max_hp; + int hp; + int strength; + int speed; + int magic; + + public: + fighter(string, int, int, int, int); + // virtual ~fighter(); + + string getName(); + + int getMaximumHP(); + int getCurrentHP(); + int getStrength(); + int getSpeed(); + int getMagic(); + + virtual string get_type() = 0; + + virtual int getDamage() = 0; + void takeDamage(int damage); + virtual void reset() = 0; + virtual void regenerate(); + virtual bool useAbility() = 0; + + bool isSimplified(); + + friend ostream & operator<<(ostream & os, fighter & a); +}; + +#endif diff --git a/cs142/lab10/main.cpp b/cs142/lab10/main.cpp new file mode 100644 index 0000000..c0417c3 --- /dev/null +++ b/cs142/lab10/main.cpp @@ -0,0 +1,205 @@ +#include +#include + +using namespace std; + +#include "Battle.h" +#include "Factory.h" +#include "arena.h" +#include "archer.h" +#include "cleric.h" +#include "robot.h" + +void test_fighter() { + archer a = archer("bilbo", 100, 60, 1, 5); + a.takeDamage(90); + a.regenerate(); + assert(a.getCurrentHP() == 20); + archer b = archer("frodo", 100, 0, 1, 5); + b.takeDamage(90); + b.regenerate(); +} + +void test_archer() { + archer a("stephen", 666, 66, 6, 0); + a.takeDamage(100); + assert(a.getCurrentHP() == 567); + assert(a.get_original_speed() == 6); + assert(a.getSpeed() == 6); +} + +void test_cleric() { + cleric a("Derek", 666, 66, 6, 20); + assert(a.getDamage() == 20); + assert(a.get_mana() == 100); + a.takeDamage(100); + assert(a.getCurrentHP() == 567); + a.reset(); + assert(a.getCurrentHP() == 666); + + cleric b("SaintColleen", 100, 90, 4, 60); + b.takeDamage(100); + b.useAbility(); + assert(b.getCurrentHP() == 21); + + cleric c("Vanessa", 100, 90, 4, 1); + c.takeDamage(100); + c.useAbility(); + assert(c.getCurrentHP() == 1); + + cleric d("Vanessa", 100, 90, 4, 5); + d.takeDamage(100); + d.useAbility(); + assert(d.getCurrentHP() == 2); +} + +void test_robot() { + robot a("Derek", 100, 20, 10, 10); + assert(a.getDamage() == 20); + a.useAbility(); + assert(a.getDamage() == 40); + assert(a.getDamage() == 20); + a.useAbility(); + assert(a.getDamage() == 26); + a.takeDamage(100); + assert(a.getCurrentHP() == 2); + a.reset(); + assert(a.getCurrentHP() == 100); +} + +void test_input_parser() { + ArenaInterface * A = Factory::createArena(); + arena * a = dynamic_cast(A); + + string input = "Xephos A 200 13 21 10"; + assert(a->addFighter(input)); + + input = "Stephen A 200 13 21 10"; + assert(a->addFighter(input)); + + input = "Billy Bob Thorton A 0 13 21 10"; + assert(not a->addFighter(input)); + + input = "Xephos a 200 13 21 10"; + assert(not a->addFighter(input)); + + input = "Derek A 200 13 21 a10"; + assert(not a->addFighter(input)); + + input = "Derek A 200 13 stupid21 10"; + assert(not a->addFighter(input)); + + delete A; +} + +void test_add() { + ArenaInterface * A = Factory::createArena(); + arena * a = dynamic_cast(A); + + string input = "Xephos A 200 13 21 10"; + assert(a->addFighter(input)); + + input = "Stephen A 200 13 21 10"; + assert(a->addFighter(input)); + + // do not allow for duplicate fighers + input = "Xephos A 200 13 21 10"; + bool double_add = a->addFighter(input); + assert(not double_add); + + input = "Stephen A 0 13 21 10"; + assert(not a->addFighter(input)); + + input = "Derek A 200 13 21 10"; + assert(a->addFighter(input)); + + // another attempt for not allowing duplicate fighters + input = "Stephen A 200 13 21 10"; + assert(not a->addFighter(input)); + delete A; +} + +void test_remove() { + ArenaInterface * A = Factory::createArena(); + arena * a = dynamic_cast(A); + + string input = "Michael A 200 13 21 10"; + a->addFighter(input); + input = "Derek A 200 13 21 10"; + a->addFighter(input); + input = "Bryan A 200 13 21 10"; + a->addFighter(input); + + assert(not a->removeFighter("Zaphodbeblebrox")); + + bool remove_non_existant = a->removeFighter("Stephen"); + assert(not remove_non_existant); + assert(a->getSize() == 3); + + bool remove_fighter = a->removeFighter("Michael"); + assert(remove_fighter); + assert(a->getSize() == 2); + + a->removeFighter("Derek"); + a->removeFighter("Bryan"); + assert(a->getSize() == 0); + delete a; +} + +void test_find() { + ArenaInterface * A = Factory::createArena(); + arena * a = dynamic_cast(A); + + string input = "Michael A 200 13 21 10"; + a->addFighter(input); + input = "Derek A 200 13 21 10"; + a->addFighter(input); + input = "Bryan A 200 13 21 10"; + a->addFighter(input); + + fighter * f; + f = dynamic_cast(a->getFighter("Stephen")); + assert(not f); + f = dynamic_cast(a->getFighter("Derek")); + assert(f); + + delete a; +} + +void test_archer_reset() { + archer a("stephen", 666, 66, 6, 0); + a.takeDamage(100); + assert(a.getCurrentHP() == 567); + a.reset(); + assert(a.getCurrentHP() == a.getMaximumHP()); + assert(a.getSpeed() == a.get_original_speed()); + assert(a.getSpeed() == 6); + assert(a.get_original_speed() == 6); +} + +void test_archer_usability() { + archer a("stephen", 666, 66, 6, 0); + assert(a.getSpeed() == 6); + a.useAbility(); + assert(a.getSpeed() == 7); +} + +void test_battle() { + archer a("stephen", 200, 66, 60, 100); + robot b("derek", 1000, 20, 15, 200); + fight(&a, &b, true); +} + +int main() { + test_fighter(); + test_archer(); + test_cleric(); + test_robot(); + test_input_parser(); + test_add(); + test_remove(); + test_find(); + test_archer_reset(); + test_archer_usability(); + test_battle(); +} diff --git a/cs142/lab10/robot.cpp b/cs142/lab10/robot.cpp new file mode 100644 index 0000000..879911d --- /dev/null +++ b/cs142/lab10/robot.cpp @@ -0,0 +1,30 @@ +#include +#include "FighterInterface.h" +#include "robot.h" + +robot::robot(string name, int max_hp, int strength, int speed, int magic) : + fighter(name, max_hp, strength, speed, magic), + max_energy(2 * magic), cur_energy(2 * magic), extra_damage(0) {} + +int robot::getDamage() { + int damage = strength + extra_damage; + extra_damage = 0; + return damage; +} + +void robot::reset() { + hp = max_hp; + cur_energy = max_energy; +} + +bool robot::useAbility() { + if(cur_energy - ROBOT_ABILITY_COST >= 0) { + double a = cur_energy/double(max_energy); + double b = pow(a, 4.0); + double increase = strength * b; + extra_damage = int(increase); + cur_energy -= ROBOT_ABILITY_COST; + return true; + } + return false; +} diff --git a/cs142/lab10/robot.h b/cs142/lab10/robot.h new file mode 100644 index 0000000..9649470 --- /dev/null +++ b/cs142/lab10/robot.h @@ -0,0 +1,23 @@ +#ifndef __ROBOT_H__ +#define __ROBOT_H__ + +#include "fighter.h" + +class robot : public fighter { + private: + int max_energy; + int cur_energy; + int extra_damage; + public: + robot(string, int, int, int, int); + + string get_type() { return "A"; }; + + int getDamage(); + void reset(); + bool useAbility(); + + int get_original_speed(); +}; + +#endif diff --git a/cs142/lab10/util.cpp b/cs142/lab10/util.cpp new file mode 100644 index 0000000..5f49982 --- /dev/null +++ b/cs142/lab10/util.cpp @@ -0,0 +1,60 @@ +#include +#include +using namespace std; +#include +#include "util.h" + +vector tokenize(const string & str, const string & delimiters) { + vector tokens; + string::size_type lastPos = str.find_first_not_of(delimiters, 0); + string::size_type pos = str.find_first_of(delimiters, lastPos); + while (string::npos != pos || string::npos != lastPos) + { + tokens.push_back(str.substr(lastPos, pos - lastPos)); + lastPos = str.find_first_not_of(delimiters, pos); + pos = str.find_first_of(delimiters, lastPos); + } + return tokens; +} + +bool parse_n_load(const string & input, string & name, string & type, + int & max_hp, int & strength, int & speed, int & magic) { + vector tokens = tokenize(input); + vector tokens2 = tokenize(input, "."); + + if (tokens.size() != 6 or tokens2.size() > 1) { + return false; + } + + name = tokens[0]; + + string parsed_type = tokens[1]; + if(parsed_type.size() != 1) { + return false; + } + if (not ( parsed_type == "A" + or parsed_type == "C" + or parsed_type == "R")) { + return false; + } + + type = parsed_type; + + + int parsed_max_hp = atoi(tokens[2].c_str()); + int parsed_strength = atoi(tokens[3].c_str()); + int parsed_speed = atoi(tokens[4].c_str()); + int parsed_magic = atoi(tokens[5].c_str()); + + if (parsed_max_hp == 0 or parsed_strength == 0 or parsed_speed == 0 or + parsed_magic == 0) { + return false; + } + + max_hp = parsed_max_hp; + strength = parsed_strength; + speed = parsed_speed; + magic = parsed_magic; + + return true; +} diff --git a/cs142/lab10/util.h b/cs142/lab10/util.h new file mode 100644 index 0000000..209e44c --- /dev/null +++ b/cs142/lab10/util.h @@ -0,0 +1,14 @@ +#ifndef __UTIL_H__ +#define __UTIL_H__ + +#include +#include + +using namespace std; + +void print(const string & in); +vector tokenize(const string & str, const string & delimiters=" "); +bool parse_n_load(const string & input, string & name, string & type, + int & max_hp, int & strength, int & speed, int & magic); + +#endif diff --git a/cs142/smcquay/cootie/Makefile b/cs142/smcquay/cootie/Makefile new file mode 100644 index 0000000..8e3f52d --- /dev/null +++ b/cs142/smcquay/cootie/Makefile @@ -0,0 +1,14 @@ +CPPFLAGS=-Wall -g -std=c++0x + +all: cootie + +cootie: cootie.cc dice.o player.o + +dice.o: dice.cc dice.h +player.o: player.cc player.h + +test: all + ./cootie 4 + +clean: + @rm -rvf cootie cootie.dSYM *.o diff --git a/cs142/smcquay/cootie/cootie.cc b/cs142/smcquay/cootie/cootie.cc new file mode 100644 index 0000000..02efe22 --- /dev/null +++ b/cs142/smcquay/cootie/cootie.cc @@ -0,0 +1,42 @@ +#include +#include +#include +#include "dice.h" +#include "player.h" + +using namespace std; + +const string usage = "usage: cootie "; + +int main(int argc, char * argv[]) { + if(argc < 2) { + cerr << usage << endl;; + return 1; + } + + random_init(); + + int number_of_players = int(atof(argv[1])); + vector players; + for(int i=0; i < number_of_players; i++) { + players.push_back(player(i)); + } + + auto keep_playing = true; + while(keep_playing) { + for(player & p : players) { + // cout << p << endl; + p.turn(); + if(p.won()) { + keep_playing = false; + cout << "player " << p.id << " wins!!" << endl; + cout << p << endl; + break; + } + } + } + + cout << "total rolls: " << get_roll_count() << endl; + cout << "thanks for playing" << endl; + return 0; +} diff --git a/cs142/smcquay/cootie/dice.cc b/cs142/smcquay/cootie/dice.cc new file mode 100644 index 0000000..7cad9ce --- /dev/null +++ b/cs142/smcquay/cootie/dice.cc @@ -0,0 +1,25 @@ +#include +#include +#include +#include + +#include "dice.h" + +static int roll_count = 0; + +void random_init() { + struct timeval tv; + gettimeofday(&tv, NULL); + pid_t pid = getpid(); + srand(tv.tv_usec + pid); +} + +int roll() { + roll_count++; + int compliment = rand() % 6; + return compliment + 1; +} + +int get_roll_count() { + return roll_count; +} diff --git a/cs142/smcquay/cootie/dice.h b/cs142/smcquay/cootie/dice.h new file mode 100644 index 0000000..86517d1 --- /dev/null +++ b/cs142/smcquay/cootie/dice.h @@ -0,0 +1,8 @@ +#ifndef __DICE_H__ +#define __DICE_H__ + +void random_init(); +int roll(); +int get_roll_count(); + +#endif diff --git a/cs142/smcquay/cootie/player.cc b/cs142/smcquay/cootie/player.cc new file mode 100644 index 0000000..c7878af --- /dev/null +++ b/cs142/smcquay/cootie/player.cc @@ -0,0 +1,67 @@ +#include "dice.h" +#include "player.h" + +#include +using namespace std; + +player::player(int id) : id(id), head(false), body(false), + hat(false), eyes(false), mouth(false), legs(0) {} + +ostream & operator<<(ostream & os, const player & e) { + os << "{id: " << e.id + << ", body: " << e.body + << ", head: " << e.head + << ", hat: " << e.hat + << ", eyes: " << e.eyes + << ", mouth: " << e.mouth + << ", legs: " << e.legs + << "}"; + return os; +} + +void player::turn() { + bool turn_finished = false; + while(not turn_finished) { + int cur_roll = roll(); + turn_finished = true; + if(cur_roll == 1) { + if(not body) { + turn_finished = false; + body = true; + } + } + else if(body and cur_roll == 2) { + if(not head) { + turn_finished = false; + head = true; + } + } + else if(body and head) { + if (cur_roll == 3) { + turn_finished = false; + hat = true; + } + else if (cur_roll == 4) { + turn_finished = false; + eyes = true; + } + else if (cur_roll == 5) { + turn_finished = false; + mouth = true; + } + else if (cur_roll == 6) { + if (not (legs >= 6)) { + turn_finished = false; + legs++; + } + } + } + } +} + +bool player::won() { + if(head and body and hat and eyes and mouth and legs == 6) + return true; + else + return false; +} diff --git a/cs142/smcquay/cootie/player.h b/cs142/smcquay/cootie/player.h new file mode 100644 index 0000000..29ee569 --- /dev/null +++ b/cs142/smcquay/cootie/player.h @@ -0,0 +1,24 @@ +#ifndef __PLAYER_H__ +#define __PLAYER_H__ + +#include +using namespace std; + +class player { + public: + int id; + bool head; + bool body; + bool hat; + bool eyes; + bool mouth; + int legs; + + player(int); + friend ostream & operator<<(ostream &, const player &); + + void turn(); + bool won(); +}; + +#endif diff --git a/cs142/smcquay/fun_with_formatting/Makefile b/cs142/smcquay/fun_with_formatting/Makefile new file mode 100644 index 0000000..d533b50 --- /dev/null +++ b/cs142/smcquay/fun_with_formatting/Makefile @@ -0,0 +1,9 @@ +CPPFLAGS=-Wall -g -std=c++0x + +all: main + +test: all + ./main + +clean: + @rm -rfv main.o main diff --git a/cs142/smcquay/fun_with_formatting/main.cc b/cs142/smcquay/fun_with_formatting/main.cc new file mode 100644 index 0000000..b25bf6c --- /dev/null +++ b/cs142/smcquay/fun_with_formatting/main.cc @@ -0,0 +1,34 @@ +#include +#include +#include +#include + +using namespace std; + + +int main(int argc, char * argv[]) { + float a = 12.123456; + float b = 12.125100; + + cout << a << " " << b << " " << endl; + cout << setiosflags(ios::fixed) << setprecision(2) << a << " " << b << " " << endl; + + printf("%0.2f %0.2f\n", a, b); + fprintf(stdout, "%0.2f %0.2f\n", a, b); + fprintf(stderr, "%0.2f %0.2f\n", a, b); + + double input; + cin >> input; + double intpart = 0; + double fracpart = modf(input, &intpart); + printf("%f %f\n", intpart, fracpart); + + if (fracpart == 0.5) { + cout << "exactly 0.5" << endl; + } + else { + cout << "not exactly 0.5" << endl; + } + + return 0; +} diff --git a/cs142/smcquay/go/lab00/Makefile b/cs142/smcquay/go/lab00/Makefile new file mode 100644 index 0000000..71f83f0 --- /dev/null +++ b/cs142/smcquay/go/lab00/Makefile @@ -0,0 +1,7 @@ +include $(GOROOT)/src/Make.inc + +TARG=hello +GOFILES=\ + hello.go + +include $(GOROOT)/src/Make.cmd diff --git a/cs142/smcquay/go/lab00/hello.go b/cs142/smcquay/go/lab00/hello.go new file mode 100644 index 0000000..4ddce22 --- /dev/null +++ b/cs142/smcquay/go/lab00/hello.go @@ -0,0 +1,7 @@ +package main + +import "fmt" + +func main() { + fmt.Println("hello world! My name is Stephen McQuay.") +} diff --git a/cs142/smcquay/go/lab01/Makefile b/cs142/smcquay/go/lab01/Makefile new file mode 100644 index 0000000..299f08f --- /dev/null +++ b/cs142/smcquay/go/lab01/Makefile @@ -0,0 +1,7 @@ +include $(GOROOT)/src/Make.inc + +TARG=trivia +GOFILES=\ + trivia.go + +include $(GOROOT)/src/Make.cmd diff --git a/cs142/smcquay/go/lab01/trivia.go b/cs142/smcquay/go/lab01/trivia.go new file mode 100644 index 0000000..31b9608 --- /dev/null +++ b/cs142/smcquay/go/lab01/trivia.go @@ -0,0 +1,29 @@ +package main + +import "fmt" + +type QA struct { + question string + answer string +} + +func main() { + fmt.Printf("%48s\n", "Basic BYU Trivia") + fmt.Printf("%25s %38s\n\n", "Questions", "Answers") + + qas := []QA{ + {"What was the original name of BYU?", "Brigham Young Academy"}, + {"When was BYU established?", "1875"}, + {"Who was the first \"permanent\" principal of BYA?", + "Karl G. Maeser"}, + {"When did BYA become BYU?", "1903"}, + {"To what sports conference do we belong?", + "Mountain West Conference (MWC)"}, + {"WHen did BYU win the national football title?", "1984"}, + {"Who won the Heisman Trophy in 1990?", "Ty Detmer"}, + } + + for _, v := range qas { + fmt.Printf("%-48s %s\n", v.question, v.answer) + } +} diff --git a/cs142/smcquay/go/lab02/binary/Makefile b/cs142/smcquay/go/lab02/binary/Makefile new file mode 100644 index 0000000..da15818 --- /dev/null +++ b/cs142/smcquay/go/lab02/binary/Makefile @@ -0,0 +1,7 @@ +include $(GOROOT)/src/Make.inc + +TARG=binary +GOFILES=\ + binary.go + +include $(GOROOT)/src/Make.cmd diff --git a/cs142/smcquay/go/lab02/binary/binary.go b/cs142/smcquay/go/lab02/binary/binary.go new file mode 100644 index 0000000..6be03c4 --- /dev/null +++ b/cs142/smcquay/go/lab02/binary/binary.go @@ -0,0 +1,26 @@ +package main + +import ( + "fmt" +) + +func itob(i int) string { + var buf [64]byte + j := len(buf) + b := 2 + for i > 0 { + j-- + buf[j] = "0123456789abcdefghipqrstuvwxyz"[i%b] + i /= b + } + + return string(buf[j:]) +} + + +func main() { + var i int + fmt.Print("please enter a number: ") + fmt.Scan(&i) + fmt.Printf("%d as a binary: %s\n", i, itob(i)) +} diff --git a/cs142/smcquay/go/lab02/seconds/Makefile b/cs142/smcquay/go/lab02/seconds/Makefile new file mode 100644 index 0000000..c163b18 --- /dev/null +++ b/cs142/smcquay/go/lab02/seconds/Makefile @@ -0,0 +1,7 @@ +include $(GOROOT)/src/Make.inc + +TARG=seconds +GOFILES=\ + seconds.go + +include $(GOROOT)/src/Make.cmd diff --git a/cs142/smcquay/go/lab02/seconds/seconds.go b/cs142/smcquay/go/lab02/seconds/seconds.go new file mode 100644 index 0000000..d477a8f --- /dev/null +++ b/cs142/smcquay/go/lab02/seconds/seconds.go @@ -0,0 +1,36 @@ +package main + +import ( + "fmt" + "math" +) + +const SECONDS_PER_HOUR = 3600 +const SECONDS_PER_MINUTE = 60 + +type time struct { + hours int + minutes int + seconds int +} + +func (t time) String() string { + return fmt.Sprintf("%dH:%dM:%dS", t.hours, t.minutes, t.seconds); +} + +func int2time(i int) time { + var r_secs int + hours := i / SECONDS_PER_HOUR + r_secs = i % SECONDS_PER_HOUR + mins := r_secs / SECONDS_PER_MINUTE + r_secs = r_secs % SECONDS_PER_MINUTE + return time{hours, mins, r_secs} +} + +func main() { + var seconds int + fmt.Print("please enter total seconds: ") + fmt.Scan(&seconds) + fmt.Printf("%v\n", int2time(seconds)) + fmt.Printf("%v\n", int2time(int(math.Sqrt(float64(seconds))))) +} diff --git a/cs142/smcquay/go/lab02/temperature/Makefile b/cs142/smcquay/go/lab02/temperature/Makefile new file mode 100644 index 0000000..5d0e1e0 --- /dev/null +++ b/cs142/smcquay/go/lab02/temperature/Makefile @@ -0,0 +1,7 @@ +include $(GOROOT)/src/Make.inc + +TARG=temp +GOFILES=\ + temp.go + +include $(GOROOT)/src/Make.cmd diff --git a/cs142/smcquay/go/lab02/temperature/temp.go b/cs142/smcquay/go/lab02/temperature/temp.go new file mode 100644 index 0000000..b670893 --- /dev/null +++ b/cs142/smcquay/go/lab02/temperature/temp.go @@ -0,0 +1,21 @@ +package main + +import ( + "fmt" +) + +func f2c(temp_F float32) float32 { + return 5.0/9.0 * (temp_F-32); +} + +func main() { + var temp_F float32 + fmt.Print("please enter a temperature: ") + fmt.Scan(&temp_F) + temp_C := f2c(temp_F) + + fmt.Printf("%0.4fF as:\n", temp_F) + fmt.Printf("an int: %dF\n", int(temp_F)) + fmt.Printf("a celsius float32: %0.4fC\n", temp_C) + fmt.Printf("a celcius int: %dC\n", int(temp_C)) +} diff --git a/cs142/smcquay/go/lab03/Makefile b/cs142/smcquay/go/lab03/Makefile new file mode 100644 index 0000000..ddb851a --- /dev/null +++ b/cs142/smcquay/go/lab03/Makefile @@ -0,0 +1,7 @@ +include $(GOROOT)/src/Make.inc + +TARG=grades +GOFILES=\ + grades.go + +include $(GOROOT)/src/Make.cmd diff --git a/cs142/smcquay/go/lab03/grades.go b/cs142/smcquay/go/lab03/grades.go new file mode 100644 index 0000000..e399362 --- /dev/null +++ b/cs142/smcquay/go/lab03/grades.go @@ -0,0 +1,10 @@ +package main + +import ( + "fmt" +) + + +func main() { + fmt.Println("hello") +} diff --git a/cs142/smcquay/lab03/Makefile b/cs142/smcquay/lab03/Makefile new file mode 100644 index 0000000..ac8cbd3 --- /dev/null +++ b/cs142/smcquay/lab03/Makefile @@ -0,0 +1,10 @@ +CXXFLAGS=-Wall -g -std=c++0x +all: grade +test: grade + ./grade < test.txt + ./grade -n < test.txt + ./grade -p < test.txt + +clean: + @rm -vf grade + @rm -rvf grade.dSYM diff --git a/cs142/smcquay/lab03/grade.cc b/cs142/smcquay/lab03/grade.cc new file mode 100644 index 0000000..ef961be --- /dev/null +++ b/cs142/smcquay/lab03/grade.cc @@ -0,0 +1,211 @@ +#include +#include +#include +#include +#include + +using namespace std; + +const int MIN_SCORE = 0; +const string usage = "\ +usage: grade [-n, --by-name] [-p, --by-points] [-v, --verbose]"; + +struct student { + string name; + + int lab_score; + int exam_score; + + int final_score; + string letter_grade; +}; +typedef struct student student; + +ostream & operator<<(ostream & os, const student & s) { + os << "name: '" << s.name + << ", final score: " << s.final_score + << ", grade: " << s.letter_grade; + return os; +} + +bool sort_by_name(const student & a, const student & b) { + return a.name < b.name; +} + +bool sort_by_score(const student & a, const student & b) { + return a.final_score > b.final_score; +} + +struct grade { + int max_score; + int min_late_days; + int max_late_days; +}; +typedef struct grade grade; + +struct result { + int score; + int late_days; +}; +typedef struct result result; + +result collect_grade(string name, int score_max, + int late_min, int late_max, bool verbose); +string determine_letter_grade(int score); + +int main(int argc, char * argv[]) { + bool verbose = false; + bool by_points = false; + bool by_name = false; + for(int i = 0; i < argc; i++) { + string cur_arg = argv[i]; + if(cur_arg == "--verbose" or cur_arg == "-v") { + verbose = true; + } + if(cur_arg == "--by-points" or cur_arg == "-p") { + by_points = true; + } + if(cur_arg == "--by-name" or cur_arg == "-n") { + by_name = true; + } + if(cur_arg == "--help" or cur_arg == "-h") { + cout << usage << endl; + return 0; + } + } + if (by_points and by_name) { + cerr << "only specify one sort order" << endl; + return -1; + } + + map labs = { + {"Lab01", {20, -2, 2}}, + {"Lab02", {20, -2, 2}}, + {"Lab03", {30, -3, 3}}, + {"Lab04", {30, -3, 3}}, + {"Lab05", {30, -3, 3}}, + {"Lab06", {30, -3, 3}}, + {"Lab07", {30, -3, 3}}, + {"Lab08", {30, -3, 3}}, + {"Lab09", {20, -2, 2}}, + {"Lab10", {20, -2, 2}}, + {"Lab11", {40, -4, 4}}, + {"exam1", {100, 0, 3}}, + {"exam2", {100, 0, 3}}, + {"final", {100, 0, 3}}, + }; + + vector students; + + while (!cin.eof()) { + if(verbose) + cerr << "Please enter name of student: "; + string name; + getline(cin, name); + if (!name.empty()) { + int total_lab_points = 0; + int total_exam_points = 0; + + for(pair l: labs) { + string n = l.first; + grade g = l.second; + try { + result cur_result = collect_grade(n, g.max_score, + g.min_late_days, g.max_late_days, verbose); + + total_lab_points += cur_result.score; + + if (n.substr(0, 3) == "lab") + total_lab_points -= 5 * cur_result.late_days; + else if (n.substr(0, 4) == "exam" or n.substr(0, 4) == "final") + total_exam_points -= 20 * cur_result.late_days; + } catch (string e) { + cerr << e << endl; + return 1; + } + } + + + int final_score = total_lab_points + total_exam_points; + student s = {name, total_lab_points, total_exam_points, + final_score, determine_letter_grade(final_score)}; + students.push_back(s); + } + } + + if(by_name) { + sort(students.begin(), students.end(), sort_by_name); + } + else if (by_points) { + sort(students.begin(), students.end(), sort_by_score); + } + + for(student s: students) { + cout << s << endl; + } + + return 0; +} + +result collect_grade(string name, int score_max, + int late_min, int late_max, bool verbose=false) { + int score = 0; + if(verbose) { + cerr << "Please enter score for " << name + << "[" << MIN_SCORE << ", " << score_max << "]: "; + } + cin >> score; + if (!(MIN_SCORE <= score and score <= score_max)) { + ostringstream s; + s << score << " is not in accepted range: [" + << MIN_SCORE << ", " + << score_max << "]" << endl; + throw s.str(); + } + + int late_days; + if (verbose) { + cerr << "Please enter late days [" + << late_min << ", " << late_max << "]: "; + } + cin >> late_days; + if (!(late_min <= late_days and late_days <= late_max)) { + ostringstream s; + s << late_days << " is not in accepted range: [" + << late_min << ", " + << late_max << "]" << endl; + throw s.str(); + } + + result r = {score, late_days}; + return r; +} + +string determine_letter_grade(int score) { + string letter_grade; + if(score >= 570) + letter_grade = "A"; + if(score < 570 && score >=540) + letter_grade = "A-"; + if(score < 540 && score >= 522) + letter_grade = "B+"; + if(score < 522 && score >= 498) + letter_grade = "B"; + if(score < 498 && score >= 480) + letter_grade = "B-"; + if(score < 480 && score >= 462) + letter_grade = "C+"; + if(score < 462 && score >= 438) + letter_grade = "C"; + if(score < 438 && score >= 420) + letter_grade = "C-"; + if(score < 420 && score >= 402) + letter_grade = "D+"; + if(score < 402 && score >= 378) + letter_grade = "D"; + if(score < 378 && score >= 360) + letter_grade = "D-"; + if(score < 360) + letter_grade = "E"; + return letter_grade; +} diff --git a/cs142/smcquay/lab03/test.txt b/cs142/smcquay/lab03/test.txt new file mode 100644 index 0000000..147ad81 --- /dev/null +++ b/cs142/smcquay/lab03/test.txt @@ -0,0 +1,165 @@ +Stephen M. McQuay +10 0 +20 0 +25 0 +15 0 +30 0 +30 0 +30 0 +30 0 +20 0 +20 0 +40 0 +10 0 +81 0 +100 0 +Vanessa H. McQuay +20 0 +20 0 +30 0 +30 0 +30 0 +30 0 +0 0 +30 0 +20 0 +20 0 +40 0 +100 0 +100 0 +100 0 +Mardson H. McQuay +20 0 +20 0 +30 0 +30 0 +30 0 +30 0 +30 0 +30 0 +20 0 +20 0 +40 0 +100 0 +100 0 +100 0 +Penelope R. McQuay +20 0 +20 0 +30 0 +30 0 +30 0 +30 0 +30 0 +30 0 +20 0 +20 0 +40 0 +100 0 +100 0 +100 0 +Stott Q. McQuay +20 0 +20 0 +30 0 +30 0 +30 0 +30 0 +30 0 +30 0 +20 0 +20 0 +40 0 +100 0 +100 0 +100 0 +Michael M. McQuay +20 0 +20 0 +30 0 +30 0 +30 0 +30 0 +30 0 +30 0 +20 0 +20 0 +40 0 +100 0 +100 0 +100 0 +Alicia D. McQuay +20 0 +20 0 +30 0 +30 0 +30 0 +30 0 +30 0 +30 0 +20 0 +20 0 +40 0 +100 0 +100 0 +100 0 +Max Menahem McQuay +20 0 +20 0 +30 0 +30 0 +30 0 +30 0 +30 0 +30 0 +20 0 +20 0 +40 0 +100 0 +100 0 +100 0 +Bryan M. McQuay +20 0 +20 0 +30 0 +30 0 +30 0 +30 0 +30 0 +30 0 +20 0 +20 0 +40 0 +100 0 +100 0 +100 0 +Derek M. McQuay +20 -2 +20 -2 +30 -3 +30 -3 +30 -3 +30 -3 +30 -3 +30 -3 +20 -2 +20 -2 +40 -2 +100 0 +100 0 +99 1 +Colleen P. McQuay +20 -2 +20 -2 +30 -3 +30 -3 +30 -3 +30 -3 +30 -3 +30 -3 +20 -2 +20 -2 +40 -4 +100 0 +100 0 +100 0 diff --git a/cs142/smcquay/lab04/Makefile b/cs142/smcquay/lab04/Makefile new file mode 100644 index 0000000..45605e3 --- /dev/null +++ b/cs142/smcquay/lab04/Makefile @@ -0,0 +1,16 @@ +CPPFLAGS=-Wall -g -std=c++0x + +all: magic test00 test01 + +magic: magic.cc num_set.o converts.o + +test00: test00.cc num_set.o converts.o +test01: test01.cc num_set.o converts.o + +num_set.o: num_set.cc num_set.h +converts.o: converts.cc converts.h + +clean: + @rm -rfv test00 test00.dSYM + @rm -rfv test01 test01.dSYM + @rm -rvf magic magic.dSYM *.o diff --git a/cs142/smcquay/lab04/converts.cc b/cs142/smcquay/lab04/converts.cc new file mode 100644 index 0000000..6fe24a9 --- /dev/null +++ b/cs142/smcquay/lab04/converts.cc @@ -0,0 +1,17 @@ +#include +#include + +#include "converts.h" + +int str2int(string s) { + int r = 0; + int i = 0; + for(auto s_it = s.rbegin(); s_it != s.rend(); s_it++) { + if (*s_it == '1') { + r += pow(2, i); + } + + i++; + } + return r; +} diff --git a/cs142/smcquay/lab04/converts.h b/cs142/smcquay/lab04/converts.h new file mode 100644 index 0000000..45cfc29 --- /dev/null +++ b/cs142/smcquay/lab04/converts.h @@ -0,0 +1,10 @@ +#ifndef __CONVERTS_H__ +#define __CONVERTS_H__ + +#include + +using namespace std; + +int str2int(string i); + +#endif diff --git a/cs142/smcquay/lab04/magic.cc b/cs142/smcquay/lab04/magic.cc new file mode 100644 index 0000000..c70cede --- /dev/null +++ b/cs142/smcquay/lab04/magic.cc @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include "num_set.h" + +using namespace std; + +const string usage = "usage: magic "; + +int main(int argc, char * argv[]) { + string play_again; + srand(time(NULL)); + while (true) { + string cur_guess_str; + for(int i=0; i < 5; i++) { + int compliment = rand() % 2; + vector nums = generate_numbers(i, compliment); + cout << nums << endl << endl; + string cur_guess; + cout << "is your number in there: "; + cin >> cur_guess; + if(cur_guess[0] == 'y' or cur_guess[0] == 'Y') { + if(compliment == 0) + cur_guess_str.push_back('0'); + else + cur_guess_str.push_back('1'); + } else { + if(compliment == 0) + cur_guess_str.push_back('1'); + else + cur_guess_str.push_back('0'); + } + } + reverse(cur_guess_str.begin(), cur_guess_str.end()); + cout << cur_guess_str << ", " << str2int(cur_guess_str) << endl; + cout << "play again? "; + cin >> play_again; + + if(!(play_again[0] == 'y' or play_again[0] == 'Y')) + break; + } + cout << "good bye" << endl; + return 0; +} diff --git a/cs142/smcquay/lab04/num_set.cc b/cs142/smcquay/lab04/num_set.cc new file mode 100644 index 0000000..c1da96d --- /dev/null +++ b/cs142/smcquay/lab04/num_set.cc @@ -0,0 +1,38 @@ +#include +#include +#include + +#include "num_set.h" + +vector zerone = {"0", "1"}; + +vector generate_numbers(int constant_index, int compliment) { + vector r; + stringstream out; + out << compliment; + auto compliment_str = out.str(); + for(int i=0; i <= 1; i++) { + for(int j=0; j <= 1; j++) { + for(int k=0; k <= 1; k++) { + for(int l=0; l <= 1; l++) { + ostringstream cur_str; + cur_str << i << j << k << l; + string s = cur_str.str(); + s.insert(s.size() - constant_index, compliment_str); + r.push_back(s); + } + } + } + } + return r; +} + +ostream & operator<<(ostream & os, const vector & nums) { + for (unsigned int i = 0; i < nums.size(); i++) { + os << setw(4) << str2int(nums[i]); + if(i % 4 == 3 and i != nums.size() - 1) { + os << endl; + } + } + return os; +} diff --git a/cs142/smcquay/lab04/num_set.h b/cs142/smcquay/lab04/num_set.h new file mode 100644 index 0000000..05c4d63 --- /dev/null +++ b/cs142/smcquay/lab04/num_set.h @@ -0,0 +1,15 @@ +#ifndef __NUM_SET_H__ +#define __NUM_SET_H__ + +#include +#include +#include + +#include "converts.h" + +using namespace std; + +vector generate_numbers(int, int); +ostream & operator<<(ostream &, const vector &); + +#endif diff --git a/cs142/smcquay/lab04/test00.cc b/cs142/smcquay/lab04/test00.cc new file mode 100644 index 0000000..52fd5df --- /dev/null +++ b/cs142/smcquay/lab04/test00.cc @@ -0,0 +1,29 @@ +#include +#include +#include +#include "num_set.h" + +using namespace std; + +const string usage = "usage: test <0/1>"; + +int main(int argc, char * argv[]) { + if (argc < 3) { + cerr << usage << endl; + return 1; + } + int index, compliment; + istringstream iss0(argv[1]); + iss0 >> index; + index = index % 5; + istringstream iss1(argv[2]); + iss1 >> compliment; + compliment = compliment % 2; + + vector nums = generate_numbers(index, compliment); + + for(string i: nums) + cout << i << endl; + + return 0; +} diff --git a/cs142/smcquay/lab04/test01.cc b/cs142/smcquay/lab04/test01.cc new file mode 100644 index 0000000..f76de72 --- /dev/null +++ b/cs142/smcquay/lab04/test01.cc @@ -0,0 +1,20 @@ +#include +#include +#include "num_set.h" +#include "converts.h" + +using namespace std; + +const string usage = "usage: test <0/1>"; + +int main() { + vector nums = generate_numbers(0, 0); + + cout << "should print evens:" << endl; + for(string n: nums) { + int i = str2int(n); + cout << ">>> " << n << ", " << i << endl; + } + + return 0; +} diff --git a/cs142/smcquay/lab06/Makefile b/cs142/smcquay/lab06/Makefile new file mode 100644 index 0000000..0308dcc --- /dev/null +++ b/cs142/smcquay/lab06/Makefile @@ -0,0 +1,40 @@ +CXX=g++ +CPPFLAGS=-Wall -g -std=c++0x +SOURCES=restaurant.cc sm_array.cc collect.cc tournament.cc +OBJECTS=$(SOURCES:.cc=.o) +EXE=restaurant + +all: $(EXE) + +$(EXE): $(OBJECTS) + $(CXX) $(LDFLAGS) $(OBJECTS) -o $@ + +sm_array.o: sm_array.cc sm_array.h +collect.o: collect.cc collect.h sm_array.h +tournament.o: tournament.cc tournament.h + +test-display: test-display.cc sm_array.o collect.o test_constants.h +test-contains: test-contains.cc sm_array.o collect.o test_constants.h +test-remove: test-remove.cc sm_array.o collect.o test_constants.h +test-add: test-add.cc sm_array.o collect.o test_constants.h +test-random: test-random.cc sm_array.o collect.o test_constants.h + +clean: + @rm -vf *.o + @rm -rvf *.dSYM + @rm -vf restaurant + @rm -vf test-display + @rm -vf test-random + @rm -vf test-contains + @rm -vf test-remove + @rm -vf test-add + +test: test-random test-display test-contains test-remove test-add + ./test-display + ./test-contains + ./test-remove + ./test-add + @echo "remember to manually inspect test-random" + +run: restaurant + ./restaurant diff --git a/cs142/smcquay/lab06/collect.cc b/cs142/smcquay/lab06/collect.cc new file mode 100644 index 0000000..d68f866 --- /dev/null +++ b/cs142/smcquay/lab06/collect.cc @@ -0,0 +1,75 @@ +#include + +#include "collect.h" + + +ostream & operator<<(ostream & os, const vector & s) { + os << "menu:\n"; + for(auto i: s) { + os << " " << i << endl; + } + return os; +} + +garray initial_restaurants() { + garray a; + a.add("Cafe Rio"); + a.add("Pappa Murphy's"); + a.add("Quiznos"); + a.add("Jimmy Johns"); + a.add("Thai Chili Gardens"); + a.add("Subway"); + a.add("Taco Bell"); + a.add("India Palace"); + return a; +} + +garray populate_restaurants() { + string input; + bool running = true; + garray restaurants = initial_restaurants(); + while(running) { + cout << "\n" << menu << endl; + cout << "your selection: "; + cin >> input; + cout << endl; + if(input[0] == 'd') { + cout << restaurants << endl; + } + else if(input[0] == 'a') { + cout << "which restaurant should I ADD: "; + string name; + cin.ignore(); + getline(cin, name); + bool add_results = restaurants.add(name); + if(add_results) { + cout << "added '" << name << "' successfully!" << endl; + } + else { + cerr << "did not add: '" << name << "' " + << "(already there or max size)" << endl; + } + } + else if(input[0] == 'r') { + cout << "which restaurant should I REMOVE: "; + string name; + cin.ignore(); + getline(cin, name); + bool remove_results = restaurants.remove(name); + if(remove_results) { + cout << "removed '" << name << "' successfully!" << endl; + } + else { + cerr << "did not remove: '" << name << "' " + << "(probably not in array)" << endl; + } + } + else if(input[0] == 's') { + restaurants.randomize(); + } + else if(input[0] == 'b') { + running = false; + } + } + return restaurants; +} diff --git a/cs142/smcquay/lab06/collect.h b/cs142/smcquay/lab06/collect.h new file mode 100644 index 0000000..7d1d8f6 --- /dev/null +++ b/cs142/smcquay/lab06/collect.h @@ -0,0 +1,25 @@ +#ifndef __COLLECT_H__ +#define __COLLECT_H__ + +#include +#include +#include + +using namespace std; + +#include "sm_array.h" + +const vector menu = { + "(d)isplay", + "(a)dd", + "(r)emove", + "(s)huffle", + "(b)egin", +}; + +ostream & operator<<(ostream &, const vector &); + +garray initial_restaurants(); +garray populate_restaurants(); + +#endif diff --git a/cs142/smcquay/lab06/restaurant.cc b/cs142/smcquay/lab06/restaurant.cc new file mode 100644 index 0000000..f24be26 --- /dev/null +++ b/cs142/smcquay/lab06/restaurant.cc @@ -0,0 +1,20 @@ +#include + +using namespace std; + +#include "sm_array.h" +#include "collect.h" +#include "tournament.h" + +int main(int argc, char * argv[]) { + garray restaurants = populate_restaurants(); + string restaurant_to_rule_them_all; + try { + restaurant_to_rule_them_all = tournament(restaurants); + } + catch (string e) { + cerr << e << endl; + } + cout << ">>> winner: " << restaurant_to_rule_them_all << endl; + return 0; +} diff --git a/cs142/smcquay/lab06/sm_array.cc b/cs142/smcquay/lab06/sm_array.cc new file mode 100644 index 0000000..e35c49a --- /dev/null +++ b/cs142/smcquay/lab06/sm_array.cc @@ -0,0 +1,65 @@ +#include + +#include "sm_array.h" + +garray::garray(): size(0) {}; + +bool garray::add(string name) { + if(name == "") { + throw string("cannot add empty string"); + } + if((not contains(name)) and size < MAX_DATA_SIZE) { + data[size] = name; + size++; + return true; + } + else { + return false; + } +} + +bool garray::contains(string name) { + for(int i = 0; i < size; i++) { + if(name == data[i]) + return true; + } + return false; +} + +bool garray::remove(string name) { + bool reduce = false; + if(contains(name)) { + reduce = true; + } + else { + return reduce; + } + garray tmp; + for(int i = 0; i < size; i++) { + if(data[i] != name) { + tmp.add(data[i]); + } + } + for(int i = 0; i < MAX_DATA_SIZE; i++) { + data[i] = tmp.data[i]; + } + if(reduce) + size--; + return reduce; +} + +void garray::randomize() { + random_shuffle(&data[0], &data[size]); +} + +ostream & operator<<(ostream & os, garray & g) { + os << "["; + for(int i = 0; i < g.size; i++) { + os << i << "-" << g.data[i]; + if (i != g.size - 1) { + os << ", "; + } + } + os << "]"; + return os; +} diff --git a/cs142/smcquay/lab06/sm_array.h b/cs142/smcquay/lab06/sm_array.h new file mode 100644 index 0000000..f0a0580 --- /dev/null +++ b/cs142/smcquay/lab06/sm_array.h @@ -0,0 +1,28 @@ +#ifndef __SM_ARRAY_H__ +#define __SM_ARRAY_H__ + +#include +#include + +using namespace std; + +const int MAX_DATA_SIZE = 16; + +struct garray { + // gimpy string container that cannot be larger than 16, + // and cannot contain empty strings + + int size; + string data [MAX_DATA_SIZE]; + + garray(); + + bool add(string name); + bool remove(string name); + void randomize(); + bool contains(string name); +}; + +ostream & operator<<(ostream &, garray &); + +#endif diff --git a/cs142/smcquay/lab06/test-add.cc b/cs142/smcquay/lab06/test-add.cc new file mode 100644 index 0000000..8551484 --- /dev/null +++ b/cs142/smcquay/lab06/test-add.cc @@ -0,0 +1,43 @@ +#include +#include + +using namespace std; + +#include "sm_array.h" +#include "collect.h" +#include "test_constants.h" + + +int main(int argc, char * argv[]) { + garray a; + + bool raised_error = false; + bool correct_error_string = false; + try { + a.add(""); + } + catch (string e) { + raised_error = true; + if(e == "cannot add empty string") { + correct_error_string = true; + } + } + + if(not raised_error) { + cerr << "should have raised an error trying to add an empty string" << endl; + return 1; + } + + if(not correct_error_string) { + cerr << "incorrect error string" << endl; + return 1; + } + + garray g = initial_restaurants(); + if(g.add("Cafe Rio") or g.add("Jimmy Johns") or not g.add("Jimbo White")) { + cerr << "shouldn't be able to add something that's already in there" << endl; + return 1; + } + + return 0; +} diff --git a/cs142/smcquay/lab06/test-contains.cc b/cs142/smcquay/lab06/test-contains.cc new file mode 100644 index 0000000..689fcfe --- /dev/null +++ b/cs142/smcquay/lab06/test-contains.cc @@ -0,0 +1,40 @@ +#include +#include + +using namespace std; + +#include "sm_array.h" +#include "collect.h" +#include "test_constants.h" + + +int main(int argc, char * argv[]) { + garray a = initial_restaurants(); + + if(a.contains("Shifty Pete's Tacos")) { + cerr << "should not contain \"Shifty Pete's Tacos\"" << endl; + return 1; + } + + if(not a.contains("Taco Bell")) { + cerr << "Should have Taco Bell" << endl; + return 1; + } + + if(not a.contains("Cafe Rio")) { + cerr << "Failed test at beginning" << endl; + return 1; + } + + if(not a.contains("India Palace")) { + cerr << "Failed test at end" << endl; + return 1; + } + + if(a.contains("")) { + cerr << "should not contain empty string" << endl; + return 1; + } + + return 0; +} diff --git a/cs142/smcquay/lab06/test-display.cc b/cs142/smcquay/lab06/test-display.cc new file mode 100644 index 0000000..f55fda8 --- /dev/null +++ b/cs142/smcquay/lab06/test-display.cc @@ -0,0 +1,29 @@ +#include +#include +#include + + +using namespace std; + +#include "sm_array.h" +#include "collect.h" +#include "test_constants.h" + + +int main(int argc, char * argv[]) { + garray a = initial_restaurants(); + ostringstream output; + output << a; + + if(output.str() != TEST_ARRAY_OUTPUT) { + cerr << "problem with text output" << endl; + return 1; + } + + if(a.size != TEST_ARRAY_SIZE) { + cerr << "problem with expected test array size" << endl; + return 1; + } + + return 0; +} diff --git a/cs142/smcquay/lab06/test-random.cc b/cs142/smcquay/lab06/test-random.cc new file mode 100644 index 0000000..42fc64b --- /dev/null +++ b/cs142/smcquay/lab06/test-random.cc @@ -0,0 +1,22 @@ +#include +#include +#include + +using namespace std; + +#include "sm_array.h" +#include "collect.h" +#include "test_constants.h" + + +int main(int argc, char * argv[]) { + srand(time(NULL)); + garray a = initial_restaurants(); + cout << " >>> " << a << endl; + cout << "should print the previous array in random orders: " << endl; + for(int i = 0; i < 10; i++) { + a.randomize(); + cout << " >>> " << a << endl; + } + return 0; +} diff --git a/cs142/smcquay/lab06/test-remove.cc b/cs142/smcquay/lab06/test-remove.cc new file mode 100644 index 0000000..3b63a66 --- /dev/null +++ b/cs142/smcquay/lab06/test-remove.cc @@ -0,0 +1,89 @@ +#include +#include +#include + + +using namespace std; + +#include "sm_array.h" +#include "collect.h" +#include "test_constants.h" + + +int main(int argc, char * argv[]) { + ostringstream output; + garray a = initial_restaurants(); + string expected; + bool successful_removal; + int expected_size; + + successful_removal = a.remove(""); + output << a; + expected = TEST_ARRAY_OUTPUT; + expected_size = 8; + if(output.str() != expected + and a.size != expected_size + and successful_removal) { + cerr << "improper removal of empty string" << endl; + cerr << "have: " << a << ", " << a.size << endl; + cerr << "expected: " << expected << ", " << expected_size << endl; + return 1; + } + + successful_removal = a.remove("Taco Bell"); + output << a; + expected = "[Cafe Rio, Pappa Murphy's, Quiznos, Jimmy Johns, Thai Chili Gardens, Subway, India Palace]"; + expected_size = 7; + if(output.str() != expected + and a.size != expected_size + and not successful_removal) { + cerr << "improper removal from middle (Taco Bell)" << endl; + cerr << "have: " << a << ", " << a.size << endl; + cerr << "expected: " << expected << ", " << expected_size << endl; + return 1; + } + + successful_removal = a.remove("India Palace"); + output.str(""); + output << a; + expected = "[Cafe Rio, Pappa Murphy's, Quiznos, Jimmy Johns, Thai Chili Gardens, Subway]"; + expected_size = 6; + if(output.str() != expected + and a.size != expected_size + and not successful_removal) { + cerr << "improper removal from end (India palace)" << endl; + cerr << "have: " << a << ", " << a.size << endl; + cerr << "expected: " << expected << ", " << expected_size << endl; + return 1; + } + + successful_removal = a.remove("Shitar's Palace"); + output.str(""); + output << a; + // same expected as last time + expected_size = 6; + if(output.str() != expected + and a.size != expected_size + and successful_removal) { + cerr << "improper removal of value that is not in the list" << endl; + cerr << "have: " << a << ", " << a.size << endl; + cerr << "expected: " << expected << ", " << expected_size << endl; + return 1; + } + + successful_removal = a.remove("Cafe Rio"); + output.str(""); + output << a; + expected = "[Pappa Murphy's, Quiznos, Jimmy Johns, Thai Chili Gardens, Subway]"; + expected_size = 6; + if(output.str() != expected + and a.size != expected_size + and not successful_removal) { + cerr << "improper removal from beginning (Cafe Rio)" << endl; + cerr << "have: " << a << ", " << a.size << endl; + cerr << "expected: " << expected << ", " << expected_size << endl; + return 1; + } + + return 0; +} diff --git a/cs142/smcquay/lab06/test_constants.h b/cs142/smcquay/lab06/test_constants.h new file mode 100644 index 0000000..851d8af --- /dev/null +++ b/cs142/smcquay/lab06/test_constants.h @@ -0,0 +1,12 @@ +#ifndef __TESTFUNCS_H__ +#define __TESTFUNCS_H__ + +#include + +const std::string TEST_ARRAY_OUTPUT = +"[0-Cafe Rio, 1-Pappa Murphy's, 2-Quiznos, " +"3-Jimmy Johns, 4-Thai Chili Gardens, 5-Subway, 6-Taco Bell, 7-India Palace]"; + +const int TEST_ARRAY_SIZE = 8; + +#endif diff --git a/cs142/smcquay/lab06/tournament.cc b/cs142/smcquay/lab06/tournament.cc new file mode 100644 index 0000000..a624028 --- /dev/null +++ b/cs142/smcquay/lab06/tournament.cc @@ -0,0 +1,46 @@ +#include +#include +#include +using namespace std; + +#include "tournament.h" + +int is_pow_2 (unsigned int x) { + return ((x != 0) && ((x & (~x + 1)) == x)); +} + +string tournament(garray & restaurants) { + if(not is_pow_2(restaurants.size)){ + ostringstream o; + o << restaurants.size << " is not a power of 2"; + throw o.str(); + } + + string selection; + + bool finished = false; + while(not finished) { + garray tmp; + for(int i=0; i < restaurants.size / 2; i++) { + int a_i = 2*i; + int b_i = a_i + 1; + string a = restaurants.data[a_i]; + string b = restaurants.data[b_i]; + cout << "(a) " << a << " (b) " << b << endl; + cout << "your selection: "; + cin >> selection; + if(selection[0] == 'a') + tmp.add(a); + else + tmp.add(b); + } + if(tmp.size == 1) { + finished = true; + selection = tmp.data[0]; + } + else { + restaurants = tmp; + } + } + return selection; +} diff --git a/cs142/smcquay/lab06/tournament.h b/cs142/smcquay/lab06/tournament.h new file mode 100644 index 0000000..56cf601 --- /dev/null +++ b/cs142/smcquay/lab06/tournament.h @@ -0,0 +1,11 @@ +#ifndef __TOURNAMENT_H__ +#define __TOURNAMENT_H__ + +#include +using namespace std; + +#include "sm_array.h" + +string tournament(garray &); + +#endif diff --git a/cs142/smcquay/lab07/Makefile b/cs142/smcquay/lab07/Makefile new file mode 100644 index 0000000..65e0086 --- /dev/null +++ b/cs142/smcquay/lab07/Makefile @@ -0,0 +1,32 @@ +CXX=g++ +CPPFLAGS=-Wall -g -std=c++0x +SOURCES=cookies.cc main.cc +OBJECTS=$(SOURCES:.cc=.o) +EXE=app + +all: $(EXE) + +main.o: cookies.cc cookies.h +cookies.o: cookies.cc cookies.h + +$(EXE): $(OBJECTS) + $(CXX) $(LDFLAGS) $(OBJECTS) -o $@ + + +clean: + @rm -vf *.o + @rm -rvf *.dSYM + @rm -vf app + + +run: $(EXE) + ./$(EXE) + +debug: $(EXE) + gdb $(EXE) + +valgrind: $(EXE) + valgrind --tool=memcheck --leak-check=yes ./$(EXE) + +autov: $(EXE) + valgrind --tool=memcheck --leak-check=yes ./$(EXE) < test.txt diff --git a/cs142/smcquay/lab07/cookies.cc b/cs142/smcquay/lab07/cookies.cc new file mode 100644 index 0000000..749884b --- /dev/null +++ b/cs142/smcquay/lab07/cookies.cc @@ -0,0 +1,92 @@ +#include +#include + +#include "cookies.h" + +void addOrder(string * cookies[], int * size, string new_name) { + string * s = findOrder(cookies, size, new_name); + if(s == NULL) + s = new string(new_name); + cookies[*size] = s; + (*size)++; +} + +int deliverOrder(string * cookies[], int * size, string name) { + string * s = findOrder(cookies, size, name); + if(s == NULL) + return 0; + + // interesting note, temp_cookies gets allocatied on the stack and (see + // note above return) ... + string * temp_cookies [MAXIMUM_SIZE] = {}; + + int removes = 0; + int temp_pos = 0; + for(int i = 0; i < *size; i++) { + if(cookies[i] == s) { + // pass + removes += 1; + } + else { + temp_cookies[temp_pos] = cookies[i]; + temp_pos++; + } + } + + // copy from the tmp buffer into the original passed-by-pointer array + for(int i = 0; i < temp_pos; i++) { + cookies[i] = temp_cookies[i]; + } + + *size = temp_pos; + + // this removes the memory newed above (in addOrder) from the HEAP + delete s; + + // ... temp_cookies (along with removes and temp_pos) gets cleaned up at + // this point ... Stack stack stack + return removes; +} + +bool modifyOrder(string * cookies[], int * size, string original_name, string new_name) { + string * s = findOrder(cookies, size, original_name); + if(s == NULL) + return false; + + *s = new_name; + return true; +} + +string displayOrders(string * cookies[], int * size) { + string r; + for(int i=0; i < *size; i++) { + r += *cookies[i]; + if(i < *size - 1) + r += ", "; + } + return r; +} + +string * findOrder(string * cookies[], int * size, string name) { + string * r = NULL; + for(int i=0; i<*size; i++) { + if(*cookies[i] == name) { + r = cookies[i]; + break; + } + } + return r; +} + +void clean_up(string * cookies[], int * size) { + string * deletable_cookies [MAXIMUM_SIZE] = {}; + int del_size = 0; + for(int i = 0; i < *size; i++) { + if(!findOrder(deletable_cookies, &del_size, *cookies[i])) { + deletable_cookies[del_size] = cookies[i]; + del_size++; + } + } + for(int i = 0; i < del_size; i++) + delete deletable_cookies[i]; +} diff --git a/cs142/smcquay/lab07/cookies.h b/cs142/smcquay/lab07/cookies.h new file mode 100644 index 0000000..8b30c57 --- /dev/null +++ b/cs142/smcquay/lab07/cookies.h @@ -0,0 +1,73 @@ +#ifndef __COOKIES_H__ +#define __COOKIES_H__ + +#include +using namespace std; + +const int MAXIMUM_SIZE = 10; + +/* + addOrder + + Adds the memory address of a new string to the given array. The new string should have the + same data as that of the given string. + + A string may already exist containing the same data as the given string (ie, the string + passed to this function as a parameter) and whose memory address is already stored within + the given array. In this situation, add to the array the memory address of the string that + already exists rather than creating a new string. + + Update the reference of size appropriately. +*/ +void addOrder(string * cookies[], int * size, string new_name); + + +/* + deliverOrder + + Removes all references to strings containing the same data as the given string and reports + the number of string references removed. The overall order of the list is unchanged. + + Update the reference of size appropriately. +*/ +int deliverOrder(string * cookies[], int * size, string name); + + +/* + modifyOrder + + Searches the given array for a memory address to a string that contains the same data as the + first given string. + + If found, the data of the found string is changed to match the data of the second given string, + and the function returns true. If not found, the function returns false. +*/ +bool modifyOrder(string * cookies[], int * size, string original_name, string new_name); + + +/* + displayOrders + + Returns a string containing a list of names referred to in the given array. + Each index in the array represents a particular box of cookies, and there may be more than + one box for each customer. Therefore, this function's output may include the same name + multiple times. +*/ +string displayOrders(string * cookies[], int * size); + + +/* + findOrder + + Returns a memory address found in the given array that references a string with the same data + as the given string. Returns null if no such string is found. + + It is recommended that you use this function within your other functions. If you do not, you + must still complete this function as described above. +*/ +string * findOrder(string * cookies[], int * size, string name); + +void clean_up(string * cookies[], int * size); + +#endif + diff --git a/cs142/smcquay/lab07/main.cc b/cs142/smcquay/lab07/main.cc new file mode 100644 index 0000000..38905f0 --- /dev/null +++ b/cs142/smcquay/lab07/main.cc @@ -0,0 +1,130 @@ +#include +#include + +using namespace std; + +#include "cookies.h" + + +int getOption(int range); +string getName(string message); + +int main() +{ + string * cookies [MAXIMUM_SIZE] = {}; + int x = 0; + int * size = &(x); + + bool done = false; + while(!done) + { + //Get menu option + cout << "MENU:" << endl; + cout << "\t1. Add an order\n\t2. Deliver an order\n\t3. Modify an order\n\t4. Quit\n" << endl; + int option = getOption(4); + + //Adding + if(option==1) + { + if((*size) >= MAXIMUM_SIZE) + { + cout << "The car is full; cannot add more orders" << endl; + } + else + { + string new_name = getName("Please enter the customer's name for the new order:"); + addOrder(cookies, size, new_name); + cout << "Cookies added for costumer [" << new_name << "]" << endl; + } + } + + //Delivering + else if(option==2) + { + string name = getName("Please enter the customer's name for the delivery:"); + int delivered = deliverOrder(cookies, size, name); + cout << "Delivered " << delivered << " boxes of cookies to [" << name << "]" << endl; + } + + //Modifying + else if(option==3) + { + string original_name = getName("Please enter the original customer's name of the order:"); + string new_name = getName("Please enter the new customer's name for the order:"); + bool changed = modifyOrder(cookies,size,original_name,new_name); + if(changed) + { + cout << "Changed name from [" << original_name << "] to [" << new_name << "]" << endl; + } + else + { + cout << "Could not find a customer with the name: [" << original_name << "]" << endl; + } + } + + //Quitting + else if(option==4) + { + done = true; + } + + cout << displayOrders(cookies, size) << endl; + } + + clean_up(cookies, size); + + cout << "Thank you for using the cookie tracker!" << endl; + //The following line may not work on all systems; therefore, you may change this line as needed + return 0; +} + +int getOption(int range) +{ + int input = 0; + bool done = false; + while(!done) + { + cout << "Please select an option:" << endl; + input = 0; + cin >> input; + cin.ignore(1000,'\n'); + if(cin.fail()) + { + cin.clear(); + cin.ignore(1000,'\n'); + cout << "Error: Invalid option" << endl; + } + else if(input < 1 || input > range) + { + cout << "Error: Invalid option number" << endl; + } + else + { + done = true; + } + } + return input; +} + +string getName(string message) +{ + string input = ""; + bool done = false; + while(!done) + { + cout << message << endl; + input = ""; + getline(cin, input); + if(cin.fail()) + { + cin.clear(); + cin.ignore(1000,'\n'); + cout << "Error: Invalid name" << endl; + } + else + { + done = true; + } + } + return input; +} diff --git a/cs142/smcquay/lab07/test.txt b/cs142/smcquay/lab07/test.txt new file mode 100644 index 0000000..1895a6f --- /dev/null +++ b/cs142/smcquay/lab07/test.txt @@ -0,0 +1,17 @@ +1 +stephen +1 +michael +1 +michael +1 +stephen +1 +derek +3 +stephen +Stephen Mardson McQuay +2 +michael +2 +derek diff --git a/cs142/smcquay/lab08/Makefile b/cs142/smcquay/lab08/Makefile new file mode 100644 index 0000000..ac0e45b --- /dev/null +++ b/cs142/smcquay/lab08/Makefile @@ -0,0 +1,37 @@ +CXX=g++ +CPPFLAGS=-Wall -g -std=c++0x +SOURCES=main.cc menu.cc person.cc people.cc +OBJECTS=$(SOURCES:.cc=.o) +EXE=app + +all: $(EXE) + +main.o: main.cc person.o people.o menu.o +menu.o: menu.h menu.cc +person.o: person.cc person.h +people.o: people.cc people.h + +$(EXE): $(OBJECTS) + $(CXX) $(LDFLAGS) $(OBJECTS) -o $@ + + +clean: + @rm -vf *.o + @rm -rvf *.dSYM + @rm -vf app + + +run: $(EXE) + ./$(EXE) + +test: $(EXE) + ./$(EXE) < test.txt + +debug: $(EXE) + gdb $(EXE) + +valgrind: $(EXE) + valgrind --tool=memcheck --leak-check=yes ./$(EXE) + +autov: $(EXE) + valgrind --tool=memcheck --leak-check=yes ./$(EXE) < test.txt diff --git a/cs142/smcquay/lab08/main.cc b/cs142/smcquay/lab08/main.cc new file mode 100644 index 0000000..c77a1d0 --- /dev/null +++ b/cs142/smcquay/lab08/main.cc @@ -0,0 +1,102 @@ +#include +#include +#include + +using namespace std; + +#include "menu.h" +#include "person.h" +#include "people.h" + +int main() { + people peeps; + peeps.add_person("Kevin Bacon", "bacon"); + + menu m; + string option; + bool done = false; + while(not done) { + cout << endl << m; + getline(cin, option); + if(option[0] == '#') + continue; + if (option[0] == 'a') { + cout << "adding a person" << endl; + string name, food; + cout << "name: "; + getline(cin, name); + cout << "food: "; + getline(cin, food); + peeps.add_person(name, food); + } + else if (option[0] == 'd') { + cout << "displaying people" << endl; + cout << peeps << endl; + } + else if (option[0] == 'm') { + cout << "make connection" << endl; + cout << peeps << endl; + try { + unsigned int a, b; + get_two_indices(peeps, a, b); + peeps.connect(a, b); + } + catch(string e) { + cerr << e << endl; + } + } + else if (option[0] == 'b') { + cout << "break connection" << endl; + cout << peeps << endl; + try { + unsigned int a, b; + get_two_indices(peeps, a, b); + peeps.unfriend(a, b); + } + catch(string e) { + cerr << e << endl; + } + } + else if (option[0] == 'c') { + cout << "change food" << endl; + cout << peeps << endl; + try { + unsigned int a; + get_index(peeps, a, "enter index of person who needs changing: "); + cout << "new food: "; + cin.ignore(); + getline(cin, option); + peeps.food_update(a, option); + } + catch(string e) { + cerr << e << endl; + } + } + else if (option[0] == 's') { + cout << "show food friends" << endl; + try { + unsigned int a; + get_index(peeps, a, "enter index of person for food friend: "); + peeps[a]->food_friend(); + } + catch(string e) { + cerr << e << endl; + } + } + else if (option[0] == 'e') { + try { + unsigned int a; + get_index(peeps, a, "enter index of person for who I shall calculate the Bacon Number: "); + cout << peeps[a]->bacon_number() << endl; + } + catch(string e) { + cerr << e << endl; + } + } + else if (option[0] == 'q') { + cout << "quitting" << endl; + done = true; + } + } + return 0; +} diff --git a/cs142/smcquay/lab08/menu.cc b/cs142/smcquay/lab08/menu.cc new file mode 100644 index 0000000..7beec4e --- /dev/null +++ b/cs142/smcquay/lab08/menu.cc @@ -0,0 +1,30 @@ +#include +using namespace std; +#include "menu.h" + +void get_index(people & p, unsigned int & a, string msg="") { + cout << msg; + cin >> a; + if(a >= p.size()) { + throw string("Not in range!!"); + } +} + +void get_two_indices(people & p, unsigned int & a, unsigned int & b) { + if(p.size() < 2) { + throw string("Not enough people to perform this operation."); + } + get_index(p, a, "enter first index: "); + get_index(p, b, "enter second index: "); + if(a == b) { + throw string("indices need to be different"); + } +} + +ostream & operator<<(ostream & os, const menu & m) { + for(auto i: menu_items) { + os << " " << i << endl; + } + os << "your selection: "; + return os; +} diff --git a/cs142/smcquay/lab08/menu.h b/cs142/smcquay/lab08/menu.h new file mode 100644 index 0000000..113deab --- /dev/null +++ b/cs142/smcquay/lab08/menu.h @@ -0,0 +1,30 @@ +#ifndef __MENU_H__ +#define __MENU_H__ + +#include +#include +#include +using namespace std; + +#include "people.h" + +const vector menu_items = { + "(a)dd person", + "(d)isplay", + "(m)ake connection", + "(b)reak connection", + "(c)hange food", + "(s)how food friends", + "(e)xtra credit (bacon number)", + "", + "(q)uit", +}; + +class menu {}; + +void get_index(people &, unsigned int &, string); +void get_two_indices(people &, unsigned int &, unsigned int &); + +ostream & operator<<(ostream & os, const menu & m); + +#endif diff --git a/cs142/smcquay/lab08/people.cc b/cs142/smcquay/lab08/people.cc new file mode 100644 index 0000000..33d3e6d --- /dev/null +++ b/cs142/smcquay/lab08/people.cc @@ -0,0 +1,65 @@ +#include "people.h" + +people::~people() { + for(auto i: persons) { + delete i; + } +} + +bool people::contains(string name) { + for(auto i: persons) { + if(i->name == name) { + return true; + } + } + return false; +} + +void people::add_person(string name, string food) { + if(not contains(name)) { + person * tmp = new person(name, food); + persons.push_back(tmp); + } +} + +void people::connect(unsigned int a, unsigned int b) { + cout << *this << endl; + person * p1 = persons[a]; + person * p2 = persons[b]; + p1->friends.insert(p2); + p2->friends.insert(p1); +} + +void people::unfriend(unsigned int a, unsigned int b) { + cout << *this << endl; + person * p1 = persons[a]; + person * p2 = persons[b]; + + auto p2it = p1->friends.find(p2); + if(p2it != p1->friends.end()) + p1->friends.erase(p2it); + + auto p1it = p2->friends.find(p1); + if(p1it != p2->friends.end()) + p2->friends.erase(p1it); +} + +void people::food_update(unsigned int a, string new_food) { + persons[a]->update_food(new_food); +} + +unsigned int people::size() { + return persons.size(); +} + +person * people::operator[](unsigned int i) { + return persons[i]; +} + +ostream & operator<<(ostream & os, people & p) { + os << "people (" << p.persons.size() << "):" << endl; + for(unsigned int i=0; i < p.persons.size(); i++) { + os << i << " : " << *p.persons[i] << endl; + } + return os; +} diff --git a/cs142/smcquay/lab08/people.h b/cs142/smcquay/lab08/people.h new file mode 100644 index 0000000..c3b7687 --- /dev/null +++ b/cs142/smcquay/lab08/people.h @@ -0,0 +1,29 @@ +#ifndef __PEOPLE_H__ +#define __PEOPLE_H__ + +#include +#include +#include +using namespace std; + +#include "person.h" + +class people { + vector persons; +public: + + ~people(); + + unsigned int size(); + bool contains(string); + void add_person(string, string); + void food_update(unsigned int, string); + + void connect(unsigned int, unsigned int); + void unfriend(unsigned int, unsigned int); + person * operator[](unsigned int); + + friend ostream & operator<<(ostream &, people &); +}; + +#endif diff --git a/cs142/smcquay/lab08/person.cc b/cs142/smcquay/lab08/person.cc new file mode 100644 index 0000000..5ce8e87 --- /dev/null +++ b/cs142/smcquay/lab08/person.cc @@ -0,0 +1,53 @@ +using namespace std; +#include "person.h" + +void person::update_food(string new_food) { + if(name != "Kevin Bacon") + favorite_food = new_food; +} + +void person::food_friend() { + cout << "freinds for " << this->name << " with similar tastes: ["; + for(auto i = friends.begin(); i != friends.end(); i++) { + if((*i)->favorite_food == this->favorite_food) { + cout << "'" << (*i)->name << "', "; + } + } + cout << "]" << endl; +} + +int person::bacon_number() { + return 0; +} + +ostream &operator<<(ostream &stream, person & p) { + stream << "{name: '" << p.name + << "', favorite_food: '" << p.favorite_food + << "'"; + + if(p.friends.size() > 0) { + stream << ", friends: ["; + for(auto i = p.friends.begin(); i != p.friends.end(); i++) { + if (i != p.friends.begin()) { + stream << ", "; + } + stream << "'" << (*i)->name << "'"; + } + stream << "]"; + } + + stream << "}"; + return stream; +} + +istream &operator>>(istream &stream, person &o) { + string buffer; + cout << "name: "; + stream.ignore(); + getline(stream, buffer); + o.name = buffer; + cout << "food: "; + getline(stream, buffer); + o.favorite_food = buffer; + return stream; +} diff --git a/cs142/smcquay/lab08/person.h b/cs142/smcquay/lab08/person.h new file mode 100644 index 0000000..8ce4df2 --- /dev/null +++ b/cs142/smcquay/lab08/person.h @@ -0,0 +1,25 @@ +#ifndef __PERSON_H__ +#define __PERSON_H__ + +#include +#include +#include +using namespace std; + +class person { + private: + friend class people; + string name; + string favorite_food; + set friends; + public: + person(string name, string food): name(name), favorite_food(food) {}; + void update_food(string); + void food_friend(); + int bacon_number(); + friend ostream & operator<<(ostream &, person &); + friend istream & operator>>(istream &, person &); +}; + + +#endif diff --git a/cs142/smcquay/lab08/test.txt b/cs142/smcquay/lab08/test.txt new file mode 100644 index 0000000..e68350e --- /dev/null +++ b/cs142/smcquay/lab08/test.txt @@ -0,0 +1,138 @@ +# stephen is 1 +a +stephen mcquay +panda steaks + +# vanessa is 2 +a +vanessa mcquay +pringles + +# stephen <-> vanessa +m +1 +2 + +# no-op +m +1 +2 + +# derek is 3 +a +derek mcquay +panda steaks + +# colleen is 4 +a +colleen +panda steaks + +# out of range +m +12 + +# derek <-> colleen +m +3 +4 + +# stephen <-> derek +m +1 +3 + +# stephen <-> colleen +m +1 +4 + +d + +# no-op +b +0 +1 + +# stephen <-> Kevin Bacon +m +0 +1 + +d + +# not allowed: +c +0 +Bacon Bits + +# Stephen's food is now Bacon Bits +c +1 +Bacon Bits + +d + +# michael is 5 +a +Michael +sushi + +# bilbo is 6 +a +Bilbo Baggins +Bacon Bits + +# frodo is 7 +a +Frodo Baggins +Bacon Bits + +d + + +# stephen <-> michael +m +1 +5 + +# stephen <-> bilbo +m +1 +6 + +# stephen <-> frodo +m +1 +7 + +d + +# show stephen has a few friends who love bacon bits +s +1 + +c +1 +bacon + +# show Kevin Bacon's friends +s +0 + +# remove friendship: stephen <-> bilbo +b +0 +6 + +# show kevin bacon's friends +s +0 + +# bacon number for stephen: +e +1 + +d + +q diff --git a/cs142/smcquay/lab09/Makefile b/cs142/smcquay/lab09/Makefile new file mode 100644 index 0000000..c235371 --- /dev/null +++ b/cs142/smcquay/lab09/Makefile @@ -0,0 +1,29 @@ +CXX=g++ +CPPFLAGS=-Wall -g -std=c++0x +SOURCES=main.cc util.cc person.cc +OBJECTS=$(SOURCES:.cc=.o) +EXE=restaurant + +all: $(EXE) + +main.o: main.cc util.o person.o +util.o: util.h util.cc +person.o: person.cc person.h + +$(EXE): $(OBJECTS) + $(CXX) $(LDFLAGS) $(OBJECTS) -o $@ + +run: $(EXE) + ./$(EXE) people.db /tmp/output.db + cat /tmp/output.db + +clean: + @rm -vf *.o + @rm -rvf *.dSYM + @rm -vf $(EXE) + +debug: $(EXE) + gdb $(EXE) + +valgrind: $(EXE) + valgrind --tool=memcheck --leak-check=yes ./$(EXE) people.db /tmp/output.db diff --git a/cs142/smcquay/lab09/main.cc b/cs142/smcquay/lab09/main.cc new file mode 100644 index 0000000..f19eb01 --- /dev/null +++ b/cs142/smcquay/lab09/main.cc @@ -0,0 +1,29 @@ +#include +#include +#include +#include + +using namespace std; + +#include "person.h" +#include "util.h" + +const string usage = "usage: app "; + +int main(int argc, char * argv []) { + if(argc != 3) { + cerr << usage << endl; + return 1; + } + string input_filename(argv[1]); + string output_filename(argv[2]); + try { + vector people = parse_file(input_filename); + save_file(output_filename, people); + } + catch(runtime_error e) { + cerr << e.what() << endl; + return 1; + } + return 0; +} diff --git a/cs142/smcquay/lab09/people.db b/cs142/smcquay/lab09/people.db new file mode 100644 index 0000000..a264d51 --- /dev/null +++ b/cs142/smcquay/lab09/people.db @@ -0,0 +1,3 @@ +stephen mcquay , 31 +derek mcquay , 21 + jimmy joshn shimmershi ne the fourth , 32 diff --git a/cs142/smcquay/lab09/person.cc b/cs142/smcquay/lab09/person.cc new file mode 100644 index 0000000..83c9910 --- /dev/null +++ b/cs142/smcquay/lab09/person.cc @@ -0,0 +1,7 @@ +#include +#include "person.h" + +ostream & operator<<(ostream & os, person & p) { + os << p.name << ", " << p.age; + return os; +} diff --git a/cs142/smcquay/lab09/person.h b/cs142/smcquay/lab09/person.h new file mode 100644 index 0000000..26ba7d4 --- /dev/null +++ b/cs142/smcquay/lab09/person.h @@ -0,0 +1,16 @@ +#ifndef __PERSON_H__ +#define __PERSON_H__ + +#include +#include +using namespace std; + +struct person { + string name; + int age; + + person(string name, int age): name(name), age(age) {}; + friend ostream & operator<<(ostream & os, person & p); +}; + +#endif diff --git a/cs142/smcquay/lab09/util.cc b/cs142/smcquay/lab09/util.cc new file mode 100644 index 0000000..2f09ad0 --- /dev/null +++ b/cs142/smcquay/lab09/util.cc @@ -0,0 +1,82 @@ +#include +#include +#include +#include +#include +#include +using namespace std; + +#include "util.h" +#include "person.h" + +ostream & operator<<(ostream & os, vector & v) { + os << "["; + for(unsigned int i = 0; i < v.size(); i++) { + os << v[i]; + if(i != v.size() - 1) { + os << ", "; + } + } + os << "]"; + return os; +} + +vector tokenize(const string & str, const string & delimiters) { + vector tokens; + // Skip delimiters at beginning. + string::size_type lastPos = str.find_first_not_of(delimiters, 0); + // Find first "non-delimiter". + string::size_type pos = str.find_first_of(delimiters, lastPos); + while (string::npos != pos || string::npos != lastPos) + { + // Found a token, add it to the vector. + tokens.push_back(str.substr(lastPos, pos - lastPos)); + // Skip delimiters. Note the "not_of" + lastPos = str.find_first_not_of(delimiters, pos); + // Find next "non-delimiter" + pos = str.find_first_of(delimiters, lastPos); + } + return tokens; +} + +vector parse_file(string filename) { + ifstream inputs(filename.c_str()); + if(inputs.good()) { + vector people; + string line; + int age; + + while(getline(inputs, line)) { + vector tokens = tokenize(line, ","); + string name = tokens[0]; + string age_s = tokens[1]; + + //clean up name + vector name_tokens = tokenize(name, " "); + name.clear(); + for(unsigned int i = 0; i < name_tokens.size(); i++) { + name += name_tokens[i]; + if(i != name_tokens.size() - 1) { + name += " "; + } + } + + // parse an int + stringstream age_parser(age_s); + age_parser >> age; + people.push_back(person(name, age)); + } + + return people; + } + else { + throw runtime_error("Input file was not good; please verify."); + } +} + +void save_file(string filename, const vector & people) { + ofstream output_file(filename.c_str()); + for(auto p: people) { + output_file << p << endl; + } +} diff --git a/cs142/smcquay/lab09/util.h b/cs142/smcquay/lab09/util.h new file mode 100644 index 0000000..4231025 --- /dev/null +++ b/cs142/smcquay/lab09/util.h @@ -0,0 +1,17 @@ +#ifndef __UTIL_H__ +#define __UTIL_H__ + +#include +#include +#include + +using namespace std; + +#include "person.h" + +ostream & operator<<(ostream &, vector &); +vector tokenize(const string & str, const string & delimiters=" "); +vector parse_file(string filename); +void save_file(string filename, const vector & people); + +#endif diff --git a/cs142/smcquay/midterm2/Makefile b/cs142/smcquay/midterm2/Makefile new file mode 100644 index 0000000..8f5649c --- /dev/null +++ b/cs142/smcquay/midterm2/Makefile @@ -0,0 +1,29 @@ +CXX=g++ +CPPFLAGS=-Wall -g -std=c++0x +SOURCES=main.cc util.cc +OBJECTS=$(SOURCES:.cc=.o) +EXE=app + +all: $(EXE) test + +main.o: main.cc util.o +util.o: util.h util.cc +unittest: util.o unittest.cc + +$(EXE): $(OBJECTS) + $(CXX) $(LDFLAGS) $(OBJECTS) -o $@ + +clean: + @rm -vf *.o + @rm -rvf *.dSYM + @rm -vf $(EXE) + @rm -vf unittest + +test: unittest + ./unittest + +debug: $(EXE) + gdb $(EXE) + +valgrind: $(EXE) + valgrind --tool=memcheck --leak-check=yes ./$(EXE) diff --git a/cs142/smcquay/midterm2/main.cc b/cs142/smcquay/midterm2/main.cc new file mode 100644 index 0000000..064b6ea --- /dev/null +++ b/cs142/smcquay/midterm2/main.cc @@ -0,0 +1,22 @@ +#include +#include +#include + +using namespace std; + +#include "util.h" + +const string usage = "usage: app "; + +int main(int argc, char * argv []) { + if(argc != 3) { + cerr << usage << endl; + return 1; + } + int number_of_people = atoi(argv[1]); + int step = atoi(argv[2]); + vector people(number_of_people, true); + vector loosers = _play_game(people, step); + cout << loosers[loosers.size()-1] << endl; + return 0; +} diff --git a/cs142/smcquay/midterm2/unittest.cc b/cs142/smcquay/midterm2/unittest.cc new file mode 100644 index 0000000..5eb171e --- /dev/null +++ b/cs142/smcquay/midterm2/unittest.cc @@ -0,0 +1,27 @@ +#include +#include + +using namespace std; + +#include "util.h" + + +int main(int argc, char * argv []) { + bool verbose = false; + if(argc > 1) + verbose = true; + assert(9 == _test_run(10, 1, verbose)); + assert(3 == _test_run(10, 3, verbose)); + assert(9 == _test_run(10, 12, verbose)); + assert(19 == _test_run(20, 3, verbose)); + assert(4 == _test_run(15, 7, verbose)); + for(int i=0; i >= -1; i--) { + try { + _test_run(1500000, i); + } + catch(string e) { + assert(e == "rule violation: m > 0"); + } + } + return 0; +} diff --git a/cs142/smcquay/midterm2/util.cc b/cs142/smcquay/midterm2/util.cc new file mode 100644 index 0000000..dddb79d --- /dev/null +++ b/cs142/smcquay/midterm2/util.cc @@ -0,0 +1,56 @@ +#include +#include +#include +using namespace std; + +#include "util.h" + +ostream & operator<<(ostream & os, vector & v) { + os << "["; + for(unsigned int i = 0; i < v.size(); i++) { + os << v[i]; + if(i != v.size() - 1) { + os << ", "; + } + } + os << "]"; + return os; +} + +int _increment_to_next_looser(const vector & players, + int start, const int step) { + int counter = 0; + // the test examples in the pdf have us start by killing the m-1th person + // offset by one for some dumb reason + int attempt = start - 1; + while(counter != step) { + attempt = (attempt + 1) % players.size(); + if(players[attempt]) { + counter++; + } + } + return attempt; +} + +vector _play_game(vector & players, int step) { + vector loosers; + int token = 0; + while(loosers.size() < players.size()) { + token = _increment_to_next_looser(players, token, step); + players[token] = false; + loosers.push_back(token); + } + return loosers; +} + +int _test_run(int n, int m, bool verbose) { + if(m < 1) { + throw string("rule violation: m > 0"); + } + vector players(n, true); + vector loosers = _play_game(players, m); + if(verbose) { + cout << loosers << endl; + } + return loosers[loosers.size()-1]; +} diff --git a/cs142/smcquay/midterm2/util.h b/cs142/smcquay/midterm2/util.h new file mode 100644 index 0000000..1cd861c --- /dev/null +++ b/cs142/smcquay/midterm2/util.h @@ -0,0 +1,16 @@ +#ifndef __UTIL_H__ +#define __UTIL_H__ + +#include +#include + +using namespace std; + +ostream & operator<<(ostream &, vector &); + +vector _play_game(vector & players, const int step); +int _increment_to_next_looser(const vector & players, int start, const int step); + +int _test_run(int n, int m, bool verbose=false); + +#endif diff --git a/cs142/smcquay/people/.sconsign.dblite b/cs142/smcquay/people/.sconsign.dblite new file mode 100644 index 0000000..f244a40 Binary files /dev/null and b/cs142/smcquay/people/.sconsign.dblite differ diff --git a/cs142/smcquay/people/Makefile b/cs142/smcquay/people/Makefile new file mode 100644 index 0000000..99b821c --- /dev/null +++ b/cs142/smcquay/people/Makefile @@ -0,0 +1,9 @@ +CPPFLAGS=-Wall -g -std=c++0x + +all: person-test person.o + +person-test: person-test.cc person.o +person.o: person.cc person.h + +clean: + @rm -fv person-test *.o diff --git a/cs142/smcquay/people/person-test.cc b/cs142/smcquay/people/person-test.cc new file mode 100644 index 0000000..1186be3 --- /dev/null +++ b/cs142/smcquay/people/person-test.cc @@ -0,0 +1,17 @@ +#include + +using std::cout; +using std::endl; + +#include "person.h" + +int main(int argc, char * argv[]) +{ + person p; + p.populate_data(); + cout << p << endl; + cout << p.as_string() << endl; + + person p2("derek mcquay", 21); + cout << p2 << endl; +} diff --git a/cs142/smcquay/people/person.cc b/cs142/smcquay/people/person.cc new file mode 100644 index 0000000..1fa60ee --- /dev/null +++ b/cs142/smcquay/people/person.cc @@ -0,0 +1,25 @@ +#include "person.h" + +void person::populate_data() { + cout << "enter name: "; + getline(cin, name); + + cout << "enter age: "; + cin >> age; +} + +string person::as_string() const { + ostringstream stm; + + stm << "name: " + << name + << ", age: " + << age; + + return stm.str(); +} + +ostream & operator<<(ostream & os, const person & e) { + os << e.as_string(); + return os; +} diff --git a/cs142/smcquay/people/person.h b/cs142/smcquay/people/person.h new file mode 100644 index 0000000..8d501ce --- /dev/null +++ b/cs142/smcquay/people/person.h @@ -0,0 +1,28 @@ +#include +#include +#include +#include + +using namespace std; + +#pragma once + +class person +{ + private: + string name; + int age; + public: + person(){}; + + person(const string name, int age): name(name), age(age){}; + string as_string() const; + + void populate_data(); + + // you can define and declare in a header too: + inline int dummy_function() { return 42; }; + + // this is what allows us to do cout << my_person; + friend ostream & operator<<(ostream & os, const person & e); +}; diff --git a/cs142/smcquay/people/tags b/cs142/smcquay/people/tags new file mode 100644 index 0000000..bf476b7 --- /dev/null +++ b/cs142/smcquay/people/tags @@ -0,0 +1,17 @@ +!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/ +!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/ +!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/ +!_TAG_PROGRAM_NAME Exuberant Ctags // +!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/ +!_TAG_PROGRAM_VERSION 5.9~svn20110310 // +CPPFLAGS Makefile /^CPPFLAGS=-Wall -g -std=c++0x$/;" m +age person.h /^ int age;$/;" m class:person +as_string person.cc /^string person::as_string() const$/;" f class:person +dummy_function person.h /^ inline int dummy_function() { return 42; };$/;" f class:person +main person-test.cc /^int main(int argc, char * argv[])$/;" f +name person.h /^ string name;$/;" m class:person +operator << person.cc /^ostream & operator<<(ostream & os, const person & e)$/;" f +person person.h /^ person(){};$/;" f class:person +person person.h /^ person(const string name, int age): name(name), age(age){};$/;" f class:person +person person.h /^class person$/;" c +populate_data person.cc /^void person::populate_data()$/;" f class:person diff --git a/cs142/smcquay/test1/Makefile b/cs142/smcquay/test1/Makefile new file mode 100644 index 0000000..089cf66 --- /dev/null +++ b/cs142/smcquay/test1/Makefile @@ -0,0 +1,10 @@ +CXXFLAGS=-Wall -g +all: tuition +clean: + @rm -vf tuition + +test: all + ./tuition < test_run.txt + +debug: all + gdb tuition diff --git a/cs142/smcquay/test1/quick.cpp b/cs142/smcquay/test1/quick.cpp new file mode 100644 index 0000000..1f11e95 --- /dev/null +++ b/cs142/smcquay/test1/quick.cpp @@ -0,0 +1,12 @@ +#include +#include +#include +#include + +using namespace std; + +int main() { + double a; + cin >> a; + printf ("using printf %4.2f\n",a); +} diff --git a/cs142/smcquay/test1/test_run.txt b/cs142/smcquay/test1/test_run.txt new file mode 100644 index 0000000..4db3492 --- /dev/null +++ b/cs142/smcquay/test1/test_run.txt @@ -0,0 +1,27 @@ +n +n +n +n +y +y +15 +n +y +n +n +y +y +20 +y +3 +5 +y +y +n +27 +25 +y +3 +26 +n +n diff --git a/cs142/smcquay/test1/tuition.cpp b/cs142/smcquay/test1/tuition.cpp new file mode 100644 index 0000000..855dff4 --- /dev/null +++ b/cs142/smcquay/test1/tuition.cpp @@ -0,0 +1,237 @@ +#include +#include +#include +#include + +using namespace std; + +int TOTAL_INPUTS_CORRECT = 0; +int TOTAL_INVALID_INPUTS = 0; + +struct student{ + //making a struct of type student to facilitate the manipulation of data during this program + bool member_of_church; + double credit_hours; + double tuition; +}; + +void undergrad_or_not(student & s) { + //function determines if the student is doing an undergrad + string input; + cout << "Are you entering information about an undergraduate student (\"y\" or \"n\")? "; + cin >> input; + if(input == "y") { + TOTAL_INPUTS_CORRECT++; + } + else { + cout << "This program deals only with undergraduate students." << endl; + TOTAL_INVALID_INPUTS++; + undergrad_or_not(s); + } +} + +bool check_credit_hours(double input) { + //checks the credit hours to make sure it is correct + double decimal = input - floor(input);//eliminate everything before the decimal to be able to evaulate + if(input > 25.0 or input < .5) { + cout << input << " is too small or too large for valid credit hour entry" << endl; + return false; + } + if(decimal == .0 or decimal == .5) { + return true; + } + else { + cout << "A student cannot enroll for " << input << " credit hours" << endl; + return false; + } +} + +void get_credit_hours(student & s) { + //function to get the number of credit hours. + double input; + cout << "Credit hours winter 2012: "; + cin >> input; + if(check_credit_hours(input) == false) { + //using check_credit_hours function to determine if in range + TOTAL_INVALID_INPUTS++; + get_credit_hours(s); + } + else { + s.credit_hours = input; + TOTAL_INPUTS_CORRECT++; + } +} + +void get_member_of_church(student & s) { + //function to determine if student is a member of the church + string input; + cout <<"Does the student belong to the LDS church (\"y\" or \"n\")? "; + cin >> input; + if(input == "n") { + s.member_of_church = false; + } + TOTAL_INPUTS_CORRECT++; +} + +void calculate_tuition(student & s) { + //this determines the tuition based on credit hours + if(s.credit_hours > 12) { + if(s.member_of_church) { + s.tuition = 2280; + } + else { + s.tuition = 4560; + } + } + else if(s.credit_hours > 9 && s.credit_hours < 11.5) { + if(s.member_of_church) { + s.tuition = 2210; + } + else { + s.tuition = 4435; + } + } + else { + if(s.member_of_church) { + s.tuition = 234 * s.credit_hours; + } + else { + s.tuition = 468 * s.credit_hours; + } + } + cout << "Tuition is $" << s.tuition << " for winter 2012" << endl; +} + +void calculate_refund(student & s) { + //used to calculate refund for student + string input; + cout << "Were there any classes that were dropped that need refund(\"y\" or \"n\")?"; + cin >> input; + if(input == "y") { + int time_frame; + double credits_dropped; + double refund; + double new_tuition; + double old_tuition; + cout << "Which of the following dates best describes when you dropped the class(es)" << endl; + cout << "1) January 19, 2012\n2) January 23, 2012\n3) Feruary 27, 2012\n4) March 16, 2012" << endl; + cin >> time_frame; + cout << "How many credit hours were dropped?" << endl; + cin >> credits_dropped; + if(check_credit_hours(credits_dropped) == false or s.credit_hours-credits_dropped <= 0) { + cout << "this is an invalid credit hours, try again" << endl; + calculate_refund(s); + TOTAL_INVALID_INPUTS++; + } + else { + s.credit_hours = s.credit_hours - credits_dropped; + old_tuition = s.tuition; + calculate_tuition(s); + new_tuition = s.tuition; + if(time_frame == 1) { + refund = (old_tuition - new_tuition) *.85; + } + if(time_frame == 2) { + refund = (old_tuition - new_tuition) *.75; + } + if(time_frame == 3) { + refund = (old_tuition - new_tuition) *.50; + } + if(time_frame == 4) { + cout << "You wont get any money back. You dropped classes too late." << endl; + } + cout << refund << " is the amount you will be refunded" << endl; + s.tuition = s.tuition - refund; + printf ("This is the new tuition after refund %4.2f\n",s.tuition); + TOTAL_INPUTS_CORRECT++; + } + } +} + +void get_max_tuition(vector & students) { + //function to get the max tuition + double max_tuition = 0; + for(unsigned int i = 0; i < students.size();i++) { + if(max_tuition < students[i].tuition) { + max_tuition = students[i].tuition; + } + } + printf ("The highest tuition is $%4.2f\n" , max_tuition); +} + +void get_min_tuition(vector & students) { + //function to get min tuition + double min_tuition = 4560; //need to initilize the double to avoid error + for(unsigned int i = 0; i < students.size(); i++) { //made it the largest number it could be so this function + if(min_tuition > students[i].tuition) { //wont fail + min_tuition = students[i].tuition; + } + } + printf ("The lowest tuition is $%4.2f\n" , min_tuition); +} + +void get_average_tuition(vector & students) { + //function to get the average tuition for all students + double average = 0; + for(unsigned int i = 0; i < students.size(); i++) { + average += students[i].tuition; + } + average = average/students.size(); + printf ("The average tuition is $%4.2f\n" , average); +} + +void get_average_credit_hours(vector & students) { + //function to get the average credit hours for all students + double average = 0; + for(unsigned int i = 0; i < students.size(); i++) { + average += students[i].credit_hours; + } + average = average/students.size(); + printf ("This is the average credit hours %4.1f\n" , average); +} + +void number_of_students(vector & students) { + //function to report how many students were recorded + cout << "You entered valid information for " << students.size() << " students" << endl; +} + +void percentage_of_correct_entries() { + //function reports percentage of correct entries + int percentage; + int total = TOTAL_INPUTS_CORRECT + TOTAL_INVALID_INPUTS; + percentage = TOTAL_INPUTS_CORRECT*100/total; + cout << percentage << "%" << " of your entries required no reprompting" << endl; +} + +bool keep_playing() { + bool r = true; + string input; + cout << "Enter another student (\"y\" or \"n\")?"; + cin >> input; + if(input == "n") { + r = false; + } + return r; +} + +int main() { + bool keep_game = true; + vector students; + //Keep the game going until person wants to quit + while(keep_game) { + student cur_student = {true, 0, 0}; + undergrad_or_not(cur_student); + get_member_of_church(cur_student); + get_credit_hours(cur_student); + calculate_tuition(cur_student); + calculate_refund(cur_student); + students.push_back(cur_student); + keep_game = keep_playing(); + } + number_of_students(students); + get_average_credit_hours(students); + get_average_tuition(students); + get_max_tuition(students); + get_min_tuition(students); + percentage_of_correct_entries(); +} diff --git a/cs142/test02/Circle.cpp b/cs142/test02/Circle.cpp new file mode 100644 index 0000000..28fe9b2 --- /dev/null +++ b/cs142/test02/Circle.cpp @@ -0,0 +1,126 @@ +#include +#include + +using namespace std; + +#include "Circle.h" + +Circle::Circle(){} + +vector Circle::getNames() { //used to populate a vector with names + string special = "Josephus"; + vector names = {{ + "Jacob", + "Isabella", + "Ethan", + "Sophia", + "Michael", + "Emma", + "Jayden", + "Olivia", + "William", + "Ava", + "Alexander", + "Emily", + "Noah", + "Abigail", + "Daniel", + "Madison", + "Aiden" , + "Chloe", + "Anthony", + }}; + return names; +} + +vector Circle::playGame(int n, int m) { + vector names = getNames(); + vector temp; + if(n < 10 or n > 20){ + names = {}; + return names; + } + if(m < 0){ + names = {}; + return names; + } + for(int i = 0; i < 20 - n; i++) { + names.pop_back(); + } + names.push_back("Josephus"); //insures that Josephus will be in the game + int count = 0; + int threshold = 0; + for(int i = 0; i < n; i++) { + int hits = 0; + while(hits < m) { + if(names[count] == ""){ + } + else { + hits++; + } + if(hits == m) { + temp.push_back(names[count]); + names[count] = ""; + hits = 100; + } + count++; + if(count+1 > names.size()) { + count = 0; + threshold++; + } + if(threshold > 100) { //threshold against infinite loop + hits = 100; + } + } + } + return temp; +} + +int Circle::reportSafeIndex(int n, int m) { //uses similar function as playGame() to determine index + vector names = getNames(); + vector temp; + int count = 0; + int threshold = 0; + if(n < 10 or n > 20){ + return -1; + } + if(m < 0){ + return -1; + } + for(int i = 0; i < 20 - n; i++) { + names.pop_back(); + } + names.push_back("Josephus"); + for(int i = 0; i < n; i++) { + int hits = 0; + while(hits < m) { + if(names[count] == ""){ + } + else { + hits++; + } + if(hits == m) { + temp.push_back(names[count]); + names[count] = ""; + hits = 100; + } + count++; + if(count+1 > names.size()) { + count = 0; + threshold++; + } + if(threshold > 100) { //incase of infinite loop due to improper input + hits = 100; + } + } + } + string index_holder = temp[n-1]; + int index = 0; + names = getNames(); + for(unsigned int i = 0; i < names.size(); i++){ + if(names[i] == index_holder) { + index = i+1; + } + } + return index; +} diff --git a/cs142/test02/Circle.h b/cs142/test02/Circle.h new file mode 100755 index 0000000..b5ff501 --- /dev/null +++ b/cs142/test02/Circle.h @@ -0,0 +1,64 @@ +#ifndef CIRCLE //Do not modify this line +#define CIRCLE //Do not modify this line +#include +//You may add "#include" statements here + +using namespace std; //Do not modify this line + +class Circle //Do not modify this line +{ //Do not modify this line + //You may insert visibility modifiers anywhere within this document + //You may declare member variables anywhere within this document + //----------------------------------------------------------------- + public: + Circle(); //Do not modify this line + ~Circle(){} //Do not modify this line + vector names; + //----------------------------------------------------------------- + /* + getNames + + Returns a list of names in the order in which the people will be standing for the "game". + Although fewer people may be playing, you must return 20 names here. Do not provide + duplicate names. + + For the sake of the test driver, this method must return the list of 20 names in the + same order every time it is called, and this list of 20 names in this order must be used + to play the "game". + + This method will be called repeatedly. + */ + vector getNames(); //Do not modify this line + //You may not implement this method here; you must do so in a .cpp document + + /* + playGame + + Plays a "game" with the first n people from the list (above) counting forward every m. An + explanation for how the "game" works can be found in the exam specs. + + This method should return a list of names in the order in which the lot fell upon them (including + the survivor, who should be last). If n is not between 10 and 20 or if m is non-positive, + return an empty vector. + + This method will be called repeatedly. + */ + vector playGame(int n, int m); //Do not modify this line + //You may not implement this method here; you must do so in a .cpp document + + /* + reportSafeIndex + + Returns the "safe index", the last index/location in the circle that will be chosen when + the "game" is played. The point of this method is to permit someone to cheat the system + by finding the safe location ahead of time. + + If n is not between 10 and 20 or if m is non-positive, return -1. + + This method may be called repeatedly. + */ + int reportSafeIndex(int n, int m); //Do not modify this line + //You may not implement this method here; you must do so in a .cpp document + //----------------------------------------------------------------- +}; //Do not modify this line +#endif //Do not modify this line diff --git a/cs142/test02/Makefile b/cs142/test02/Makefile new file mode 100644 index 0000000..d3aa7ce --- /dev/null +++ b/cs142/test02/Makefile @@ -0,0 +1,16 @@ +CXX=g++ +CPPFLAGS=-Wall -g -std=c++0x + +all: Circle + +Circle: main.o Circle.o + g++ $(CPPFLAGS) Circle.o main.o -o Circle + +main.o: main.cpp Circle.o Circle.h +Circle.o: Circle.cpp Circle.h + +clean: + rm -fv Circle *.o + +debug: Circle + gdb Circle diff --git a/cs142/test02/main.cpp b/cs142/test02/main.cpp new file mode 100644 index 0000000..732e330 --- /dev/null +++ b/cs142/test02/main.cpp @@ -0,0 +1,20 @@ +#include +#include "Circle.h" +#include + +using namespace std; + +int main() { + Circle c; + c.playGame(10,2); + c.playGame(9,2); + c.playGame(21,2); + c.playGame(10,-2); + c.reportSafeIndex(10,2); + c.reportSafeIndex(9,11); + c.reportSafeIndex(21,6); + c.reportSafeIndex(20,6); + c.reportSafeIndex(20,-1); + + +} diff --git a/cs142/test02/test.cc b/cs142/test02/test.cc new file mode 100644 index 0000000..fc92cfe --- /dev/null +++ b/cs142/test02/test.cc @@ -0,0 +1,16 @@ +#include +#include + +using namespace std; + +int main() { + vector names; + names.push_back("derek"); + names.push_back("colleen"); + names.push_back("stpehen"); + names.pop_back(); + for(int i = 0; i < names.size(); i++) { + cout << names[i] << endl; + } + cout << names.size() << endl; +}