diff --git a/changelog.txt b/changelog.txt index 3c0b75f93e7..2a1dd3d063f 100644 --- a/changelog.txt +++ b/changelog.txt @@ -13,8 +13,92 @@ Format: ================== +2013-04-23 (Kristian Spangsege) ++ Support for explicit string lengths added. Most method arguments and + return values of type 'const char*' have been changed to be of type + 'StringData'. This new type is defined in + . 'StringData' can be implicitly + constructed from 'const char*', so no change is required when + passing arguments. Source code change is required when dealing with + returned strings of type 'const char*'. The following is a complete + list: + Affected form Possible replacement + --------------------------------------------------------------------------- + group.get_table_name(...) group.get_table_name(...).data() + table.get_column_name() table.get_column_name().data() + table.get_string(...) table.get_string(...).data() + table.get_mixed(...).get_string() table.get_mixed(...).get_string().data() + table[7].string_col table[7].string_col.c_str() ++ Added support for table[7].string_col.data() and table[7].string_col.size(). ++ Full and seamless interoperability with std::string. This comes + about from the fact that StringData can be implicitly constructed + from, and convert to std::string. ++ Full support for BinaryData in queries. ++ Added BinaryData::data(), BinaryData::size(), BinaryData::operator[]() ++ Added BinaryData::operator==(), BinaryData::operator!=(), BinaryData::operator<() ++ Added BinaryData::begins_with(), BinaryData::ends_with(), BinaryData::contains() ++ Allow BinaryData to be constructed from fixed size array: + template explicit BinaryData(const char (&)[N]) +- BinaryData::pointer removed, use BinaryData::data() instead. +- BinaryData::len removed, use BinaryData::size() instead. +- BinaryData::compare_payload() removed, use BinaryData::operator==() instead. ++ The methods + Table::set_binary(std::size_t column_ndx, std::size_t row_ndx, const char* data, std::size_t size) + Table::insert_binary(std::size_t column_ndx, std::size_t row_ndx, const char* data, std::size_t size) + Table::find_first_binary(std::size_t column_ndx, const char* data, std::size_t size) + Table::find_all_binary(std::size_t column_ndx, const char* data, std::size_t size) + TableView::set_binary(std::size_t column_ndx, std::size_t row_ndx, const char* data, std::size_t size) + have been changed to + Table::set_binary(std::size_t column_ndx, std::size_t row_ndx, BinaryData) + Table::insert_binary(std::size_t column_ndx, std::size_t row_ndx, BinaryData) + Table::find_first_binary(std::size_t column_ndx, BinaryData) + Table::find_all_binary(std::size_t column_ndx, BinaryData) + TableView::set_binary(std::size_t column_ndx, std::size_t row_ndx, BinaryData) + The following changes have been made in the statically + typed API: + Affected form Possible replacement + --------------------------------------------------------- + table[7].binary_col.pointer() table[7].binary_col.data() + table[7].binary_col.len() table[7].binary_col.size() + These changes were made for consistency with StringData. ++ Added Date::operator<() ++ Return type changed from 'std::time_t' to 'Date' on the following + methods: + Mixed::get_date() + Table::get_date() + TableView::get_date() + Argument type changed from 'std::time_t' to 'Date' on many methods including these: + Mixed::set_date() + Table::set_date() + Table::insert_date() + TableView::set_date() + Changes corresponding to these have been made in the statically + typed API. These are some of the affected forms: + time_t(table[7].date_col) + table[7].date_col = val + table[7].mixed_col.get_date() + These changes were made for consistency, and to improve the + isolation of the implementation of 'Date' (it is likely that the + implementation of 'Date' will change). 'Date' can be implicitly + constructed from std::time_t, but it cannot be implicitly converted + to std::time_t (nor is it considered desireable to allow such an + implicit conversion). This means that applications will be affected + as follows: + Affected form Possible replacement + --------------------------------------------------------------------------- + table.get_date(...) table.get_date(...).get_date() + table.get_mixed(...).get_date() table.get_mixed(...).get_date().get_date() + time_t(table[7].date_col) Date(table[7].date_col).get_date() + table[7].date_col.get() table[7].date_col.get().get_date() ++ Group::write() and Group::write_to_mem() are now 'const'. ++ Group::BufferSpec eliminated. Using BinaryData instead. + + 2013-03-11 (Kristian Spangsege) -+ On Linux and OS X, installed shared libraries now carry a platform dependent API version which is computed from a platform neutral version specifier (same as GNU Libtool). This allows for multiple versions of the shared library to be concurrently installed. ++ On Linux and OS X, installed shared libraries now carry a platform + dependent API version which is computed from a platform neutral + version specifier (same as GNU Libtool). This allows for multiple + versions of the shared library to be concurrently installed. 2013-02-24 (Kristian Spangsege) @@ -52,7 +136,7 @@ Format: + Simplified open-mode for Group constructor. - Group::is_valid() removed. Errors are now reported as exceptions from the constructor. + Now using Group::BufferSpec to pass a memory buffer to the Group constructor. -+ Group::write_to_mem() now returnis a Group::BufferSpec. ++ Group::write_to_mem() now returns a Group::BufferSpec. + Addition of 'bool no_create' arguemnt to SharedGroup constructor. diff --git a/doc/css.css b/doc/css.css deleted file mode 100644 index 910e39b00f1..00000000000 --- a/doc/css.css +++ /dev/null @@ -1,24 +0,0 @@ -@font-face { - font-family: 'Open Sans'; - font-style: normal; - font-weight: 600; - src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url('https://themes.googleusercontent.com/static/fonts/opensans/v5/MTP_ySUJH_bn48VBG8sNSqRDOzjiPcYnFooOUGCOsRk.woff') format('woff'); -} -@font-face { - font-family: 'Open Sans'; - font-style: italic; - font-weight: 600; - src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url('https://themes.googleusercontent.com/static/fonts/opensans/v5/PRmiXeptR36kaC0GEAetxuw_rQOTGi-AJs5XCWaKIhU.woff') format('woff'); -} -@font-face { - font-family: 'Open Sans'; - font-style: normal; - font-weight: 700; - src: local('Open Sans Bold'), local('OpenSans-Bold'), url('https://themes.googleusercontent.com/static/fonts/opensans/v5/k3k702ZOKiLJc3WVjuplzKRDOzjiPcYnFooOUGCOsRk.woff') format('woff'); -} -@font-face { - font-family: 'Open Sans'; - font-style: normal; - font-weight: 400; - src: local('Open Sans'), local('OpenSans'), url('https://themes.googleusercontent.com/static/fonts/opensans/v5/cJZKeOuBrn4kERxqtaUH3bO3LdcAZYWl9Si6vvxL-qU.woff') format('woff'); -} diff --git a/doc/logo200.png b/doc/logo200.png deleted file mode 100644 index 27b3fca03b6..00000000000 Binary files a/doc/logo200.png and /dev/null differ diff --git a/doc/main.css b/doc/main.css deleted file mode 100644 index b438b5def18..00000000000 --- a/doc/main.css +++ /dev/null @@ -1,3619 +0,0 @@ -.p_about .left_menu { - width: 150px; - margin-right: 30px -} -.p_about .content { - float: left; - width: 800px; - margin-bottom: 25px; - overflow: hidden;*zoom:1 -} -.p_about ol { - list-style-type: decimal; - line-height: 1.3em; - margin-left: 25px -} -.p_about ol li { - margin-bottom: 12px -} -.p_about h3 { - font-size: 18px; - font-weight: bold; - margin-bottom: 1em -} -.p_about h1 { - margin-bottom: 25px; - line-height: 1.3em -} -.p_about .container ul { - list-style-type: disc; - margin-left: 25px -} -.p_about .container ul li { - margin-bottom: 12px -} -.p_about .splash { - float: right -} -.p_about .about_text { - width: 420px; - overflow: hidden;*zoom:1 -} -.p_about .about_text h1 { - line-height: 35px; - margin-bottom: 25px -} -.p_about .investors .grid { - margin-bottom: 30px; - overflow: hidden;*zoom:1 -} -.p_about .investors .angels div { - font-size: 18px; - line-height: 30px; - font-family: 'Open Sans'; - float: left; - width: 260px -} -.p_about .investors div.image { - float: left; - width: 247px; - height: 121px; - line-height: 121px; - margin-right: 15px; - margin-bottom: 15px; - background: #fff url(/images/about/box.png?1322790145) no-repeat top left; - text-align: center; - font-size: 22px; - color: #0067ab; - font-family: "Open Sans"; - vertical-align: middle -} -.p_about .investors div.image img { - vertical-align: middle; - line-height: 121px -} -.p_about .press .item { - overflow: hidden;*zoom:1; - margin-bottom: 25px -} -.p_about .press .item .logo { - float: left; - text-align: left; - width: 260px; - margin-right: 25px -} -.p_about .press .item .link { - font-size: 17px; - float: left; - line-height: 35px; - width: 700px -} -.p_about .press .item .date { - font-size: 15px; - padding-left: 15px; - color: #777 -} -.p_about_team h1 { - margin-bottom: 35px -} -.p_about_team .member { - overflow: hidden;*zoom:1; - margin-bottom: 40px -} -.p_about_team .member img { - float: left; - margin: 5px 25px 0 5px; - -moz-box-shadow: 0 0 5px 3px #ccc; - -webkit-box-shadow: 0 0 5px 3px #ccc; - -o-box-shadow: 0 0 5px 3px #ccc; - box-shadow: 0 0 5px 3px #ccc -} -.p_about_team .member div { - float: left; - width: 560px -} -.p_about_team .member div h3 { - font-size: 20px; - font-family: 'Open Sans'; - font-weight: 400; - margin-bottom: 15px -} -.p_about_team .member div h3 a { - margin-left: 15px; - color: #777; - font-size: 13px; - text-decoration: none -} -.p_about_team .member div h3 a:hover { - text-decoration: underline -} -.p_about_team .member div p { - font-size: 14px -} -.p_about_team .last { - margin-right: 0 -} -.p_about_testimonials { - background: url(/images/about/customers_bg.png?1322790145) repeat-x 0 200px -} -.p_about_testimonials h1 { - font-size: 41px; - font-weight: 800; - text-align: center; - margin-bottom: 45px; - position: relative; - right: 63px -} -.p_about_testimonials h1 img { - margin: 0 5px 0 5px; - position: relative; - top: 13px -} -.p_about_testimonials .dev { - float: left; - width: 450px; - padding: 20px; - margin-right: 35px; - margin-bottom: 35px; - background: white; - border: 1px solid #bbb; - height: 242px; - -moz-box-shadow: 0 0 5px 1px #aaa; - -webkit-box-shadow: 0 0 5px 1px #aaa; - -o-box-shadow: 0 0 5px 1px #aaa; - box-shadow: 0 0 5px 1px #aaa; - -moz-border-radius: 10px; - -webkit-border-radius: 10px; - -o-border-radius: 10px; - -ms-border-radius: 10px; - -khtml-border-radius: 10px; - border-radius: 10px; - overflow: hidden;*zoom:1 -} -.p_about_testimonials .dev .bio { - width: 170px; - float: left; - margin-right: 15px -} -.p_about_testimonials .dev .bio img { - margin-bottom: 15px; - -moz-box-shadow: 0 0 5px 1px #aaa; - -webkit-box-shadow: 0 0 5px 1px #aaa; - -o-box-shadow: 0 0 5px 1px #aaa; - box-shadow: 0 0 5px 1px #aaa -} -.p_about_testimonials .dev .bio h3 { - font-size: 18px; - color: #333; - font-weight: 600; - margin-bottom: 3px -} -.p_about_testimonials .dev .bio p { - margin-top: 2px; - margin-bottom: 2px; - font-family: 'Open Sans'; - font-size: 14px; - color: #555 -} -.p_about_testimonials .dev .bio p a { - text-decoration: none -} -.p_about_testimonials .dev .bio p a:hover { - text-decoration: underline -} -.p_about_testimonials .dev .wrap { - width: 265px; - height: 240px; - float: left; - background: url(/images/about/right_quote.png?1322790145) no-repeat bottom right -} -.p_about_testimonials .dev .wrap table { - width: 265px; - height: 240px; - background: url(/images/about/left_quote.png?1322790145) no-repeat top left -} -.p_about_testimonials .dev .wrap table tr td { - width: 265px; - padding: 25px; - height: 190px; - color: #0075ac; - font-size: 20px; - line-height: 28px; - vertical-align: center -} -.p_about_testimonials .dev .wrap table tr td.small { - font-size: 17px; - line-height: 25px -} -.p_about_testimonials .dev .wrap table tr td.smaller { - font-size: 16px; - line-height: 23px -} -.p_about_testimonials .dev .wrap table tr td.large { - font-size: 24px; - line-height: 32px; - padding: 15px -} -.p_about_testimonials .full .wrap { - width: 420px; - height: 180px; - float: none -} -.p_about_testimonials .full .wrap table { - height: 180px; - width: 100% -} -.p_about_testimonials .full .wrap table tr td { - width: 100%; - height: 130px -} -.p_about_testimonials .full .bio { - float: none; - width: 300px; - padding-left: 25px -} -.p_about_testimonials .last { - margin-right: 0; - margin-bottom: 35px -} -.p_about_pricing p { - font-size: 20px -} -.p_about_pricing small { - font-size: 12px; - color: #0067ab -} -.p_about_pricing table { - border-spacing: 1px; - border-collapse: separate; - margin-bottom: 30px -} -.p_about_pricing table tr th { - width: 177px; - font-size: 30px; - font-weight: bold; - font-family: 'Open Sans'; - height: 87px; - vertical-align: middle; - text-align: center; - color: #0067ab; - background: url(/images/about/pricing_bg.png?1322790145) repeat-x top left -} -.p_about_pricing table tr th.firstcol { - background: none -} -.p_about_pricing table tr th.enterprise { - vertical-align: top; - padding-top: 29px -} -.p_about_pricing table tr th.enterprise .contact { - margin-top: 75px; - font-size: 23px; - font-weight: normal; - line-height: 25px -} -.p_about_pricing table tr th.enterprise .email { - margin-top: 10px; - font-size: 13px; - font-weight: bold -} -.p_about_pricing table tr td { - width: 177px; - height: 57px; - color: white; - font-weight: normal; - vertical-align: middle; - text-align: center; - font-size: 20px; - background: #0067ab -} -.p_about_pricing table tr td small { - font-weight: normal; - margin-top: 4px; - display: block; - font-size: 12px; - color: white -} -.p_about_pricing table tr td.firstcol { - background: url(/images/about/pricing_bg.png?1322790145) repeat-x top left; - font-size: 15px; - text-align: right; - padding-right: 15px; - color: #0067ab; - width: 141px; - font-weight: normal -} -.p_about_pricing table tr.price td { - font-size: 33px; - font-weight: bold; - background: #4f8b06; - color: white -} -.p_about_pricing table tr.price td small { - display: inline; - font-size: 12px; - font-weight: normal; - color: white -} -.p_about_pricing table tr.price td.blank { - background: none -} -.p_about_pricing h2 { - text-align: center; - margin-bottom: 20px -} -.p_about_pricing .price { - text-align: center -} -.p_about_pricing .signup { - margin-bottom: 30px; - text-align: center -} -.p_about_tour .top { - overflow: hidden;*zoom:1 -} -.p_about_tour .top h1 { - float: left; - width: 640px; - line-height: 40px; - margin-bottom: 30px -} -.p_about_tour .top a.signup_button { - float: right; - margin-top: 18px -} -.p_about_tour .section { - background: url(/images/about/section_bg.gif?1322790145) repeat-x top left; - text-align: center; - min-width: 1024px -} -.p_about_tour .section .inner { - text-align: left; - width: 1024px; - padding: 40px 35px 35px 35px; - margin: auto; - overflow: hidden;*zoom:1; - font-size: 18px; - min-width: 1024px -} -.p_about_tour .section .inner h2 { - font-size: 28px; - line-height: 28px; - margin-bottom: 25px -} -.p_about_tour .section .inner h2 img { - margin-top: -4px; - vertical-align: middle -} -.p_about_tour .section .inner .expl { - float: left; - width: 550px; - margin-right: 55px -} -.p_about_tour .section .inner .read p { - margin-bottom: 5px -} -.p_about_tour .section .inner .read a { - color: #468500 -} -.p_about_tour .section .inner .pic { - width: 400px; - text-align: center; - float: left -} -.p_about_jobs h1 { - font-size: 45px; - font-weight: bold; - margin-bottom: 15px -} -.p_about_jobs h2 { - font-size: 20px; - font-weight: normal; - margin-bottom: 35px -} -.p_about_jobs h3 { - font-size: 28px; - font-weight: bold -} -.p_about_jobs ul.section { - list-style-type: none; - padding: 15px 0 15px 25px; - margin-left: 0; - border-left: 7px solid #ccc; - margin-bottom: 25px -} -.p_about_jobs ul.section li { - font-size: 23px -} -.p_about_jobs ul.section li p { - margin-bottom: 3px; - color: #444 -} -.p_about_jobs ul.section li small { - color: #777; - display: block; - font-size: 12px -} -.p_about_faq h2,.p_about_faq p { - margin-left: 0; - width: 700px; - text-align: left -} -.p_about_faq h1 { - margin-bottom: 40px -} -.p_about_faq h2 { - margin: 30px auto 15px 0 -} -.p_accounts p { - margin-top: 15px -} -.admin_menu { - display: block; - overflow: hidden;*zoom:1; - background: #eee; - padding: 15px; - margin-bottom: 25px -} -.admin_menu li { - float: left; - margin-right: 15px; - font-size: 18px -} -.admin_menu li a { - padding: 5px 10px; - background: #ddd; - text-decoration: none; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - -o-border-radius: 5px; - -ms-border-radius: 5px; - -khtml-border-radius: 5px; - border-radius: 5px -} -.admin_menu li a:hover { - background: #ccc -} -.p_admin-daily_stats table,.p_admin-users table { - width: 1024px -} -.p_admin-daily_stats table tr th,.p_admin-users table tr th { - font-weight: bold -} -.p_admin-daily_stats table tr td,.p_admin-daily_stats table tr th,.p_admin-users table tr td,.p_admin-users table tr th { - vertical-align: top; - padding: 8px; - border: 1px solid #ccc -} -.p_admin-daily_stats table tr td ul li,.p_admin-daily_stats table tr th ul li,.p_admin-users table tr td ul li,.p_admin-users table tr th ul li { - line-height: 22px -} -.p_admin-daily_stats .pagination,.p_admin-users .pagination { - background: white; - cursor: default; - height: 22px -} -.p_admin-daily_stats .pagination a,.p_admin-daily_stats .pagination span,.p_admin-daily_stats .pagination em,.p_admin-users .pagination a,.p_admin-users .pagination span,.p_admin-users .pagination em { - padding: .2em .5em; - display: block; - float: left; - margin-right: 1px -} -.p_admin-daily_stats .pagination .disabled,.p_admin-users .pagination .disabled { - display: none -} -.p_admin-daily_stats .pagination .current,.p_admin-users .pagination .current { - font-style: normal; - font-weight: bold; - background: #2e6ab1; - color: white; - border: 1px solid #2e6ab1 -} -.p_admin-daily_stats .pagination a,.p_admin-users .pagination a { - text-decoration: none; - color: #105cb6; - border: 1px solid #9aafe5 -} -.p_admin-daily_stats .pagination a:hover,.p_admin-daily_stats .pagination a:focus,.p_admin-users .pagination a:hover,.p_admin-users .pagination a:focus { - color: #003; - border-color: #003 -} -.p_admin-daily_stats .pagination .page_info,.p_admin-users .pagination .page_info { - background: #2e6ab1; - color: white; - padding: .4em .6em; - width: 22em; - margin-bottom: .3em; - text-align: center -} -.p_admin-daily_stats .pagination .page_info b,.p_admin-users .pagination .page_info b { - color: #003; - background: #6aa6ed; - padding: .1em .25em -} -.p_admin-daily_stats #chart { - margin-bottom: 25px -} -.p_admin-daily_stats table tr.first td { - font-size: 25px; - font-weight: bold -} -.p_admin-invites small { - display: block; - color: #777; - font-style: normal; - font-family: Helvetica -} -.p_admin-invites textarea { - font-size: 15px -} -.p_admin-invites label { - font-weight: bold; - color: #333 -} -.p_apps .oauth_creds { - background: #d3f28d; - padding: 15px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - -o-border-radius: 5px; - -ms-border-radius: 5px; - -khtml-border-radius: 5px; - border-radius: 5px; - font-size: 18px; - width: 75%; - margin-top: 25px; - line-height: 22px; - margin-bottom: 1em -} -.p_apps .oauth_creds code { - border: 0; - background: 0 -} -.p_apps_edit .manage { - margin-top: 55px; - margin-bottom: 25px -} -.p_apps_edit .manage .delete { - background: red; - font-size: 13px -} -.p_apps_quickstart h1 { - padding: 8px 10px 8px 0; - float: left -} -.p_apps_quickstart .intro { - margin: 25px auto 25px auto -} -.p_apps_quickstart .code { - font-size: 14px; - line-height: 16px -} -.p_apps_quickstart p { - font-size: 17px; - line-height: 22px -} -.p_apps_quickstart h2 { - margin-bottom: 15px; - margin-top: 35px -} -.p_apps_quickstart h3 { - font-size: 17px; - font-weight: bold; - margin-bottom: 15px; - margin-top: 15px -} -.p_apps_quickstart h2.underline { - margin-top: 35px; - margin-bottom: 15px -} -.p_apps_quickstart .ios_selection { - padding-left: 125px; - background: url(/images/apps/ios_letters.png?1322790145) no-repeat 15px 30px -} -.p_apps_quickstart .android_selection { - padding-left: 125px; - background: url(/images/apps/android.png?1322790145) no-repeat 19px 5px -} -.p_apps_quickstart .video_container { - margin-top: 25px; - padding: 20px; - background: #5ca202; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - -o-border-radius: 5px; - -ms-border-radius: 5px; - -khtml-border-radius: 5px; - border-radius: 5px -} -.p_apps_quickstart .video_container a.close { - float: right; - display: block; - width: 21px; - height: 21px; - background: url(/images/apps/x.png?1322790145) no-repeat -} -.p_apps_quickstart .video_container h2 { - margin-top: 0; - color: white -} -.p_apps_quickstart .app_name { - float: left; - background: #5ca202; - padding: 8px 10px; - color: white; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - -o-border-radius: 5px; - -ms-border-radius: 5px; - -khtml-border-radius: 5px; - border-radius: 5px; - font-weight: normal; - font-size: 27px; - margin-left: 10px; - position: relative -} -.p_apps_quickstart .app_name .select { - position: absolute; - background: #5ca202; - top: 40px; - left: 0; - border: 3px solid #3f7001; - color: white; - font-size: 27px; - width: 400px -} -.p_apps_quickstart .app_name .select ul li a { - padding: 8px 10px; - display: block; - color: white; - text-decoration: none -} -.p_apps_quickstart .app_name .select ul li a:hover { - background: #3f7001 -} -.p_apps_quickstart .multiple { - cursor: pointer; - padding-right: 43px; - background: #5ca202 url(/images/docs/white_arrow.png?1322790145) no-repeat center right -} -.p_apps_quickstart .multiple:hover { - background-color: #3f7001 -} -.p_apps_quickstart .xcode_selection ul { - list-style-type: none; - padding-top: 12px -} -.p_apps_quickstart .xcode_selection ul li { - float: left; - margin-right: 15px -} -.p_apps_quickstart .xcode_selection ul li .other { - display: block; - padding: 4px 3px; - -moz-border-radius: 1px; - -webkit-border-radius: 1px; - -o-border-radius: 1px; - -ms-border-radius: 1px; - -khtml-border-radius: 1px; - border-radius: 1px; - color: black; - text-decoration: none; - font-size: 16px -} -.p_apps_quickstart .xcode_selection ul li a { - display: block; - padding: 5px 9px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - -o-border-radius: 5px; - -ms-border-radius: 5px; - -khtml-border-radius: 5px; - border-radius: 5px; - color: #0067ab; - text-decoration: none; - font-size: 14px -} -.p_apps_quickstart .xcode_selection ul li a:hover { - background: #eee -} -.p_apps_quickstart .xcode_selection ul li.active a { - color: white; - background: #0067ab -} -.p_apps_quickstart .choice li { - overflow: hidden;*zoom:1; - margin-bottom: 5px -} -.p_apps_quickstart .choice li input { - position: relative; - top: -2px; - margin-right: 5px -} -.p_apps_quickstart .choice li a.selection { - float: left; - display: block; - width: 735px; - padding: 15px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - -o-border-radius: 5px; - -ms-border-radius: 5px; - -khtml-border-radius: 5px; - border-radius: 5px; - text-decoration: none; - font-size: 21px; - margin-right: 15px -} -.p_apps_quickstart .choice li a.selection:hover { - background: #ddd -} -.p_apps_quickstart .choice li a.selection.active { - background: #5ca202; - color: white -} -.p_apps_quickstart .choice li a.selection.active:hover { - background: #5ca202 -} -.p_apps_quickstart .choice li a.video_button { - float: left; - display: block; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - -o-border-radius: 5px; - -ms-border-radius: 5px; - -khtml-border-radius: 5px; - border-radius: 5px; - background: #ddd url(/images/apps/video.png?1322790145) no-repeat 15px 20px; - line-height: 18px; - padding: 10px 10px 10px 55px; - color: #666; - height: 34px; - font-size: 12px; - width: 50px; - text-decoration: none -} -.p_apps_quickstart .choice li a.video_button:hover { - cursor: pointer; - background-color: #ccc -} -.p_apps_quickstart .oauth_creds { - background: #d3f28d; - padding: 15px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - -o-border-radius: 5px; - -ms-border-radius: 5px; - -khtml-border-radius: 5px; - border-radius: 5px; - font-size: 18px; - width: 75%; - margin-top: 25px; - line-height: 22px; - margin-bottom: 1em -} -.p_apps_quickstart .oauth_creds code { - border: 0; - background: 0 -} -.p_apps_quickstart p { - width: 800px -} -.p_apps_quickstart .platform_section { - padding-top: 25px; - overflow: hidden;*zoom:1 -} -.p_apps_quickstart .platform_section .platform { - float: left; - width: 200px; - text-align: center -} -.p_apps_quickstart .platform_section .platform img { - display: inline; - margin-bottom: 5px -} -.p_apps_quickstart .platform_section .platform p { - width: 100px; - margin: auto; - text-align: center -} -.p_apps_quickstart .platform_section .downloads { - width: 700px; - font-size: 25px; - line-height: 25px -} -.p_apps_quickstart .platform_section .downloads li { - margin-bottom: 10px -} -.p_apps_quickstart .platform_section .downloads li img { - margin-right: 5px; - position: relative; - top: -3px; - vertical-align: middle -} -.p_apps_quickstart .platform_section .soon { - padding-top: 75px; - font-size: 35px; - color: #888 -} -.p_apps_quickstart .waiting { - background: #d3f28d; - padding: 25px; - font-size: 25px; - color: #666; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - -o-border-radius: 5px; - -ms-border-radius: 5px; - -khtml-border-radius: 5px; - border-radius: 5px; - margin: 25px auto 45px auto; - overflow: hidden;*zoom:1 -} -.p_apps_quickstart .waiting a { - float: left; - margin-right: 15px -} -.p_apps_quickstart .waiting .inner { - padding-top: 10px; - margin-left: 45px -} -.p_apps_quickstart .waiting img { - vertical-align: middle; - position: relative; - top: -4px -} -.p_apps_quickstart .waiting .finished { - font-weight: bold; - color: green -} -.p_apps_quickstart .waiting .obj { - color: #333; - font-weight: normal; - margin-top: 15px; - padding-left: 35px; - font-size: 20px; - font-family: "Courier New",Courier -} -.p_apps_quickstart .pic { - margin-top: 15px -} -.p_apps_quickstart ol { - width: 800px; - list-style-type: decimal; - padding-left: 35px; - margin: 15px auto 15px 0 -} -.p_apps_quickstart ol li { - font-size: 18px; - line-height: 18px; - color: #444; - margin-bottom: 1em -} -.p_apps_quickstart ol li ul { - padding-top: 10px; - list-style-type: disc; - padding-left: 18px -} -.p_apps_quickstart ol li ul li { - margin-bottom: 3px -} -.p_beta_requests label { - width: 600px; - line-height: 19px -} -.p_collections .empty_start,.p_admin-collections .empty_start { - margin-top: 25px -} -.p_collections .empty_start a,.p_admin-collections .empty_start a { - display: block; - cursor: pointer; - text-decoration: none; - display: block; - padding: 25px; - background-color: #ecf4f7; - margin-bottom: 15px; - -moz-border-radius: 3px; - -webkit-border-radius: 3px; - -o-border-radius: 3px; - -ms-border-radius: 3px; - -khtml-border-radius: 3px; - border-radius: 3px; - background-position: 25px 25px; - background-repeat: no-repeat; - font-size: 30px; - padding-left: 80px; - color: #0067ab -} -.p_collections .empty_start a:hover,.p_admin-collections .empty_start a:hover { - background-color: #c8dfe8 -} -.p_collections .empty_start a.import,.p_admin-collections .empty_start a.import { - background-image: url(/images/collections/document.png?1322790145); - background-position: 30px 25px -} -.p_collections .empty_start a.quick,.p_admin-collections .empty_start a.quick { - background-image: url(/images/collections/quick.png?1322790145); - background-position: 25px 20px -} -.p_collections .empty_start a.new_class,.p_admin-collections .empty_start a.new_class { - background-image: url(/images/collections/plus.png?1322790145) -} -.p_collections #browser,.p_admin-collections #browser { - overflow: hidden;*zoom:1; - margin-bottom: 25px -} -.p_collections #browser .classes,.p_admin-collections #browser .classes { - margin-top: 15px; - float: left; - width: 160px; - overflow: hidden -} -.p_collections #browser .classes h3,.p_admin-collections #browser .classes h3 { - font-size: 17px; - font-weight: bold; - margin-bottom: 10px; - padding-left: 6px -} -.p_collections #browser .classes ul,.p_admin-collections #browser .classes ul { - margin-bottom: 15px -} -.p_collections #browser .classes ul li a,.p_admin-collections #browser .classes ul li a { - display: block; - padding: 6px; - -moz-border-radius-topleft: 3px; - -webkit-border-top-left-radius: 3px; - -o-border-top-left-radius: 3px; - -ms-border-top-left-radius: 3px; - -khtml-border-top-left-radius: 3px; - border-top-left-radius: 3px; - -moz-border-radius-bottomleft: 3px; - -webkit-border-bottom-left-radius: 3px; - -o-border-bottom-left-radius: 3px; - -ms-border-bottom-left-radius: 3px; - -khtml-border-bottom-left-radius: 3px; - border-bottom-left-radius: 3px; - color: #0067ab; - text-decoration: none -} -.p_collections #browser .classes ul li a:hover,.p_admin-collections #browser .classes ul li a:hover { - background: #ddd -} -.p_collections #browser .classes ul li a .user,.p_admin-collections #browser .classes ul li a .user { - float: right; - margin-right: 5px; - margin-top: 2px; - width: 13px; - height: 12px; - background: url(/images/collections/user_icon.png?1322790145) no-repeat top left -} -.p_collections #browser .classes ul li a.selected,.p_admin-collections #browser .classes ul li a.selected { - background: #0067ab; - color: white; - text-decoration: none -} -.p_collections #browser .classes ul li a.selected:hover,.p_admin-collections #browser .classes ul li a.selected:hover { - background: #0067ab -} -.p_collections #browser .classes ul li a.selected .user,.p_admin-collections #browser .classes ul li a.selected .user { - background-position: 0 -12px -} -.p_collections #browser .classes p,.p_admin-collections #browser .classes p { - margin-bottom: .5em -} -.p_collections #browser .classes p a,.p_admin-collections #browser .classes p a { - margin: 6px 6px 6px 0; - padding: 3px 6px; - font-size: 13px; - color: #333; - -moz-border-radius: 3px; - -webkit-border-radius: 3px; - -o-border-radius: 3px; - -ms-border-radius: 3px; - -khtml-border-radius: 3px; - border-radius: 3px; - border: 1px solid #ccc; - background: #eee; - text-decoration: none -} -.p_collections #browser .classes p a:hover,.p_admin-collections #browser .classes p a:hover { - background: #ddd -} -.p_collections #browser .classes p a.disabled,.p_admin-collections #browser .classes p a.disabled { - color: #999 -} -.p_collections #browser .classes p a.disabled:hover,.p_admin-collections #browser .classes p a.disabled:hover { - background: #eee; - cursor: auto -} -.p_collections #browser .message,.p_admin-collections #browser .message { - visibility: hidden; - text-align: center; - margin: 0 auto 15px 0; - float: right; - width: 850px; - padding-top: 3px -} -.p_collections #browser .message .inner,.p_admin-collections #browser .message .inner { - margin-top: 3px; - padding: 3px 6px; - -moz-border-radius: 3px; - -webkit-border-radius: 3px; - -o-border-radius: 3px; - -ms-border-radius: 3px; - -khtml-border-radius: 3px; - border-radius: 3px; - border: 1px solid #ddd; - background: #ffc; - font-weight: bold; - font-size: 13px; - color: #222 -} -.p_collections #browser .utility,.p_admin-collections #browser .utility { - overflow: hidden;*zoom:1; - margin-left: 160px; - border: 1px solid #ddd; - width: 850px; - background: #d1dfea -} -.p_collections #browser .utility .right_section,.p_admin-collections #browser .utility .right_section { - float: right; - width: 250px -} -.p_collections #browser .utility .right_section button,.p_admin-collections #browser .utility .right_section button { - float: right -} -.p_collections #browser .utility .left_section,.p_admin-collections #browser .utility .left_section { - float: left; - padding-left: 6px -} -.p_collections #browser .utility .left_section button,.p_admin-collections #browser .utility .left_section button { - float: left -} -.p_collections #browser .utility .spinner,.p_admin-collections #browser .utility .spinner { - float: right; - visibility: visible; - margin-top: 5px; - margin-left: 15px; - visibility: hidden -} -.p_collections #browser .utility .info,.p_admin-collections #browser .utility .info { - float: right; - font-size: 14px; - margin-right: 15px; - margin-left: 10px; - line-height: 36px; - vertical-align: middle -} -.p_collections #browser .utility .pagination,.p_admin-collections #browser .utility .pagination { - float: right -} -.p_collections #browser .utility .pagination a,.p_admin-collections #browser .utility .pagination a { - float: right; - margin: 6px 6px 6px 0; - padding: 5px 6px; - font-size: 13px; - color: #333; - -moz-border-radius: 3px; - -webkit-border-radius: 3px; - -o-border-radius: 3px; - -ms-border-radius: 3px; - -khtml-border-radius: 3px; - border-radius: 3px; - border: 1px solid #ccc; - background: #eee; - display: block; - cursor: pointer -} -.p_collections #browser .utility .pagination a:hover,.p_admin-collections #browser .utility .pagination a:hover { - background: #ddd -} -.p_collections #browser .utility .pagination a div,.p_admin-collections #browser .utility .pagination a div { - width: 9px; - height: 10px -} -.p_collections #browser .utility .pagination a.left div,.p_admin-collections #browser .utility .pagination a.left div { - background: url(/images/collections/left_arrow.png?1322790145) no-repeat top left -} -.p_collections #browser .utility .pagination a.right div,.p_admin-collections #browser .utility .pagination a.right div { - background: url(/images/collections/right_arrow.png?1322790145) no-repeat top left -} -.p_collections #browser .utility .pagination a.inactive,.p_admin-collections #browser .utility .pagination a.inactive { - cursor: auto; - background: #ddd -} -.p_collections #browser .utility .pagination a.inactive div,.p_admin-collections #browser .utility .pagination a.inactive div { - background-position: 0 -10px -} -.p_collections #browser .utility a.button,.p_admin-collections #browser .utility a.button { - margin: 6px 6px 6px 0; - padding: 3px 6px; - font-size: 13px; - color: #333; - -moz-border-radius: 3px; - -webkit-border-radius: 3px; - -o-border-radius: 3px; - -ms-border-radius: 3px; - -khtml-border-radius: 3px; - border-radius: 3px; - border: 1px solid #ccc; - background: #eee -} -.p_collections #browser .utility a.button:hover,.p_admin-collections #browser .utility a.button:hover { - background: #ddd -} -.p_collections #browser .utility a.button.disabled,.p_admin-collections #browser .utility a.button.disabled { - color: #999 -} -.p_collections #browser .utility a.button.disabled:hover,.p_admin-collections #browser .utility a.button.disabled:hover { - background: #eee; - cursor: auto -} -.p_collections #browser .utility button,.p_admin-collections #browser .utility button { - margin: 6px 6px 6px 0; - padding: 3px 6px; - font-size: 13px; - color: #333; - -moz-border-radius: 3px; - -webkit-border-radius: 3px; - -o-border-radius: 3px; - -ms-border-radius: 3px; - -khtml-border-radius: 3px; - border-radius: 3px; - border: 1px solid #ccc; - background: #eee -} -.p_collections #browser .utility button:hover,.p_admin-collections #browser .utility button:hover { - background: #ddd -} -.p_collections #browser .utility button.disabled,.p_admin-collections #browser .utility button.disabled { - color: #999 -} -.p_collections #browser .utility button.disabled:hover,.p_admin-collections #browser .utility button.disabled:hover { - background: #eee; - cursor: auto -} -.p_collections #browser .data,.p_admin-collections #browser .data { - width: 850px; - margin-left: 160px; - border: solid #ddd; - border-width: 0 1px 1px 1px; - border-bottom: 0 -} -.p_collections #browser .data .spinner,.p_admin-collections #browser .data .spinner { - background: url(/images/collections/big_spinner.gif?1322790145) no-repeat center center; - padding: 45px; - text-align: center -} -.p_collections #browser .data .slick-cell,.p_admin-collections #browser .data .slick-cell { - font-size: 12px; - padding: 5px -} -.p_collections #browser .data .slick-cell .undefined,.p_admin-collections #browser .data .slick-cell .undefined { - color: #ccc -} -.p_collections #browser .data .slick-cell em,.p_admin-collections #browser .data .slick-cell em { - font-style: italic -} -.p_collections #browser .data .slick-cell .null,.p_admin-collections #browser .data .slick-cell .null { - font-style: italic -} -.p_collections #browser .data .editor-text,.p_admin-collections #browser .data .editor-text { - position: relative; - top: -4px; - left: -4px -} -.p_collections #browser .data .slick-column-name input,.p_admin-collections #browser .data .slick-column-name input { - margin-left: 4px -} -.p_collections #browser .data .slick-header-columns,.p_admin-collections #browser .data .slick-header-columns { - background: #eee; - font-weight: bold; - font-size: 12px -} -.p_collections #browser .data .slick-column-name .type,.p_admin-collections #browser .data .slick-column-name .type { - color: #999; - font-size: 10px; - margin-left: 4px; - font-weight: normal -} -.p_collections #browser .data .empty,.p_admin-collections #browser .data .empty { - font-size: 19px; - color: #777; - text-align: center; - padding: 45px; - font-weight: bold -} -.p_collections #browser .data table,.p_admin-collections #browser .data table { - border-collapse: collapse; - width: 800px; - font-size: 13px -} -.p_collections #browser .data table .id_col,.p_admin-collections #browser .data table .id_col { - width: 100px -} -.p_collections #browser .data table th,.p_admin-collections #browser .data table th { - padding: 10px; - background: #eee; - font-weight: bold -} -.p_collections #browser .data table td,.p_admin-collections #browser .data table td { - padding: 10px; - line-height: 16px -} -.p_collections #browser .data table tr,.p_admin-collections #browser .data table tr { - border-bottom: 1px solid #ddd -} -.p_docs p { - font-size: 17px; - line-height: 22px -} -.p_docs .section { - display: block -} -.p_docs h2 { - margin-bottom: 25px; - -moz-border-radius: 3px; - -webkit-border-radius: 3px; - -o-border-radius: 3px; - -ms-border-radius: 3px; - -khtml-border-radius: 3px; - border-radius: 3px; - margin-top: 35px; - border-bottom: 1px solid #cbe3f3; - background: #e0eef8; - padding: 10px; - color: #0067ab; - font-size: 22px -} -.p_docs h3 { - color: #0067ab; - font-size: 20px; - font-weight: 600; - margin-bottom: 15px; - margin-top: 35px -} -.p_docs h3.first { - margin-top: 0 -} -.p_docs h4 { - color: #0067ab; - font-size: 17px; -/* font-weight: 600; -*/ - margin-bottom: 15px; - margin-top: 20px - background: #e0eef8; - border-bottom: 1px solid #cbe3f3; - margin-bottom: 25px; - -moz-border-radius: 3px; - -webkit-border-radius: 3px; - -o-border-radius: 3px; - -ms-border-radius: 3px; - -khtml-border-radius: 3px; - border-radius: 3px; - margin-top: 35px; - border-bottom: 1px solid #cbe3f3; - background: #e0eef8; - padding: 5px; -} -.p_docs h2.underline { - margin-top: 35px; - margin-bottom: 15px -} -.p_docs .pic { - margin-top: 15px; - margin-bottom: 15px -} -.p_docs table.endpoints tr th { - background: #0067ab; - color: white; - border: 1px solid #0067ab -} -.p_docs table.endpoints tr td.url { - width: 350px -} -.p_docs .left_col { - width: 725px -} -.p_docs .right_col_container { - position: relative; - width: 257px; - float: right -} -.p_docs .right_col { - width: 257px -} -.p_docs .right_col .download_box { - background: #e0eef8; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - -o-border-radius: 5px; - -ms-border-radius: 5px; - -khtml-border-radius: 5px; - border-radius: 5px; - border: 1px solid #cbe3f3; - padding: 15px; - font-size: 14px -} -.p_docs .right_col .download_box .sect { - overflow: hidden;*zoom:1; - margin-bottom: 20px -} -.p_docs .right_col .download_box .sect .platform { - float: left; - font-size: 13px; - width: 60px; - text-align: center; - margin-right: 15px -} -.p_docs .right_col .download_box .sect .platform img { - margin-bottom: 5px -} -.p_docs .right_col .download_box .sect .files { - float: left; - font-size: 14px; - width: 140px -} -.p_docs .right_col .download_box .sect .files ul { - margin-top: 9px -} -.p_docs .right_col .download_box .sect .files ul li { - margin-bottom: 10px -} -.p_docs .right_col .download_box .sect .soon { - color: #666 -} -.p_docs .right_col .download_box .sect .soon p { - margin-top: 25px -} -.p_docs .right_col .download_box ul li { - margin-bottom: 5px -} -.p_docs .right_col .download_box ul li ul { - margin-top: 0; - margin-left: 5px -} -.p_docs .right_col .box { - background: #e0eef8; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - -o-border-radius: 5px; - -ms-border-radius: 5px; - -khtml-border-radius: 5px; - border-radius: 5px; - border: 1px solid #cbe3f3; - padding: 15px; - font-size: 14px -} -.p_docs .right_col .box h3 { - font-weight: 600; - font-size: 15px; - margin-bottom: 15px -} -.p_docs .right_col .box .last { - margin-bottom: 0 -} -.p_docs .right_col .box a { - display: block; - -moz-border-radius: 3px; - -webkit-border-radius: 3px; - -o-border-radius: 3px; - -ms-border-radius: 3px; - -khtml-border-radius: 3px; - border-radius: 3px; - padding: 3px 5px 3px 10px; - text-decoration: none -} -.p_docs .right_col .box a:hover { - background: #b6d7ef -} -.p_docs .right_col .box a.active { - background: #b6d7ef -} -.p_docs .right_col .box ul strong { - display: block; - font-size: 18px; - margin: 5px auto 5px auto -} -.p_docs .right_col .box ul strong.first { - margin-top: 0 -} -.p_docs .right_col .box ul li { - margin-bottom: 1px -} -.p_docs .right_col .box ul li ul { - margin-top: 0; - margin-left: 5px -} -.p_docs table { - width: 700px -} -.p_docs table tr th { - font-weight: bold -} -.p_docs table tr td,.p_docs table tr th { - vertical-align: top; - padding: 8px; - border: 1px solid #ccc -} -.p_docs table tr td ul li,.p_docs table tr th ul li { - line-height: 22px -} -.p_docs_ios_guide ol,.p_docs_android_guide ol { - list-style-type: decimal; - padding-left: 35px; - margin-bottom: 15px -} -.p_docs_ios_guide ol li,.p_docs_android_guide ol li { - margin-bottom: 8px; - line-height: 20px -} -.p_docs_ios_guide ol li .code,.p_docs_android_guide ol li .code { - margin-top: 15px -} -.p_docs_ios .container,.p_docs_android .container { - overflow: hidden;*zoom:1 -} -.p_docs_ios h2,.p_docs_android h2 { - margin-top: 0 -} -.p_docs_ios .api_menu,.p_docs_android .api_menu { - float: left; - width: 150px; - margin-right: 15px -} -.p_docs_ios .api_menu ul li,.p_docs_android .api_menu ul li { - font-size: 18px -} -.p_docs_ios .api_menu ul li a,.p_docs_android .api_menu ul li a { - display: block; - padding: 6px 9px; - color: #0067ab; - text-decoration: none; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - -o-border-radius: 5px; - -ms-border-radius: 5px; - -khtml-border-radius: 5px; - border-radius: 5px -} -.p_docs_ios .api_menu ul li a.active,.p_docs_android .api_menu ul li a.active { - background: #0067ab; - color: white -} -.p_docs_ios .api_menu ul li a.active:hover,.p_docs_android .api_menu ul li a.active:hover { - background: #0067ab -} -.p_docs_ios .api_menu ul li a:hover,.p_docs_android .api_menu ul li a:hover { - background: #eee -} -.p_docs_ios iframe.autoheight,.p_docs_android iframe.autoheight { - float: left; - width: 800px; - overflow: hidden -} -.c { - color: #408080; - font-style: italic -} -.err { - border: 1px solid #f00 -} -.k { - color: #0067ab; - font-weight: bold -} -.o { - color: #666 -} -.cm { - color: #408080; - font-style: italic -} -.cp { - color: #a36900 -} -.c1 { - color: #408080; - font-style: italic -} -.cs { - color: #408080; - font-style: italic -} -.gd { - color: #a00000 -} -.ge { - font-style: italic -} -.gr { - color: #f00 -} -.gh { - color: #000080; - font-weight: bold -} -.gi { - color: #00a000 -} -.go { - color: #808080 -} -.gp { - color: #000080; - font-weight: bold -} -.gs { - font-weight: bold -} -.gu { - color: #800080; - font-weight: bold -} -.gt { - color: #0040d0 -} -.kc { - color: #008000; - font-weight: bold -} -.kd { - color: #008000; - font-weight: bold -} -.kp { - color: #008000 -} -.kr { - color: #008000; - font-weight: bold -} -.kt { - color: #b00040 -} -.m { - color: #666 -} -.s { - color: #ba2121 -} -.na { - color: #7d9029 -} -.nb { - color: #008000 -} -.nc { - color: #00f; - font-weight: bold -} -.no { - color: #800 -} -.nd { - color: #a2f -} -.ni { - color: #999; - font-weight: bold -} -.ne { - color: #d2413a; - font-weight: bold -} -.nf { - color: #00f -} -.nl { - color: green -} -.nn { - color: #00f; - font-weight: bold -} -.nt { - color: #008000; - font-weight: bold -} -.nv { - color: #19177c -} -.ow { - color: #a2f; - font-weight: bold -} -.w { - color: #bbb -} -.mf { - color: #666 -} -.mh { - color: #666 -} -.mi { - color: #666 -} -.mo { - color: #666 -} -.sb { - color: #ba2121 -} -.sc { - color: #ba2121 -} -.sd { - color: #ba2121; - font-style: italic -} -.s2 { - color: #ba2121 -} -.se { - color: #b62; - font-weight: bold -} -.sh { - color: #ba2121 -} -.si { - color: #b68; - font-weight: bold -} -.sx { - color: #008000 -} -.sr { - color: #b68 -} -.s1 { - color: #ba2121 -} -.ss { - color: #19177c -} -.bp { - color: #008000 -} -.vc { - color: #19177c -} -.vg { - color: #19177c -} -.vi { - color: #19177c -} -.il { - color: #666 -} -.p_home_index .top { - overflow: hidden;*zoom:1 -} -.p_home_index .top .call { - float: left; - width: 360px; - margin-right: 15px -} -.p_home_index .top .call h1 { - margin-top: 20px; - font-size: 40px; - font-weight: 600; - text-shadow: #ccc 2px 2px 3px; - margin-bottom: 20px; - line-height: 45px -} -.p_home_index .top .call h2 { - font-size: 17px; - font-weight: 200; - color: #666; - margin-bottom: 25px; - line-height: 22px -} -.p_home_index .top .call .sign_up .action { - float: left; - margin-right: 25px; - color: white; - font-size: 24px; - width: 214px; - height: 55px; - line-height: 55px; - text-align: center; - background: url(/images/home/signup_button.png?1322790145) no-repeat; - background-position: 0 0; - text-decoration: none -} -.p_home_index .top .call .sign_up .action:hover { - background-position: 0 -55px -} -.p_home_index .top .call .sign_up .action:active { - background-position: 0 -110px -} -.p_home_index .top .call .sign_up small { - font-weight: bold; - margin-top: 11px; - width: 120px; - display: block; - line-height: 17px; - float: left; - font-size: 13px; - color: #555 -} -.p_home_index .top .splash { - float: left; - text-align: right; - width: 611px -} -.p_home_index .top .splash .bubbles { - float: right; - background: url(/images/home/bubbles.png?1322790145) no-repeat top left; - width: 544px; - height: 111px; - margin-bottom: 15px; - position: relative; - top: 25px; - opacity: 0 -} -.p_home_index .top .splash .phones { - float: right; - background: url(/images/home/phones.jpg?1322790145) no-repeat top right; - width: 519px; - height: 240px -} -.p_home_index .gray { - background: url(/images/home/gray_pixels.png?1322790145) repeat top left; - -moz-box-shadow: 0 2px 3px 0 #ccc; - -webkit-box-shadow: 0 2px 3px 0 #ccc; - -o-box-shadow: 0 2px 3px 0 #ccc; - box-shadow: 0 2px 3px 0 #ccc; - min-width: 1024px; - padding: 0 35px 0 35px; - font-size: 17px; - color: #666; - text-align: center -} -.p_home_index .gray ul,.p_home_index .gray .inner { - width: 1024px; - margin: auto -} -.p_home_index .gray ul { - text-align: left -} -.p_home_index .gray ul li { - float: left; - margin-right: 52px; - line-height: 100px -} -.p_home_index .gray ul li img { - vertical-align: middle; - position: relative -} -.p_home_index .trusted { - height: 100px; - line-height: 100px -} -.p_home_index .testimonials { - padding: 25px 35px 25px 35px; - font-family: 'Open Sans'; - overflow: hidden;*zoom:1; - text-align: left -} -.p_home_index .testimonials .inner { - position: relative; - width: 1024px; - margin: auto -} -.p_home_index .testimonials h2 { - font-size: 16px; - color: #333; - margin-bottom: 19px -} -.p_home_index .testimonials .press { - width: 400px; - float: right -} -.p_home_index .testimonials .press img { - margin-right: 15px; - margin-bottom: 15px -} -.p_home_index .testimonials .testimonial { - overflow: hidden;*zoom:1; - float: left; - width: 588px; - text-align: left -} -.p_home_index .testimonials .testimonial img { - float: left; - margin-left: 5px; - margin-top: 5px; - -moz-box-shadow: 0 0 5px 0 #aaa; - -webkit-box-shadow: 0 0 5px 0 #aaa; - -o-box-shadow: 0 0 5px 0 #aaa; - box-shadow: 0 0 5px 0 #aaa -} -.p_home_index .testimonials .testimonial .quote { - width: 500px; - padding-left: 88px; - color: #0067ab; - font-size: 22px; - line-height: 26px; - margin-bottom: 7px -} -.p_home_index .testimonials .testimonial small { - display: block; - font-size: 12px; - color: #666; - padding-left: 88px; - line-height: 15px -} -.p_home_index .testimonials .testimonial .read { - position: absolute; - bottom: 5px; - font-size: 12px; - right: 0 -} -.p_home_index .testimonials .testimonial .read a { - color: #666; - text-decoration: none -} -.p_home_index .testimonials .testimonial .read a:hover { - text-decoration: underline -} -.p_home_index .explain { - margin: 45px auto 45px auto -} -.p_home_index .explain h3 { - font-size: 27px; - font-weight: bold; - margin-bottom: 30px -} -.p_home_index .explain .explainer { - overflow: hidden;*zoom:1 -} -.p_home_index .explain .explainer ul { - width: 225px -} -.p_home_index .explain .explainer ul li a span { - display: block; - float: left; - margin-right: 10px; - width: 25px; - height: 25px; - margin-top: 9px -} -.p_home_index .explain .explainer ul li a#data span { - background: url(/images/home/data_icon.png?1322790145) no-repeat top left -} -.p_home_index .explain .explainer ul li a#push span { - background: url(/images/home/push_icon.png?1322790145) no-repeat top left -} -.p_home_index .explain .explainer ul li a#user span { - background: url(/images/home/user_icon.png?1322790145) no-repeat top left -} -.p_home_index .explain .explainer ul li a#social span { - background: url(/images/home/social_icon.png?1322790145) no-repeat top left -} -.p_home_index .explain .explainer ul li a.active span { - background-position: 0 -25px!important -} -.p_home_index .explain .explainer ul li.read { - background: white; - padding: 0 -} -.p_home_index .explain .explainer ul li.read a { - font-size: 17px; - padding: 0; - background: white; - color: #0067ab; - text-decoration: underline -} -.p_home_index .explain .explainer .explanation { - float: left; - width: 760px -} -.p_home_index .explain .explainer .explanation .code { - border: 1px solid #ddd; - background-color: white; - background-position: bottom right; - background-repeat: no-repeat; - -moz-box-shadow: 0 0 5px 0 #aaa; - -webkit-box-shadow: 0 0 5px 0 #aaa; - -o-box-shadow: 0 0 5px 0 #aaa; - box-shadow: 0 0 5px 0 #aaa; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - -o-border-radius: 5px; - -ms-border-radius: 5px; - -khtml-border-radius: 5px; - border-radius: 5px -} -.p_home_index .explain .explainer .explanation .objective-c { - background-image: url(/images/home/ios.png?1322790145) -} -.p_home_index .explain .explainer .explanation .java { - background-image: url(/images/home/android.png?1322790145) -} -.p_home_index .explain .explainer .explanation .learn img { - margin-left: 3px -} -.p_home_index .seen { - padding-top: 15px -} -.p_home_index .seen ul { - padding-top: 10px; - overflow: hidden;*zoom:1 -} -.p_home_index .seen ul li { - float: left; - margin-right: 10px; - line-height: 40px -} -.p_home_index .seen ul li img { - vertical-align: middle -} -.p_home_index .seen .press_item { - overflow: hidden;*zoom:1; - margin-bottom: 20px -} -.p_home_index .seen .press_item .pub { - float: left; - width: 260px; - margin-right: 15px -} -.p_home_index .seen .press_item .quote { - float: left; - width: 600px; - text-decoration: none; - display: block; - font-size: 18px; - font-family: "Open Sans"; - color: #666; - line-height: 29px; - background: url(/images/home/left_quote_gray.png?1322790145) no-repeat top left; - padding: 0 0 0 35px -} -.p_home_index .seen .press_item .quote .inner { - padding-right: 35px; - background: url(/images/home/right_quote_gray.png?1322790145) no-repeat bottom right -} -.p_home_index .seen h3 a { - text-decoration: none -} -.p_home_index .seen h3 img { - margin-left: 5px; - position: relative; - top: 9px -} -.p_home .right_col { - float: right; - background: url(/images/home/side_bg.png?1322790145) repeat-y top left; - padding: 15px 0 15px 25px -} -.p_home .right_col h3 { - font-weight: bold; - margin-bottom: 10px -} -.p_home .right_col p { - margin-bottom: 5px -} -.p_home .main { - width: 700px -} -.p_home ul.apps { - list-style-type: none; - margin-bottom: 25px; - margin-top: 25px -} -.p_home ul.apps li { - cursor: pointer; - text-decoration: none; - display: block; - padding: 10px 15px 15px 15px; - background: #ecf4f7; - margin-bottom: 15px; - -moz-border-radius: 3px; - -webkit-border-radius: 3px; - -o-border-radius: 3px; - -ms-border-radius: 3px; - -khtml-border-radius: 3px; - border-radius: 3px -} -.p_home ul.apps li:hover { - background: #c8dfe8 -} -.p_home ul.apps li .name { - font-size: 23px; - margin-bottom: 15px; - color: #0067ab -} -.p_home ul.apps li .name img { - position: relative; - top: 7px; - line-height: 23px; - margin-right: 5px -} -.p_home ul.apps li .info { - color: #888; - font-size: 14px -} -html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video { - margin: 0; - padding: 0; - border: 1; - font-size: 100%; - font: inherit; - vertical-align: baseline -} -body { - line-height: 1 -} -ol,ul { - list-style: none -} -table { - border-collapse: collapse; - border-spacing: 0 -} -caption,th,td { - text-align: left; - font-weight: normal; - vertical-align: middle -} -q,blockquote { - quotes: none -} -q:before,q:after,blockquote:before,blockquote:after { - content: ""; - content: none -} -a img { - border: none -} -article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section,summary { - display: block -} -html,body { - height: 100%; - -ms-box-sizing: border-box; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box -} -body { - font-family: "Helvetica Neue",Helvetica -} -h1,h2,h3,h4,h5 { - color: #0067ab; - font-family: 'Open Sans','Helvetica Neue',Helvetica -} -h1 { - font-size: 30px; - font-weight: 600; - margin-bottom: 15px -} -h2 { - font-size: 21px; - font-weight: 600 -} -h2.underline { - border-bottom: 1px solid #ddd; - padding-bottom: 5px -} -p { - margin-bottom: 1em; - line-height: 1.3em -} -strong { - font-weight: bold -} -a { - color: #0067ab -} -a:hover { - color: #004878 -} -.callout { - border-left: 8px solid #999; - background: #eee; - font-weight: 200; - font-size: 19px; - color: #333; - padding: 20px 15px; - margin: 15px auto 15px auto -} -.last { - margin-bottom: 0!important -} -.sticky { - position: fixed; - top: 5px -} -#utility_header { - background: url(/images/header/utility.png?1322790145) repeat-x top left; - height: 29px; - text-align: center; - min-width: 1024px; - padding: 0 35px 0 35px -} -#utility_header ul { - width: 1024px; - font-size: 12px; - color: white; - padding-top: 8px; - margin: auto -} -#utility_header ul a { - font-weight: 300; - color: white; - text-decoration: none -} -#utility_header ul a:hover { - text-decoration: underline -} -#utility_header ul li { - float: right; - background: url(/images/header/separator.png?1322790145) no-repeat top left; - padding-left: 10px; - margin-left: 8px -} -#utility_header ul li em { - font-style: italic -} -#utility_header ul li.last { - background: none -} -#header { - background: #fff url(/images/header_bg.gif?1322790145) repeat-x top left; - text-align: center; - padding: 0 35px 15px 35px; - margin-bottom: 35px; - height: 50px; - position: relative; - min-width: 1024px -} -#header .inner { - width: 1024px; - text-align: left; - margin: auto; - position: relative -} -#header .inner .logo { - background: url(/images/logo_header.png?1322790145) no-repeat top left; - width: 142px; - height: 43px; - display: block; - float: left; - margin-top: 18px; - margin-right: 0 -} -#header .header_signup { - display: block; - float: right; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - -o-border-radius: 5px; - -ms-border-radius: 5px; - -khtml-border-radius: 5px; - border-radius: 5px; - color: #0067ab; - font-family: 'Open Sans'; - padding: 8px 13px; - -moz-box-shadow: inset 0 0 5px 5px #bbb; - -webkit-box-shadow: inset 0 0 5px 5px #bbb; - -o-box-shadow: inset 0 0 5px 5px #bbb; - box-shadow: inset 0 0 5px 5px #bbb; - background: #ddd; - text-decoration: none; - margin-top: 17px; - font-size: 14px -} -#header .header_signup:hover { - background: #eee; - -moz-box-shadow: inset 0 0 5px 5px #ccc; - -webkit-box-shadow: inset 0 0 5px 5px #ccc; - -o-box-shadow: inset 0 0 5px 5px #ccc; - box-shadow: inset 0 0 5px 5px #ccc -} -#header ul { - list-style-type: none; - float: left; - padding-top: 17px; - margin-left: 0 -} -#header ul li { - float: left; - margin-right: 10px; - font-size: 16px -} -#header ul li a { - font-family: 'Open Sans'; - display: block; - padding: 8px 13px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - -o-border-radius: 5px; - -ms-border-radius: 5px; - -khtml-border-radius: 5px; - border-radius: 5px; - color: white; - text-decoration: none -} -#header ul li.active a,#header ul li a:hover { - color: white; - -moz-box-shadow: inset 0 0 5px 5px #003f75; - -webkit-box-shadow: inset 0 0 5px 5px #003f75; - -o-box-shadow: inset 0 0 5px 5px #003f75; - box-shadow: inset 0 0 5px 5px #003f75; - background: #004988 -} -ul.left_menu { - list-style-type: none!important; - padding-left: 0!important; - margin-left: 0!important; - margin-right: 20px; - float: left -} -ul.left_menu li { - margin-bottom: 10px; - height: 42px; - font-size: 18px; - color: #333 -} -ul.left_menu li a { - font-family: 'Open Sans'; - display: block; - background: #eee url(/images/menu/menu_arrow_inv.png?1322790145) no-repeat top right; - line-height: 42px; - color: #333; - padding-left: 10px; - text-decoration: none -} -ul.left_menu li a:hover { - background-color: #ddd -} -ul.left_menu li a.active { - color: white; - background-color: #0067ab -} -ul.left_menu li.active a { - color: white; - background-color: #0067ab -} -.flash { - margin-bottom: 20px; - border: 1px solid #bbb; - background: #FFC; - padding: 15px -} -.container { - width: 1024px; - padding: 0 35px 0 35px; - margin: 0 auto 0 auto; - position: relative -} -form label { - font-size: 15px; - color: #666; - display: block; - margin-bottom: 7px; - margin-top: 25px -} -form label.checkbox { - display: inline; - color: #333 -} -form input.watermark { - color: #aaa -} -form input[type=text],form input[type=password] { - font-size: 25px; - padding: 5px; - width: 500px; - font-family: "Helvetica Neue",Helvetica -} -form textarea { - padding: 5px; - width: 500px; - height: 100px; - font-size: 15px; - font-family: "Helvetica Neue",Helvetica -} -form button { - margin-top: 25px -} -form small { - display: block; - line-height: 1.3em; - margin-top: 5px; - font-size: 13px; - color: #999; - font-style: italic -} -form .buttons { - clear: both; - overflow: hidden;*zoom:1 -} -form .buttons button { - float: left; - margin-right: 25px -} -form .buttons .along { - font-size: 14px; - margin-top: 40px; - float: left; - display: block -} -button,a.button,.signup_button,a.button_small { - font-size: 22px; - color: white; - background: #0067ab; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - -o-border-radius: 5px; - -ms-border-radius: 5px; - -khtml-border-radius: 5px; - border-radius: 5px; - padding: 10px 14px; - border: 0; - cursor: pointer; - outline: none; - display: block; - font-family: "Helvetica Neue",Helvetica -} -button:hover,a.button:hover,.signup_button:hover,a.button_small:hover { - background: #004878 -} -button.small,a.button.small,.small.signup_button,a.button_small.small { - padding: 7px 11px; - font-size: 16px -} -a.button_small { - font-size: 16px; - padding: 8px 12px -} -button.disabled { - background: #aaa; - color: #fff -} -button.inactive { - background: #ddd; - color: #bbb; - cursor: auto -} -a.button,.signup_button,a.button_small { - display: inline-block; - text-decoration: none -} -.errors { - border: 1px solid red; - background: #fdeff0; - padding: 15px; - margin: 15px 0 -} -.errors ul { - padding-left: 25px; - list-style-type: disc -} -.errors ul li { - margin-bottom: 3px -} -.signup_button { - -moz-border-radius: 7px; - -webkit-border-radius: 7px; - -o-border-radius: 7px; - -ms-border-radius: 7px; - -khtml-border-radius: 7px; - border-radius: 7px; - background: #5ca202; - border: 4px solid #468600; - color: white -} -.signup_button:hover { - color: white; - background: #569802 -} -.clear { - clear: both -} -code { - font-size: .9em; - font-family: "Monaco","Courier New",Courier; - color: green; - line-height: 1.3em -} -.code { - background: #e0eef8; - border: 1px solid #b6d7ef; - padding: 15px; - font-size: 13px; - line-height: 19px; - font-family: "Monaco","Courier New",Courier; - margin-bottom: 25px -} -.toggled-code { - position: relative; - background: #e0eef8; - border: 1px solid #b6d7ef; - padding: 15px; - padding-bottom: 30px; - margin-bottom: 25px -} -.toggled-code .code-container { - font-size: 13px; - line-height: 19px; - font-family: "Monaco","Courier New",Courier -} -.toggled-code .code-container .code-section { - display: none -} -.toggled-code .toggles { - position: absolute; - bottom: 0; - right: 0; - padding-right: 10px -} -.toggled-code .toggles .toggle-item { - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - -o-border-radius: 5px; - -ms-border-radius: 5px; - -khtml-border-radius: 5px; - border-radius: 5px; - display: inline-block; - padding: 5px; - margin: 5px; - line-height: 10px -} -.toggled-code .toggles .toggle-item a { - font-size: 12px; - color: #0067ab; - text-decoration: none -} -.toggled-code .toggles .toggle-item.selected { - background-color: #0067ab -} -.toggled-code .toggles .toggle-item.selected a { - color: white -} -.app_menu { - height: 47px; - background: url(/images/menu/bg.png?1322790145) repeat-x top left; - overflow: hidden;*zoom:1; - text-align: center; - margin-bottom: 35px; - padding: 0 35px 0 35px -} -.app_menu ul { - border-left: 1px solid #ccc; - width: 1024px; - margin: 0 auto 0 auto; - overflow: hidden;*zoom:1 -} -.app_menu ul li { - float: left; - border-right: 1px solid #ccc -} -.app_menu ul li a { - height: 47px; - line-height: 47px; - display: block; - padding: 0 15px; - font-size: 18px; - color: #333; - text-decoration: none -} -.app_menu ul li a:hover { - background: url(/images/menu/hover_bg.png?1322790145) repeat-x top left -} -.app_menu ul li.active a { - -moz-box-shadow: inset 0 0 5px 5px #005187; - -webkit-box-shadow: inset 0 0 5px 5px #005187; - -o-box-shadow: inset 0 0 5px 5px #005187; - box-shadow: inset 0 0 5px 5px #005187; - background: #0067ab; - color: white; - font-weight: bold -} -.clearfix { - overflow: hidden;*zoom:1 -} -#footer { - background: #004f8a url(/images/footer_bg.gif?1322790145) repeat-x top left; - clear: both; - overflow: hidden;*zoom:1; - font-family: 'Open Sans'; - padding: 45px 35px 45px 35px; - margin: 35px auto 0 auto; - color: white; - min-width: 1024px -} -#footer ul { - float: left; - width: 250px; - overflow: hidden;*zoom:1 -} -#footer ul li { - margin-bottom: 15px -} -#footer ul li.header { - font-weight: bold; - font-size: 17px -} -#footer ul li a { - color: white; - text-decoration: none -} -#footer ul li a:hover { - text-decoration: underline -} -#footer .inner { - width: 1024px; - margin: auto -} -.ui-dialog { - -moz-box-shadow: 0 0 15px 3px #333; - -webkit-box-shadow: 0 0 15px 3px #333; - -o-box-shadow: 0 0 15px 3px #333; - box-shadow: 0 0 15px 3px #333 -} -.lightbox form .errors { - background: #c33; - padding: 5px; - color: white -} -.lightbox h2 { - margin-top: 15px -} -.lightbox input[type="checkbox"] { - margin-right: 5px -} -.tips { - float: right; - width: 300px; - background: #eee; - padding: 15px 20px; - font-size: 13px; - margin-bottom: 25px; - color: #666; - border: 1px solid #ddd -} -.tips h3 { - font-size: 17px; - margin-bottom: 1em; - color: black -} -body.bare .container { - margin-top: 45px -} -.question_tip { - background: url(/images/question.png?1322790145) no-repeat top left; - width: 15px; - height: 16px; - display: inline-block; - cursor: pointer; - margin-left: 5px -} -.question_tip:hover { - background-position: 0 -16px -} -ul.text,ol.text { - list-style-type: disc; - margin-top: 10px; - margin-left: 25px; - margin-bottom: 25px -} -ul.text li,ol.text li { - line-height: 1.2em; - margin-bottom: 10px -} -ol.text { - list-style-type: decimal -} -.p_users .good { - padding: 15px; - margin-top: 15px; - margin-bottom: 45px; - background: #0067ab; - color: white; - float: left; - font-size: 20px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - -o-border-radius: 5px; - -ms-border-radius: 5px; - -khtml-border-radius: 5px; - border-radius: 5px; - overflow: hidden;*zoom:1 -} -.p_users h1 { - line-height: 40px -} -.ui-helper-hidden { - display: none -} -.ui-helper-hidden-accessible { - position: absolute!important; - clip: rect(1px 1px 1px 1px); - clip: rect(1px,1px,1px,1px) -} -.ui-helper-reset { - margin: 0; - padding: 0; - border: 0; - outline: 0; - line-height: 1.3; - text-decoration: none; - font-size: 100%; - list-style: none -} -.ui-helper-clearfix:after { - content: "."; - display: block; - height: 0; - clear: both; - visibility: hidden -} -.ui-helper-clearfix { - display: inline-block -} -* html .ui-helper-clearfix { - height: 1% -} -.ui-helper-clearfix { - display: block -} -.ui-helper-zfix { - width: 100%; - height: 100%; - top: 0; - left: 0; - position: absolute; - opacity: 0; - filter: Alpha(Opacity=0) -} -.ui-state-disabled { - cursor: default!important -} -.ui-icon { - display: block; - text-indent: -99999px; - overflow: hidden; - background-repeat: no-repeat -} -.ui-widget-overlay { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100% -} -.ui-widget .ui-widget { - font-size: 1em -} -.ui-widget-content { - background: white; - color: #333 -} -.ui-widget-content a { - color: #333 -} -.ui-widget-header { - background: #0067ab 50% 50% repeat-x; - color: #fff; - font-weight: bold -} -.ui-widget-header a { - color: #fff -} -.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default { - border: 1px solid #ccc; - background: #f6f6f6 50% 50% repeat-x; - font-weight: bold; - color: #1c94c4 -} -.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited { - color: #1c94c4; - text-decoration: none -} -.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus { - border: 1px solid #fbcb09; - background: #fdf5ce 50% 50% repeat-x; - font-weight: bold; - color: #c77405 -} -.ui-state-hover a,.ui-state-hover a:hover { - color: #c77405; - text-decoration: none -} -.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active { - border: 1px solid #fbd850; - background: #fff 50% 50% repeat-x; - font-weight: bold; - color: #eb8f00 -} -.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited { - color: #eb8f00; - text-decoration: none -} -.ui-widget :active { - outline: none -} -.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight { - border: 1px solid #fed22f; - background: #ffe45c 50% top repeat-x; - color: #363636 -} -.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { - color: #363636 -} -.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error { - border: 1px solid #cd0a0a; - background: #b81900 50% 50% repeat; - color: #fff -} -.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a { - color: #fff -} -.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text { - color: #fff -} -.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary { - font-weight: bold -} -.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary { - opacity: .7; - filter: Alpha(Opacity=70); - font-weight: normal -} -.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled { - opacity: .35; - filter: Alpha(Opacity=35); - background-image: none -} -.ui-icon { - width: 16px; - height: 16px; - background-image: url(/images/vendor/ui-icons_222222_256x240.png?1322790145) -} -.ui-widget-content .ui-icon { - background-image: url(/images/vendor/ui-icons_222222_256x240.png?1322790145) -} -.ui-widget-header .ui-icon { - background-image: url(/images/vendor/ui-icons_ffffff_256x240.png?1322790145) -} -.ui-state-default .ui-icon { - background-image: url(/images/vendor/ui-icons_ef8c08_256x240.png?1322790145) -} -.ui-state-hover .ui-icon,.ui-state-focus .ui-icon { - background-image: url(/images/vendor/ui-icons_ef8c08_256x240.png?1322790145) -} -.ui-state-active .ui-icon { - background-image: url(/images/vendor/ui-icons_ef8c08_256x240.png?1322790145) -} -.ui-state-highlight .ui-icon { - background-image: url(/images/vendor/ui-icons_228ef1_256x240.png?1322790145) -} -.ui-state-error .ui-icon,.ui-state-error-text .ui-icon { - background-image: url(/images/vendor/ui-icons_ffd27a_256x240.png?1322790145) -} -.ui-icon-carat-1-n { - background-position: 0 0 -} -.ui-icon-carat-1-ne { - background-position: -16px 0 -} -.ui-icon-carat-1-e { - background-position: -32px 0 -} -.ui-icon-carat-1-se { - background-position: -48px 0 -} -.ui-icon-carat-1-s { - background-position: -64px 0 -} -.ui-icon-carat-1-sw { - background-position: -80px 0 -} -.ui-icon-carat-1-w { - background-position: -96px 0 -} -.ui-icon-carat-1-nw { - background-position: -112px 0 -} -.ui-icon-carat-2-n-s { - background-position: -128px 0 -} -.ui-icon-carat-2-e-w { - background-position: -144px 0 -} -.ui-icon-triangle-1-n { - background-position: 0 -16px -} -.ui-icon-triangle-1-ne { - background-position: -16px -16px -} -.ui-icon-triangle-1-e { - background-position: -32px -16px -} -.ui-icon-triangle-1-se { - background-position: -48px -16px -} -.ui-icon-triangle-1-s { - background-position: -64px -16px -} -.ui-icon-triangle-1-sw { - background-position: -80px -16px -} -.ui-icon-triangle-1-w { - background-position: -96px -16px -} -.ui-icon-triangle-1-nw { - background-position: -112px -16px -} -.ui-icon-triangle-2-n-s { - background-position: -128px -16px -} -.ui-icon-triangle-2-e-w { - background-position: -144px -16px -} -.ui-icon-arrow-1-n { - background-position: 0 -32px -} -.ui-icon-arrow-1-ne { - background-position: -16px -32px -} -.ui-icon-arrow-1-e { - background-position: -32px -32px -} -.ui-icon-arrow-1-se { - background-position: -48px -32px -} -.ui-icon-arrow-1-s { - background-position: -64px -32px -} -.ui-icon-arrow-1-sw { - background-position: -80px -32px -} -.ui-icon-arrow-1-w { - background-position: -96px -32px -} -.ui-icon-arrow-1-nw { - background-position: -112px -32px -} -.ui-icon-arrow-2-n-s { - background-position: -128px -32px -} -.ui-icon-arrow-2-ne-sw { - background-position: -144px -32px -} -.ui-icon-arrow-2-e-w { - background-position: -160px -32px -} -.ui-icon-arrow-2-se-nw { - background-position: -176px -32px -} -.ui-icon-arrowstop-1-n { - background-position: -192px -32px -} -.ui-icon-arrowstop-1-e { - background-position: -208px -32px -} -.ui-icon-arrowstop-1-s { - background-position: -224px -32px -} -.ui-icon-arrowstop-1-w { - background-position: -240px -32px -} -.ui-icon-arrowthick-1-n { - background-position: 0 -48px -} -.ui-icon-arrowthick-1-ne { - background-position: -16px -48px -} -.ui-icon-arrowthick-1-e { - background-position: -32px -48px -} -.ui-icon-arrowthick-1-se { - background-position: -48px -48px -} -.ui-icon-arrowthick-1-s { - background-position: -64px -48px -} -.ui-icon-arrowthick-1-sw { - background-position: -80px -48px -} -.ui-icon-arrowthick-1-w { - background-position: -96px -48px -} -.ui-icon-arrowthick-1-nw { - background-position: -112px -48px -} -.ui-icon-arrowthick-2-n-s { - background-position: -128px -48px -} -.ui-icon-arrowthick-2-ne-sw { - background-position: -144px -48px -} -.ui-icon-arrowthick-2-e-w { - background-position: -160px -48px -} -.ui-icon-arrowthick-2-se-nw { - background-position: -176px -48px -} -.ui-icon-arrowthickstop-1-n { - background-position: -192px -48px -} -.ui-icon-arrowthickstop-1-e { - background-position: -208px -48px -} -.ui-icon-arrowthickstop-1-s { - background-position: -224px -48px -} -.ui-icon-arrowthickstop-1-w { - background-position: -240px -48px -} -.ui-icon-arrowreturnthick-1-w { - background-position: 0 -64px -} -.ui-icon-arrowreturnthick-1-n { - background-position: -16px -64px -} -.ui-icon-arrowreturnthick-1-e { - background-position: -32px -64px -} -.ui-icon-arrowreturnthick-1-s { - background-position: -48px -64px -} -.ui-icon-arrowreturn-1-w { - background-position: -64px -64px -} -.ui-icon-arrowreturn-1-n { - background-position: -80px -64px -} -.ui-icon-arrowreturn-1-e { - background-position: -96px -64px -} -.ui-icon-arrowreturn-1-s { - background-position: -112px -64px -} -.ui-icon-arrowrefresh-1-w { - background-position: -128px -64px -} -.ui-icon-arrowrefresh-1-n { - background-position: -144px -64px -} -.ui-icon-arrowrefresh-1-e { - background-position: -160px -64px -} -.ui-icon-arrowrefresh-1-s { - background-position: -176px -64px -} -.ui-icon-arrow-4 { - background-position: 0 -80px -} -.ui-icon-arrow-4-diag { - background-position: -16px -80px -} -.ui-icon-extlink { - background-position: -32px -80px -} -.ui-icon-newwin { - background-position: -48px -80px -} -.ui-icon-refresh { - background-position: -64px -80px -} -.ui-icon-shuffle { - background-position: -80px -80px -} -.ui-icon-transfer-e-w { - background-position: -96px -80px -} -.ui-icon-transferthick-e-w { - background-position: -112px -80px -} -.ui-icon-folder-collapsed { - background-position: 0 -96px -} -.ui-icon-folder-open { - background-position: -16px -96px -} -.ui-icon-document { - background-position: -32px -96px -} -.ui-icon-document-b { - background-position: -48px -96px -} -.ui-icon-note { - background-position: -64px -96px -} -.ui-icon-mail-closed { - background-position: -80px -96px -} -.ui-icon-mail-open { - background-position: -96px -96px -} -.ui-icon-suitcase { - background-position: -112px -96px -} -.ui-icon-comment { - background-position: -128px -96px -} -.ui-icon-person { - background-position: -144px -96px -} -.ui-icon-print { - background-position: -160px -96px -} -.ui-icon-trash { - background-position: -176px -96px -} -.ui-icon-locked { - background-position: -192px -96px -} -.ui-icon-unlocked { - background-position: -208px -96px -} -.ui-icon-bookmark { - background-position: -224px -96px -} -.ui-icon-tag { - background-position: -240px -96px -} -.ui-icon-home { - background-position: 0 -112px -} -.ui-icon-flag { - background-position: -16px -112px -} -.ui-icon-calendar { - background-position: -32px -112px -} -.ui-icon-cart { - background-position: -48px -112px -} -.ui-icon-pencil { - background-position: -64px -112px -} -.ui-icon-clock { - background-position: -80px -112px -} -.ui-icon-disk { - background-position: -96px -112px -} -.ui-icon-calculator { - background-position: -112px -112px -} -.ui-icon-zoomin { - background-position: -128px -112px -} -.ui-icon-zoomout { - background-position: -144px -112px -} -.ui-icon-search { - background-position: -160px -112px -} -.ui-icon-wrench { - background-position: -176px -112px -} -.ui-icon-gear { - background-position: -192px -112px -} -.ui-icon-heart { - background-position: -208px -112px -} -.ui-icon-star { - background-position: -224px -112px -} -.ui-icon-link { - background-position: -240px -112px -} -.ui-icon-cancel { - background-position: 0 -128px -} -.ui-icon-plus { - background-position: -16px -128px -} -.ui-icon-plusthick { - background-position: -32px -128px -} -.ui-icon-minus { - background-position: -48px -128px -} -.ui-icon-minusthick { - background-position: -64px -128px -} -.ui-icon-close { - background-position: -80px -128px -} -.ui-icon-closethick { - background-position: -96px -128px -} -.ui-icon-key { - background-position: -112px -128px -} -.ui-icon-lightbulb { - background-position: -128px -128px -} -.ui-icon-scissors { - background-position: -144px -128px -} -.ui-icon-clipboard { - background-position: -160px -128px -} -.ui-icon-copy { - background-position: -176px -128px -} -.ui-icon-contact { - background-position: -192px -128px -} -.ui-icon-image { - background-position: -208px -128px -} -.ui-icon-video { - background-position: -224px -128px -} -.ui-icon-script { - background-position: -240px -128px -} -.ui-icon-alert { - background-position: 0 -144px -} -.ui-icon-info { - background-position: -16px -144px -} -.ui-icon-notice { - background-position: -32px -144px -} -.ui-icon-help { - background-position: -48px -144px -} -.ui-icon-check { - background-position: -64px -144px -} -.ui-icon-bullet { - background-position: -80px -144px -} -.ui-icon-radio-off { - background-position: -96px -144px -} -.ui-icon-radio-on { - background-position: -112px -144px -} -.ui-icon-pin-w { - background-position: -128px -144px -} -.ui-icon-pin-s { - background-position: -144px -144px -} -.ui-icon-play { - background-position: 0 -160px -} -.ui-icon-pause { - background-position: -16px -160px -} -.ui-icon-seek-next { - background-position: -32px -160px -} -.ui-icon-seek-prev { - background-position: -48px -160px -} -.ui-icon-seek-end { - background-position: -64px -160px -} -.ui-icon-seek-start { - background-position: -80px -160px -} -.ui-icon-seek-first { - background-position: -80px -160px -} -.ui-icon-stop { - background-position: -96px -160px -} -.ui-icon-eject { - background-position: -112px -160px -} -.ui-icon-volume-off { - background-position: -128px -160px -} -.ui-icon-volume-on { - background-position: -144px -160px -} -.ui-icon-power { - background-position: 0 -176px -} -.ui-icon-signal-diag { - background-position: -16px -176px -} -.ui-icon-signal { - background-position: -32px -176px -} -.ui-icon-battery-0 { - background-position: -48px -176px -} -.ui-icon-battery-1 { - background-position: -64px -176px -} -.ui-icon-battery-2 { - background-position: -80px -176px -} -.ui-icon-battery-3 { - background-position: -96px -176px -} -.ui-icon-circle-plus { - background-position: 0 -192px -} -.ui-icon-circle-minus { - background-position: -16px -192px -} -.ui-icon-circle-close { - background-position: -32px -192px -} -.ui-icon-circle-triangle-e { - background-position: -48px -192px -} -.ui-icon-circle-triangle-s { - background-position: -64px -192px -} -.ui-icon-circle-triangle-w { - background-position: -80px -192px -} -.ui-icon-circle-triangle-n { - background-position: -96px -192px -} -.ui-icon-circle-arrow-e { - background-position: -112px -192px -} -.ui-icon-circle-arrow-s { - background-position: -128px -192px -} -.ui-icon-circle-arrow-w { - background-position: -144px -192px -} -.ui-icon-circle-arrow-n { - background-position: -160px -192px -} -.ui-icon-circle-zoomin { - background-position: -176px -192px -} -.ui-icon-circle-zoomout { - background-position: -192px -192px -} -.ui-icon-circle-check { - background-position: -208px -192px -} -.ui-icon-circlesmall-plus { - background-position: 0 -208px -} -.ui-icon-circlesmall-minus { - background-position: -16px -208px -} -.ui-icon-circlesmall-close { - background-position: -32px -208px -} -.ui-icon-squaresmall-plus { - background-position: -48px -208px -} -.ui-icon-squaresmall-minus { - background-position: -64px -208px -} -.ui-icon-squaresmall-close { - background-position: -80px -208px -} -.ui-icon-grip-dotted-vertical { - background-position: 0 -224px -} -.ui-icon-grip-dotted-horizontal { - background-position: -16px -224px -} -.ui-icon-grip-solid-vertical { - background-position: -32px -224px -} -.ui-icon-grip-solid-horizontal { - background-position: -48px -224px -} -.ui-icon-gripsmall-diagonal-se { - background-position: -64px -224px -} -.ui-icon-grip-diagonal-se { - background-position: -80px -224px -} -.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl { - -moz-border-radius-topleft: 4px; - -webkit-border-top-left-radius: 4px; - -khtml-border-top-left-radius: 4px; - border-top-left-radius: 4px -} -.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr { - -moz-border-radius-topright: 4px; - -webkit-border-top-right-radius: 4px; - -khtml-border-top-right-radius: 4px; - border-top-right-radius: 4px -} -.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl { - -moz-border-radius-bottomleft: 4px; - -webkit-border-bottom-left-radius: 4px; - -khtml-border-bottom-left-radius: 4px; - border-bottom-left-radius: 4px -} -.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br { - -moz-border-radius-bottomright: 4px; - -webkit-border-bottom-right-radius: 4px; - -khtml-border-bottom-right-radius: 4px; - border-bottom-right-radius: 4px -} -.ui-widget-overlay { - background: #666 50% 50% repeat; - opacity: .50; - filter: Alpha(Opacity=50) -} -.ui-widget-shadow { - margin: -5px 0 0 -5px; - padding: 5px; - background: #000 url(/images/vendor/ui-bg_flat_10_000000_40x100.png) 50% 50% repeat-x; - opacity: .20; - filter: Alpha(Opacity=20); - -moz-border-radius: 5px; - -khtml-border-radius: 5px; - -webkit-border-radius: 5px; - border-radius: 5px -} -.ui-dialog { - position: absolute; - padding: .2em; - width: 300px; - overflow: hidden -} -.ui-dialog .ui-dialog-titlebar { - padding: .4em 1em; - position: relative -} -.ui-dialog .ui-dialog-title { - float: left; - margin: .1em 16px .1em 0 -} -.ui-dialog .ui-dialog-titlebar-close { - position: absolute; - right: .3em; - top: 50%; - width: 19px; - margin: -10px 0 0 0; - padding: 1px; - height: 18px -} -.ui-dialog .ui-dialog-titlebar-close span { - display: block; - margin: 1px -} -.ui-dialog .ui-dialog-titlebar-close:hover,.ui-dialog .ui-dialog-titlebar-close:focus { - padding: 0 -} -.ui-dialog .ui-dialog-content { - position: relative; - border: 0; - padding: .5em 1em; - background: none; - overflow: auto; - zoom: 1 -} -.ui-dialog .ui-dialog-buttonpane { - text-align: left; - border-width: 1px 0 0 0; - background-image: none; - margin: .5em 0 0 0; - padding: .3em 1em .5em .4em -} -.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { - float: right -} -.ui-dialog .ui-dialog-buttonpane button { - margin: .5em .4em .5em 0; - cursor: pointer -} -.ui-dialog .ui-resizable-se { - width: 14px; - height: 14px; - right: 3px; - bottom: 3px -} -.ui-draggable .ui-dialog-titlebar { - cursor: move -} -.slick-header.ui-state-default,.slick-headerrow.ui-state-default { - width: 100%; - overflow: hidden; - border-left: 0 -} -.slick-header-columns,.slick-headerrow-columns { - width: 999999px; - position: relative; - white-space: nowrap; - cursor: default; - overflow: hidden -} -.slick-header-column.ui-state-default { - position: relative; - display: inline-block; - overflow: hidden; - text-overflow: ellipsis; - height: 16px; - line-height: 16px; - margin: 0; - padding: 4px; - border-right: 1px solid silver; - border-left: 0; - border-top: 0; - border-bottom: 0; - float: left -} -.slick-headerrow-column.ui-state-default { - padding: 4px -} -.slick-header-column-sorted { - font-style: italic -} -.slick-sort-indicator { - display: inline-block; - width: 8px; - height: 5px; - margin-left: 4px -} -.slick-sort-indicator-desc { - background: url(../stylesheets/compiled/main/vendor/images/sort-desc.gif) -} -.slick-sort-indicator-asc { - background: url(../stylesheets/compiled/main/vendor/images/sort-asc.gif) -} -.slick-resizable-handle { - position: absolute; - font-size: .1px; - display: block; - cursor: col-resize; - width: 4px; - right: 0; - top: 0; - height: 100% -} -.slick-sortable-placeholder { - background: silver -} -.grid-canvas { - position: relative; - outline: 0 -} -.slick-row.ui-widget-content,.slick-row.ui-state-active { - position: absolute; - border: 0 -} -.slick-cell,.slick-headerrow-column { - float: left; - border: 1px solid transparent; - border-right: 1px dotted silver; - border-bottom-color: silver; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - vertical-align: middle; - z-index: 1; - padding: 1px 2px 2px 1px; - margin: 0; - white-space: nowrap; - cursor: default -} -.slick-group-toggle { - display: inline-block -} -.slick-cell.highlighted { - background: lightskyblue; - background: rgba(0,0,255,0.2); - -webkit-transition: all .5s; - -moz-transition: all .5s; - transition: all .5s -} -.slick-cell.flashing { - border: 1px solid red!important -} -.slick-cell.editable { - z-index: 11; - overflow: visible; - background: white; - border-color: black; - border-style: solid -} -.slick-cell:focus { - outline: none -} -.slick-reorder-proxy { - display: inline-block; - background: blue; - opacity: .15; - filter: alpha(opacity=15); - cursor: move -} -.slick-reorder-guide { - display: inline-block; - height: 2px; - background: blue; - opacity: .7; - filter: alpha(opacity=70) -} -.slick-selection { - z-index: 10; - position: absolute; - border: 2px dashed black -} -.slick-header-columns { - border-bottom: 1px solid silver -} -.slick-header-column { - border-right: 1px solid silver -} -.slick-headerrow { - background: #fafafa -} -.slick-headerrow-column { - background: #fafafa; - border-bottom: 0; - height: 100% -} -.slick-row.ui-state-active { - background: #f5f7d7 -} -.slick-row { - position: absolute; - background: white; - border: 0; - line-height: 20px -} -.slick-row.selected { - z-index: 10; - background: #dfe8f6 -} -.slick-cell { - padding-left: 4px; - padding-right: 4px -} -.slick-group { - border-bottom: 2px solid silver -} -.slick-group-toggle { - width: 9px; - height: 9px; - margin-right: 5px -} -.slick-group-toggle.expanded { - background: url(../stylesheets/compiled/main/images/collapse.gif) no-repeat center center -} -.slick-group-toggle.collapsed { - background: url(../stylesheets/compiled/main/images/expand.gif) no-repeat center center -} -.slick-group-totals { - color: gray; - background: white -} -.slick-cell.selected { - background-color: beige -} -.slick-cell.active { - border-color: gray; - border-style: solid -} -.slick-sortable-placeholder { - background: silver!important -} -.slick-row[row$="1"],.slick-row[row$="3"],.slick-row[row$="5"],.slick-row[row$="7"],.slick-row[row$="9"] { - background: #fafafa -} -.slick-row.ui-state-active { - background: #f5f7d7 -} -.slick-row.loading { - opacity: .5; - filter: alpha(opacity=50) -} -.slick-cell.invalid { - border-color: red -} diff --git a/doc/main.js b/doc/main.js deleted file mode 100644 index 2d4017d7fdf..00000000000 --- a/doc/main.js +++ /dev/null @@ -1,106 +0,0 @@ -/*! - * jQuery JavaScript Library v1.6.1 - * http://jquery.com/ - * - * Copyright 2011, John Resig - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * Copyright 2011, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * - * Date: Thu May 12 15:04:36 2011 -0400 - */ -(function(be,N){var au=be.document,bw=be.navigator,bn=be.location;var b=(function(){var bG=function(b0,b1){return new bG.fn.init(b0,b1,bE)},bV=be.jQuery,bI=be.$,bE,bZ=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,bO=/\S/,bK=/^\s+/,bF=/\s+$/,bJ=/\d/,bC=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,bP=/^[\],:{}\s]*$/,bX=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,bR=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,bL=/(?:^|:|,)(?:\s*\[)+/g,bA=/(webkit)[ \/]([\w.]+)/,bT=/(opera)(?:.*version)?[ \/]([\w.]+)/,bS=/(msie) ([\w.]+)/,bU=/(mozilla)(?:.*? rv:([\w.]+))?/,bY=bw.userAgent,bW,bD,e,bN=Object.prototype.toString,bH=Object.prototype.hasOwnProperty,bB=Array.prototype.push,bM=Array.prototype.slice,bQ=String.prototype.trim,bx=Array.prototype.indexOf,bz={};bG.fn=bG.prototype={constructor:bG,init:function(b0,b4,b3){var b2,b5,b1,b6;if(!b0){return this}if(b0.nodeType){this.context=this[0]=b0;this.length=1;return this}if(b0==="body"&&!b4&&au.body){this.context=au;this[0]=au.body;this.selector=b0;this.length=1;return this}if(typeof b0==="string"){if(b0.charAt(0)==="<"&&b0.charAt(b0.length-1)===">"&&b0.length>=3){b2=[null,b0,null]}else{b2=bZ.exec(b0)}if(b2&&(b2[1]||!b4)){if(b2[1]){b4=b4 instanceof bG?b4[0]:b4;b6=(b4?b4.ownerDocument||b4:au);b1=bC.exec(b0);if(b1){if(bG.isPlainObject(b4)){b0=[au.createElement(b1[1])];bG.fn.attr.call(b0,b4,true)}else{b0=[b6.createElement(b1[1])]}}else{b1=bG.buildFragment([b2[1]],[b6]);b0=(b1.cacheable?bG.clone(b1.fragment):b1.fragment).childNodes}return bG.merge(this,b0)}else{b5=au.getElementById(b2[2]);if(b5&&b5.parentNode){if(b5.id!==b2[2]){return b3.find(b0)}this.length=1;this[0]=b5}this.context=au;this.selector=b0;return this}}else{if(!b4||b4.jquery){return(b4||b3).find(b0)}else{return this.constructor(b4).find(b0)}}}else{if(bG.isFunction(b0)){return b3.ready(b0)}}if(b0.selector!==N){this.selector=b0.selector;this.context=b0.context}return bG.makeArray(b0,this)},selector:"",jquery:"1.6.1",length:0,size:function(){return this.length},toArray:function(){return bM.call(this,0)},get:function(b0){return b0==null?this.toArray():(b0<0?this[this.length+b0]:this[b0])},pushStack:function(b1,b3,b0){var b2=this.constructor();if(bG.isArray(b1)){bB.apply(b2,b1)}else{bG.merge(b2,b1)}b2.prevObject=this;b2.context=this.context;if(b3==="find"){b2.selector=this.selector+(this.selector?" ":"")+b0}else{if(b3){b2.selector=this.selector+"."+b3+"("+b0+")"}}return b2},each:function(b1,b0){return bG.each(this,b1,b0)},ready:function(b0){bG.bindReady();bD.done(b0);return this},eq:function(b0){return b0===-1?this.slice(b0):this.slice(b0,+b0+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(bM.apply(this,arguments),"slice",bM.call(arguments).join(","))},map:function(b0){return this.pushStack(bG.map(this,function(b2,b1){return b0.call(b2,b1,b2)}))},end:function(){return this.prevObject||this.constructor(null)},push:bB,sort:[].sort,splice:[].splice};bG.fn.init.prototype=bG.fn;bG.extend=bG.fn.extend=function(){var b9,b2,b0,b1,b6,b7,b5=arguments[0]||{},b4=1,b3=arguments.length,b8=false;if(typeof b5==="boolean"){b8=b5;b5=arguments[1]||{};b4=2}if(typeof b5!=="object"&&!bG.isFunction(b5)){b5={}}if(b3===b4){b5=this;--b4}for(;b40){return}bD.resolveWith(au,[bG]);if(bG.fn.trigger){bG(au).trigger("ready").unbind("ready")}}},bindReady:function(){if(bD){return}bD=bG._Deferred();if(au.readyState==="complete"){return setTimeout(bG.ready,1)}if(au.addEventListener){au.addEventListener("DOMContentLoaded",e,false);be.addEventListener("load",bG.ready,false)}else{if(au.attachEvent){au.attachEvent("onreadystatechange",e);be.attachEvent("onload",bG.ready);var b0=false;try{b0=be.frameElement==null}catch(b1){}if(au.documentElement.doScroll&&b0){by()}}}},isFunction:function(b0){return bG.type(b0)==="function"},isArray:Array.isArray||function(b0){return bG.type(b0)==="array"},isWindow:function(b0){return b0&&typeof b0==="object"&&"setInterval" in b0},isNaN:function(b0){return b0==null||!bJ.test(b0)||isNaN(b0)},type:function(b0){return b0==null?String(b0):bz[bN.call(b0)]||"object"},isPlainObject:function(b1){if(!b1||bG.type(b1)!=="object"||b1.nodeType||bG.isWindow(b1)){return false}if(b1.constructor&&!bH.call(b1,"constructor")&&!bH.call(b1.constructor.prototype,"isPrototypeOf")){return false}var b0;for(b0 in b1){}return b0===N||bH.call(b1,b0)},isEmptyObject:function(b1){for(var b0 in b1){return false}return true},error:function(b0){throw b0},parseJSON:function(b0){if(typeof b0!=="string"||!b0){return null}b0=bG.trim(b0);if(be.JSON&&be.JSON.parse){return be.JSON.parse(b0)}if(bP.test(b0.replace(bX,"@").replace(bR,"]").replace(bL,""))){return(new Function("return "+b0))()}bG.error("Invalid JSON: "+b0)},parseXML:function(b2,b0,b1){if(be.DOMParser){b1=new DOMParser();b0=b1.parseFromString(b2,"text/xml")}else{b0=new ActiveXObject("Microsoft.XMLDOM");b0.async="false";b0.loadXML(b2)}b1=b0.documentElement;if(!b1||!b1.nodeName||b1.nodeName==="parsererror"){bG.error("Invalid XML: "+b2)}return b0},noop:function(){},globalEval:function(b0){if(b0&&bO.test(b0)){(be.execScript||function(b1){be["eval"].call(be,b1)})(b0)}},nodeName:function(b1,b0){return b1.nodeName&&b1.nodeName.toUpperCase()===b0.toUpperCase()},each:function(b3,b6,b2){var b1,b4=0,b5=b3.length,b0=b5===N||bG.isFunction(b3);if(b2){if(b0){for(b1 in b3){if(b6.apply(b3[b1],b2)===false){break}}}else{for(;b40&&b0[0]&&b0[b1-1])||b1===0||bG.isArray(b0));if(b3){for(;b21?aJ.call(arguments,0):bE;if(!(--bA)){e.resolveWith(e,aJ.call(bx,0))}}}if(bB>1){for(;by
a";bB=bH.getElementsByTagName("*");bO=bH.getElementsByTagName("a")[0];if(!bB||!bB.length||!bO){return{}}bI=au.createElement("select");bz=bI.appendChild(au.createElement("option"));bG=bH.getElementsByTagName("input")[0];bE={leadingWhitespace:(bH.firstChild.nodeType===3),tbody:!bH.getElementsByTagName("tbody").length,htmlSerialize:!!bH.getElementsByTagName("link").length,style:/top/.test(bO.getAttribute("style")),hrefNormalized:(bO.getAttribute("href")==="/a"),opacity:/^0.55$/.test(bO.style.opacity),cssFloat:!!bO.style.cssFloat,checkOn:(bG.value==="on"),optSelected:bz.selected,getSetAttribute:bH.className!=="t",submitBubbles:true,changeBubbles:true,focusinBubbles:false,deleteExpando:true,noCloneEvent:true,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableMarginRight:true};bG.checked=true;bE.noCloneChecked=bG.cloneNode(true).checked;bI.disabled=true;bE.optDisabled=!bz.disabled;try{delete bH.test}catch(bM){bE.deleteExpando=false}if(!bH.addEventListener&&bH.attachEvent&&bH.fireEvent){bH.attachEvent("onclick",function bJ(){bE.noCloneEvent=false;bH.detachEvent("onclick",bJ)});bH.cloneNode(true).fireEvent("onclick")}bG=au.createElement("input");bG.value="t";bG.setAttribute("type","radio");bE.radioValue=bG.value==="t";bG.setAttribute("checked","checked");bH.appendChild(bG);by=au.createDocumentFragment();by.appendChild(bH.firstChild);bE.checkClone=by.cloneNode(true).cloneNode(true).lastChild.checked;bH.innerHTML="";bH.style.width=bH.style.paddingLeft="1px";bF=au.createElement("body");bx={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"};for(bL in bx){bF.style[bL]=bx[bL]}bF.appendChild(bH);bN.insertBefore(bF,bN.firstChild);bE.appendChecked=bG.checked;bE.boxModel=bH.offsetWidth===2;if("zoom" in bH.style){bH.style.display="inline";bH.style.zoom=1;bE.inlineBlockNeedsLayout=(bH.offsetWidth===2);bH.style.display="";bH.innerHTML="
";bE.shrinkWrapBlocks=(bH.offsetWidth!==2)}bH.innerHTML="
t
";bK=bH.getElementsByTagName("td");bP=(bK[0].offsetHeight===0);bK[0].style.display="";bK[1].style.display="none";bE.reliableHiddenOffsets=bP&&(bK[0].offsetHeight===0);bH.innerHTML="";if(au.defaultView&&au.defaultView.getComputedStyle){bC=au.createElement("div");bC.style.width="0";bC.style.marginRight="0";bH.appendChild(bC);bE.reliableMarginRight=(parseInt((au.defaultView.getComputedStyle(bC,null)||{marginRight:0}).marginRight,10)||0)===0}bF.innerHTML="";bN.removeChild(bF);if(bH.attachEvent){for(bL in {submit:1,change:1,focusin:1}){bD="on"+bL;bP=(bD in bH);if(!bP){bH.setAttribute(bD,"return;");bP=(typeof bH[bD]==="function")}bE[bL+"Bubbles"]=bP}}return bE})();b.boxModel=b.support.boxModel;var aQ=/^(?:\{.*\}|\[.*\])$/,az=/([a-z])([A-Z])/g;b.extend({cache:{},uuid:0,expando:"jQuery"+(b.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},hasData:function(e){e=e.nodeType?b.cache[e[b.expando]]:e[b.expando];return !!e&&!W(e)},data:function(bz,bx,bB,bA){if(!b.acceptData(bz)){return}var bE=b.expando,bD=typeof bx==="string",bC,bF=bz.nodeType,e=bF?b.cache:bz,by=bF?bz[b.expando]:bz[b.expando]&&b.expando;if((!by||(bA&&by&&!e[by][bE]))&&bD&&bB===N){return}if(!by){if(bF){bz[b.expando]=by=++b.uuid}else{by=b.expando}}if(!e[by]){e[by]={};if(!bF){e[by].toJSON=b.noop}}if(typeof bx==="object"||typeof bx==="function"){if(bA){e[by][bE]=b.extend(e[by][bE],bx)}else{e[by]=b.extend(e[by],bx)}}bC=e[by];if(bA){if(!bC[bE]){bC[bE]={}}bC=bC[bE]}if(bB!==N){bC[b.camelCase(bx)]=bB}if(bx==="events"&&!bC[bx]){return bC[bE]&&bC[bE].events}return bD?bC[b.camelCase(bx)]:bC},removeData:function(bA,by,bB){if(!b.acceptData(bA)){return}var bD=b.expando,bE=bA.nodeType,bx=bE?b.cache:bA,bz=bE?bA[b.expando]:b.expando;if(!bx[bz]){return}if(by){var bC=bB?bx[bz][bD]:bx[bz];if(bC){delete bC[by];if(!W(bC)){return}}}if(bB){delete bx[bz][bD];if(!W(bx[bz])){return}}var e=bx[bz][bD];if(b.support.deleteExpando||bx!=be){delete bx[bz]}else{bx[bz]=null}if(e){bx[bz]={};if(!bE){bx[bz].toJSON=b.noop}bx[bz][bD]=e}else{if(bE){if(b.support.deleteExpando){delete bA[b.expando]}else{if(bA.removeAttribute){bA.removeAttribute(b.expando)}else{bA[b.expando]=null}}}}},_data:function(bx,e,by){return b.data(bx,e,by,true)},acceptData:function(bx){if(bx.nodeName){var e=b.noData[bx.nodeName.toLowerCase()];if(e){return !(e===true||bx.getAttribute("classid")!==e)}}return true}});b.fn.extend({data:function(bA,bC){var bB=null;if(typeof bA==="undefined"){if(this.length){bB=b.data(this[0]);if(this[0].nodeType===1){var e=this[0].attributes,by;for(var bz=0,bx=e.length;bz-1){return true}}return false},val:function(bz){var e,bx,by=this[0];if(!arguments.length){if(by){e=b.valHooks[by.nodeName.toLowerCase()]||b.valHooks[by.type];if(e&&"get" in e&&(bx=e.get(by,"value"))!==N){return bx}return(by.value||"").replace(aS,"")}return N}var bA=b.isFunction(bz);return this.each(function(bC){var bB=b(this),bD;if(this.nodeType!==1){return}if(bA){bD=bz.call(this,bC,bB.val())}else{bD=bz}if(bD==null){bD=""}else{if(typeof bD==="number"){bD+=""}else{if(b.isArray(bD)){bD=b.map(bD,function(bE){return bE==null?"":bE+""})}}}e=b.valHooks[this.nodeName.toLowerCase()]||b.valHooks[this.type];if(!e||!("set" in e)||e.set(this,bD,"value")===N){this.value=bD}})}});b.extend({valHooks:{option:{get:function(e){var bx=e.attributes.value;return !bx||bx.specified?e.value:e.text}},select:{get:function(e){var bC,bA=e.selectedIndex,bD=[],bE=e.options,bz=e.type==="select-one";if(bA<0){return null}for(var bx=bz?bA:0,bB=bz?bA+1:bE.length;bx=0});if(!e.length){bx.selectedIndex=-1}return e}}},attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attrFix:{tabindex:"tabIndex"},attr:function(bC,bz,bD,bB){var bx=bC.nodeType;if(!bC||bx===3||bx===8||bx===2){return N}if(bB&&bz in b.attrFn){return b(bC)[bz](bD)}if(!("getAttribute" in bC)){return b.prop(bC,bz,bD)}var by,e,bA=bx!==1||!b.isXMLDoc(bC);bz=bA&&b.attrFix[bz]||bz;e=b.attrHooks[bz];if(!e){if(an.test(bz)&&(typeof bD==="boolean"||bD===N||bD.toLowerCase()===bz.toLowerCase())){e=aZ}else{if(a5&&(b.nodeName(bC,"form")||ba.test(bz))){e=a5}}}if(bD!==N){if(bD===null){b.removeAttr(bC,bz);return N}else{if(e&&"set" in e&&bA&&(by=e.set(bC,bD,bz))!==N){return by}else{bC.setAttribute(bz,""+bD);return bD}}}else{if(e&&"get" in e&&bA){return e.get(bC,bz)}else{by=bC.getAttribute(bz);return by===null?N:by}}},removeAttr:function(bx,e){var by;if(bx.nodeType===1){e=b.attrFix[e]||e;if(b.support.getSetAttribute){bx.removeAttribute(e)}else{b.attr(bx,e,"");bx.removeAttributeNode(bx.getAttributeNode(e))}if(an.test(e)&&(by=b.propFix[e]||e) in bx){bx[by]=false}}},attrHooks:{type:{set:function(e,bx){if(g.test(e.nodeName)&&e.parentNode){b.error("type property can't be changed")}else{if(!b.support.radioValue&&bx==="radio"&&b.nodeName(e,"input")){var by=e.value;e.setAttribute("type",bx);if(by){e.value=by}return bx}}}},tabIndex:{get:function(bx){var e=bx.getAttributeNode("tabIndex");return e&&e.specified?parseInt(e.value,10):G.test(bx.nodeName)||m.test(bx.nodeName)&&bx.href?0:N}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(bB,bz,bC){var bx=bB.nodeType;if(!bB||bx===3||bx===8||bx===2){return N}var by,e,bA=bx!==1||!b.isXMLDoc(bB);bz=bA&&b.propFix[bz]||bz;e=b.propHooks[bz];if(bC!==N){if(e&&"set" in e&&(by=e.set(bB,bC,bz))!==N){return by}else{return(bB[bz]=bC)}}else{if(e&&"get" in e&&(by=e.get(bB,bz))!==N){return by}else{return bB[bz]}}},propHooks:{}});aZ={get:function(bx,e){return bx[b.propFix[e]||e]?e.toLowerCase():N},set:function(bx,bz,e){var by;if(bz===false){b.removeAttr(bx,e)}else{by=b.propFix[e]||e;if(by in bx){bx[by]=bz}bx.setAttribute(e,e.toLowerCase())}return e}};b.attrHooks.value={get:function(bx,e){if(a5&&b.nodeName(bx,"button")){return a5.get(bx,e)}return bx.value},set:function(bx,by,e){if(a5&&b.nodeName(bx,"button")){return a5.set(bx,by,e)}bx.value=by}};if(!b.support.getSetAttribute){b.attrFix=b.propFix;a5=b.attrHooks.name=b.valHooks.button={get:function(by,bx){var e;e=by.getAttributeNode(bx);return e&&e.nodeValue!==""?e.nodeValue:N},set:function(by,bz,bx){var e=by.getAttributeNode(bx);if(e){e.nodeValue=bz;return bz}}};b.each(["width","height"],function(bx,e){b.attrHooks[e]=b.extend(b.attrHooks[e],{set:function(by,bz){if(bz===""){by.setAttribute(e,"auto");return bz}}})})}if(!b.support.hrefNormalized){b.each(["href","src","width","height"],function(bx,e){b.attrHooks[e]=b.extend(b.attrHooks[e],{get:function(bz){var by=bz.getAttribute(e,2);return by===null?N:by}})})}if(!b.support.style){b.attrHooks.style={get:function(e){return e.style.cssText.toLowerCase()||N},set:function(e,bx){return(e.style.cssText=""+bx)}}}if(!b.support.optSelected){b.propHooks.selected=b.extend(b.propHooks.selected,{get:function(bx){var e=bx.parentNode;if(e){e.selectedIndex;if(e.parentNode){e.parentNode.selectedIndex}}}})}if(!b.support.checkOn){b.each(["radio","checkbox"],function(){b.valHooks[this]={get:function(e){return e.getAttribute("value")===null?"on":e.value}}})}b.each(["radio","checkbox"],function(){b.valHooks[this]=b.extend(b.valHooks[this],{set:function(e,bx){if(b.isArray(bx)){return(e.checked=b.inArray(b(e).val(),bx)>=0)}}})});var aG=Object.prototype.hasOwnProperty,a1=/\.(.*)$/,bg=/^(?:textarea|input|select)$/i,Q=/\./g,bk=/ /g,aF=/[^\w\s.|`]/g,J=function(e){return e.replace(aF,"\\$&")};b.event={add:function(bz,bD,bI,bB){if(bz.nodeType===3||bz.nodeType===8){return}if(bI===false){bI=bm}else{if(!bI){return}}var bx,bH;if(bI.handler){bx=bI;bI=bx.handler}if(!bI.guid){bI.guid=b.guid++}var bE=b._data(bz);if(!bE){return}var bJ=bE.events,bC=bE.handle;if(!bJ){bE.events=bJ={}}if(!bC){bE.handle=bC=function(bK){return typeof b!=="undefined"&&(!bK||b.event.triggered!==bK.type)?b.event.handle.apply(bC.elem,arguments):N}}bC.elem=bz;bD=bD.split(" ");var bG,bA=0,e;while((bG=bD[bA++])){bH=bx?b.extend({},bx):{handler:bI,data:bB};if(bG.indexOf(".")>-1){e=bG.split(".");bG=e.shift();bH.namespace=e.slice(0).sort().join(".")}else{e=[];bH.namespace=""}bH.type=bG;if(!bH.guid){bH.guid=bI.guid}var by=bJ[bG],bF=b.event.special[bG]||{};if(!by){by=bJ[bG]=[];if(!bF.setup||bF.setup.call(bz,bB,e,bC)===false){if(bz.addEventListener){bz.addEventListener(bG,bC,false)}else{if(bz.attachEvent){bz.attachEvent("on"+bG,bC)}}}}if(bF.add){bF.add.call(bz,bH);if(!bH.handler.guid){bH.handler.guid=bI.guid}}by.push(bH);b.event.global[bG]=true}bz=null},global:{},remove:function(bL,bG,by,bC){if(bL.nodeType===3||bL.nodeType===8){return}if(by===false){by=bm}var bO,bB,bD,bI,bJ=0,bz,bE,bH,bA,bF,e,bN,bK=b.hasData(bL)&&b._data(bL),bx=bK&&bK.events;if(!bK||!bx){return}if(bG&&bG.type){by=bG.handler;bG=bG.type}if(!bG||typeof bG==="string"&&bG.charAt(0)==="."){bG=bG||"";for(bB in bx){b.event.remove(bL,bB+bG)}return}bG=bG.split(" ");while((bB=bG[bJ++])){bN=bB;e=null;bz=bB.indexOf(".")<0;bE=[];if(!bz){bE=bB.split(".");bB=bE.shift();bH=new RegExp("(^|\\.)"+b.map(bE.slice(0).sort(),J).join("\\.(?:.*\\.)?")+"(\\.|$)")}bF=bx[bB];if(!bF){continue}if(!by){for(bI=0;bI=0){bG=bG.slice(0,-1);bx=true}if(bG.indexOf(".")>=0){by=bG.split(".");bG=by.shift();by.sort()}if((!bB||b.event.customEvent[bG])&&!b.event.global[bG]){return}e=typeof e==="object"?e[b.expando]?e:new b.Event(bG,e):new b.Event(bG);e.type=bG;e.exclusive=bx;e.namespace=by.join(".");e.namespace_re=new RegExp("(^|\\.)"+by.join("\\.(?:.*\\.)?")+"(\\.|$)");if(bI||!bB){e.preventDefault();e.stopPropagation()}if(!bB){b.each(b.cache,function(){var bK=b.expando,bJ=this[bK];if(bJ&&bJ.events&&bJ.events[bG]){b.event.trigger(e,bD,bJ.handle.elem)}});return}if(bB.nodeType===3||bB.nodeType===8){return}e.result=N;e.target=bB;bD=bD?b.makeArray(bD):[];bD.unshift(e);var bH=bB,bz=bG.indexOf(":")<0?"on"+bG:"";do{var bE=b._data(bH,"handle");e.currentTarget=bH;if(bE){bE.apply(bH,bD)}if(bz&&b.acceptData(bH)&&bH[bz]&&bH[bz].apply(bH,bD)===false){e.result=false;e.preventDefault()}bH=bH.parentNode||bH.ownerDocument||bH===e.target.ownerDocument&&be}while(bH&&!e.isPropagationStopped());if(!e.isDefaultPrevented()){var bA,bF=b.event.special[bG]||{};if((!bF._default||bF._default.call(bB.ownerDocument,e)===false)&&!(bG==="click"&&b.nodeName(bB,"a"))&&b.acceptData(bB)){try{if(bz&&bB[bG]){bA=bB[bz];if(bA){bB[bz]=null}b.event.triggered=bG;bB[bG]()}}catch(bC){}if(bA){bB[bz]=bA}b.event.triggered=N}}return e.result},handle:function(bD){bD=b.event.fix(bD||be.event);var bx=((b._data(this,"events")||{})[bD.type]||[]).slice(0),bC=!bD.exclusive&&!bD.namespace,bA=Array.prototype.slice.call(arguments,0);bA[0]=bD;bD.currentTarget=this;for(var bz=0,e=bx.length;bz-1?b.map(bx.options,function(bz){return bz.selected}).join("-"):""}else{if(b.nodeName(bx,"select")){by=bx.selectedIndex}}}return by},ac=function ac(bz){var bx=bz.target,by,bA;if(!bg.test(bx.nodeName)||bx.readOnly){return}by=b._data(bx,"_change_data");bA=l(bx);if(bz.type!=="focusout"||bx.type!=="radio"){b._data(bx,"_change_data",bA)}if(by===N||bA===by){return}if(by!=null||bA){bz.type="change";bz.liveFired=N;b.event.trigger(bz,arguments[1],bx)}};b.event.special.change={filters:{focusout:ac,beforedeactivate:ac,click:function(bz){var by=bz.target,bx=b.nodeName(by,"input")?by.type:"";if(bx==="radio"||bx==="checkbox"||b.nodeName(by,"select")){ac.call(this,bz)}},keydown:function(bz){var by=bz.target,bx=b.nodeName(by,"input")?by.type:"";if((bz.keyCode===13&&!b.nodeName(by,"textarea"))||(bz.keyCode===32&&(bx==="checkbox"||bx==="radio"))||bx==="select-multiple"){ac.call(this,bz)}},beforeactivate:function(by){var bx=by.target;b._data(bx,"_change_data",l(bx))}},setup:function(by,bx){if(this.type==="file"){return false}for(var e in bp){b.event.add(this,e+".specialChange",bp[e])}return bg.test(this.nodeName)},teardown:function(e){b.event.remove(this,".specialChange");return bg.test(this.nodeName)}};bp=b.event.special.change.filters;bp.focus=bp.beforeactivate}function aY(bx,bz,e){var by=b.extend({},e[0]);by.type=bx;by.originalEvent={};by.liveFired=N;b.event.handle.call(bz,by);if(by.isDefaultPrevented()){e[0].preventDefault()}}if(!b.support.focusinBubbles){b.each({focus:"focusin",blur:"focusout"},function(bz,e){var bx=0;b.event.special[e]={setup:function(){if(bx++===0){au.addEventListener(bz,by,true)}},teardown:function(){if(--bx===0){au.removeEventListener(bz,by,true)}}};function by(bA){var bB=b.event.fix(bA);bB.type=e;bB.originalEvent={};b.event.trigger(bB,null,bB.target);if(bB.isDefaultPrevented()){bA.preventDefault()}}})}b.each(["bind","one"],function(bx,e){b.fn[e]=function(bD,bE,bC){var bB;if(typeof bD==="object"){for(var bA in bD){this[e](bA,bE,bD[bA],bC)}return this}if(arguments.length===2||bE===false){bC=bE;bE=N}if(e==="one"){bB=function(bF){b(this).unbind(bF,bB);return bC.apply(this,arguments)};bB.guid=bC.guid||b.guid++}else{bB=bC}if(bD==="unload"&&e!=="one"){this.one(bD,bE,bC)}else{for(var bz=0,by=this.length;bzbz){break}bH.currentTarget=bB.elem;bH.data=bB.handleObj.data;bH.handleObj=bB.handleObj;bL=bB.handleObj.origHandler.apply(bB.elem,arguments);if(bL===false||bH.isPropagationStopped()){bz=bB.level;if(bL===false){bE=false}if(bH.isImmediatePropagationStopped()){break}}}return bE}function s(bx,e){return(bx&&bx!=="*"?bx+".":"")+e.replace(Q,"`").replace(bk,"&")}b.each(("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error").split(" "),function(bx,e){b.fn[e]=function(bz,by){if(by==null){by=bz;bz=null}return arguments.length>0?this.bind(e,bz,by):this.trigger(e)};if(b.attrFn){b.attrFn[e]=true}}); -/*! - * Sizzle CSS Selector Engine - * Copyright 2011, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * More information: http://sizzlejs.com/ - */ -(function(){var bH=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,bI=0,bL=Object.prototype.toString,bC=false,bB=true,bJ=/\\/g,bP=/\W/;[0,0].sort(function(){bB=false;return 0});var bz=function(bU,e,bX,bY){bX=bX||[];e=e||au;var b0=e;if(e.nodeType!==1&&e.nodeType!==9){return[]}if(!bU||typeof bU!=="string"){return bX}var bR,b2,b5,bQ,b1,b4,b3,bW,bT=true,bS=bz.isXML(e),bV=[],bZ=bU;do{bH.exec("");bR=bH.exec(bZ);if(bR){bZ=bR[3];bV.push(bR[1]);if(bR[2]){bQ=bR[3];break}}}while(bR);if(bV.length>1&&bD.exec(bU)){if(bV.length===2&&bE.relative[bV[0]]){b2=bM(bV[0]+bV[1],e)}else{b2=bE.relative[bV[0]]?[e]:bz(bV.shift(),e);while(bV.length){bU=bV.shift();if(bE.relative[bU]){bU+=bV.shift()}b2=bM(bU,b2)}}}else{if(!bY&&bV.length>1&&e.nodeType===9&&!bS&&bE.match.ID.test(bV[0])&&!bE.match.ID.test(bV[bV.length-1])){b1=bz.find(bV.shift(),e,bS);e=b1.expr?bz.filter(b1.expr,b1.set)[0]:b1.set[0]}if(e){b1=bY?{expr:bV.pop(),set:bF(bY)}:bz.find(bV.pop(),bV.length===1&&(bV[0]==="~"||bV[0]==="+")&&e.parentNode?e.parentNode:e,bS);b2=b1.expr?bz.filter(b1.expr,b1.set):b1.set;if(bV.length>0){b5=bF(b2)}else{bT=false}while(bV.length){b4=bV.pop();b3=b4;if(!bE.relative[b4]){b4=""}else{b3=bV.pop()}if(b3==null){b3=e}bE.relative[b4](b5,b3,bS)}}else{b5=bV=[]}}if(!b5){b5=b2}if(!b5){bz.error(b4||bU)}if(bL.call(b5)==="[object Array]"){if(!bT){bX.push.apply(bX,b5)}else{if(e&&e.nodeType===1){for(bW=0;b5[bW]!=null;bW++){if(b5[bW]&&(b5[bW]===true||b5[bW].nodeType===1&&bz.contains(e,b5[bW]))){bX.push(b2[bW])}}}else{for(bW=0;b5[bW]!=null;bW++){if(b5[bW]&&b5[bW].nodeType===1){bX.push(b2[bW])}}}}}else{bF(b5,bX)}if(bQ){bz(bQ,b0,bX,bY);bz.uniqueSort(bX)}return bX};bz.uniqueSort=function(bQ){if(bK){bC=bB;bQ.sort(bK);if(bC){for(var e=1;e0};bz.find=function(bW,e,bX){var bV;if(!bW){return[]}for(var bS=0,bR=bE.order.length;bS":function(bV,bQ){var bU,bT=typeof bQ==="string",bR=0,e=bV.length;if(bT&&!bP.test(bQ)){bQ=bQ.toLowerCase();for(;bR=0)){if(!bR){e.push(bU)}}else{if(bR){bQ[bT]=false}}}}return false},ID:function(e){return e[1].replace(bJ,"")},TAG:function(bQ,e){return bQ[1].replace(bJ,"").toLowerCase()},CHILD:function(e){if(e[1]==="nth"){if(!e[2]){bz.error(e[0])}e[2]=e[2].replace(/^\+|\s*/g,"");var bQ=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(e[2]==="even"&&"2n"||e[2]==="odd"&&"2n+1"||!/\D/.test(e[2])&&"0n+"+e[2]||e[2]);e[2]=(bQ[1]+(bQ[2]||1))-0;e[3]=bQ[3]-0}else{if(e[2]){bz.error(e[0])}}e[0]=bI++;return e},ATTR:function(bT,bQ,bR,e,bU,bV){var bS=bT[1]=bT[1].replace(bJ,"");if(!bV&&bE.attrMap[bS]){bT[1]=bE.attrMap[bS]}bT[4]=(bT[4]||bT[5]||"").replace(bJ,"");if(bT[2]==="~="){bT[4]=" "+bT[4]+" "}return bT},PSEUDO:function(bT,bQ,bR,e,bU){if(bT[1]==="not"){if((bH.exec(bT[3])||"").length>1||/^\w/.test(bT[3])){bT[3]=bz(bT[3],null,null,bQ)}else{var bS=bz.filter(bT[3],bQ,bR,true^bU);if(!bR){e.push.apply(e,bS)}return false}}else{if(bE.match.POS.test(bT[0])||bE.match.CHILD.test(bT[0])){return true}}return bT},POS:function(e){e.unshift(true);return e}},filters:{enabled:function(e){return e.disabled===false&&e.type!=="hidden"},disabled:function(e){return e.disabled===true},checked:function(e){return e.checked===true},selected:function(e){if(e.parentNode){e.parentNode.selectedIndex}return e.selected===true},parent:function(e){return !!e.firstChild},empty:function(e){return !e.firstChild},has:function(bR,bQ,e){return !!bz(e[3],bR).length},header:function(e){return(/h\d/i).test(e.nodeName)},text:function(bR){var e=bR.getAttribute("type"),bQ=bR.type;return bR.nodeName.toLowerCase()==="input"&&"text"===bQ&&(e===bQ||e===null)},radio:function(e){return e.nodeName.toLowerCase()==="input"&&"radio"===e.type},checkbox:function(e){return e.nodeName.toLowerCase()==="input"&&"checkbox"===e.type},file:function(e){return e.nodeName.toLowerCase()==="input"&&"file"===e.type},password:function(e){return e.nodeName.toLowerCase()==="input"&&"password"===e.type},submit:function(bQ){var e=bQ.nodeName.toLowerCase();return(e==="input"||e==="button")&&"submit"===bQ.type},image:function(e){return e.nodeName.toLowerCase()==="input"&&"image"===e.type},reset:function(bQ){var e=bQ.nodeName.toLowerCase();return(e==="input"||e==="button")&&"reset"===bQ.type},button:function(bQ){var e=bQ.nodeName.toLowerCase();return e==="input"&&"button"===bQ.type||e==="button"},input:function(e){return(/input|select|textarea|button/i).test(e.nodeName)},focus:function(e){return e===e.ownerDocument.activeElement}},setFilters:{first:function(bQ,e){return e===0},last:function(bR,bQ,e,bS){return bQ===bS.length-1},even:function(bQ,e){return e%2===0},odd:function(bQ,e){return e%2===1},lt:function(bR,bQ,e){return bQe[3]-0},nth:function(bR,bQ,e){return e[3]-0===bQ},eq:function(bR,bQ,e){return e[3]-0===bQ}},filter:{PSEUDO:function(bR,bW,bV,bX){var e=bW[1],bQ=bE.filters[e];if(bQ){return bQ(bR,bV,bW,bX)}else{if(e==="contains"){return(bR.textContent||bR.innerText||bz.getText([bR])||"").indexOf(bW[3])>=0}else{if(e==="not"){var bS=bW[3];for(var bU=0,bT=bS.length;bU=0)}}},ID:function(bQ,e){return bQ.nodeType===1&&bQ.getAttribute("id")===e},TAG:function(bQ,e){return(e==="*"&&bQ.nodeType===1)||bQ.nodeName.toLowerCase()===e},CLASS:function(bQ,e){return(" "+(bQ.className||bQ.getAttribute("class"))+" ").indexOf(e)>-1},ATTR:function(bU,bS){var bR=bS[1],e=bE.attrHandle[bR]?bE.attrHandle[bR](bU):bU[bR]!=null?bU[bR]:bU.getAttribute(bR),bV=e+"",bT=bS[2],bQ=bS[4];return e==null?bT==="!=":bT==="="?bV===bQ:bT==="*="?bV.indexOf(bQ)>=0:bT==="~="?(" "+bV+" ").indexOf(bQ)>=0:!bQ?bV&&e!==false:bT==="!="?bV!==bQ:bT==="^="?bV.indexOf(bQ)===0:bT==="$="?bV.substr(bV.length-bQ.length)===bQ:bT==="|="?bV===bQ||bV.substr(0,bQ.length+1)===bQ+"-":false},POS:function(bT,bQ,bR,bU){var e=bQ[2],bS=bE.setFilters[e];if(bS){return bS(bT,bR,bQ,bU)}}}};var bD=bE.match.POS,by=function(bQ,e){return"\\"+(e-0+1)};for(var bA in bE.match){bE.match[bA]=new RegExp(bE.match[bA].source+(/(?![^\[]*\])(?![^\(]*\))/.source));bE.leftMatch[bA]=new RegExp(/(^(?:.|\r|\n)*?)/.source+bE.match[bA].source.replace(/\\(\d+)/g,by))}var bF=function(bQ,e){bQ=Array.prototype.slice.call(bQ,0);if(e){e.push.apply(e,bQ);return e}return bQ};try{Array.prototype.slice.call(au.documentElement.childNodes,0)[0].nodeType}catch(bO){bF=function(bT,bS){var bR=0,bQ=bS||[];if(bL.call(bT)==="[object Array]"){Array.prototype.push.apply(bQ,bT)}else{if(typeof bT.length==="number"){for(var e=bT.length;bR";e.insertBefore(bQ,e.firstChild);if(au.getElementById(bR)){bE.find.ID=function(bT,bU,bV){if(typeof bU.getElementById!=="undefined"&&!bV){var bS=bU.getElementById(bT[1]);return bS?bS.id===bT[1]||typeof bS.getAttributeNode!=="undefined"&&bS.getAttributeNode("id").nodeValue===bT[1]?[bS]:N:[]}};bE.filter.ID=function(bU,bS){var bT=typeof bU.getAttributeNode!=="undefined"&&bU.getAttributeNode("id");return bU.nodeType===1&&bT&&bT.nodeValue===bS}}e.removeChild(bQ);e=bQ=null})();(function(){var e=au.createElement("div");e.appendChild(au.createComment(""));if(e.getElementsByTagName("*").length>0){bE.find.TAG=function(bQ,bU){var bT=bU.getElementsByTagName(bQ[1]);if(bQ[1]==="*"){var bS=[];for(var bR=0;bT[bR];bR++){if(bT[bR].nodeType===1){bS.push(bT[bR])}}bT=bS}return bT}}e.innerHTML="";if(e.firstChild&&typeof e.firstChild.getAttribute!=="undefined"&&e.firstChild.getAttribute("href")!=="#"){bE.attrHandle.href=function(bQ){return bQ.getAttribute("href",2)}}e=null})();if(au.querySelectorAll){(function(){var e=bz,bS=au.createElement("div"),bR="__sizzle__";bS.innerHTML="

";if(bS.querySelectorAll&&bS.querySelectorAll(".TEST").length===0){return}bz=function(b3,bU,bY,b2){bU=bU||au;if(!b2&&!bz.isXML(bU)){var b1=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b3);if(b1&&(bU.nodeType===1||bU.nodeType===9)){if(b1[1]){return bF(bU.getElementsByTagName(b3),bY)}else{if(b1[2]&&bE.find.CLASS&&bU.getElementsByClassName){return bF(bU.getElementsByClassName(b1[2]),bY)}}}if(bU.nodeType===9){if(b3==="body"&&bU.body){return bF([bU.body],bY)}else{if(b1&&b1[3]){var bX=bU.getElementById(b1[3]);if(bX&&bX.parentNode){if(bX.id===b1[3]){return bF([bX],bY)}}else{return bF([],bY)}}}try{return bF(bU.querySelectorAll(b3),bY)}catch(bZ){}}else{if(bU.nodeType===1&&bU.nodeName.toLowerCase()!=="object"){var bV=bU,bW=bU.getAttribute("id"),bT=bW||bR,b5=bU.parentNode,b4=/^\s*[+~]/.test(b3);if(!bW){bU.setAttribute("id",bT)}else{bT=bT.replace(/'/g,"\\$&")}if(b4&&b5){bU=bU.parentNode}try{if(!b4||b5){return bF(bU.querySelectorAll("[id='"+bT+"'] "+b3),bY)}}catch(b0){}finally{if(!bW){bV.removeAttribute("id")}}}}}return e(b3,bU,bY,b2)};for(var bQ in e){bz[bQ]=e[bQ]}bS=null})()}(function(){var e=au.documentElement,bR=e.matchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.msMatchesSelector;if(bR){var bT=!bR.call(au.createElement("div"),"div"),bQ=false;try{bR.call(au.documentElement,"[test!='']:sizzle")}catch(bS){bQ=true}bz.matchesSelector=function(bV,bX){bX=bX.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!bz.isXML(bV)){try{if(bQ||!bE.match.PSEUDO.test(bX)&&!/!=/.test(bX)){var bU=bR.call(bV,bX);if(bU||!bT||bV.document&&bV.document.nodeType!==11){return bU}}}catch(bW){}}return bz(bX,null,null,[bV]).length>0}}})();(function(){var e=au.createElement("div");e.innerHTML="
";if(!e.getElementsByClassName||e.getElementsByClassName("e").length===0){return}e.lastChild.className="e";if(e.getElementsByClassName("e").length===1){return}bE.order.splice(1,0,"CLASS");bE.find.CLASS=function(bQ,bR,bS){if(typeof bR.getElementsByClassName!=="undefined"&&!bS){return bR.getElementsByClassName(bQ[1])}};e=null})();function bx(bQ,bV,bU,bY,bW,bX){for(var bS=0,bR=bY.length;bS0){bT=e;break}}}e=e[bQ]}bY[bS]=bT}}}if(au.documentElement.contains){bz.contains=function(bQ,e){return bQ!==e&&(bQ.contains?bQ.contains(e):true)}}else{if(au.documentElement.compareDocumentPosition){bz.contains=function(bQ,e){return !!(bQ.compareDocumentPosition(e)&16)}}else{bz.contains=function(){return false}}}bz.isXML=function(e){var bQ=(e?e.ownerDocument||e:0).documentElement;return bQ?bQ.nodeName!=="HTML":false};var bM=function(e,bW){var bU,bS=[],bT="",bR=bW.nodeType?[bW]:bW;while((bU=bE.match.PSEUDO.exec(e))){bT+=bU[0];e=e.replace(bE.match.PSEUDO,"")}e=bE.relative[e]?e+"*":e;for(var bV=0,bQ=bR.length;bV0){for(bD=bC;bD0:this.filter(e).length>0)},closest:function(bG,bx){var bD=[],bA,by,bF=this[0];if(b.isArray(bG)){var bC,bz,bB={},e=1;if(bF&&bG.length){for(bA=0,by=bG.length;bA-1:b(bF).is(bC)){bD.push({selector:bz,elem:bF,level:e})}}bF=bF.parentNode;e++}}return bD}var bE=K.test(bG)||typeof bG!=="string"?b(bG,bx||this.context):0;for(bA=0,by=this.length;bA-1:b.find.matchesSelector(bF,bG)){bD.push(bF);break}else{bF=bF.parentNode;if(!bF||!bF.ownerDocument||bF===bx||bF.nodeType===11){break}}}}bD=bD.length>1?b.unique(bD):bD;return this.pushStack(bD,"closest",bG)},index:function(e){if(!e||typeof e==="string"){return b.inArray(this[0],e?b(e):this.parent().children())}return b.inArray(e.jquery?e[0]:e,this)},add:function(e,bx){var bz=typeof e==="string"?b(e,bx):b.makeArray(e&&e.nodeType?[e]:e),by=b.merge(this.get(),bz);return this.pushStack(F(bz[0])||F(by[0])?by:b.unique(by))},andSelf:function(){return this.add(this.prevObject)}});function F(e){return !e||!e.parentNode||e.parentNode.nodeType===11}b.each({parent:function(bx){var e=bx.parentNode;return e&&e.nodeType!==11?e:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(bx,e,by){return b.dir(bx,"parentNode",by)},next:function(e){return b.nth(e,2,"nextSibling")},prev:function(e){return b.nth(e,2,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(bx,e,by){return b.dir(bx,"nextSibling",by)},prevUntil:function(bx,e,by){return b.dir(bx,"previousSibling",by)},siblings:function(e){return b.sibling(e.parentNode.firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:b.makeArray(e.childNodes)}},function(e,bx){b.fn[e]=function(bB,by){var bA=b.map(this,bx,bB),bz=S.call(arguments);if(!ab.test(e)){by=bB}if(by&&typeof by==="string"){bA=b.filter(by,bA)}bA=this.length>1&&!ax[e]?b.unique(bA):bA;if((this.length>1||bc.test(by))&&ap.test(e)){bA=bA.reverse()}return this.pushStack(bA,e,bz.join(","))}});b.extend({filter:function(by,e,bx){if(bx){by=":not("+by+")"}return e.length===1?b.find.matchesSelector(e[0],by)?[e[0]]:[]:b.find.matches(by,e)},dir:function(by,bx,bA){var e=[],bz=by[bx];while(bz&&bz.nodeType!==9&&(bA===N||bz.nodeType!==1||!b(bz).is(bA))){if(bz.nodeType===1){e.push(bz)}bz=bz[bx]}return e},nth:function(bA,e,by,bz){e=e||1;var bx=0;for(;bA;bA=bA[by]){if(bA.nodeType===1&&++bx===e){break}}return bA},sibling:function(by,bx){var e=[];for(;by;by=by.nextSibling){if(by.nodeType===1&&by!==bx){e.push(by)}}return e}});function aE(bz,by,e){by=by||0;if(b.isFunction(by)){return b.grep(bz,function(bB,bA){var bC=!!by.call(bB,bA,bB);return bC===e})}else{if(by.nodeType){return b.grep(bz,function(bB,bA){return(bB===by)===e})}else{if(typeof by==="string"){var bx=b.grep(bz,function(bA){return bA.nodeType===1});if(bs.test(by)){return b.filter(by,bx,!e)}else{by=b.filter(by,bx)}}}}return b.grep(bz,function(bB,bA){return(b.inArray(bB,by)>=0)===e})}var ag=/ jQuery\d+="(?:\d+|null)"/g,aq=/^\s+/,V=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,d=/<([\w:]+)/,z=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]};aw.optgroup=aw.option;aw.tbody=aw.tfoot=aw.colgroup=aw.caption=aw.thead;aw.th=aw.td;if(!b.support.htmlSerialize){aw._default=[1,"div
","
"]}b.fn.extend({text:function(e){if(b.isFunction(e)){return this.each(function(by){var bx=b(this);bx.text(e.call(this,by,bx.text()))})}if(typeof e!=="object"&&e!==N){return this.empty().append((this[0]&&this[0].ownerDocument||au).createTextNode(e))}return b.text(this)},wrapAll:function(e){if(b.isFunction(e)){return this.each(function(by){b(this).wrapAll(e.call(this,by))})}if(this[0]){var bx=b(e,this[0].ownerDocument).eq(0).clone(true);if(this[0].parentNode){bx.insertBefore(this[0])}bx.map(function(){var by=this;while(by.firstChild&&by.firstChild.nodeType===1){by=by.firstChild}return by}).append(this)}return this},wrapInner:function(e){if(b.isFunction(e)){return this.each(function(bx){b(this).wrapInner(e.call(this,bx))})}return this.each(function(){var bx=b(this),by=bx.contents();if(by.length){by.wrapAll(e)}else{bx.append(e)}})},wrap:function(e){return this.each(function(){b(this).wrapAll(e)})},unwrap:function(){return this.parent().each(function(){if(!b.nodeName(this,"body")){b(this).replaceWith(this.childNodes)}}).end()},append:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.appendChild(e)}})},prepend:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.insertBefore(e,this.firstChild)}})},before:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bx){this.parentNode.insertBefore(bx,this)})}else{if(arguments.length){var e=b(arguments[0]);e.push.apply(e,this.toArray());return this.pushStack(e,"before",arguments)}}},after:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bx){this.parentNode.insertBefore(bx,this.nextSibling)})}else{if(arguments.length){var e=this.pushStack(this,"after",arguments);e.push.apply(e,b(arguments[0]).toArray());return e}}},remove:function(e,bz){for(var bx=0,by;(by=this[bx])!=null;bx++){if(!e||b.filter(e,[by]).length){if(!bz&&by.nodeType===1){b.cleanData(by.getElementsByTagName("*"));b.cleanData([by])}if(by.parentNode){by.parentNode.removeChild(by)}}}return this},empty:function(){for(var e=0,bx;(bx=this[e])!=null;e++){if(bx.nodeType===1){b.cleanData(bx.getElementsByTagName("*"))}while(bx.firstChild){bx.removeChild(bx.firstChild)}}return this},clone:function(bx,e){bx=bx==null?false:bx;e=e==null?bx:e;return this.map(function(){return b.clone(this,bx,e)})},html:function(bz){if(bz===N){return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(ag,""):null}else{if(typeof bz==="string"&&!R.test(bz)&&(b.support.leadingWhitespace||!aq.test(bz))&&!aw[(d.exec(bz)||["",""])[1].toLowerCase()]){bz=bz.replace(V,"<$1>");try{for(var by=0,bx=this.length;by1&&by0?this.clone(true):this).get();b(bE[bC])[bx](bA);bB=bB.concat(bA)}return this.pushStack(bB,e,bE.selector)}}});function bh(e){if("getElementsByTagName" in e){return e.getElementsByTagName("*")}else{if("querySelectorAll" in e){return e.querySelectorAll("*")}else{return[]}}}function ay(e){if(e.type==="checkbox"||e.type==="radio"){e.defaultChecked=e.checked}}function H(e){if(b.nodeName(e,"input")){ay(e)}else{if(e.getElementsByTagName){b.grep(e.getElementsByTagName("input"),ay)}}}b.extend({clone:function(bA,bC,by){var bB=bA.cloneNode(true),e,bx,bz;if((!b.support.noCloneEvent||!b.support.noCloneChecked)&&(bA.nodeType===1||bA.nodeType===11)&&!b.isXMLDoc(bA)){ah(bA,bB);e=bh(bA);bx=bh(bB);for(bz=0;e[bz];++bz){ah(e[bz],bx[bz])}}if(bC){w(bA,bB);if(by){e=bh(bA);bx=bh(bB);for(bz=0;e[bz];++bz){w(e[bz],bx[bz])}}}return bB},clean:function(by,bA,bJ,bC){var bH;bA=bA||au;if(typeof bA.createElement==="undefined"){bA=bA.ownerDocument||bA[0]&&bA[0].ownerDocument||au}var bK=[],bD;for(var bG=0,bB;(bB=by[bG])!=null;bG++){if(typeof bB==="number"){bB+=""}if(!bB){continue}if(typeof bB==="string"){if(!Y.test(bB)){bB=bA.createTextNode(bB)}else{bB=bB.replace(V,"<$1>");var bM=(d.exec(bB)||["",""])[1].toLowerCase(),bz=aw[bM]||aw._default,bF=bz[0],bx=bA.createElement("div");bx.innerHTML=bz[1]+bB+bz[2];while(bF--){bx=bx.lastChild}if(!b.support.tbody){var e=z.test(bB),bE=bM==="table"&&!e?bx.firstChild&&bx.firstChild.childNodes:bz[1]===""&&!e?bx.childNodes:[];for(bD=bE.length-1;bD>=0;--bD){if(b.nodeName(bE[bD],"tbody")&&!bE[bD].childNodes.length){bE[bD].parentNode.removeChild(bE[bD])}}}if(!b.support.leadingWhitespace&&aq.test(bB)){bx.insertBefore(bA.createTextNode(aq.exec(bB)[0]),bx.firstChild)}bB=bx.childNodes}}var bI;if(!b.support.appendChecked){if(bB[0]&&typeof(bI=bB.length)==="number"){for(bD=0;bD=0){return bz+"px"}}else{return bz}}}});if(!b.support.opacity){b.cssHooks.opacity={get:function(bx,e){return at.test((e&&bx.currentStyle?bx.currentStyle.filter:bx.style.filter)||"")?(parseFloat(RegExp.$1)/100)+"":e?"1":""},set:function(bA,bB){var bz=bA.style,bx=bA.currentStyle;bz.zoom=1;var e=b.isNaN(bB)?"":"alpha(opacity="+bB*100+")",by=bx&&bx.filter||bz.filter||"";bz.filter=ak.test(by)?by.replace(ak,e):by+" "+e}}}b(function(){if(!b.support.reliableMarginRight){b.cssHooks.marginRight={get:function(by,bx){var e;b.swap(by,{display:"inline-block"},function(){if(bx){e=Z(by,"margin-right","marginRight")}else{e=by.style.marginRight}});return e}}}});if(au.defaultView&&au.defaultView.getComputedStyle){aI=function(bA,by){var bx,bz,e;by=by.replace(C,"-$1").toLowerCase();if(!(bz=bA.ownerDocument.defaultView)){return N}if((e=bz.getComputedStyle(bA,null))){bx=e.getPropertyValue(by);if(bx===""&&!b.contains(bA.ownerDocument.documentElement,bA)){bx=b.style(bA,by)}}return bx}}if(au.documentElement.currentStyle){aW=function(bA,by){var bB,bx=bA.currentStyle&&bA.currentStyle[by],e=bA.runtimeStyle&&bA.runtimeStyle[by],bz=bA.style;if(!bf.test(bx)&&bq.test(bx)){bB=bz.left;if(e){bA.runtimeStyle.left=bA.currentStyle.left}bz.left=by==="fontSize"?"1em":(bx||0);bx=bz.pixelLeft+"px";bz.left=bB;if(e){bA.runtimeStyle.left=e}}return bx===""?"auto":bx}}Z=aI||aW;function r(by,bx,e){var bA=bx==="width"?am:a3,bz=bx==="width"?by.offsetWidth:by.offsetHeight;if(e==="border"){return bz}b.each(bA,function(){if(!e){bz-=parseFloat(b.css(by,"padding"+this))||0}if(e==="margin"){bz+=parseFloat(b.css(by,"margin"+this))||0}else{bz-=parseFloat(b.css(by,"border"+this+"Width"))||0}});return bz}if(b.expr&&b.expr.filters){b.expr.filters.hidden=function(by){var bx=by.offsetWidth,e=by.offsetHeight;return(bx===0&&e===0)||(!b.support.reliableHiddenOffsets&&(by.style.display||b.css(by,"display"))==="none")};b.expr.filters.visible=function(e){return !b.expr.filters.hidden(e)}}var k=/%20/g,ao=/\[\]$/,bv=/\r?\n/g,bt=/#.*$/,aC=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,a0=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,aM=/^(?:about|app|app\-storage|.+\-extension|file|widget):$/,aP=/^(?:GET|HEAD)$/,c=/^\/\//,O=/\?/,a8=/)<[^<]*)*<\/script>/gi,t=/^(?:select|textarea)/i,h=/\s+/,bu=/([?&])_=[^&]*/,M=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,D=b.fn.load,aa={},u={},aD,v;try{aD=bn.href}catch(av){aD=au.createElement("a");aD.href="";aD=aD.href}v=M.exec(aD.toLowerCase())||[];function f(e){return function(bA,bC){if(typeof bA!=="string"){bC=bA;bA="*"}if(b.isFunction(bC)){var bz=bA.toLowerCase().split(h),by=0,bB=bz.length,bx,bD,bE;for(;by=0){var e=by.slice(bA,by.length);by=by.slice(0,bA)}var bz="GET";if(bB){if(b.isFunction(bB)){bC=bB;bB=N}else{if(typeof bB==="object"){bB=b.param(bB,b.ajaxSettings.traditional);bz="POST"}}}var bx=this;b.ajax({url:by,type:bz,dataType:"html",data:bB,complete:function(bE,bD,bF){bF=bE.responseText;if(bE.isResolved()){bE.done(function(bG){bF=bG});bx.html(e?b("
").append(bF.replace(a8,"")).find(e):bF)}if(bC){bx.each(bC,[bF,bD,bE])}}});return this},serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?b.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||t.test(this.nodeName)||a0.test(this.type))}).map(function(e,bx){var by=b(this).val();return by==null?null:b.isArray(by)?b.map(by,function(bA,bz){return{name:bx.name,value:bA.replace(bv,"\r\n")}}):{name:bx.name,value:by.replace(bv,"\r\n")}}).get()}});b.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(e,bx){b.fn[bx]=function(by){return this.bind(bx,by)}});b.each(["get","post"],function(e,bx){b[bx]=function(by,bA,bB,bz){if(b.isFunction(bA)){bz=bz||bB;bB=bA;bA=N}return b.ajax({type:bx,url:by,data:bA,success:bB,dataType:bz})}});b.extend({getScript:function(e,bx){return b.get(e,N,bx,"script")},getJSON:function(e,bx,by){return b.get(e,bx,by,"json")},ajaxSetup:function(by,e){if(!e){e=by;by=b.extend(true,b.ajaxSettings,e)}else{b.extend(true,by,b.ajaxSettings,e)}for(var bx in {context:1,url:1}){if(bx in e){by[bx]=e[bx]}else{if(bx in b.ajaxSettings){by[bx]=b.ajaxSettings[bx]}}}return by},ajaxSettings:{url:aD,isLocal:aM.test(v[1]),global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":"*/*"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":be.String,"text html":true,"text json":b.parseJSON,"text xml":b.parseXML}},ajaxPrefilter:f(aa),ajaxTransport:f(u),ajax:function(bB,bz){if(typeof bB==="object"){bz=bB;bB=N}bz=bz||{};var bF=b.ajaxSetup({},bz),bU=bF.context||bF,bI=bU!==bF&&(bU.nodeType||bU instanceof b)?b(bU):b.event,bT=b.Deferred(),bP=b._Deferred(),bD=bF.statusCode||{},bE,bJ={},bQ={},bS,bA,bN,bG,bK,bC=0,by,bM,bL={readyState:0,setRequestHeader:function(bV,bW){if(!bC){var e=bV.toLowerCase();bV=bQ[e]=bQ[e]||bV;bJ[bV]=bW}return this},getAllResponseHeaders:function(){return bC===2?bS:null},getResponseHeader:function(bV){var e;if(bC===2){if(!bA){bA={};while((e=aC.exec(bS))){bA[e[1].toLowerCase()]=e[2]}}e=bA[bV.toLowerCase()]}return e===N?null:e},overrideMimeType:function(e){if(!bC){bF.mimeType=e}return this},abort:function(e){e=e||"abort";if(bN){bN.abort(e)}bH(0,e);return this}};function bH(b0,bY,b1,bX){if(bC===2){return}bC=2;if(bG){clearTimeout(bG)}bN=N;bS=bX||"";bL.readyState=b0?4:0;var bV,b5,b4,bZ=b1?bl(bF,bL,b1):N,bW,b3;if(b0>=200&&b0<300||b0===304){if(bF.ifModified){if((bW=bL.getResponseHeader("Last-Modified"))){b.lastModified[bE]=bW}if((b3=bL.getResponseHeader("Etag"))){b.etag[bE]=b3}}if(b0===304){bY="notmodified";bV=true}else{try{b5=I(bF,bZ);bY="success";bV=true}catch(b2){bY="parsererror";b4=b2}}}else{b4=bY;if(!bY||b0){bY="error";if(b0<0){b0=0}}}bL.status=b0;bL.statusText=bY;if(bV){bT.resolveWith(bU,[b5,bY,bL])}else{bT.rejectWith(bU,[bL,bY,b4])}bL.statusCode(bD);bD=N;if(by){bI.trigger("ajax"+(bV?"Success":"Error"),[bL,bF,bV?b5:b4])}bP.resolveWith(bU,[bL,bY]);if(by){bI.trigger("ajaxComplete",[bL,bF]);if(!(--b.active)){b.event.trigger("ajaxStop")}}}bT.promise(bL);bL.success=bL.done;bL.error=bL.fail;bL.complete=bP.done;bL.statusCode=function(bV){if(bV){var e;if(bC<2){for(e in bV){bD[e]=[bD[e],bV[e]]}}else{e=bV[bL.status];bL.then(e,e)}}return this};bF.url=((bB||bF.url)+"").replace(bt,"").replace(c,v[1]+"//");bF.dataTypes=b.trim(bF.dataType||"*").toLowerCase().split(h);if(bF.crossDomain==null){bK=M.exec(bF.url.toLowerCase());bF.crossDomain=!!(bK&&(bK[1]!=v[1]||bK[2]!=v[2]||(bK[3]||(bK[1]==="http:"?80:443))!=(v[3]||(v[1]==="http:"?80:443))))}if(bF.data&&bF.processData&&typeof bF.data!=="string"){bF.data=b.param(bF.data,bF.traditional)}aU(aa,bF,bz,bL);if(bC===2){return false}by=bF.global;bF.type=bF.type.toUpperCase();bF.hasContent=!aP.test(bF.type);if(by&&b.active++===0){b.event.trigger("ajaxStart")}if(!bF.hasContent){if(bF.data){bF.url+=(O.test(bF.url)?"&":"?")+bF.data}bE=bF.url;if(bF.cache===false){var bx=b.now(),bR=bF.url.replace(bu,"$1_="+bx);bF.url=bR+((bR===bF.url)?(O.test(bF.url)?"&":"?")+"_="+bx:"")}}if(bF.data&&bF.hasContent&&bF.contentType!==false||bz.contentType){bL.setRequestHeader("Content-Type",bF.contentType)}if(bF.ifModified){bE=bE||bF.url;if(b.lastModified[bE]){bL.setRequestHeader("If-Modified-Since",b.lastModified[bE])}if(b.etag[bE]){bL.setRequestHeader("If-None-Match",b.etag[bE])}}bL.setRequestHeader("Accept",bF.dataTypes[0]&&bF.accepts[bF.dataTypes[0]]?bF.accepts[bF.dataTypes[0]]+(bF.dataTypes[0]!=="*"?", */*; q=0.01":""):bF.accepts["*"]);for(bM in bF.headers){bL.setRequestHeader(bM,bF.headers[bM])}if(bF.beforeSend&&(bF.beforeSend.call(bU,bL,bF)===false||bC===2)){bL.abort();return false}for(bM in {success:1,error:1,complete:1}){bL[bM](bF[bM])}bN=aU(u,bF,bz,bL);if(!bN){bH(-1,"No Transport")}else{bL.readyState=1;if(by){bI.trigger("ajaxSend",[bL,bF])}if(bF.async&&bF.timeout>0){bG=setTimeout(function(){bL.abort("timeout")},bF.timeout)}try{bC=1;bN.send(bJ,bH)}catch(bO){if(status<2){bH(-1,bO)}else{b.error(bO)}}}return bL},param:function(e,by){var bx=[],bA=function(bB,bC){bC=b.isFunction(bC)?bC():bC;bx[bx.length]=encodeURIComponent(bB)+"="+encodeURIComponent(bC)};if(by===N){by=b.ajaxSettings.traditional}if(b.isArray(e)||(e.jquery&&!b.isPlainObject(e))){b.each(e,function(){bA(this.name,this.value)})}else{for(var bz in e){y(bz,e[bz],by,bA)}}return bx.join("&").replace(k,"+")}});function y(by,bA,bx,bz){if(b.isArray(bA)){b.each(bA,function(bC,bB){if(bx||ao.test(by)){bz(by,bB)}else{y(by+"["+(typeof bB==="object"||b.isArray(bB)?bC:"")+"]",bB,bx,bz)}})}else{if(!bx&&bA!=null&&typeof bA==="object"){for(var e in bA){y(by+"["+e+"]",bA[e],bx,bz)}}else{bz(by,bA)}}}b.extend({active:0,lastModified:{},etag:{}});function bl(bF,bE,bB){var bx=bF.contents,bD=bF.dataTypes,by=bF.responseFields,bA,bC,bz,e;for(bC in by){if(bC in bB){bE[by[bC]]=bB[bC]}}while(bD[0]==="*"){bD.shift();if(bA===N){bA=bF.mimeType||bE.getResponseHeader("content-type")}}if(bA){for(bC in bx){if(bx[bC]&&bx[bC].test(bA)){bD.unshift(bC);break}}}if(bD[0] in bB){bz=bD[0]}else{for(bC in bB){if(!bD[0]||bF.converters[bC+" "+bD[0]]){bz=bC;break}if(!e){e=bC}}bz=bz||e}if(bz){if(bz!==bD[0]){bD.unshift(bz)}return bB[bz]}}function I(bJ,bB){if(bJ.dataFilter){bB=bJ.dataFilter(bB,bJ.dataType)}var bF=bJ.dataTypes,bI={},bC,bG,by=bF.length,bD,bE=bF[0],bz,bA,bH,bx,e;for(bC=1;bC=bx.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();bx.animatedProperties[this.prop]=true;for(by in bx.animatedProperties){if(bx.animatedProperties[by]!==true){e=false}}if(e){if(bx.overflow!=null&&!b.support.shrinkWrapBlocks){b.each(["","X","Y"],function(bE,bF){bB.style["overflow"+bF]=bx.overflow[bE]})}if(bx.hide){b(bB).hide()}if(bx.hide||bx.show){for(var bC in bx.animatedProperties){b.style(bB,bC,bx.orig[bC])}}bx.complete.call(bB)}return false}else{if(bx.duration==Infinity){this.now=bz}else{bD=bz-this.startTime;this.state=bD/bx.duration;this.pos=b.easing[bx.animatedProperties[this.prop]](this.state,bD,0,1,bx.duration);this.now=this.start+((this.end-this.start)*this.pos)}this.update()}return true}};b.extend(b.fx,{tick:function(){for(var bx=b.timers,e=0;e").appendTo("body"),bx=e.css("display");e.remove();if(bx==="none"||bx===""){if(!bb){bb=au.createElement("iframe");bb.frameBorder=bb.width=bb.height=0}au.body.appendChild(bb);if(!n||!bb.createElement){n=(bb.contentWindow||bb.contentDocument).document;n.write("")}e=n.createElement(by);n.body.appendChild(e);bx=b.css(e,"display");au.body.removeChild(bb)}T[by]=bx}return T[by]}var X=/^t(?:able|d|h)$/i,ad=/^(?:body|html)$/i;if("getBoundingClientRect" in au.documentElement){b.fn.offset=function(bK){var bA=this[0],bD;if(bK){return this.each(function(e){b.offset.setOffset(this,bK,e)})}if(!bA||!bA.ownerDocument){return null}if(bA===bA.ownerDocument.body){return b.offset.bodyOffset(bA)}try{bD=bA.getBoundingClientRect()}catch(bH){}var bJ=bA.ownerDocument,by=bJ.documentElement;if(!bD||!b.contains(by,bA)){return bD?{top:bD.top,left:bD.left}:{top:0,left:0}}var bE=bJ.body,bF=aK(bJ),bC=by.clientTop||bE.clientTop||0,bG=by.clientLeft||bE.clientLeft||0,bx=bF.pageYOffset||b.support.boxModel&&by.scrollTop||bE.scrollTop,bB=bF.pageXOffset||b.support.boxModel&&by.scrollLeft||bE.scrollLeft,bI=bD.top+bx-bC,bz=bD.left+bB-bG;return{top:bI,left:bz}}}else{b.fn.offset=function(bH){var bB=this[0];if(bH){return this.each(function(bI){b.offset.setOffset(this,bH,bI)})}if(!bB||!bB.ownerDocument){return null}if(bB===bB.ownerDocument.body){return b.offset.bodyOffset(bB)}b.offset.initialize();var bE,by=bB.offsetParent,bx=bB,bG=bB.ownerDocument,bz=bG.documentElement,bC=bG.body,bD=bG.defaultView,e=bD?bD.getComputedStyle(bB,null):bB.currentStyle,bF=bB.offsetTop,bA=bB.offsetLeft;while((bB=bB.parentNode)&&bB!==bC&&bB!==bz){if(b.offset.supportsFixedPosition&&e.position==="fixed"){break}bE=bD?bD.getComputedStyle(bB,null):bB.currentStyle;bF-=bB.scrollTop;bA-=bB.scrollLeft;if(bB===by){bF+=bB.offsetTop;bA+=bB.offsetLeft;if(b.offset.doesNotAddBorder&&!(b.offset.doesAddBorderForTableAndCells&&X.test(bB.nodeName))){bF+=parseFloat(bE.borderTopWidth)||0;bA+=parseFloat(bE.borderLeftWidth)||0}bx=by;by=bB.offsetParent}if(b.offset.subtractsBorderForOverflowNotVisible&&bE.overflow!=="visible"){bF+=parseFloat(bE.borderTopWidth)||0;bA+=parseFloat(bE.borderLeftWidth)||0}e=bE}if(e.position==="relative"||e.position==="static"){bF+=bC.offsetTop;bA+=bC.offsetLeft}if(b.offset.supportsFixedPosition&&e.position==="fixed"){bF+=Math.max(bz.scrollTop,bC.scrollTop);bA+=Math.max(bz.scrollLeft,bC.scrollLeft)}return{top:bF,left:bA}}}b.offset={initialize:function(){var e=au.body,bx=au.createElement("div"),bA,bC,bB,bD,by=parseFloat(b.css(e,"marginTop"))||0,bz="
";b.extend(bx.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});bx.innerHTML=bz;e.insertBefore(bx,e.firstChild);bA=bx.firstChild;bC=bA.firstChild;bD=bA.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(bC.offsetTop!==5);this.doesAddBorderForTableAndCells=(bD.offsetTop===5);bC.style.position="fixed";bC.style.top="20px";this.supportsFixedPosition=(bC.offsetTop===20||bC.offsetTop===15);bC.style.position=bC.style.top="";bA.style.overflow="hidden";bA.style.position="relative";this.subtractsBorderForOverflowNotVisible=(bC.offsetTop===-5);this.doesNotIncludeMarginInBodyOffset=(e.offsetTop!==by);e.removeChild(bx);b.offset.initialize=b.noop},bodyOffset:function(e){var by=e.offsetTop,bx=e.offsetLeft;b.offset.initialize();if(b.offset.doesNotIncludeMarginInBodyOffset){by+=parseFloat(b.css(e,"marginTop"))||0;bx+=parseFloat(b.css(e,"marginLeft"))||0}return{top:by,left:bx}},setOffset:function(bz,bI,bC){var bD=b.css(bz,"position");if(bD==="static"){bz.style.position="relative"}var bB=b(bz),bx=bB.offset(),e=b.css(bz,"top"),bG=b.css(bz,"left"),bH=(bD==="absolute"||bD==="fixed")&&b.inArray("auto",[e,bG])>-1,bF={},bE={},by,bA;if(bH){bE=bB.position();by=bE.top;bA=bE.left}else{by=parseFloat(e)||0;bA=parseFloat(bG)||0}if(b.isFunction(bI)){bI=bI.call(bz,bC,bx)}if(bI.top!=null){bF.top=(bI.top-bx.top)+by}if(bI.left!=null){bF.left=(bI.left-bx.left)+bA}if("using" in bI){bI.using.call(bz,bF)}else{bB.css(bF)}}};b.fn.extend({position:function(){if(!this[0]){return null}var by=this[0],bx=this.offsetParent(),bz=this.offset(),e=ad.test(bx[0].nodeName)?{top:0,left:0}:bx.offset();bz.top-=parseFloat(b.css(by,"marginTop"))||0;bz.left-=parseFloat(b.css(by,"marginLeft"))||0;e.top+=parseFloat(b.css(bx[0],"borderTopWidth"))||0;e.left+=parseFloat(b.css(bx[0],"borderLeftWidth"))||0;return{top:bz.top-e.top,left:bz.left-e.left}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||au.body;while(e&&(!ad.test(e.nodeName)&&b.css(e,"position")==="static")){e=e.offsetParent}return e})}});b.each(["Left","Top"],function(bx,e){var by="scroll"+e;b.fn[by]=function(bB){var bz,bA;if(bB===N){bz=this[0];if(!bz){return null}bA=aK(bz);return bA?("pageXOffset" in bA)?bA[bx?"pageYOffset":"pageXOffset"]:b.support.boxModel&&bA.document.documentElement[by]||bA.document.body[by]:bz[by]}return this.each(function(){bA=aK(this);if(bA){bA.scrollTo(!bx?bB:b(bA).scrollLeft(),bx?bB:b(bA).scrollTop())}else{this[by]=bB}})}});function aK(e){return b.isWindow(e)?e:e.nodeType===9?e.defaultView||e.parentWindow:false}b.each(["Height","Width"],function(bx,e){var by=e.toLowerCase();b.fn["inner"+e]=function(){return this[0]?parseFloat(b.css(this[0],by,"padding")):null};b.fn["outer"+e]=function(bz){return this[0]?parseFloat(b.css(this[0],by,bz?"margin":"border")):null};b.fn[by]=function(bA){var bB=this[0];if(!bB){return bA==null?null:this}if(b.isFunction(bA)){return this.each(function(bF){var bE=b(this);bE[by](bA.call(this,bF,bE[by]()))})}if(b.isWindow(bB)){var bC=bB.document.documentElement["client"+e];return bB.document.compatMode==="CSS1Compat"&&bC||bB.document.body["client"+e]||bC}else{if(bB.nodeType===9){return Math.max(bB.documentElement["client"+e],bB.body["scroll"+e],bB.documentElement["scroll"+e],bB.body["offset"+e],bB.documentElement["offset"+e])}else{if(bA===N){var bD=b.css(bB,by),bz=parseFloat(bD);return b.isNaN(bz)?bD:bz}else{return this.css(by,typeof bA==="string"?bA:bA+"px")}}}}});be.jQuery=be.$=b})(window); -/*! - * jQuery UI 1.8.14 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI - */ -(function(e,d){function b(f,c){var g=f.nodeName.toLowerCase();if("area"===g){c=f.parentNode;g=c.name;if(!f.href||!g||c.nodeName.toLowerCase()!=="map"){return false}f=e("img[usemap=#"+g+"]")[0];return !!f&&a(f)}return(/input|select|textarea|button|object/.test(g)?!f.disabled:"a"==g?f.href||c:c)&&a(f)}function a(c){return !e(c).parents().andSelf().filter(function(){return e.curCSS(this,"visibility")==="hidden"||e.expr.filters.hidden(this)}).length}e.ui=e.ui||{};if(!e.ui.version){e.extend(e.ui,{version:"1.8.14",keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}});e.fn.extend({_focus:e.fn.focus,focus:function(f,c){return typeof f==="number"?this.each(function(){var g=this;setTimeout(function(){e(g).focus();c&&c.call(g)},f)}):this._focus.apply(this,arguments)},scrollParent:function(){var c;c=e.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.curCSS(this,"position",1))&&/(auto|scroll)/.test(e.curCSS(this,"overflow",1)+e.curCSS(this,"overflow-y",1)+e.curCSS(this,"overflow-x",1))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(e.curCSS(this,"overflow",1)+e.curCSS(this,"overflow-y",1)+e.curCSS(this,"overflow-x",1))}).eq(0);return/fixed/.test(this.css("position"))||!c.length?e(document):c},zIndex:function(f){if(f!==d){return this.css("zIndex",f)}if(this.length){f=e(this[0]);for(var c;f.length&&f[0]!==document;){c=f.css("position");if(c==="absolute"||c==="relative"||c==="fixed"){c=parseInt(f.css("zIndex"),10);if(!isNaN(c)&&c!==0){return c}}f=f.parent()}}return 0},disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(c){c.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}});e.each(["Width","Height"],function(f,c){function l(q,o,h,r){e.each(k,function(){o-=parseFloat(e.curCSS(q,"padding"+this,true))||0;if(h){o-=parseFloat(e.curCSS(q,"border"+this+"Width",true))||0}if(r){o-=parseFloat(e.curCSS(q,"margin"+this,true))||0}});return o}var k=c==="Width"?["Left","Right"]:["Top","Bottom"],j=c.toLowerCase(),g={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+c]=function(h){if(h===d){return g["inner"+c].call(this)}return this.each(function(){e(this).css(j,l(this,h)+"px")})};e.fn["outer"+c]=function(m,h){if(typeof m!=="number"){return g["outer"+c].call(this,m)}return this.each(function(){e(this).css(j,l(this,m,true,h)+"px")})}});e.extend(e.expr[":"],{data:function(f,c,g){return !!e.data(f,g[3])},focusable:function(c){return b(c,!isNaN(e.attr(c,"tabindex")))},tabbable:function(f){var c=e.attr(f,"tabindex"),g=isNaN(c);return(g||c>=0)&&b(f,!g)}});e(function(){var f=document.body,c=f.appendChild(c=document.createElement("div"));e.extend(c.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0});e.support.minHeight=c.offsetHeight===100;e.support.selectstart="onselectstart" in c;f.removeChild(c).style.display="none"});e.extend(e.ui,{plugin:{add:function(f,c,h){f=e.ui[f].prototype;for(var g in h){f.plugins[g]=f.plugins[g]||[];f.plugins[g].push([c,h[g]])}},call:function(f,c,h){if((c=f.plugins[c])&&f.element[0].parentNode){for(var g=0;g0){return true}f[c]=1;g=f[c]>0;f[c]=0;return g},isOverAxis:function(f,c,g){return f>c&&f=9)&&!b.button){return this._mouseUp(b)}if(this._mouseStarted){this._mouseDrag(b);return b.preventDefault()}if(this._mouseDistanceMet(b)&&this._mouseDelayMet(b)){(this._mouseStarted=this._mouseStart(this._mouseDownEvent,b)!==false)?this._mouseDrag(b):this._mouseUp(b)}return !this._mouseStarted},_mouseUp:function(b){a(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;b.target==this._mouseDownEvent.target&&a.data(b.target,this.widgetName+".preventClickEvent",true);this._mouseStop(b)}return false},_mouseDistanceMet:function(b){return Math.max(Math.abs(this._mouseDownEvent.pageX-b.pageX),Math.abs(this._mouseDownEvent.pageY-b.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return true}})})(jQuery);(function(f){f.ui=f.ui||{};var e=/left|center|right/,d=/top|center|bottom/,b=f.fn.position,a=f.fn.offset;f.fn.position=function(c){if(!c||!c.of){return b.apply(this,arguments)}c=f.extend({},c);var l=f(c.of),s=l[0],q=(c.collision||"flip").split(" "),r=c.offset?c.offset.split(" "):[0,0],o,m,n;if(s.nodeType===9){o=l.width();m=l.height();n={top:0,left:0}}else{if(s.setTimeout){o=l.width();m=l.height();n={top:l.scrollTop(),left:l.scrollLeft()}}else{if(s.preventDefault){c.at="left top";o=m=0;n={top:c.of.pageY,left:c.of.pageX}}else{o=l.outerWidth();m=l.outerHeight();n=l.offset()}}}f.each(["my","at"],function(){var g=(c[this]||"").split(" ");if(g.length===1){g=e.test(g[0])?g.concat(["center"]):d.test(g[0])?["center"].concat(g):["center","center"]}g[0]=e.test(g[0])?g[0]:"center";g[1]=d.test(g[1])?g[1]:"center";c[this]=g});if(q.length===1){q[1]=q[0]}r[0]=parseInt(r[0],10)||0;if(r.length===1){r[1]=r[0]}r[1]=parseInt(r[1],10)||0;if(c.at[0]==="right"){n.left+=o}else{if(c.at[0]==="center"){n.left+=o/2}}if(c.at[1]==="bottom"){n.top+=m}else{if(c.at[1]==="center"){n.top+=m/2}}n.left+=r[0];n.top+=r[1];return this.each(function(){var x=f(this),t=x.outerWidth(),k=x.outerHeight(),j=parseInt(f.curCSS(this,"marginLeft",true))||0,h=parseInt(f.curCSS(this,"marginTop",true))||0,z=t+j+(parseInt(f.curCSS(this,"marginRight",true))||0),y=k+h+(parseInt(f.curCSS(this,"marginBottom",true))||0),u=f.extend({},n),g;if(c.my[0]==="right"){u.left-=t}else{if(c.my[0]==="center"){u.left-=t/2}}if(c.my[1]==="bottom"){u.top-=k}else{if(c.my[1]==="center"){u.top-=k/2}}u.left=Math.round(u.left);u.top=Math.round(u.top);g={left:u.left-j,top:u.top-h};f.each(["left","top"],function(w,v){f.ui.position[q[w]]&&f.ui.position[q[w]][v](u,{targetWidth:o,targetHeight:m,elemWidth:t,elemHeight:k,collisionPosition:g,collisionWidth:z,collisionHeight:y,offset:r,my:c.my,at:c.at})});f.fn.bgiframe&&x.bgiframe();x.offset(f.extend(u,{using:c.using}))})};f.ui.position={fit:{left:function(c,g){var h=f(window);h=g.collisionPosition.left+g.collisionWidth-h.width()-h.scrollLeft();c.left=h>0?c.left-h:Math.max(c.left-g.collisionPosition.left,c.left)},top:function(c,g){var h=f(window);h=g.collisionPosition.top+g.collisionHeight-h.height()-h.scrollTop();c.top=h>0?c.top-h:Math.max(c.top-g.collisionPosition.top,c.top)}},flip:{left:function(c,j){if(j.at[0]!=="center"){var n=f(window);n=j.collisionPosition.left+j.collisionWidth-n.width()-n.scrollLeft();var l=j.my[0]==="left"?-j.elemWidth:j.my[0]==="right"?j.elemWidth:0,m=j.at[0]==="left"?j.targetWidth:-j.targetWidth,k=-2*j.offset[0];c.left+=j.collisionPosition.left<0?l+m+k:n>0?l+m+k:0}},top:function(c,j){if(j.at[1]!=="center"){var n=f(window);n=j.collisionPosition.top+j.collisionHeight-n.height()-n.scrollTop();var l=j.my[1]==="top"?-j.elemHeight:j.my[1]==="bottom"?j.elemHeight:0,m=j.at[1]==="top"?j.targetHeight:-j.targetHeight,k=-2*j.offset[1];c.top+=j.collisionPosition.top<0?l+m+k:n>0?l+m+k:0}}}};if(!f.offset.setOffset){f.offset.setOffset=function(c,j){if(/static/.test(f.curCSS(c,"position"))){c.style.position="relative"}var n=f(c),l=n.offset(),m=parseInt(f.curCSS(c,"top",true),10)||0,k=parseInt(f.curCSS(c,"left",true),10)||0;l={top:j.top-l.top+m,left:j.left-l.left+k};"using" in j?j.using.call(c,l):n.css(l)};f.fn.offset=function(c){var g=this[0];if(!g||!g.ownerDocument){return null}if(c){return this.each(function(){f.offset.setOffset(this,c)})}return a.call(this)}}})(jQuery);(function(a){a.widget("ui.draggable",a.ui.mouse,{widgetEventPrefix:"drag",options:{addClasses:true,appendTo:"parent",axis:false,connectToSortable:false,containment:false,cursor:"auto",cursorAt:false,grid:false,handle:false,helper:"original",iframeFix:false,opacity:false,refreshPositions:false,revert:false,revertDuration:500,scope:"default",scroll:true,scrollSensitivity:20,scrollSpeed:20,snap:false,snapMode:"both",snapTolerance:20,stack:false,zIndex:false},_create:function(){if(this.options.helper=="original"&&!/^(?:r|a|f)/.test(this.element.css("position"))){this.element[0].style.position="relative"}this.options.addClasses&&this.element.addClass("ui-draggable");this.options.disabled&&this.element.addClass("ui-draggable-disabled");this._mouseInit()},destroy:function(){if(this.element.data("draggable")){this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled");this._mouseDestroy();return this}},_mouseCapture:function(d){var c=this.options;if(this.helper||c.disabled||a(d.target).is(".ui-resizable-handle")){return false}this.handle=this._getHandle(d);if(!this.handle){return false}a(c.iframeFix===true?"iframe":c.iframeFix).each(function(){a('
').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1000}).css(a(this).offset()).appendTo("body")});return true},_mouseStart:function(d){var c=this.options;this.helper=this._createHelper(d);this._cacheHelperProportions();if(a.ui.ddmanager){a.ui.ddmanager.current=this}this._cacheMargins();this.cssPosition=this.helper.css("position");this.scrollParent=this.helper.scrollParent();this.offset=this.positionAbs=this.element.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};a.extend(this.offset,{click:{left:d.pageX-this.offset.left,top:d.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this.position=this._generatePosition(d);this.originalPageX=d.pageX;this.originalPageY=d.pageY;c.cursorAt&&this._adjustOffsetFromHelper(c.cursorAt);c.containment&&this._setContainment();if(this._trigger("start",d)===false){this._clear();return false}this._cacheHelperProportions();a.ui.ddmanager&&!c.dropBehaviour&&a.ui.ddmanager.prepareOffsets(this,d);this.helper.addClass("ui-draggable-dragging");this._mouseDrag(d,true);a.ui.ddmanager&&a.ui.ddmanager.dragStart(this,d);return true},_mouseDrag:function(d,c){this.position=this._generatePosition(d);this.positionAbs=this._convertPositionTo("absolute");if(!c){c=this._uiHash();if(this._trigger("drag",d,c)===false){this._mouseUp({});return false}this.position=c.position}if(!this.options.axis||this.options.axis!="y"){this.helper[0].style.left=this.position.left+"px"}if(!this.options.axis||this.options.axis!="x"){this.helper[0].style.top=this.position.top+"px"}a.ui.ddmanager&&a.ui.ddmanager.drag(this,d);return false},_mouseStop:function(e){var d=false;if(a.ui.ddmanager&&!this.options.dropBehaviour){d=a.ui.ddmanager.drop(this,e)}if(this.dropped){d=this.dropped;this.dropped=false}if((!this.element[0]||!this.element[0].parentNode)&&this.options.helper=="original"){return false}if(this.options.revert=="invalid"&&!d||this.options.revert=="valid"&&d||this.options.revert===true||a.isFunction(this.options.revert)&&this.options.revert.call(this.element,d)){var f=this;a(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){f._trigger("stop",e)!==false&&f._clear()})}else{this._trigger("stop",e)!==false&&this._clear()}return false},_mouseUp:function(b){this.options.iframeFix===true&&a("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)});a.ui.ddmanager&&a.ui.ddmanager.dragStop(this,b);return a.ui.mouse.prototype._mouseUp.call(this,b)},cancel:function(){this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear();return this},_getHandle:function(d){var c=!this.options.handle||!a(this.options.handle,this.element).length?true:false;a(this.options.handle,this.element).find("*").andSelf().each(function(){if(this==d.target){c=true}});return c},_createHelper:function(d){var c=this.options;d=a.isFunction(c.helper)?a(c.helper.apply(this.element[0],[d])):c.helper=="clone"?this.element.clone().removeAttr("id"):this.element;d.parents("body").length||d.appendTo(c.appendTo=="parent"?this.element[0].parentNode:c.appendTo);d[0]!=this.element[0]&&!/(fixed|absolute)/.test(d.css("position"))&&d.css("position","absolute");return d},_adjustOffsetFromHelper:function(b){if(typeof b=="string"){b=b.split(" ")}if(a.isArray(b)){b={left:+b[0],top:+b[1]||0}}if("left" in b){this.offset.click.left=b.left+this.margins.left}if("right" in b){this.offset.click.left=this.helperProportions.width-b.right+this.margins.left}if("top" in b){this.offset.click.top=b.top+this.margins.top}if("bottom" in b){this.offset.click.top=this.helperProportions.height-b.bottom+this.margins.top}},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var b=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0])){b.left+=this.scrollParent.scrollLeft();b.top+=this.scrollParent.scrollTop()}if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&a.browser.msie){b={top:0,left:0}}return{top:b.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:b.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var b=this.element.position();return{top:b.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:b.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else{return{top:0,left:0}}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e=this.options;if(e.containment=="parent"){e.containment=this.helper[0].parentNode}if(e.containment=="document"||e.containment=="window"){this.containment=[e.containment=="document"?0:a(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,e.containment=="document"?0:a(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,(e.containment=="document"?0:a(window).scrollLeft())+a(e.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(e.containment=="document"?0:a(window).scrollTop())+(a(e.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]}if(!/^(document|window|parent)$/.test(e.containment)&&e.containment.constructor!=Array){e=a(e.containment);var d=e[0];if(d){e.offset();var f=a(d).css("overflow")!="hidden";this.containment=[(parseInt(a(d).css("borderLeftWidth"),10)||0)+(parseInt(a(d).css("paddingLeft"),10)||0),(parseInt(a(d).css("borderTopWidth"),10)||0)+(parseInt(a(d).css("paddingTop"),10)||0),(f?Math.max(d.scrollWidth,d.offsetWidth):d.offsetWidth)-(parseInt(a(d).css("borderLeftWidth"),10)||0)-(parseInt(a(d).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(f?Math.max(d.scrollHeight,d.offsetHeight):d.offsetHeight)-(parseInt(a(d).css("borderTopWidth"),10)||0)-(parseInt(a(d).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom];this.relative_container=e}}else{if(e.containment.constructor==Array){this.containment=e.containment}}},_convertPositionTo:function(e,d){if(!d){d=this.position}e=e=="absolute"?1:-1;var h=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,g=/(html|body)/i.test(h[0].tagName);return{top:d.top+this.offset.relative.top*e+this.offset.parent.top*e-(a.browser.safari&&a.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():g?0:h.scrollTop())*e),left:d.left+this.offset.relative.left*e+this.offset.parent.left*e-(a.browser.safari&&a.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():g?0:h.scrollLeft())*e)}},_generatePosition:function(j){var d=this.options,o=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,m=/(html|body)/i.test(o[0].tagName),n=j.pageX,k=j.pageY;if(this.originalPosition){var l;if(this.containment){if(this.relative_container){l=this.relative_container.offset();l=[this.containment[0]+l.left,this.containment[1]+l.top,this.containment[2]+l.left,this.containment[3]+l.top]}else{l=this.containment}if(j.pageX-this.offset.click.leftl[2]){n=l[2]+this.offset.click.left}if(j.pageY-this.offset.click.top>l[3]){k=l[3]+this.offset.click.top}}if(d.grid){k=d.grid[1]?this.originalPageY+Math.round((k-this.originalPageY)/d.grid[1])*d.grid[1]:this.originalPageY;k=l?!(k-this.offset.click.topl[3])?k:!(k-this.offset.click.topl[2])?n:!(n-this.offset.click.left=0;E--){var D=J.snapElements[E].left,B=D+J.snapElements[E].width,C=J.snapElements[E].top,A=C+J.snapElements[E].height;if(D-I=n&&s<=d||q>=n&&q<=d||sd)&&(t>=o&&t<=m||r>=o&&r<=m||tm);default:return false}};a.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(j,d){var o=a.ui.ddmanager.droppables[j.options.scope]||[],n=d?d.type:null,l=(j.currentItem||j.element).find(":data(droppable)").andSelf(),m=0;j:for(;m *",opacity:false,placeholder:false,revert:false,scroll:true,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1000},_create:function(){var b=this.options;this.containerCache={};this.element.addClass("ui-sortable");this.refresh();this.floating=this.items.length?b.axis==="x"||/left|right/.test(this.items[0].item.css("float"))||/inline|table-cell/.test(this.items[0].item.css("display")):false;this.offset=this.element.offset();this._mouseInit()},destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").removeData("sortable").unbind(".sortable");this._mouseDestroy();for(var b=this.items.length-1;b>=0;b--){this.items[b].item.removeData("sortable-item")}return this},_setOption:function(d,c){if(d==="disabled"){this.options[d]=c;this.widget()[c?"addClass":"removeClass"]("ui-sortable-disabled")}else{a.Widget.prototype._setOption.apply(this,arguments)}},_mouseCapture:function(g,d){if(this.reverting){return false}if(this.options.disabled||this.options.type=="static"){return false}this._refreshItems(g);var k=null,j=this;a(g.target).parents().each(function(){if(a.data(this,"sortable-item")==j){k=a(this);return false}});if(a.data(g.target,"sortable-item")==j){k=a(g.target)}if(!k){return false}if(this.options.handle&&!d){var h=false;a(this.options.handle,k).find("*").andSelf().each(function(){if(this==g.target){h=true}});if(!h){return false}}this.currentItem=k;this._removeCurrentsFromItems();return true},_mouseStart:function(f,d,h){d=this.options;var g=this;this.currentContainer=this;this.refreshPositions();this.helper=this._createHelper(f);this._cacheHelperProportions();this._cacheMargins();this.scrollParent=this.helper.scrollParent();this.offset=this.currentItem.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};this.helper.css("position","absolute");this.cssPosition=this.helper.css("position");a.extend(this.offset,{click:{left:f.pageX-this.offset.left,top:f.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(f);this.originalPageX=f.pageX;this.originalPageY=f.pageY;d.cursorAt&&this._adjustOffsetFromHelper(d.cursorAt);this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]};this.helper[0]!=this.currentItem[0]&&this.currentItem.hide();this._createPlaceholder();d.containment&&this._setContainment();if(d.cursor){if(a("body").css("cursor")){this._storedCursor=a("body").css("cursor")}a("body").css("cursor",d.cursor)}if(d.opacity){if(this.helper.css("opacity")){this._storedOpacity=this.helper.css("opacity")}this.helper.css("opacity",d.opacity)}if(d.zIndex){if(this.helper.css("zIndex")){this._storedZIndex=this.helper.css("zIndex")}this.helper.css("zIndex",d.zIndex)}if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){this.overflowOffset=this.scrollParent.offset()}this._trigger("start",f,this._uiHash());this._preserveHelperProportions||this._cacheHelperProportions();if(!h){for(h=this.containers.length-1;h>=0;h--){this.containers[h]._trigger("activate",f,g._uiHash(this))}}if(a.ui.ddmanager){a.ui.ddmanager.current=this}a.ui.ddmanager&&!d.dropBehaviour&&a.ui.ddmanager.prepareOffsets(this,f);this.dragging=true;this.helper.addClass("ui-sortable-helper");this._mouseDrag(f);return true},_mouseDrag:function(g){this.position=this._generatePosition(g);this.positionAbs=this._convertPositionTo("absolute");if(!this.lastPositionAbs){this.lastPositionAbs=this.positionAbs}if(this.options.scroll){var d=this.options,k=false;if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){if(this.overflowOffset.top+this.scrollParent[0].offsetHeight-g.pageY=0;d--){k=this.items[d];var j=k.item[0],h=this._intersectsWithPointer(k);if(h){if(j!=this.currentItem[0]&&this.placeholder[h==1?"next":"prev"]()[0]!=j&&!a.ui.contains(this.placeholder[0],j)&&(this.options.type=="semi-dynamic"?!a.ui.contains(this.element[0],j):true)){this.direction=h==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(k)){this._rearrange(g,k)}else{break}this._trigger("change",g,this._uiHash());break}}}this._contactContainers(g);a.ui.ddmanager&&a.ui.ddmanager.drag(this,g);this._trigger("sort",g,this._uiHash());this.lastPositionAbs=this.positionAbs;return false},_mouseStop:function(e,d){if(e){a.ui.ddmanager&&!this.options.dropBehaviour&&a.ui.ddmanager.drop(this,e);if(this.options.revert){var f=this;d=f.placeholder.offset();f.reverting=true;a(this.helper).animate({left:d.left-this.offset.parent.left-f.margins.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft),top:d.top-this.offset.parent.top-f.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){f._clear(e)})}else{this._clear(e,d)}return false}},cancel:function(){var d=this;if(this.dragging){this._mouseUp({target:null});this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var c=this.containers.length-1;c>=0;c--){this.containers[c]._trigger("deactivate",null,d._uiHash(this));if(this.containers[c].containerCache.over){this.containers[c]._trigger("out",null,d._uiHash(this));this.containers[c].containerCache.over=0}}}if(this.placeholder){this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove();a.extend(this,{helper:null,dragging:false,reverting:false,_noFinalSort:null});this.domPosition.prev?a(this.domPosition.prev).after(this.currentItem):a(this.domPosition.parent).prepend(this.currentItem)}return this},serialize:function(e){var d=this._getItemsAsjQuery(e&&e.connected),f=[];e=e||{};a(d).each(function(){var b=(a(e.item||this).attr(e.attribute||"id")||"").match(e.expression||/(.+)[-=_](.+)/);if(b){f.push((e.key||b[1]+"[]")+"="+(e.key&&e.expression?b[1]:b[2]))}});!f.length&&e.key&&f.push(e.key+"=");return f.join("&")},toArray:function(e){var d=this._getItemsAsjQuery(e&&e.connected),f=[];e=e||{};d.each(function(){f.push(a(e.item||this).attr(e.attribute||"id")||"")});return f},_intersectsWith:function(w){var v=this.positionAbs.left,u=v+this.helperProportions.width,t=this.positionAbs.top,s=t+this.helperProportions.height,r=w.left,q=r+w.width,o=w.top,m=o+w.height,n=this.offset.click.top,d=this.offset.click.left;n=t+n>o&&t+nr&&v+dw[this.floating?"width":"height"]?n:r0?"down":"up")},_getDragHorizontalDirection:function(){var b=this.positionAbs.left-this.lastPositionAbs.left;return b!=0&&(b>0?"right":"left")},refresh:function(b){this._refreshItems(b);this.refreshPositions();return this},_connectWith:function(){var b=this.options;return b.connectWith.constructor==String?[b.connectWith]:b.connectWith},_getItemsAsjQuery:function(j){var d=[],o=[],n=this._connectWith();if(n&&j){for(j=n.length-1;j>=0;j--){for(var m=a(n[j]),l=m.length-1;l>=0;l--){var k=a.data(m[l],"sortable");if(k&&k!=this&&!k.options.disabled){o.push([a.isFunction(k.options.items)?k.options.items.call(k.element):a(k.options.items,k.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),k])}}}}o.push([a.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):a(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(j=o.length-1;j>=0;j--){o[j][0].each(function(){d.push(this)})}return a(d)},_removeCurrentsFromItems:function(){for(var e=this.currentItem.find(":data(sortable-item)"),d=0;d=0;n--){for(var m=a(o[n]),l=m.length-1;l>=0;l--){var k=a.data(m[l],"sortable");if(k&&k!=this&&!k.options.disabled){q.push([a.isFunction(k.options.items)?k.options.items.call(k.element[0],j,{item:this.currentItem}):a(k.options.items,k.element),k]);this.containers.push(k)}}}}for(n=q.length-1;n>=0;n--){j=q[n][1];o=q[n][0];l=0;for(m=o.length;l=0;d--){var h=this.items[d];if(!(h.instance!=this.currentContainer&&this.currentContainer&&h.item[0]!=this.currentItem[0])){var g=this.options.toleranceElement?a(this.options.toleranceElement,h.item):h.item;if(!f){h.width=g.outerWidth();h.height=g.outerHeight()}g=g.offset();h.left=g.left;h.top=g.top}}if(this.options.custom&&this.options.custom.refreshContainers){this.options.custom.refreshContainers.call(this)}else{for(d=this.containers.length-1;d>=0;d--){g=this.containers[d].element.offset();this.containers[d].containerCache.left=g.left;this.containers[d].containerCache.top=g.top;this.containers[d].containerCache.width=this.containers[d].element.outerWidth();this.containers[d].containerCache.height=this.containers[d].element.outerHeight()}}return this},_createPlaceholder:function(f){var d=f||this,h=d.options;if(!h.placeholder||h.placeholder.constructor==String){var g=h.placeholder;h.placeholder={element:function(){var b=a(document.createElement(d.currentItem[0].nodeName)).addClass(g||d.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];if(!g){b.style.visibility="hidden"}return b},update:function(c,b){if(!(g&&!h.forcePlaceholderSize)){b.height()||b.height(d.currentItem.innerHeight()-parseInt(d.currentItem.css("paddingTop")||0,10)-parseInt(d.currentItem.css("paddingBottom")||0,10));b.width()||b.width(d.currentItem.innerWidth()-parseInt(d.currentItem.css("paddingLeft")||0,10)-parseInt(d.currentItem.css("paddingRight")||0,10))}}}}d.placeholder=a(h.placeholder.element.call(d.element,d.currentItem));d.currentItem.after(d.placeholder);h.placeholder.update(d,d.placeholder)},_contactContainers:function(j){for(var d=null,o=null,n=this.containers.length-1;n>=0;n--){if(!a.ui.contains(this.currentItem[0],this.containers[n].element[0])){if(this._intersectsWith(this.containers[n].containerCache)){if(!(d&&a.ui.contains(this.containers[n].element[0],d.element[0]))){d=this.containers[n];o=n}}else{if(this.containers[n].containerCache.over){this.containers[n]._trigger("out",j,this._uiHash(this));this.containers[n].containerCache.over=0}}}}if(d){if(this.containers.length===1){this.containers[o]._trigger("over",j,this._uiHash(this));this.containers[o].containerCache.over=1}else{if(this.currentContainer!=this.containers[o]){d=10000;n=null;for(var m=this.positionAbs[this.containers[o].floating?"left":"top"],l=this.items.length-1;l>=0;l--){if(a.ui.contains(this.containers[o].element[0],this.items[l].item[0])){var k=this.items[l][this.containers[o].floating?"left":"top"];if(Math.abs(k-m)this.containment[2]){k=this.containment[2]+this.offset.click.left}if(h.pageY-this.offset.click.top>this.containment[3]){j=this.containment[3]+this.offset.click.top}}if(d.grid){j=this.originalPageY+Math.round((j-this.originalPageY)/d.grid[1])*d.grid[1];j=this.containment?!(j-this.offset.click.topthis.containment[3])?j:!(j-this.offset.click.topthis.containment[2])?k:!(k-this.offset.click.left=0;g--){if(a.ui.contains(this.containers[g].element[0],this.currentItem[0])&&!d){h.push(function(b){return function(c){b._trigger("receive",c,this._uiHash(this))}}.call(this,this.containers[g]));h.push(function(b){return function(c){b._trigger("update",c,this._uiHash(this))}}.call(this,this.containers[g]))}}}for(g=this.containers.length-1;g>=0;g--){d||h.push(function(b){return function(c){b._trigger("deactivate",c,this._uiHash(this))}}.call(this,this.containers[g]));if(this.containers[g].containerCache.over){h.push(function(b){return function(c){b._trigger("out",c,this._uiHash(this))}}.call(this,this.containers[g]));this.containers[g].containerCache.over=0}}this._storedCursor&&a("body").css("cursor",this._storedCursor);this._storedOpacity&&this.helper.css("opacity",this._storedOpacity);if(this._storedZIndex){this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex)}this.dragging=false;if(this.cancelHelperRemoval){if(!d){this._trigger("beforeStop",f,this._uiHash());for(g=0;g")).appendTo(document.body).hide().addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+c.dialogClass).css({zIndex:c.zIndex}).attr("tabIndex",-1).css("outline",0).keydown(function(g){if(c.closeOnEscape&&g.keyCode&&g.keyCode===f.ui.keyCode.ESCAPE){j.close(g);g.preventDefault()}}).attr({role:"dialog","aria-labelledby":n}).mousedown(function(g){j.moveToTop(false,g)});j.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(l);var m=(j.uiDialogTitlebar=f("
")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(l),k=f('').addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").hover(function(){k.addClass("ui-state-hover")},function(){k.removeClass("ui-state-hover")}).focus(function(){k.addClass("ui-state-focus")}).blur(function(){k.removeClass("ui-state-focus")}).click(function(g){j.close(g);return false}).appendTo(m);(j.uiDialogTitlebarCloseText=f("")).addClass("ui-icon ui-icon-closethick").text(c.closeText).appendTo(k);f("").addClass("ui-dialog-title").attr("id",n).html(o).prependTo(m);if(f.isFunction(c.beforeclose)&&!f.isFunction(c.beforeClose)){c.beforeClose=c.beforeclose}m.find("*").add(m).disableSelection();c.draggable&&f.fn.draggable&&j._makeDraggable();c.resizable&&f.fn.resizable&&j._makeResizable();j._createButtons(c.buttons);j._isOpen=false;f.fn.bgiframe&&l.bgiframe()},_init:function(){this.options.autoOpen&&this.open()},destroy:function(){var c=this;c.overlay&&c.overlay.destroy();c.uiDialog.hide();c.element.unbind(".dialog").removeData("dialog").removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body");c.uiDialog.remove();c.originalTitle&&c.element.attr("title",c.originalTitle);return c},widget:function(){return this.uiDialog},close:function(g){var c=this,j,h;if(false!==c._trigger("beforeClose",g)){c.overlay&&c.overlay.destroy();c.uiDialog.unbind("keypress.ui-dialog");c._isOpen=false;if(c.options.hide){c.uiDialog.hide(c.options.hide,function(){c._trigger("close",g)})}else{c.uiDialog.hide();c._trigger("close",g)}f.ui.dialog.overlay.resize();if(c.options.modal){j=0;f(".ui-dialog").each(function(){if(this!==c.uiDialog[0]){h=f(this).css("z-index");isNaN(h)||(j=Math.max(j,h))}});f.ui.dialog.maxZ=j}return c}},isOpen:function(){return this._isOpen},moveToTop:function(g,c){var j=this,h=j.options;if(h.modal&&!g||!h.stack&&!h.modal){return j._trigger("focus",c)}if(h.zIndex>f.ui.dialog.maxZ){f.ui.dialog.maxZ=h.zIndex}if(j.overlay){f.ui.dialog.maxZ+=1;j.overlay.$el.css("z-index",f.ui.dialog.overlay.maxZ=f.ui.dialog.maxZ)}g={scrollTop:j.element.attr("scrollTop"),scrollLeft:j.element.attr("scrollLeft")};f.ui.dialog.maxZ+=1;j.uiDialog.css("z-index",f.ui.dialog.maxZ);j.element.attr(g);j._trigger("focus",c);return j},open:function(){if(!this._isOpen){var g=this,c=g.options,h=g.uiDialog;g.overlay=c.modal?new f.ui.dialog.overlay(g):null;g._size();g._position(c.position);h.show(c.show);g.moveToTop(true);c.modal&&h.bind("keypress.ui-dialog",function(l){if(l.keyCode===f.ui.keyCode.TAB){var j=f(":tabbable",this),k=j.filter(":first");j=j.filter(":last");if(l.target===j[0]&&!l.shiftKey){k.focus(1);return false}else{if(l.target===k[0]&&l.shiftKey){j.focus(1);return false}}}});f(g.element.find(":tabbable").get().concat(h.find(".ui-dialog-buttonpane :tabbable").get().concat(h.get()))).eq(0).focus();g._isOpen=true;g._trigger("open");return g}},_createButtons:function(h){var c=this,l=false,k=f("
").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),j=f("
").addClass("ui-dialog-buttonset").appendTo(k);c.uiDialog.find(".ui-dialog-buttonpane").remove();typeof h==="object"&&h!==null&&f.each(h,function(){return !(l=true)});if(l){f.each(h,function(n,m){m=f.isFunction(m)?{click:m,text:n}:m;var g=f('').click(function(){m.click.apply(c.element[0],arguments)}).appendTo(j);f.each(m,function(q,o){if(q!=="click"){q in d?g[q](o):g.attr(q,o)}});f.fn.button&&g.button()});k.appendTo(c.uiDialog)}},_makeDraggable:function(){function h(g){return{position:g.position,offset:g.offset}}var c=this,l=c.options,k=f(document),j;c.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(m,g){j=l.height==="auto"?"auto":f(this).height();f(this).height(f(this).height()).addClass("ui-dialog-dragging");c._trigger("dragStart",m,h(g))},drag:function(m,g){c._trigger("drag",m,h(g))},stop:function(m,g){l.position=[g.position.left-k.scrollLeft(),g.position.top-k.scrollTop()];f(this).removeClass("ui-dialog-dragging").height(j);c._trigger("dragStop",m,h(g));f.ui.dialog.overlay.resize()}})},_makeResizable:function(h){function c(g){return{originalPosition:g.originalPosition,originalSize:g.originalSize,position:g.position,size:g.size}}h=h===b?this.options.resizable:h;var l=this,k=l.options,j=l.uiDialog.css("position");h=typeof h==="string"?h:"n,e,s,w,se,sw,ne,nw";l.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:l.element,maxWidth:k.maxWidth,maxHeight:k.maxHeight,minWidth:k.minWidth,minHeight:l._minHeight(),handles:h,start:function(m,g){f(this).addClass("ui-dialog-resizing");l._trigger("resizeStart",m,c(g))},resize:function(m,g){l._trigger("resize",m,c(g))},stop:function(m,g){f(this).removeClass("ui-dialog-resizing");k.height=f(this).height();k.width=f(this).width();l._trigger("resizeStop",m,c(g));f.ui.dialog.overlay.resize()}}).css("position",j).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_minHeight:function(){var c=this.options;return c.height==="auto"?c.minHeight:Math.min(c.minHeight,c.height)},_position:function(g){var c=[],j=[0,0],h;if(g){if(typeof g==="string"||typeof g==="object"&&"0" in g){c=g.split?g.split(" "):[g[0],g[1]];if(c.length===1){c[1]=c[0]}f.each(["left","top"],function(k,l){if(+c[k]===c[k]){j[k]=c[k];c[k]=l}});g={my:c.join(" "),at:c.join(" "),offset:j.join(" ")}}g=f.extend({},f.ui.dialog.prototype.options.position,g)}else{g=f.ui.dialog.prototype.options.position}(h=this.uiDialog.is(":visible"))||this.uiDialog.show();this.uiDialog.css({top:0,left:0}).position(f.extend({of:window},g));h||this.uiDialog.hide()},_setOptions:function(g){var c=this,j={},h=false;f.each(g,function(k,l){c._setOption(k,l);if(k in a){h=true}if(k in e){j[k]=l}});h&&this._size();this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option",j)},_setOption:function(h,c){var l=this,k=l.uiDialog;switch(h){case"beforeclose":h="beforeClose";break;case"buttons":l._createButtons(c);break;case"closeText":l.uiDialogTitlebarCloseText.text(""+c);break;case"dialogClass":k.removeClass(l.options.dialogClass).addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+c);break;case"disabled":c?k.addClass("ui-dialog-disabled"):k.removeClass("ui-dialog-disabled");break;case"draggable":var j=k.is(":data(draggable)");j&&!c&&k.draggable("destroy");!j&&c&&l._makeDraggable();break;case"position":l._position(c);break;case"resizable":(j=k.is(":data(resizable)"))&&!c&&k.resizable("destroy");j&&typeof c==="string"&&k.resizable("option","handles",c);!j&&c!==false&&l._makeResizable(c);break;case"title":f(".ui-dialog-title",l.uiDialogTitlebar).html(""+(c||" "));break}f.Widget.prototype._setOption.apply(l,arguments)},_size:function(){var g=this.options,c,j,h=this.uiDialog.is(":visible");this.element.show().css({width:"auto",minHeight:0,height:0});if(g.minWidth>g.width){g.width=g.minWidth}c=this.uiDialog.css({height:"auto",width:g.width}).height();j=Math.max(0,g.minHeight-c);if(g.height==="auto"){if(f.support.minHeight){this.element.css({minHeight:j,height:"auto"})}else{this.uiDialog.show();g=this.element.css("height","auto").height();h||this.uiDialog.hide();this.element.height(Math.max(g,j))}}else{this.element.height(Math.max(g.height-c,0))}this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())}});f.extend(f.ui.dialog,{version:"1.8.14",uuid:0,maxZ:0,getTitleId:function(c){c=c.attr("id");if(!c){this.uuid+=1;c=this.uuid}return"ui-dialog-title-"+c},overlay:function(c){this.$el=f.ui.dialog.overlay.create(c)}});f.extend(f.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:f.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(c){return c+".dialog-overlay"}).join(" "),create:function(g){if(this.instances.length===0){setTimeout(function(){f.ui.dialog.overlay.instances.length&&f(document).bind(f.ui.dialog.overlay.events,function(h){if(f(h.target).zIndex()").addClass("ui-widget-overlay")).appendTo(document.body).css({width:this.width(),height:this.height()});f.fn.bgiframe&&c.bgiframe();this.instances.push(c);return c},destroy:function(g){var c=f.inArray(g,this.instances);c!=-1&&this.oldInstances.push(this.instances.splice(c,1)[0]);this.instances.length===0&&f([document,window]).unbind(".dialog-overlay");g.remove();var h=0;f.each(this.instances,function(){h=Math.max(h,this.css("z-index"))});this.maxZ=h},height:function(){var g,c;if(f.browser.msie&&f.browser.version<7){g=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight);c=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight);return g").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0});k.wrap(f);f=k.parent();if(k.css("position")=="static"){f.css({position:"relative"});k.css({position:"relative"})}else{v.extend(j,{position:k.css("position"),zIndex:k.css("z-index")});v.each(["top","left","bottom","right"],function(m,l){j[l]=k.css(l);if(isNaN(parseInt(j[l],10))){j[l]="auto"}});k.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})}return f.css(j).show()},removeWrapper:function(f){if(f.parent().is(".ui-effects-wrapper")){return f.parent().replaceWith(f)}return f},setTransition:function(l,j,f,k){k=k||{};v.each(j,function(n,m){unit=l.cssUnit(m);if(unit[0]>0){k[m]=unit[0]*f+unit[1]}});return k}});v.fn.extend({effect:function(l){var j=h.apply(this,arguments),f={options:j[1],duration:j[2],callback:j[3]};j=f.options.mode;var k=v.effects[l];if(v.fx.off||!k){return j?this[j](f.duration,f.callback):this.each(function(){f.callback&&f.callback.call(this)})}return k.call(this,f)},_show:v.fn.show,show:function(j){if(g(j)){return this._show.apply(this,arguments)}else{var f=h.apply(this,arguments);f[1].mode="show";return this.effect.apply(this,f)}},_hide:v.fn.hide,hide:function(j){if(g(j)){return this._hide.apply(this,arguments)}else{var f=h.apply(this,arguments);f[1].mode="hide";return this.effect.apply(this,f)}},__toggle:v.fn.toggle,toggle:function(j){if(g(j)||typeof j==="boolean"||v.isFunction(j)){return this.__toggle.apply(this,arguments)}else{var f=h.apply(this,arguments);f[1].mode="toggle";return this.effect.apply(this,f)}},cssUnit:function(k){var j=this.css(k),f=[];v.each(["em","px","%","pt"],function(m,l){if(j.indexOf(l)>0){f=[parseFloat(j),l]}});return f}});v.easing.jswing=v.easing.swing;v.extend(v.easing,{def:"easeOutQuad",swing:function(m,j,f,l,k){return v.easing[v.easing.def](m,j,f,l,k)},easeInQuad:function(m,j,f,l,k){return l*(j/=k)*j+f},easeOutQuad:function(m,j,f,l,k){return -l*(j/=k)*(j-2)+f},easeInOutQuad:function(m,j,f,l,k){if((j/=k/2)<1){return l/2*j*j+f}return -l/2*(--j*(j-2)-1)+f},easeInCubic:function(m,j,f,l,k){return l*(j/=k)*j*j+f},easeOutCubic:function(m,j,f,l,k){return l*((j=j/k-1)*j*j+1)+f},easeInOutCubic:function(m,j,f,l,k){if((j/=k/2)<1){return l/2*j*j*j+f}return l/2*((j-=2)*j*j+2)+f},easeInQuart:function(m,j,f,l,k){return l*(j/=k)*j*j*j+f},easeOutQuart:function(m,j,f,l,k){return -l*((j=j/k-1)*j*j*j-1)+f},easeInOutQuart:function(m,j,f,l,k){if((j/=k/2)<1){return l/2*j*j*j*j+f}return -l/2*((j-=2)*j*j*j-2)+f},easeInQuint:function(m,j,f,l,k){return l*(j/=k)*j*j*j*j+f},easeOutQuint:function(m,j,f,l,k){return l*((j=j/k-1)*j*j*j*j+1)+f},easeInOutQuint:function(m,j,f,l,k){if((j/=k/2)<1){return l/2*j*j*j*j*j+f}return l/2*((j-=2)*j*j*j*j+2)+f},easeInSine:function(m,j,f,l,k){return -l*Math.cos(j/k*(Math.PI/2))+l+f},easeOutSine:function(m,j,f,l,k){return l*Math.sin(j/k*(Math.PI/2))+f},easeInOutSine:function(m,j,f,l,k){return -l/2*(Math.cos(Math.PI*j/k)-1)+f},easeInExpo:function(m,j,f,l,k){return j==0?f:l*Math.pow(2,10*(j/k-1))+f},easeOutExpo:function(m,j,f,l,k){return j==k?f+l:l*(-Math.pow(2,-10*j/k)+1)+f},easeInOutExpo:function(m,j,f,l,k){if(j==0){return f}if(j==k){return f+l}if((j/=k/2)<1){return l/2*Math.pow(2,10*(j-1))+f}return l/2*(-Math.pow(2,-10*--j)+2)+f},easeInCirc:function(m,j,f,l,k){return -l*(Math.sqrt(1-(j/=k)*j)-1)+f},easeOutCirc:function(m,j,f,l,k){return l*Math.sqrt(1-(j=j/k-1)*j)+f},easeInOutCirc:function(m,j,f,l,k){if((j/=k/2)<1){return -l/2*(Math.sqrt(1-j*j)-1)+f}return l/2*(Math.sqrt(1-(j-=2)*j)+1)+f},easeInElastic:function(o,j,f,n,m){o=1.70158;var l=0,k=n;if(j==0){return f}if((j/=m)==1){return f+n}l||(l=m*0.3);if(k0&&c.which!=f.which)){if(!d(c.target).is(f.not)){if(!(f.handle&&!d(c.target).closest(f.handle,c.currentTarget).length)){f.propagates=1;f.interactions=[e.interaction(this,f)];f.target=c.target;f.pageX=c.pageX;f.pageY=c.pageY;f.dragging=null;g=e.hijack(c,"draginit",f);if(f.propagates){if((g=e.flatten(g))&&g.length){f.interactions=[];d.each(g,function(){f.interactions.push(e.interaction(this,f))})}f.propagates=f.interactions.length;f.drop!==false&&b.drop&&b.drop.handler(c,f);e.textselect(false);a.add(document,"mousemove mouseup",e.handler,f);return false}}}}},interaction:function(c,f){return{drag:c,callback:new e.callback,droppable:[],offset:d(c)[f.relative?"position":"offset"]()||{top:0,left:0}}},handler:function(c){var f=c.data;switch(c.type){case !f.dragging&&"mousemove":if(Math.pow(c.pageX-f.pageX,2)+Math.pow(c.pageY-f.pageY,2)'+k(a(j).val().length)+""+h+"").insertAfter(j);var d=a("#"+this.id+"_counter span");j.bind("keyup click blur focus change paste",function(e){switch(b.type){case"char":e=a(j).val().length;break;case"word":e=j.val()===""?0:a.trim(j.val()).replace(/\s+/g," ").split(" ").length;break;default:}switch(b.count){case"up":if(k(e)>=b.goal&&b.type==="char"){a(this).val(a(this).val().substring(0,b.goal));c=true;break}if(k(e)===b.goal&&b.type==="word"){c=true;break}else{if(k(e)>b.goal&&b.type==="word"){a(this).val("");d.text("0");c=true;break}}break;case"down":if(k(e)<=0&&b.type==="char"){a(this).val(a(this).val().substring(0,b.goal));c=true;break}if(k(e)===0&&b.type==="word"){c=true}else{if(k(e)<0&&b.type==="word"){a(this).val("");c=true;break}}break;default:}j.keydown(function(f){if(c){this.focus();if(f.keyCode!==46&&f.keyCode!==8){if(a(this).val().length>b.goal&&b.type==="char"){a(this).val(a(this).val().substring(0,b.goal));return false}else{return f.keyCode!==32&&f.keyCode!==8&&b.type==="word"?true:false}}else{c=false;return true}}});d.text(k(e))})})}})})(jQuery);(function(){var w=this;var t=w._;var b={};var j=Array.prototype,D=Object.prototype,F=Function.prototype;var u=j.slice,y=j.unshift,x=D.toString,q=D.hasOwnProperty;var n=j.forEach,h=j.map,B=j.reduce,e=j.reduceRight,m=j.filter,a=j.every,A=j.some,v=j.indexOf,f=j.lastIndexOf,c=Array.isArray,C=Object.keys,k=F.bind;var E=function(G){return new g(G)};if(typeof module!=="undefined"&&module.exports){module.exports=E;E._=E}else{w._=E}E.VERSION="1.1.6";var d=E.each=E.forEach=function(L,K,J){if(L==null){return}if(n&&L.forEach===n){L.forEach(K,J)}else{if(E.isNumber(L.length)){for(var I=0,G=L.length;I=G.computed&&(G={value:N,computed:L})});return G.value};E.min=function(J,I,H){if(!I&&E.isArray(J)){return Math.min.apply(Math,J)}var G={computed:Infinity};d(J,function(N,K,M){var L=I?I.call(H,N,K,M):N;LJ?1:0}),"value")};E.sortedIndex=function(L,K,I){I||(I=E.identity);var G=0,J=L.length;while(G>1;I(L[H])=0})})};E.zip=function(){var G=u.call(arguments);var J=E.max(E.pluck(G,"length"));var I=new Array(J);for(var H=0;H=0;I--){H=[G[I].apply(this,H)]}return H[0]}};E.after=function(H,G){return function(){if(--H<1){return G.apply(this,arguments)}}};E.keys=C||function(I){if(I!==Object(I)){throw new TypeError("Invalid object")}var H=[];for(var G in I){if(q.call(I,G)){H[H.length]=G}}return H};E.values=function(G){return E.map(G,E.identity)};E.functions=E.methods=function(G){return E.filter(E.keys(G),function(H){return E.isFunction(G[H])}).sort()};E.extend=function(G){d(u.call(arguments,1),function(H){for(var I in H){if(H[I]!==void 0){G[I]=H[I]}}});return G};E.defaults=function(G){d(u.call(arguments,1),function(H){for(var I in H){if(G[I]==null){G[I]=H[I]}}});return G};E.clone=function(G){return E.isArray(G)?G.slice():E.extend({},G)};E.tap=function(H,G){G(H);return H};E.isEqual=function(H,G){if(H===G){return true}var K=typeof(H),M=typeof(G);if(K!=M){return false}if(H==G){return true}if((!H&&G)||(H&&!G)){return false}if(H._chain){H=H._wrapped}if(G._chain){G=G._wrapped}if(H.isEqual){return H.isEqual(G)}if(E.isDate(H)&&E.isDate(G)){return H.getTime()===G.getTime()}if(E.isNaN(H)&&E.isNaN(G)){return false}if(E.isRegExp(H)&&E.isRegExp(G)){return H.source===G.source&&H.global===G.global&&H.ignoreCase===G.ignoreCase&&H.multiline===G.multiline}if(K!=="object"){return false}if(H.length&&(H.length!==G.length)){return false}var I=E.keys(H),L=E.keys(G);if(I.length!=L.length){return false}for(var J in H){if(!(J in G)||!E.isEqual(H[J],G[J])){return false}}return true};E.isEmpty=function(H){if(E.isArray(H)||E.isString(H)){return H.length===0}for(var G in H){if(q.call(H,G)){return false}}return true};E.isElement=function(G){return !!(G&&G.nodeType==1)};E.isArray=c||function(G){return x.call(G)==="[object Array]"};E.isArguments=function(G){return !!(G&&q.call(G,"callee"))};E.isFunction=function(G){return !!(G&&G.constructor&&G.call&&G.apply)};E.isString=function(G){return !!(G===""||(G&&G.charCodeAt&&G.substr))};E.isNumber=function(G){return !!(G===0||(G&&G.toExponential&&G.toFixed))};E.isNaN=function(G){return G!==G};E.isBoolean=function(G){return G===true||G===false};E.isDate=function(G){return !!(G&&G.getTimezoneOffset&&G.setUTCFullYear)};E.isRegExp=function(G){return !!(G&&G.test&&G.exec&&(G.ignoreCase||G.ignoreCase===false))};E.isNull=function(G){return G===null};E.isUndefined=function(G){return G===void 0};E.noConflict=function(){w._=t;return this};E.identity=function(G){return G};E.times=function(J,I,H){for(var G=0;G/g,interpolate:/<%=([\s\S]+?)%>/g};E.template=function(J,I){var K=E.templateSettings;var G="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+J.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(K.interpolate,function(L,M){return"',"+M.replace(/\\'/g,"'")+",'"}).replace(K.evaluate||null,function(L,M){return"');"+M.replace(/\\'/g,"'").replace(/[\r\n\t]/g," ")+"__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');";var H=new Function("obj",G);return I?H(I):H};var g=function(G){this._wrapped=G};E.prototype=g.prototype;var o=function(H,G){return G?E(H).chain():H};var s=function(G,H){g.prototype[G]=function(){var I=u.call(arguments);y.call(I,this._wrapped);return o(H.apply(E,I),this._chain)}};E.mixin(E);d(["pop","push","reverse","shift","sort","splice","unshift"],function(G){var H=j[G];g.prototype[G]=function(){H.apply(this._wrapped,arguments);return o(this._wrapped,this._chain)}});d(["concat","join","slice"],function(G){var H=j[G];g.prototype[G]=function(){return o(H.apply(this._wrapped,arguments),this._chain)}});g.prototype.chain=function(){this._chain=true;return this};g.prototype.value=function(){return this._wrapped}})();(function(g){g.extend(true,window,{Slick:{Event:b,EventData:e,Range:h,NonDataRow:d,Group:c,GroupTotals:a,EditorLock:f,GlobalEditorLock:new f()}});function e(){var j=false;var k=false;this.stopPropagation=function(){j=true};this.isPropagationStopped=function(){return j};this.stopImmediatePropagation=function(){k=true};this.isImmediatePropagationStopped=function(){return k}}function b(){var j=[];this.subscribe=function(k){j.push(k)};this.unsubscribe=function(l){for(var k=j.length-1;k>=0;k--){if(j[k]===l){j.splice(k,1)}}};this.notify=function(k,o,n){o=o||new e();n=n||this;var m;for(var l=0;l=this.fromRow&&o<=this.toRow&&n>=this.fromCell&&n<=this.toCell};this.toString=function(){if(this.isSingleCell()){return"("+this.fromRow+":"+this.fromCell+")"}else{return"("+this.fromRow+":"+this.fromCell+" - "+this.toRow+":"+this.toCell+")"}}}function d(){this.__nonDataRow=true}function c(){this.__group=true;this.__updated=false;this.count=0;this.value=null;this.title=null;this.collapsed=false;this.totals=null}c.prototype=new d();c.prototype.equals=function(j){return this.value===j.value&&this.count===j.count&&this.collapsed===j.collapsed};function a(){this.__groupTotals=true;this.group=null}a.prototype=new d();function f(){var j=null;this.isActive=function(l){return(l?j===l:j!==null)};this.activate=function(l){if(l===j){return}if(j!==null){throw"SlickGrid.EditorLock.activate: an editController is still active, can't activate another editController"}if(!l.commitCurrentEdit){throw"SlickGrid.EditorLock.activate: editController must implement .commitCurrentEdit()"}if(!l.cancelCurrentEdit){throw"SlickGrid.EditorLock.activate: editController must implement .cancelCurrentEdit()"}j=l};this.deactivate=function(l){if(j!==l){throw"SlickGrid.EditorLock.deactivate: specified editController is not the currently active one"}j=null};this.commitCurrentEdit=function(){return(j?j.commitCurrentEdit():true)};this.cancelCurrentEdit=function k(){return(j?j.cancelCurrentEdit():true)}}})(jQuery);(function(){var l;if(typeof exports!=="undefined"){l=exports}else{l=this.Backbone={}}l.VERSION="0.3.3";var n=this._;if(!n&&(typeof require!=="undefined")){n=require("underscore")._}var e=this.jQuery||this.Zepto;l.emulateHTTP=false;l.emulateJSON=false;l.Events={bind:function(t,v){var s=this._callbacks||(this._callbacks={});var u=this._callbacks[t]||(this._callbacks[t]=[]);u.push(v);return this},unbind:function(v,x){var u;if(!v){this._callbacks={}}else{if(u=this._callbacks){if(!x){u[v]=[]}else{var w=u[v];if(!w){return this}for(var t=0,s=w.length;t').hide().appendTo("body")[0].contentWindow}if("onhashchange" in window&&!t){e(window).bind("hashchange",this.checkUrl)}else{setInterval(this.checkUrl,this.interval)}return this.loadUrl()},route:function(s,t){this.handlers.push({route:s,callback:t})},checkUrl:function(){var s=this.getFragment();if(s==this.fragment&&this.iframe){s=this.getFragment(this.iframe.location)}if(s==this.fragment||s==decodeURIComponent(this.fragment)){return false}if(this.iframe){window.location.hash=this.iframe.location.hash=s}this.loadUrl()},loadUrl:function(){var t=this.fragment=this.getFragment();var s=n.any(this.handlers,function(u){if(u.route.test(t)){u.callback(t);return true}});return s},saveLocation:function(s){s=(s||"").replace(m,"");if(this.fragment==s){return}window.location.hash=this.fragment=s;if(this.iframe&&(s!=this.getFragment(this.iframe.location))){this.iframe.document.open().close();this.iframe.location.hash=s}}});l.View=function(s){this._configure(s||{});this._ensureElement();this.delegateEvents();this.initialize(s)};var a=function(s){return e(s,this.el)};var o=/^(\w+)\s*(.*)$/;n.extend(l.View.prototype,l.Events,{tagName:"div",$:a,initialize:function(){},render:function(){return this},remove:function(){e(this.el).remove();return this},make:function(t,s,v){var u=document.createElement(t);if(s){e(u).attr(s)}if(v){e(u).html(v)}return u},delegateEvents:function(x){if(!(x||(x=this.events))){return}e(this.el).unbind();for(var w in x){var u=x[w];var v=w.match(o);var t=v[1],s=v[2];var y=n.bind(this[u],this);if(s===""){e(this.el).bind(t,y)}else{e(this.el).delegate(s,t,y)}}},_configure:function(s){if(this.options){s=n.extend({},this.options,s)}if(s.model){this.model=s.model}if(s.collection){this.collection=s.collection}if(s.el){this.el=s.el}if(s.id){this.id=s.id}if(s.className){this.className=s.className}if(s.tagName){this.tagName=s.tagName}this.options=s},_ensureElement:function(){if(this.el){return}var s={};if(this.id){s.id=this.id}if(this.className){s["class"]=this.className}this.el=this.make(this.tagName,s)}});var g=function(s,t){var u=j(this,s,t);u.extend=g;return u};l.Model.extend=l.Collection.extend=l.Controller.extend=l.View.extend=g;var b={create:"POST",update:"PUT","delete":"DELETE",read:"GET"};l.sync=function(y,t,w,s){var u=b[y];var x=(y==="create"||y==="update")?JSON.stringify(t.toJSON()):null;var v={url:h(t),type:u,contentType:"application/json",data:x,dataType:"json",processData:false,success:w,error:s};if(l.emulateJSON){v.contentType="application/x-www-form-urlencoded";v.processData=true;v.data=x?{model:x}:{}}if(l.emulateHTTP){if(u==="PUT"||u==="DELETE"){if(l.emulateJSON){v.data._method=u}v.type="POST";v.beforeSend=function(z){z.setRequestHeader("X-HTTP-Method-Override",u)}}}e.ajax(v)};var k=function(){};var j=function(t,s,u){var v;if(s&&s.hasOwnProperty("constructor")){v=s.constructor}else{v=function(){return t.apply(this,arguments)}}k.prototype=t.prototype;v.prototype=new k();if(s){n.extend(v.prototype,s)}if(u){n.extend(v,u)}v.prototype.constructor=v;v.__super__=t.prototype;return v};var h=function(s){if(!(s&&s.url)){throw new Error("A 'url' property or function must be specified")}return n.isFunction(s.url)?s.url():s.url};var d=function(u,t,s){return function(v){if(u){u(t,v)}else{t.trigger("error",t,v,s)}}};var q=function(s){return s.replace(/&(?!\w+;)/g,"&").replace(//g,">").replace(/"/g,""")}})(); -/*! - * jQuery Cycle Plugin (with Transition Definitions) - * Examples and documentation at: http://jquery.malsup.com/cycle/ - * Copyright (c) 2007-2010 M. Alsup - * Version: 2.9994 (28-JUL-2011) - * Dual licensed under the MIT and GPL licenses. - * http://jquery.malsup.com/license.html - * Requires: jQuery v1.3.2 or later - */ -(function(j){var m="2.9994";if(j.support==undefined){j.support={opacity:!(j.browser.msie)}}function a(t){j.fn.cycle.debug&&f(t)}function f(){window.console&&console.log&&console.log("[cycle] "+Array.prototype.join.call(arguments," "))}j.expr[":"].paused=function(t){return t.cyclePause};j.fn.cycle=function(u,t){var v={s:this.selector,c:this.context};if(this.length===0&&u!="stop"){if(!j.isReady&&v.s){f("DOM not ready, queuing slideshow");j(function(){j(v.s,v.c).cycle(u,t)});return this}f("terminating; zero elements found by selector"+(j.isReady?"":" (DOM not ready)"));return this}return this.each(function(){var z=o(this,u,t);if(z===false){return}z.updateActivePagerLink=z.updateActivePagerLink||j.fn.cycle.updateActivePagerLink;if(this.cycleTimeout){clearTimeout(this.cycleTimeout)}this.cycleTimeout=this.cyclePause=0;var A=j(this);var B=z.slideExpr?j(z.slideExpr,this):A.children();var x=B.get();var w=l(A,B,x,z,v);if(w===false){return}if(x.length<2){f("terminating; too few slides: "+x.length);return}var y=w.continuous?10:h(x[w.currSlide],x[w.nextSlide],w,!w.backwards);if(y){y+=(w.delay||0);if(y<10){y=10}a("first timeout: "+y);this.cycleTimeout=setTimeout(function(){e(x,w,0,!z.backwards)},y)}})};function n(t,w,v){var x=j(t).data("cycle.opts");var u=!!t.cyclePause;if(u&&x.paused){x.paused(t,x,w,v)}else{if(!u&&x.resumed){x.resumed(t,x,w,v)}}}function o(t,w,u){if(t.cycleStop==undefined){t.cycleStop=0}if(w===undefined||w===null){w={}}if(w.constructor==String){switch(w){case"destroy":case"stop":var y=j(t).data("cycle.opts");if(!y){return false}t.cycleStop++;if(t.cycleTimeout){clearTimeout(t.cycleTimeout)}t.cycleTimeout=0;y.elements&&j(y.elements).stop();j(t).removeData("cycle.opts");if(w=="destroy"){s(y)}return false;case"toggle":t.cyclePause=(t.cyclePause===1)?0:1;x(t.cyclePause,u,t);n(t);return false;case"pause":t.cyclePause=1;n(t);return false;case"resume":t.cyclePause=0;x(false,u,t);n(t);return false;case"prev":case"next":var y=j(t).data("cycle.opts");if(!y){f('options not found, "prev/next" ignored');return false}j.fn.cycle[w](y);return false;default:w={fx:w}}return w}else{if(w.constructor==Number){var v=w;w=j(t).data("cycle.opts");if(!w){f("options not found, can not advance slide");return false}if(v<0||v>=w.elements.length){f("invalid slide index: "+v);return false}w.nextSlide=v;if(t.cycleTimeout){clearTimeout(t.cycleTimeout);t.cycleTimeout=0}if(typeof u=="string"){w.oneTimeFx=u}e(w.elements,w,1,v>=w.currSlide);return false}}return w;function x(A,B,z){if(!A&&B===true){var C=j(z).data("cycle.opts");if(!C){f("options not found, can not resume");return false}if(z.cycleTimeout){clearTimeout(z.cycleTimeout);z.cycleTimeout=0}e(C.elements,C,1,!C.backwards)}}}function b(t,u){if(!j.support.opacity&&u.cleartype&&t.style.filter){try{t.style.removeAttribute("filter")}catch(v){}}}function s(t){if(t.next){j(t.next).unbind(t.prevNextEvent)}if(t.prev){j(t.prev).unbind(t.prevNextEvent)}if(t.pager||t.pagerAnchorBuilder){j.each(t.pagerAnchors||[],function(){this.unbind().remove()})}t.pagerAnchors=null;if(t.destroy){t.destroy(t)}}function l(C,P,z,y,J){var H=j.extend({},j.fn.cycle.defaults,y||{},j.metadata?C.metadata():j.meta?C.data():{});var F=j.isFunction(C.data)?C.data(H.metaAttr):null;if(F){H=j.extend(H,F)}if(H.autostop){H.countdown=H.autostopCount||z.length}var u=C[0];C.data("cycle.opts",H);H.$cont=C;H.stopCount=u.cycleStop;H.elements=z;H.before=H.before?[H.before]:[];H.after=H.after?[H.after]:[];if(!j.support.opacity&&H.cleartype){H.after.push(function(){b(this,H)})}if(H.continuous){H.after.push(function(){e(z,H,0,!H.backwards)})}q(H);if(!j.support.opacity&&H.cleartype&&!H.cleartypeNoBg){g(P)}if(C.css("position")=="static"){C.css("position","relative")}if(H.width){C.width(H.width)}if(H.height&&H.height!="auto"){C.height(H.height)}if(H.startingSlide){H.startingSlide=parseInt(H.startingSlide,10)}else{if(H.backwards){H.startingSlide=z.length-1}}if(H.random){H.randomMap=[];for(var N=0;N=z.length){H.startingSlide=0}}H.currSlide=H.startingSlide||0;var B=H.startingSlide;P.css({position:"absolute",top:0,left:0}).hide().each(function(w){var R;if(H.backwards){R=B?w<=B?z.length+(w-B):B-w:z.length-w}else{R=B?w>=B?z.length-(w-B):B-w:z.length-w}j(this).css("z-index",R)});j(z[B]).css("opacity",1).show();b(z[B],H);if(H.fit){if(!H.aspect){if(H.width){P.width(H.width)}if(H.height&&H.height!="auto"){P.height(H.height)}}else{P.each(function(){var R=j(this);var w=(H.aspect===true)?R.width()/R.height():H.aspect;if(H.width&&R.width()!=H.width){R.width(H.width);R.height(H.width/w)}if(H.height&&R.height()A?E:A;G=O>G?O:G}if(A>0&&G>0){C.css({width:A+"px",height:G+"px"})}}var x=false;if(H.pause){C.hover(function(){x=true;this.cyclePause++;n(u,true)},function(){x&&this.cyclePause--;n(u,true)})}if(c(H)===false){return false}var v=false;y.requeueAttempts=y.requeueAttempts||0;P.each(function(){var T=j(this);this.cycleH=(H.fit&&H.height)?H.height:(T.height()||this.offsetHeight||this.height||T.attr("height")||0);this.cycleW=(H.fit&&H.width)?H.width:(T.width()||this.offsetWidth||this.width||T.attr("width")||0);if(T.is("img")){var R=(j.browser.msie&&this.cycleW==28&&this.cycleH==30&&!this.complete);var U=(j.browser.mozilla&&this.cycleW==34&&this.cycleH==19&&!this.complete);var S=(j.browser.opera&&((this.cycleW==42&&this.cycleH==19)||(this.cycleW==37&&this.cycleH==17))&&!this.complete);var w=(this.cycleH==0&&this.cycleW==0&&!this.complete);if(R||U||S||w){if(J.s&&H.requeueOnImageNotLoaded&&++y.requeueAttempts<100){f(y.requeueAttempts," - img slide not loaded, requeuing slideshow: ",this.src,this.cycleW,this.cycleH);setTimeout(function(){j(J.s,J.c).cycle(y)},H.requeueTimeout);v=true;return false}else{f("could not determine size of image: "+this.src,this.cycleW,this.cycleH)}}}return true});if(v){return false}H.cssBefore=H.cssBefore||{};H.cssAfter=H.cssAfter||{};H.cssFirst=H.cssFirst||{};H.animIn=H.animIn||{};H.animOut=H.animOut||{};P.not(":eq("+B+")").css(H.cssBefore);j(P[B]).css(H.cssFirst);if(H.timeout){H.timeout=parseInt(H.timeout,10);if(H.speed.constructor==String){H.speed=j.fx.speeds[H.speed]||parseInt(H.speed,10)}if(!H.sync){H.speed=H.speed/2}var K=H.fx=="none"?0:H.fx=="shuffle"?500:250;while((H.timeout-H.speed)=(z.length-1)?0:H.startingSlide+1}}if(!H.multiFx){var M=j.fn.cycle.transitions[H.fx];if(j.isFunction(M)){M(C,P,H)}else{if(H.fx!="custom"&&!H.multiFx){f("unknown transition: "+H.fx,"; slideshow terminating");return false}}}var D=P[B];if(!H.skipInitializationCallbacks){if(H.before.length){H.before[0].apply(D,[D,D,H,true])}if(H.after.length){H.after[0].apply(D,[D,D,H,true])}}if(H.next){j(H.next).bind(H.prevNextEvent,function(){return r(H,1)})}if(H.prev){j(H.prev).bind(H.prevNextEvent,function(){return r(H,0)})}if(H.pager||H.pagerAnchorBuilder){d(z,H)}k(H,z);return H}function q(t){t.original={before:[],after:[]};t.original.cssBefore=j.extend({},t.cssBefore);t.original.cssAfter=j.extend({},t.cssAfter);t.original.animIn=j.extend({},t.animIn);t.original.animOut=j.extend({},t.animOut);j.each(t.before,function(){t.original.before.push(this)});j.each(t.after,function(){t.original.after.push(this)})}function c(z){var x,v,u=j.fn.cycle.transitions;if(z.fx.indexOf(",")>0){z.multiFx=true;z.fxs=z.fx.replace(/\s*/g,"").split(",");for(x=0;x=t.fxs.length)){t.lastFx=0}else{if(!C&&(t.lastFx==undefined||--t.lastFx<0)){t.lastFx=t.fxs.length-1}}y=t.fxs[t.lastFx]}if(t.oneTimeFx){y=t.oneTimeFx;t.oneTimeFx=null}j.fn.cycle.resetState(t,y);if(t.before.length){j.each(t.before,function(F,G){if(x.cycleStop!=t.stopCount){return}G.apply(D,[E,D,t,C])})}var v=function(){t.busy=0;j.each(t.after,function(F,G){if(x.cycleStop!=t.stopCount){return}G.apply(D,[E,D,t,C])})};a("tx firing("+y+"); currSlide: "+t.currSlide+"; nextSlide: "+t.nextSlide);t.busy=1;if(t.fxFn){t.fxFn(E,D,t,v,C,z&&t.fastOnEvent)}else{if(j.isFunction(j.fn.cycle[t.fx])){j.fn.cycle[t.fx](E,D,t,v,C,z&&t.fastOnEvent)}else{j.fn.cycle.custom(E,D,t,v,C,z&&t.fastOnEvent)}}}if(B||t.nextSlide==t.currSlide){t.lastSlide=t.currSlide;if(t.random){t.currSlide=t.nextSlide;if(++t.randomIndex==A.length){t.randomIndex=0}t.nextSlide=t.randomMap[t.randomIndex];if(t.nextSlide==t.currSlide){t.nextSlide=(t.currSlide==t.slideCount-1)?0:t.currSlide+1}}else{if(t.backwards){var w=(t.nextSlide-1)<0;if(w&&t.bounce){t.backwards=!t.backwards;t.nextSlide=1;t.currSlide=0}else{t.nextSlide=w?(A.length-1):t.nextSlide-1;t.currSlide=w?0:t.nextSlide+1}}else{var w=(t.nextSlide+1)==A.length;if(w&&t.bounce){t.backwards=!t.backwards;t.nextSlide=A.length-2;t.currSlide=A.length-1}else{t.nextSlide=w?0:t.nextSlide+1;t.currSlide=w?A.length-1:t.nextSlide-1}}}}if(B&&t.pager){t.updateActivePagerLink(t.pager,t.currSlide,t.activePagerClass)}var u=0;if(t.timeout&&!t.continuous){u=h(A[t.currSlide],A[t.nextSlide],t,C)}else{if(t.continuous&&x.cyclePause){u=10}}if(u>0){x.cycleTimeout=setTimeout(function(){e(A,t,0,!t.backwards)},u)}}j.fn.cycle.updateActivePagerLink=function(t,v,u){j(t).each(function(){j(this).children().removeClass(u).eq(v).addClass(u)})};function h(y,w,x,v){if(x.timeoutFn){var u=x.timeoutFn.call(y,y,w,x,v);while(x.fx!="none"&&(u-x.speed)<250){u+=x.speed}a("calculated timeout: "+u+"; speed: "+x.speed);if(u!==false){return u}}return x.timeout}j.fn.cycle.next=function(t){r(t,1)};j.fn.cycle.prev=function(t){r(t,0)};function r(w,v){var z=v?1:-1;var u=w.elements;var y=w.$cont[0],x=y.cycleTimeout;if(x){clearTimeout(x);y.cycleTimeout=0}if(w.random&&z<0){w.randomIndex--;if(--w.randomIndex==-2){w.randomIndex=u.length-2}else{if(w.randomIndex==-1){w.randomIndex=u.length-1}}w.nextSlide=w.randomMap[w.randomIndex]}else{if(w.random){w.nextSlide=w.randomMap[w.randomIndex]}else{w.nextSlide=w.currSlide+z;if(w.nextSlide<0){if(w.nowrap){return false}w.nextSlide=u.length-1}else{if(w.nextSlide>=u.length){if(w.nowrap){return false}w.nextSlide=0}}}}var t=w.onPrevNextEvent||w.prevNextClick;if(j.isFunction(t)){t(z>0,w.nextSlide,u[w.nextSlide])}e(u,w,1,v);return false}function d(u,v){var t=j(v.pager);j.each(u,function(w,x){j.fn.cycle.createPagerAnchor(w,x,t,u,v)});v.updateActivePagerLink(v.pager,v.startingSlide,v.activePagerClass)}j.fn.cycle.createPagerAnchor=function(y,v,A,x,u){var B;if(j.isFunction(u.pagerAnchorBuilder)){B=u.pagerAnchorBuilder(y,v);a("pagerAnchorBuilder("+y+", el) returned: "+B)}else{B=''+(y+1)+""}if(!B){return}var w=j(B);if(w.parents("body").length===0){var z=[];if(A.length>1){A.each(function(){var D=w.clone(true);j(this).append(D);z.push(D[0])});w=j(z)}else{w.appendTo(A)}}u.pagerAnchors=u.pagerAnchors||[];u.pagerAnchors.push(w);w.bind(u.pagerEvent,function(G){G.preventDefault();u.nextSlide=y;var F=u.$cont[0],E=F.cycleTimeout;if(E){clearTimeout(E);F.cycleTimeout=0}var D=u.onPagerEvent||u.pagerClick;if(j.isFunction(D)){D(u.nextSlide,x[u.nextSlide])}e(x,u,1,u.currSlidet?x-t:w.slideCount-t}else{u=x=0){var x=w.match(/\d+/g);return"#"+u(x[0])+u(x[1])+u(x[2])}if(w&&w!="transparent"){return w}}return"#ffffff"}v.each(function(){j(this).css("background-color",t(this))})}j.fn.cycle.commonReset=function(z,x,y,u,v,t){j(y.elements).not(z).hide();if(typeof y.cssBefore.opacity=="undefined"){y.cssBefore.opacity=1}y.cssBefore.display="block";if(y.slideResize&&u!==false&&x.cycleW>0){y.cssBefore.width=x.cycleW}if(y.slideResize&&v!==false&&x.cycleH>0){y.cssBefore.height=x.cycleH}y.cssAfter=y.cssAfter||{};y.cssAfter.display="none";j(z).css("zIndex",y.slideCount+(t===true?1:0));j(x).css("zIndex",y.slideCount+(t===true?0:1))};j.fn.cycle.custom=function(F,z,t,w,y,u){var E=j(F),A=j(z);var v=t.speedIn,D=t.speedOut,x=t.easeIn,C=t.easeOut;A.css(t.cssBefore);if(u){if(typeof u=="number"){v=D=u}else{v=D=1}x=C=null}var B=function(){A.animate(t.animIn,v,x,function(){w()})};E.animate(t.animOut,D,C,function(){E.css(t.cssAfter);if(!t.sync){B()}});if(t.sync){B()}};j.fn.cycle.transitions={fade:function(u,v,t){v.not(":eq("+t.currSlide+")").css("opacity",0);t.before.push(function(y,w,x){j.fn.cycle.commonReset(y,w,x);x.cssBefore.opacity=0});t.animIn={opacity:1};t.animOut={opacity:0};t.cssBefore={top:0,left:0}}};j.fn.cycle.ver=function(){return m};j.fn.cycle.defaults={activePagerClass:"activeSlide",after:null,allowPagerClickBubble:false,animIn:null,animOut:null,aspect:false,autostop:0,autostopCount:0,backwards:false,before:null,center:null,cleartype:!j.support.opacity,cleartypeNoBg:false,containerResize:1,continuous:0,cssAfter:null,cssBefore:null,delay:0,easeIn:null,easeOut:null,easing:null,end:null,fastOnEvent:0,fit:0,fx:"fade",fxFn:null,height:"auto",manualTrump:true,metaAttr:"cycle",next:null,nowrap:0,onPagerEvent:null,onPrevNextEvent:null,pager:null,pagerAnchorBuilder:null,pagerEvent:"click.cycle",pause:0,pauseOnPagerHover:0,prev:null,prevNextEvent:"click.cycle",random:0,randomizeEffects:1,requeueOnImageNotLoaded:true,requeueTimeout:250,rev:0,shuffle:null,skipInitializationCallbacks:false,slideExpr:null,slideResize:1,speed:1000,speedIn:null,speedOut:null,startingSlide:0,sync:1,timeout:4000,timeoutFn:null,updateActivePagerLink:null,width:null}})(jQuery); -/*! - * jQuery Cycle Plugin Transition Definitions - * This script is a plugin for the jQuery Cycle Plugin - * Examples and documentation at: http://malsup.com/jquery/cycle/ - * Copyright (c) 2007-2010 M. Alsup - * Version: 2.73 - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html - */ -(function(a){a.fn.cycle.transitions.none=function(c,d,b){b.fxFn=function(g,e,f,h){a(e).show();a(g).hide();h()}};a.fn.cycle.transitions.fadeout=function(c,d,b){d.not(":eq("+b.currSlide+")").css({display:"block",opacity:1});b.before.push(function(l,j,k,f,g,e){a(l).css("zIndex",k.slideCount+(!e===true?1:0));a(j).css("zIndex",k.slideCount+(!e===true?0:1))});b.animIn.opacity=1;b.animOut.opacity=0;b.cssBefore.opacity=1;b.cssBefore.display="block";b.cssAfter.zIndex=0};a.fn.cycle.transitions.scrollUp=function(d,e,c){d.css("overflow","hidden");c.before.push(a.fn.cycle.commonReset);var b=d.height();c.cssBefore.top=b;c.cssBefore.left=0;c.cssFirst.top=0;c.animIn.top=0;c.animOut.top=-b};a.fn.cycle.transitions.scrollDown=function(d,e,c){d.css("overflow","hidden");c.before.push(a.fn.cycle.commonReset);var b=d.height();c.cssFirst.top=0;c.cssBefore.top=-b;c.cssBefore.left=0;c.animIn.top=0;c.animOut.top=b};a.fn.cycle.transitions.scrollLeft=function(d,e,c){d.css("overflow","hidden");c.before.push(a.fn.cycle.commonReset);var b=d.width();c.cssFirst.left=0;c.cssBefore.left=b;c.cssBefore.top=0;c.animIn.left=0;c.animOut.left=0-b};a.fn.cycle.transitions.scrollRight=function(d,e,c){d.css("overflow","hidden");c.before.push(a.fn.cycle.commonReset);var b=d.width();c.cssFirst.left=0;c.cssBefore.left=-b;c.cssBefore.top=0;c.animIn.left=0;c.animOut.left=b};a.fn.cycle.transitions.scrollHorz=function(c,d,b){c.css("overflow","hidden").width();b.before.push(function(h,f,g,e){if(g.rev){e=!e}a.fn.cycle.commonReset(h,f,g);g.cssBefore.left=e?(f.cycleW-1):(1-f.cycleW);g.animOut.left=e?-h.cycleW:h.cycleW});b.cssFirst.left=0;b.cssBefore.top=0;b.animIn.left=0;b.animOut.top=0};a.fn.cycle.transitions.scrollVert=function(c,d,b){c.css("overflow","hidden");b.before.push(function(h,f,g,e){if(g.rev){e=!e}a.fn.cycle.commonReset(h,f,g);g.cssBefore.top=e?(1-f.cycleH):(f.cycleH-1);g.animOut.top=e?h.cycleH:-h.cycleH});b.cssFirst.top=0;b.cssBefore.left=0;b.animIn.top=0;b.animOut.left=0};a.fn.cycle.transitions.slideX=function(c,d,b){b.before.push(function(g,e,f){a(f.elements).not(g).hide();a.fn.cycle.commonReset(g,e,f,false,true);f.animIn.width=e.cycleW});b.cssBefore.left=0;b.cssBefore.top=0;b.cssBefore.width=0;b.animIn.width="show";b.animOut.width=0};a.fn.cycle.transitions.slideY=function(c,d,b){b.before.push(function(g,e,f){a(f.elements).not(g).hide();a.fn.cycle.commonReset(g,e,f,true,false);f.animIn.height=e.cycleH});b.cssBefore.left=0;b.cssBefore.top=0;b.cssBefore.height=0;b.animIn.height="show";b.animOut.height=0};a.fn.cycle.transitions.shuffle=function(e,f,d){var c,b=e.css("overflow","visible").width();f.css({left:0,top:0});d.before.push(function(j,g,h){a.fn.cycle.commonReset(j,g,h,true,true,true)});if(!d.speedAdjusted){d.speed=d.speed/2;d.speedAdjusted=true}d.random=0;d.shuffle=d.shuffle||{left:-b,top:15};d.els=[];for(c=0;c0)){C.content={text:C.content}}if(typeof C.content.title!=="object"){C.content.title={text:C.content.title}}if(typeof C.position!=="object"){C.position={corner:C.position}}if(typeof C.position.corner!=="object"){C.position.corner={target:C.position.corner,tooltip:C.position.corner}}if(typeof C.show!=="object"){C.show={when:C.show}}if(typeof C.show.when!=="object"){C.show.when={event:C.show.when}}if(typeof C.show.effect!=="object"){C.show.effect={type:C.show.effect}}if(typeof C.hide!=="object"){C.hide={when:C.hide}}if(typeof C.hide.when!=="object"){C.hide.when={event:C.hide.when}}if(typeof C.hide.effect!=="object"){C.hide.effect={type:C.hide.effect}}if(typeof C.style!=="object"){C.style={name:C.style}}C.style=c(C.style);t=f.extend(true,{},f.fn.qtip.defaults,C);t.style=a.call({options:t},t.style);t.user=f.extend(true,{},C)}return f(this).each(function(){if(typeof C=="string"){x=C.toLowerCase();B=f(this).qtip("interfaces");if(typeof B=="object"){if(v===true&&x=="destroy"){while(B.length>0){B[B.length-1].destroy()}}else{if(v!==true){B=[f(this).qtip("api")]}for(z=0;z0))}if(typeof t.options.show.solo=="object"){A=f(t.options.show.solo)}else{if(t.options.show.solo===true){A=f("div.qtip").not(t.elements.tooltip)}}if(A){A.each(function(){if(f(this).qtip("api").status.rendered===true){f(this).qtip("api").hide()}})}if(typeof t.options.show.effect.type=="function"){t.options.show.effect.type.call(t.elements.tooltip,t.options.show.effect.length);t.elements.tooltip.queue(function(){x();f(this).dequeue()})}else{switch(t.options.show.effect.type.toLowerCase()){case"fade":t.elements.tooltip.fadeIn(t.options.show.effect.length,x);break;case"slide":t.elements.tooltip.slideDown(t.options.show.effect.length,function(){x();if(t.options.position.type!=="static"){t.updatePosition(z,true)}});break;case"grow":t.elements.tooltip.show(t.options.show.effect.length,x);break;default:t.elements.tooltip.show(null,x);break}t.elements.tooltip.addClass(t.options.style.classes.active)}return f.fn.qtip.log.error.call(t,1,f.fn.qtip.constants.EVENT_SHOWN,"show")},hide:function(z){var y;if(!t.status.rendered){return f.fn.qtip.log.error.call(t,2,f.fn.qtip.constants.TOOLTIP_NOT_RENDERED,"hide")}else{if(t.elements.tooltip.css("display")==="none"){return t}}clearTimeout(t.timers.show);t.elements.tooltip.stop(true,false);y=t.beforeHide.call(t,z);if(y===false){return t}function x(){t.onHide.call(t,z)}t.cache.toggle=0;if(typeof t.options.hide.effect.type=="function"){t.options.hide.effect.type.call(t.elements.tooltip,t.options.hide.effect.length);t.elements.tooltip.queue(function(){x();f(this).dequeue()})}else{switch(t.options.hide.effect.type.toLowerCase()){case"fade":t.elements.tooltip.fadeOut(t.options.hide.effect.length,x);break;case"slide":t.elements.tooltip.slideUp(t.options.hide.effect.length,x);break;case"grow":t.elements.tooltip.hide(t.options.hide.effect.length,x);break;default:t.elements.tooltip.hide(null,x);break}t.elements.tooltip.removeClass(t.options.style.classes.active)}return f.fn.qtip.log.error.call(t,1,f.fn.qtip.constants.EVENT_HIDDEN,"hide")},updatePosition:function(x,y){var D,H,M,K,I,F,z,J,C,E,L,B,G,A;if(!t.status.rendered){return f.fn.qtip.log.error.call(t,2,f.fn.qtip.constants.TOOLTIP_NOT_RENDERED,"updatePosition")}else{if(t.options.position.type=="static"){return f.fn.qtip.log.error.call(t,1,f.fn.qtip.constants.CANNOT_POSITION_STATIC,"updatePosition")}}H={position:{left:0,top:0},dimensions:{height:0,width:0},corner:t.options.position.corner.target};M={position:t.getPosition(),dimensions:t.getDimensions(),corner:t.options.position.corner.tooltip};if(t.options.position.target!=="mouse"){if(t.options.position.target.get(0).nodeName.toLowerCase()=="area"){K=t.options.position.target.attr("coords").split(",");for(D=0;DH.dimensions.width){H.dimensions.width=K[D]}if(K[D]H.dimensions.height){H.dimensions.height=K[D]}if(K[D]0){if(M.corner.search(/Left/)!==-1){z.left-=t.options.style.border.radius}else{if(M.corner.search(/Right/)!==-1){z.left+=t.options.style.border.radius}}if(M.corner.search(/Top/)!==-1){z.top-=t.options.style.border.radius}else{if(M.corner.search(/Bottom/)!==-1){z.top+=t.options.style.border.radius}}}if(J){if(M.corner.search(/top/)!==-1){z.top-=J}else{if(M.corner.search(/bottom/)!==-1){z.top+=J}}if(M.corner.search(/left/)!==-1){z.left-=J}else{if(M.corner.search(/right/)!==-1){z.left+=J}}if(M.corner.search(/leftMiddle|rightMiddle/)!==-1){z.top-=1}}if(t.options.position.adjust.screen===true){z=o.call(t,z,H,M)}if(t.options.position.target==="mouse"&&t.options.position.adjust.mouse===true){if(t.options.position.adjust.screen===true&&t.elements.tip){L=t.elements.tip.attr("rel")}else{L=t.options.position.corner.tooltip}z.left+=(L.search(/right/i)!==-1)?-6:6;z.top+=(L.search(/bottom/i)!==-1)?-6:6}if(!t.elements.bgiframe&&f.browser.msie&&parseInt(f.browser.version.charAt(0))==6){f("select, object").each(function(){B=f(this).offset();B.bottom=B.top+f(this).height();B.right=B.left+f(this).width();if(z.top+M.dimensions.height>=B.top&&z.left+M.dimensions.width>=B.left){k.call(t)}})}z.left+=t.options.position.adjust.x;z.top+=t.options.position.adjust.y;G=t.getPosition();if(z.left!=G.left||z.top!=G.top){A=t.beforePositionUpdate.call(t,x);if(A===false){return t}t.cache.position=z;if(y===true){t.status.animated=true;t.elements.tooltip.animate(z,200,"swing",function(){t.status.animated=false})}else{t.elements.tooltip.css(z)}t.onPositionUpdate.call(t,x);if(typeof x!=="undefined"&&x.type&&x.type!=="mousemove"){f.fn.qtip.log.error.call(t,1,f.fn.qtip.constants.EVENT_POSITION_UPDATED,"updatePosition")}}return t},updateWidth:function(x){var y;if(!t.status.rendered){return f.fn.qtip.log.error.call(t,2,f.fn.qtip.constants.TOOLTIP_NOT_RENDERED,"updateWidth")}else{if(x&&typeof x!=="number"){return f.fn.qtip.log.error.call(t,2,"newWidth must be of type number","updateWidth")}}y=t.elements.contentWrapper.siblings().add(t.elements.tip).add(t.elements.button);if(!x){if(typeof t.options.style.width.value=="number"){x=t.options.style.width.value}else{t.elements.tooltip.css({width:"auto"});y.hide();if(f.browser.msie){t.elements.wrapper.add(t.elements.contentWrapper.children()).css({zoom:"normal"})}x=t.getDimensions().width+1;if(!t.options.style.width.value){if(x>t.options.style.width.max){x=t.options.style.width.max}if(x").get(0).getContext){A=t.elements.tooltip.find(".qtip-tip canvas:first");y=A.get(0).getContext("2d");y.clearRect(0,0,300,300);z=A.parent("div[rel]:first").attr("rel");C=b(z,t.options.style.tip.size.width,t.options.style.tip.size.height);h.call(t,A,C,t.options.style.tip.color||t.options.style.border.color)}else{if(f.browser.msie){A=t.elements.tooltip.find('.qtip-tip [nodeName="shape"]');A.attr("fillcolor",t.options.style.tip.color||t.options.style.border.color)}}}if(t.options.style.border.radius>0){t.elements.tooltip.find(".qtip-betweenCorners").css({backgroundColor:t.options.style.border.color});if(f("").get(0).getContext){B=g(t.options.style.border.radius);t.elements.tooltip.find(".qtip-wrapper canvas").each(function(){y=f(this).get(0).getContext("2d");y.clearRect(0,0,300,300);z=f(this).parent("div[rel]:first").attr("rel");s.call(t,f(this),B[z],t.options.style.border.radius,t.options.style.border.color)})}else{if(f.browser.msie){t.elements.tooltip.find('.qtip-wrapper [nodeName="arc"]').each(function(){f(this).attr("fillcolor",t.options.style.border.color)})}}}return f.fn.qtip.log.error.call(t,1,f.fn.qtip.constants.EVENT_STYLE_UPDATED,"updateStyle")},updateContent:function(B,z){var A,y,x;if(!t.status.rendered){return f.fn.qtip.log.error.call(t,2,f.fn.qtip.constants.TOOLTIP_NOT_RENDERED,"updateContent")}else{if(!B){return f.fn.qtip.log.error.call(t,2,f.fn.qtip.constants.NO_CONTENT_PROVIDED,"updateContent")}}A=t.beforeContentUpdate.call(t,B);if(typeof A=="string"){B=A}else{if(A===false){return}}if(f.browser.msie){t.elements.contentWrapper.children().css({zoom:"normal"})}if(B.jquery&&B.length>0){B.clone(true).appendTo(t.elements.content).show()}else{t.elements.content.html(B)}y=t.elements.content.find("img[complete=false]");if(y.length>0){x=0;y.each(function(D){f('').load(function(){if(++x==y.length){C()}})})}else{C()}function C(){t.updateWidth();if(z!==false){if(t.options.position.type!=="static"){t.updatePosition(t.elements.tooltip.is(":visible"),true)}if(t.options.style.tip.corner!==false){n.call(t)}}}t.onContentUpdate.call(t);return f.fn.qtip.log.error.call(t,1,f.fn.qtip.constants.EVENT_CONTENT_UPDATED,"loadContent")},loadContent:function(x,A,B){var z;if(!t.status.rendered){return f.fn.qtip.log.error.call(t,2,f.fn.qtip.constants.TOOLTIP_NOT_RENDERED,"loadContent")}z=t.beforeContentLoad.call(t);if(z===false){return t}if(B=="post"){f.post(x,A,y)}else{f.get(x,A,y)}function y(C){t.onContentLoad.call(t);f.fn.qtip.log.error.call(t,1,f.fn.qtip.constants.EVENT_CONTENT_LOADED,"loadContent");t.updateContent(C)}return t},updateTitle:function(x){if(!t.status.rendered){return f.fn.qtip.log.error.call(t,2,f.fn.qtip.constants.TOOLTIP_NOT_RENDERED,"updateTitle")}else{if(!x){return f.fn.qtip.log.error.call(t,2,f.fn.qtip.constants.NO_CONTENT_PROVIDED,"updateTitle")}}returned=t.beforeTitleUpdate.call(t);if(returned===false){return t}if(t.elements.button){t.elements.button=t.elements.button.clone(true)}t.elements.title.html(x);if(t.elements.button){t.elements.title.prepend(t.elements.button)}t.onTitleUpdate.call(t);return f.fn.qtip.log.error.call(t,1,f.fn.qtip.constants.EVENT_TITLE_UPDATED,"updateTitle")},focus:function(B){var z,y,x,A;if(!t.status.rendered){return f.fn.qtip.log.error.call(t,2,f.fn.qtip.constants.TOOLTIP_NOT_RENDERED,"focus")}else{if(t.options.position.type=="static"){return f.fn.qtip.log.error.call(t,1,f.fn.qtip.constants.CANNOT_FOCUS_STATIC,"focus")}}z=parseInt(t.elements.tooltip.css("z-index"));y=6000+f("div.qtip[qtip]").length-1;if(!t.status.focused&&z!==y){A=t.beforeFocus.call(t,B);if(A===false){return t}f("div.qtip[qtip]").not(t.elements.tooltip).each(function(){if(f(this).qtip("api").status.rendered===true){x=parseInt(f(this).css("z-index"));if(typeof x=="number"&&x>-1){f(this).css({zIndex:parseInt(f(this).css("z-index"))-1})}f(this).qtip("api").status.focused=false}});t.elements.tooltip.css({zIndex:y});t.status.focused=true;t.onFocus.call(t,B);f.fn.qtip.log.error.call(t,1,f.fn.qtip.constants.EVENT_FOCUSED,"focus")}return t},disable:function(x){if(!t.status.rendered){return f.fn.qtip.log.error.call(t,2,f.fn.qtip.constants.TOOLTIP_NOT_RENDERED,"disable")}if(x){if(!t.status.disabled){t.status.disabled=true;f.fn.qtip.log.error.call(t,1,f.fn.qtip.constants.EVENT_DISABLED,"disable")}else{f.fn.qtip.log.error.call(t,1,f.fn.qtip.constants.TOOLTIP_ALREADY_DISABLED,"disable")}}else{if(t.status.disabled){t.status.disabled=false;f.fn.qtip.log.error.call(t,1,f.fn.qtip.constants.EVENT_ENABLED,"disable")}else{f.fn.qtip.log.error.call(t,1,f.fn.qtip.constants.TOOLTIP_ALREADY_ENABLED,"disable")}}return t},destroy:function(){var x,y,z;y=t.beforeDestroy.call(t);if(y===false){return t}if(t.status.rendered){t.options.show.when.target.unbind("mousemove.qtip",t.updatePosition);t.options.show.when.target.unbind("mouseout.qtip",t.hide);t.options.show.when.target.unbind(t.options.show.when.event+".qtip");t.options.hide.when.target.unbind(t.options.hide.when.event+".qtip");t.elements.tooltip.unbind(t.options.hide.when.event+".qtip");t.elements.tooltip.unbind("mouseover.qtip",t.focus);t.elements.tooltip.remove()}else{t.options.show.when.target.unbind(t.options.show.when.event+".qtip-create")}if(typeof t.elements.target.data("qtip")=="object"){z=t.elements.target.data("qtip").interfaces;if(typeof z=="object"&&z.length>0){for(x=0;x0){t.elements.target.data("qtip").current=z.length-1}else{t.elements.target.removeData("qtip")}t.onDestroy.call(t);f.fn.qtip.log.error.call(t,1,f.fn.qtip.constants.EVENT_DESTROYED,"destroy");return t.elements.target},getPosition:function(){var x,y;if(!t.status.rendered){return f.fn.qtip.log.error.call(t,2,f.fn.qtip.constants.TOOLTIP_NOT_RENDERED,"getPosition")}x=(t.elements.tooltip.css("display")!=="none")?false:true;if(x){t.elements.tooltip.css({visiblity:"hidden"}).show()}y=t.elements.tooltip.offset();if(x){t.elements.tooltip.css({visiblity:"visible"}).hide()}return y},getDimensions:function(){var x,y;if(!t.status.rendered){return f.fn.qtip.log.error.call(t,2,f.fn.qtip.constants.TOOLTIP_NOT_RENDERED,"getDimensions")}x=(!t.elements.tooltip.is(":visible"))?true:false;if(x){t.elements.tooltip.css({visiblity:"hidden"}).show()}y={height:t.elements.tooltip.outerHeight(),width:t.elements.tooltip.outerWidth()};if(x){t.elements.tooltip.css({visiblity:"visible"}).hide()}return y}})}function q(){var t,x,v,u,w,z,y;t=this;t.beforeRender.call(t);t.status.rendered=true;t.elements.tooltip='';t.elements.tooltip=f(t.elements.tooltip);t.elements.tooltip.appendTo(t.options.position.container);t.elements.tooltip.data("qtip",{current:0,interfaces:[t]});t.elements.wrapper=t.elements.tooltip.children("div:first");t.elements.contentWrapper=t.elements.wrapper.children("div:first").css({background:t.options.style.background});t.elements.content=t.elements.contentWrapper.children("div:first").css(r(t.options.style));if(f.browser.msie){t.elements.wrapper.add(t.elements.content).css({zoom:1})}if(t.options.hide.when.event=="unfocus"){t.elements.tooltip.attr("unfocus",true)}if(typeof t.options.style.width.value=="number"){t.updateWidth()}if(f("").get(0).getContext||f.browser.msie){if(t.options.style.border.radius>0){m.call(t)}else{t.elements.contentWrapper.css({border:t.options.style.border.width+"px solid "+t.options.style.border.color})}if(t.options.style.tip.corner!==false){e.call(t)}}else{t.elements.contentWrapper.css({border:t.options.style.border.width+"px solid "+t.options.style.border.color});t.options.style.border.radius=0;t.options.style.tip.corner=false;f.fn.qtip.log.error.call(t,2,f.fn.qtip.constants.CANVAS_VML_NOT_SUPPORTED,"render")}if((typeof t.options.content.text=="string"&&t.options.content.text.length>0)||(t.options.content.text.jquery&&t.options.content.text.length>0)){v=t.options.content.text}else{if(typeof t.elements.target.attr("title")=="string"&&t.elements.target.attr("title").length>0){v=t.elements.target.attr("title").replace("\\n","
");t.elements.target.attr("title","")}else{if(typeof t.elements.target.attr("alt")=="string"&&t.elements.target.attr("alt").length>0){v=t.elements.target.attr("alt").replace("\\n","
");t.elements.target.attr("alt","")}else{v=" ";f.fn.qtip.log.error.call(t,1,f.fn.qtip.constants.NO_VALID_CONTENT,"render")}}}if(t.options.content.title.text!==false){j.call(t)}t.updateContent(v);l.call(t);if(t.options.show.ready===true){t.show()}if(t.options.content.url!==false){u=t.options.content.url;w=t.options.content.data;z=t.options.content.method||"get";t.loadContent(u,w,z)}t.onRender.call(t);f.fn.qtip.log.error.call(t,1,f.fn.qtip.constants.EVENT_RENDERED,"render")}function m(){var G,A,u,C,y,F,v,H,E,z,x,D,B,t,w;G=this;G.elements.wrapper.find(".qtip-borderBottom, .qtip-borderTop").remove();u=G.options.style.border.width;C=G.options.style.border.radius;y=G.options.style.border.color||G.options.style.tip.color;F=g(C);v={};for(A in F){v[A]='
';if(f("").get(0).getContext){v[A]+=''}else{if(f.browser.msie){H=C*2+3;v[A]+=''}}v[A]+="
"}E=G.getDimensions().width-(Math.max(u,C)*2);z='
';x='
'+v.topLeft+v.topRight+z;G.elements.wrapper.prepend(x);D='
'+v.bottomLeft+v.bottomRight+z;G.elements.wrapper.append(D);if(f("").get(0).getContext){G.elements.wrapper.find("canvas").each(function(){B=F[f(this).parent("[rel]:first").attr("rel")];s.call(G,f(this),B,C,y)})}else{if(f.browser.msie){G.elements.tooltip.append('')}}t=Math.max(C,(C+(u-C)));w=Math.max(u-C,0);G.elements.contentWrapper.css({border:"0px solid "+y,borderWidth:w+"px "+t+"px"})}function s(v,x,t,u){var w=v.get(0).getContext("2d");w.fillStyle=u;w.beginPath();w.arc(x[0],x[1],t,0,Math.PI*2,false);w.fill()}function e(w){var u,t,y,v,x;u=this;if(u.elements.tip!==null){u.elements.tip.remove()}t=u.options.style.tip.color||u.options.style.border.color;if(u.options.style.tip.corner===false){return}else{if(!w){w=u.options.style.tip.corner}}y=b(w,u.options.style.tip.size.width,u.options.style.tip.size.height);u.elements.tip='
';if(f("").get(0).getContext){u.elements.tip+=''}else{if(f.browser.msie){v=u.options.style.tip.size.width+","+u.options.style.tip.size.height;x="m"+y[0][0]+","+y[0][1];x+=" l"+y[1][0]+","+y[1][1];x+=" "+y[2][0]+","+y[2][1];x+=" xe";u.elements.tip+='';u.elements.tip+='';u.elements.contentWrapper.css("position","relative")}}u.elements.tooltip.prepend(u.elements.tip+"
");u.elements.tip=u.elements.tooltip.find("."+u.options.style.classes.tip).eq(0);if(f("").get(0).getContext){h.call(u,u.elements.tip.find("canvas:first"),y,t)}if(w.search(/top/)!==-1&&f.browser.msie&&parseInt(f.browser.version.charAt(0))===6){u.elements.tip.css({marginTop:-4})}n.call(u,w)}function h(u,w,t){var v=u.get(0).getContext("2d");v.fillStyle=t;v.beginPath();v.moveTo(w[0][0],w[0][1]);v.lineTo(w[1][0],w[1][1]);v.lineTo(w[2][0],w[2][1]);v.fill()}function n(v){var u,x,t,y,w;u=this;if(u.options.style.tip.corner===false||!u.elements.tip){return}if(!v){v=u.elements.tip.attr("rel")}x=positionAdjust=(f.browser.msie)?1:0;u.elements.tip.css(v.match(/left|right|top|bottom/)[0],0);if(v.search(/top|bottom/)!==-1){if(f.browser.msie){if(parseInt(f.browser.version.charAt(0))===6){positionAdjust=(v.search(/top/)!==-1)?-3:1}else{positionAdjust=(v.search(/top/)!==-1)?1:2}}if(v.search(/Middle/)!==-1){u.elements.tip.css({left:"50%",marginLeft:-(u.options.style.tip.size.width/2)})}else{if(v.search(/Left/)!==-1){u.elements.tip.css({left:u.options.style.border.radius-x})}else{if(v.search(/Right/)!==-1){u.elements.tip.css({right:u.options.style.border.radius+x})}}}if(v.search(/top/)!==-1){u.elements.tip.css({top:-positionAdjust})}else{u.elements.tip.css({bottom:positionAdjust})}}else{if(v.search(/left|right/)!==-1){if(f.browser.msie){positionAdjust=(parseInt(f.browser.version.charAt(0))===6)?1:((v.search(/left/)!==-1)?1:2)}if(v.search(/Middle/)!==-1){u.elements.tip.css({top:"50%",marginTop:-(u.options.style.tip.size.height/2)})}else{if(v.search(/Top/)!==-1){u.elements.tip.css({top:u.options.style.border.radius-x})}else{if(v.search(/Bottom/)!==-1){u.elements.tip.css({bottom:u.options.style.border.radius+x})}}}if(v.search(/left/)!==-1){u.elements.tip.css({left:-positionAdjust})}else{u.elements.tip.css({right:positionAdjust})}}}t="padding-"+v.match(/left|right|top|bottom/)[0];y=u.options.style.tip.size[(t.search(/left|right/)!==-1)?"width":"height"];u.elements.tooltip.css("padding",0);u.elements.tooltip.css(t,y);if(f.browser.msie&&parseInt(f.browser.version.charAt(0))==6){w=parseInt(u.elements.tip.css("margin-top"))||0;w+=parseInt(u.elements.content.css("margin-top"))||0;u.elements.tip.css({marginTop:w})}}function j(){var t=this;if(t.elements.title!==null){t.elements.title.remove()}t.elements.title=f('
').css(r(t.options.style.title,true)).css({zoom:(f.browser.msie)?1:0}).prependTo(t.elements.contentWrapper);if(t.options.content.title.text){t.updateTitle.call(t,t.options.content.title.text)}if(t.options.content.title.button!==false&&typeof t.options.content.title.button=="string"){t.elements.button=f('').css(r(t.options.style.button,true)).html(t.options.content.title.button).prependTo(t.elements.title).click(function(u){if(!t.status.disabled){t.hide(u)}})}}function l(){var u,w,v,t;u=this;w=u.options.show.when.target;v=u.options.hide.when.target;if(u.options.hide.fixed){v=v.add(u.elements.tooltip)}if(u.options.hide.when.event=="inactive"){t=["click","dblclick","mousedown","mouseup","mousemove","mouseout","mouseenter","mouseleave","mouseover"];function z(A){if(u.status.disabled===true){return}clearTimeout(u.timers.inactive);u.timers.inactive=setTimeout(function(){f(t).each(function(){v.unbind(this+".qtip-inactive");u.elements.content.unbind(this+".qtip-inactive")});u.hide(A)},u.options.hide.delay)}}else{if(u.options.hide.fixed===true){u.elements.tooltip.bind("mouseover.qtip",function(){if(u.status.disabled===true){return}clearTimeout(u.timers.hide)})}}function y(A){if(u.status.disabled===true){return}if(u.options.hide.when.event=="inactive"){f(t).each(function(){v.bind(this+".qtip-inactive",z);u.elements.content.bind(this+".qtip-inactive",z)});z()}clearTimeout(u.timers.show);clearTimeout(u.timers.hide);u.timers.show=setTimeout(function(){u.show(A)},u.options.show.delay)}function x(A){if(u.status.disabled===true){return}if(u.options.hide.fixed===true&&u.options.hide.when.event.search(/mouse(out|leave)/i)!==-1&&f(A.relatedTarget).parents("div.qtip[qtip]").length>0){A.stopPropagation();A.preventDefault();clearTimeout(u.timers.hide);return false}clearTimeout(u.timers.show);clearTimeout(u.timers.hide);u.elements.tooltip.stop(true,true);u.timers.hide=setTimeout(function(){u.hide(A)},u.options.hide.delay)}if((u.options.show.when.target.add(u.options.hide.when.target).length===1&&u.options.show.when.event==u.options.hide.when.event&&u.options.hide.when.event!=="inactive")||u.options.hide.when.event=="unfocus"){u.cache.toggle=0;w.bind(u.options.show.when.event+".qtip",function(A){if(u.cache.toggle==0){y(A)}else{x(A)}})}else{w.bind(u.options.show.when.event+".qtip",y);if(u.options.hide.when.event!=="inactive"){v.bind(u.options.hide.when.event+".qtip",x)}}if(u.options.position.type.search(/(fixed|absolute)/)!==-1){u.elements.tooltip.bind("mouseover.qtip",u.focus)}if(u.options.position.target==="mouse"&&u.options.position.type!=="static"){w.bind("mousemove.qtip",function(A){u.cache.mouse={x:A.pageX,y:A.pageY};if(u.status.disabled===false&&u.options.position.adjust.mouse===true&&u.options.position.type!=="static"&&u.elements.tooltip.css("display")!=="none"){u.updatePosition(A)}})}}function o(v,w,B){var A,t,y,z,u,x;A=this;if(B.corner=="center"){return w.position}t=f.extend({},v);z={x:false,y:false};u={left:(t.left=f.fn.qtip.cache.screen.width+f.fn.qtip.cache.screen.scroll.left),top:(t.top=f.fn.qtip.cache.screen.height+f.fn.qtip.cache.screen.scroll.top)};y={left:(u.left&&(B.corner.search(/right/i)!=-1||(B.corner.search(/right/i)==-1&&!u.right))),right:(u.right&&(B.corner.search(/left/i)!=-1||(B.corner.search(/left/i)==-1&&!u.left))),top:(u.top&&B.corner.search(/top/i)==-1),bottom:(u.bottom&&B.corner.search(/bottom/i)==-1)};if(y.left){if(A.options.position.target!=="mouse"){t.left=w.position.left+w.dimensions.width}else{t.left=A.cache.mouse.x}z.x="Left"}else{if(y.right){if(A.options.position.target!=="mouse"){t.left=w.position.left-B.dimensions.width}else{t.left=A.cache.mouse.x-B.dimensions.width}z.x="Right"}}if(y.top){if(A.options.position.target!=="mouse"){t.top=w.position.top+w.dimensions.height}else{t.top=A.cache.mouse.y}z.y="top"}else{if(y.bottom){if(A.options.position.target!=="mouse"){t.top=w.position.top-B.dimensions.height}else{t.top=A.cache.mouse.y-B.dimensions.height}z.y="bottom"}}if(t.left<0){t.left=v.left;z.x=false}if(t.top<0){t.top=v.top;z.y=false}if(A.options.style.tip.corner!==false){t.corner=new String(B.corner);if(z.x!==false){t.corner=t.corner.replace(/Left|Right|Middle/,z.x)}if(z.y!==false){t.corner=t.corner.replace(/top|bottom/,z.y)}if(t.corner!==A.elements.tip.attr("rel")){e.call(A,t.corner)}}return t}function r(v,u){var w,t;w=f.extend(true,{},v);for(t in w){if(u===true&&t.search(/(tip|classes)/i)!==-1){delete w[t]}else{if(!u&&t.search(/(width|border|tip|title|classes|user)/i)!==-1){delete w[t]}}}return w}function c(t){if(typeof t.tip!=="object"){t.tip={corner:t.tip}}if(typeof t.tip.size!=="object"){t.tip.size={width:t.tip.size,height:t.tip.size}}if(typeof t.border!=="object"){t.border={width:t.border}}if(typeof t.width!=="object"){t.width={value:t.width}}if(typeof t.width.max=="string"){t.width.max=parseInt(t.width.max.replace(/([0-9]+)/i,"$1"))}if(typeof t.width.min=="string"){t.width.min=parseInt(t.width.min.replace(/([0-9]+)/i,"$1"))}if(typeof t.tip.size.x=="number"){t.tip.size.width=t.tip.size.x;delete t.tip.size.x}if(typeof t.tip.size.y=="number"){t.tip.size.height=t.tip.size.y;delete t.tip.size.y}return t}function a(){var t,u,v,y,w,x;t=this;v=[true,{}];for(u=0;u0){w.tip.size.width+=1}if(w.tip.size.height%2>0){w.tip.size.height+=1}if(w.tip.corner===true){w.tip.corner=(t.options.position.corner.tooltip==="center")?false:t.options.position.corner.tooltip}return w}function b(w,v,u){var t={bottomRight:[[0,0],[v,u],[v,0]],bottomLeft:[[0,0],[v,0],[0,u]],topRight:[[0,u],[v,0],[v,u]],topLeft:[[0,0],[0,u],[v,u]],topMiddle:[[0,u],[v/2,0],[v,u]],bottomMiddle:[[0,0],[v,0],[v/2,u]],rightMiddle:[[0,0],[v,u/2],[0,u]],leftMiddle:[[v,0],[v,u],[0,u/2]]};t.leftTop=t.bottomRight;t.rightTop=t.bottomLeft;t.leftBottom=t.topRight;t.rightBottom=t.topLeft;return t[w]}function g(t){var u;if(f("").get(0).getContext){u={topLeft:[t,t],topRight:[0,t],bottomLeft:[t,0],bottomRight:[0,0]}}else{if(f.browser.msie){u={topLeft:[-90,90,0],topRight:[-90,90,-t],bottomLeft:[90,270,0],bottomRight:[90,270,-t]}}}return u}function k(){var t,u,v;t=this;v=t.getDimensions();u='')}catch(d){c=H.createElement("iframe"),ga(c, -a)}c.height="0";c.width="0";c.style.display="none";c.style.visibility="hidden";var e=H[x],e=ke+"/u/post_iframe.html#"+ba(e.protocol+"//"+e[na]+"/favicon.ico"),f=function(){c.src="";c.parentNode&&c.parentNode.removeChild(c)};Ba(V,"beforeunload",f);var k=j,o=0,r=function(){if(!k){try{if(9 bool Array::minmax(int64_t& result, size_t st // We originally had declared '__m128i state2' and did an 'state2 = state' assignment. When we read from state2 through int16_t, int32_t or int64_t in GetUniversal(), // the compiler thinks it cannot alias state2 and hence reorders the read and assignment. - // In this fixed version using memcpy, we have char-read-access from __m128i (OK aliasing) and char-write-access to char-array, and finally int8/16/32/64 + // In this fixed version using memcpy, we have char-read-access from __m128i (OK aliasing) and char-write-access to char-array, and finally int8/16/32/64 // read access from char-array (OK aliasing). memcpy(&state2, &state, sizeof(state)); for (size_t t = 0; t < sizeof(__m128i) * 8 / no0(w); ++t) { @@ -747,7 +747,7 @@ template bool Array::minmax(int64_t& result, size_t st if (find_max ? v > m : v < m) { m = v; } - } + } } } #endif @@ -1531,7 +1531,7 @@ template void Array::sort() size_t lo = 0; size_t hi = m_len - 1; - std::vector count; + vector count; int64_t min; int64_t max; bool b = false; @@ -1669,9 +1669,9 @@ template void Array::QuickSort(size_t lo, size_t hi) if (i < (int)hi) QuickSort(i, hi); } -std::vector Array::ToVector() const +vector Array::ToVector() const { - std::vector v; + vector v; const size_t count = size(); for (size_t t = 0; t < count; ++t) v.push_back(Get(t)); @@ -1694,12 +1694,12 @@ bool Array::Compare(const Array& c) const void Array::Print() const { - std::cout << std::hex << GetRef() << std::dec << ": (" << size() << ") "; + cout << hex << GetRef() << dec << ": (" << size() << ") "; for (size_t i = 0; i < size(); ++i) { - if (i) std::cout << ", "; - std::cout << Get(i); + if (i) cout << ", "; + cout << Get(i); } - std::cout << "\n"; + cout << "\n"; } void Array::Verify() const @@ -1714,25 +1714,25 @@ void Array::Verify() const TIGHTDB_ASSERT(ref_in_parent == (IsValid() ? m_ref : 0)); } -void Array::ToDot(std::ostream& out, const char* title) const +void Array::ToDot(ostream& out, StringData title) const { const size_t ref = GetRef(); - if (title) { - out << "subgraph cluster_" << ref << " {" << std::endl; - out << " label = \"" << title << "\";" << std::endl; - out << " color = white;" << std::endl; + if (0 < title.size()) { + out << "subgraph cluster_" << ref << " {" << endl; + out << " label = \"" << title << "\";" << endl; + out << " color = white;" << endl; } - out << "n" << std::hex << ref << std::dec << "[shape=none,label=<"; - out << "" << std::endl; + out << "n" << hex << ref << dec << "[shape=none,label=<"; + out << "
" << endl; // Header out << "" << std::endl; + out << "" << endl; // Values for (size_t i = 0; i < m_len; ++i) { @@ -1744,23 +1744,23 @@ void Array::ToDot(std::ostream& out, const char* title) const else out << "" << std::endl; + out << "" << endl; } - out << "
"; - out << "0x" << std::hex << ref << std::dec << "
"; + out << "0x" << hex << ref << dec << "
"; if (m_isNode) out << "IsNode
"; if (m_hasRefs) out << "HasRefs
"; - out << "
"; } else out << "" << v; - out << "
>];" << std::endl; - if (title) out << "}" << std::endl; + out << ">];" << endl; + if (0 < title.size()) out << "}" << endl; if (m_hasRefs) { for (size_t i = 0; i < m_len; ++i) { const int64_t target = Get(i); if (target == 0 || target & 0x1) continue; // zero-refs and refs that are not 64-aligned do not point to sub-trees - out << "n" << std::hex << ref << std::dec << ":" << i; - out << " -> n" << std::hex << target << std::dec << std::endl; + out << "n" << hex << ref << dec << ":" << i; + out << " -> n" << hex << target << dec << endl; } } - out << std::endl; + out << endl; } void Array::Stats(MemStats& stats) const @@ -1858,8 +1858,7 @@ inline int64_t get_direct(const char* data, size_t width, size_t ndx) TIGHTDB_NO // // It may be worth considering if overall efficiency can be improved // by doing a linear search for short sequences. -template -inline size_t lower_bound(const char* header, int64_t value) TIGHTDB_NOEXCEPT +template inline size_t lower_bound(const char* header, int64_t value) TIGHTDB_NOEXCEPT { const char* data = tightdb::Array::get_data_from_header(header); @@ -1874,14 +1873,15 @@ inline size_t lower_bound(const char* header, int64_t value) TIGHTDB_NOEXCEPT i = mid + 1; size -= half + 1; } - else size = half; + else { + size = half; + } } return i; } // See lower_bound() -template -inline size_t upper_bound(const char* header, int64_t value) TIGHTDB_NOEXCEPT +template inline size_t upper_bound(const char* header, int64_t value) TIGHTDB_NOEXCEPT { const char* data = tightdb::Array::get_data_from_header(header); @@ -1896,7 +1896,9 @@ inline size_t upper_bound(const char* header, int64_t value) TIGHTDB_NOEXCEPT i = mid + 1; size -= half + 1; } - else size = half; + else { + size = half; + } } return i; } @@ -2102,40 +2104,46 @@ int64_t Array::column_get(size_t ndx) const TIGHTDB_NOEXCEPT return get_direct(data, width, p.second); } -const char* Array::string_column_get(size_t ndx) const TIGHTDB_NOEXCEPT +StringData Array::string_column_get(size_t ndx) const TIGHTDB_NOEXCEPT { if (is_leaf()) { - if (HasRefs()) - return static_cast(this)->Get(ndx); - return static_cast(this)->Get(ndx); + if (HasRefs()) { + return static_cast(this)->get(ndx); + } + return static_cast(this)->get(ndx); } pair p = find_leaf(this, ndx); const char* header = p.first; ndx = p.second; - int width = get_width_from_header(header); if (!get_hasrefs_from_header(header)) { - // short strings - if (width == 0) return ""; - return get_data_from_header(header) + (ndx * width); + return ArrayString::get_from_header(header, ndx); // short strings } // long strings + int width = get_width_from_header(header); pair p2; TIGHTDB_TEMPEX(p2 = ::get_two_as_size, width, (header, 0)); const size_t offsets_ref = p2.first; const size_t blob_ref = p2.second; - size_t offset = 0; + header = static_cast(m_alloc.Translate(offsets_ref)); + width = get_width_from_header(header); + size_t begin, end; if (0 < ndx) { - header = static_cast(m_alloc.Translate(offsets_ref)); - width = get_width_from_header(header); - offset = to_size_t(get_direct(get_data_from_header(header), width, ndx-1)); + TIGHTDB_TEMPEX(p2 = ::get_two_as_size, width, (header, ndx-1)); + begin = p2.first; + end = p2.second; + } + else { + begin = 0; + end = to_size_t(get_direct(get_data_from_header(header), width, 0)); } + --end; // Discount the terminating zero header = static_cast(m_alloc.Translate(blob_ref)); - return get_data_from_header(header) + offset; + return StringData(ArrayBlob::get_from_header(header, begin), end-begin); } // Find value direct through column b-tree without instatiating any Arrays. @@ -2182,9 +2190,10 @@ size_t Array::ColumnFind(int64_t target, size_t ref, Array& cache) const } } -size_t Array::IndexStringFindFirst(const char* value, void* column, StringGetter get_func) const +size_t Array::IndexStringFindFirst(StringData value, void* column, StringGetter get_func) const { - const char* v = value; + const char* v = value.data(); + const char* v_end = v + value.size(); const char* data = m_data; const char* header; size_t width = m_width; @@ -2193,10 +2202,10 @@ size_t Array::IndexStringFindFirst(const char* value, void* column, StringGetter top: // Create 4 byte index key int32_t key = 0; - if (*v) key = (int32_t(*v++) << 24); - if (*v) key |= (int32_t(*v++) << 16); - if (*v) key |= (int32_t(*v++) << 8); - if (*v) key |= int32_t(*v++); + if (v != v_end) key = (int32_t(*v++) << 24); + if (v != v_end) key |= (int32_t(*v++) << 16); + if (v != v_end) key |= (int32_t(*v++) << 8); + if (v != v_end) key |= int32_t(*v++); for (;;) { // Get subnode table @@ -2237,8 +2246,8 @@ size_t Array::IndexStringFindFirst(const char* value, void* column, StringGetter // compared against the entire (target) string if (!(stored_key << 24)) return row_ref; - const char* str = (*get_func)(column, row_ref); - if (strcmp(str, value) == 0) return row_ref; + StringData str = (*get_func)(column, row_ref); + if (str == value) return row_ref; else return not_found; } @@ -2265,8 +2274,8 @@ size_t Array::IndexStringFindFirst(const char* value, void* column, StringGetter // compared against the entire (target) string if (!(stored_key << 24)) return row_ref; - const char* str = (*get_func)(column, row_ref); - if (strcmp(str, value) == 0) return row_ref; + StringData str = (*get_func)(column, row_ref); + if (str == value) return row_ref; else return not_found; } @@ -2281,9 +2290,10 @@ size_t Array::IndexStringFindFirst(const char* value, void* column, StringGetter } } -void Array::IndexStringFindAll(Array& result, const char* value, void* column, StringGetter get_func) const +void Array::IndexStringFindAll(Array& result, StringData value, void* column, StringGetter get_func) const { - const char* v = value; + const char* v = value.data(); + const char* v_end = v + value.size(); const char* data = m_data; const char* header; size_t width = m_width; @@ -2292,10 +2302,10 @@ void Array::IndexStringFindAll(Array& result, const char* value, void* column, S top: // Create 4 byte index key int32_t key = 0; - if (*v) key = (int32_t(*v++) << 24); - if (*v) key |= (int32_t(*v++) << 16); - if (*v) key |= (int32_t(*v++) << 8); - if (*v) key |= int32_t(*v++); + if (v != v_end) key = (int32_t(*v++) << 24); + if (v != v_end) key |= (int32_t(*v++) << 16); + if (v != v_end) key |= (int32_t(*v++) << 8); + if (v != v_end) key |= int32_t(*v++); for (;;) { // Get subnode table @@ -2339,8 +2349,8 @@ void Array::IndexStringFindAll(Array& result, const char* value, void* column, S return; } - const char* const str = (*get_func)(column, row_ref); - if (strcmp(str, value) == 0) { + StringData str = (*get_func)(column, row_ref); + if (str == value) { result.add(row_ref); return; } @@ -2364,8 +2374,8 @@ void Array::IndexStringFindAll(Array& result, const char* value, void* column, S // If the last byte in the stored key is not zero, we have // not yet compared against the entire (target) string if ((stored_key << 24)) { - const char* const str = (*get_func)(column, first_row_ref); - if (strcmp(str, value) != 0) + StringData str = (*get_func)(column, first_row_ref); + if (str != value) return; // not_found } @@ -2379,13 +2389,13 @@ void Array::IndexStringFindAll(Array& result, const char* value, void* column, S } else { const Column sub(ref, NULL, 0, m_alloc); - const size_t first_row_ref = to_size_t(sub.Get(0)); + const size_t first_row_ref = to_size_t(sub.get(0)); // If the last byte in the stored key is not zero, we have // not yet compared against the entire (target) string if ((stored_key << 24)) { - const char* const str = (*get_func)(column, first_row_ref); - if (strcmp(str, value) != 0) + StringData str = (*get_func)(column, first_row_ref); + if (str != value) return; // not_found } @@ -2393,7 +2403,7 @@ void Array::IndexStringFindAll(Array& result, const char* value, void* column, S const size_t sub_len = sub.Size(); for (size_t i = 0; i < sub_len; ++i) { - const size_t row_ref = to_size_t(sub.Get(i)); + const size_t row_ref = to_size_t(sub.get(i)); result.add(row_ref); } } @@ -2411,9 +2421,10 @@ void Array::IndexStringFindAll(Array& result, const char* value, void* column, S } } -size_t Array::IndexStringCount(const char* value, void* column, StringGetter get_func) const +size_t Array::IndexStringCount(StringData value, void* column, StringGetter get_func) const { - const char* v = value; + const char* v = value.data(); + const char* v_end = v + value.size(); const char* data = m_data; const char* header; size_t width = m_width; @@ -2422,10 +2433,10 @@ size_t Array::IndexStringCount(const char* value, void* column, StringGetter get top: // Create 4 byte index key int32_t key = 0; - if (*v) key = (int32_t(*v++) << 24); - if (*v) key |= (int32_t(*v++) << 16); - if (*v) key |= (int32_t(*v++) << 8); - if (*v) key |= int32_t(*v++); + if (v != v_end) key = (int32_t(*v++) << 24); + if (v != v_end) key |= (int32_t(*v++) << 16); + if (v != v_end) key |= (int32_t(*v++) << 8); + if (v != v_end) key |= int32_t(*v++); for (;;) { // Get subnode table @@ -2466,8 +2477,8 @@ size_t Array::IndexStringCount(const char* value, void* column, StringGetter get // compared against the entire (target) string if (!(stored_key << 24)) return 1; - const char* const str = (*get_func)(column, row_ref); - if (strcmp(str, value) == 0) return 1; + StringData str = (*get_func)(column, row_ref); + if (str == value) return 1; else return 0; } @@ -2501,11 +2512,11 @@ size_t Array::IndexStringCount(const char* value, void* column, StringGetter get // compared against the entire (target) string if (!(stored_key << 24)) return sub_count; - row_ref = to_size_t(sub.Get(0)); + row_ref = to_size_t(sub.get(0)); } - const char* const str = (*get_func)(column, row_ref); - if (strcmp(str, value) == 0) return sub_count; + StringData str = (*get_func)(column, row_ref); + if (str == value) return sub_count; else return 0; } diff --git a/src/tightdb/array.hpp b/src/tightdb/array.hpp index 3acc4bff1f3..b2c56458149 100644 --- a/src/tightdb/array.hpp +++ b/src/tightdb/array.hpp @@ -38,6 +38,7 @@ Searching: The main finding function is: #ifndef TIGHTDB_ARRAY_HPP #define TIGHTDB_ARRAY_HPP +#include #include // unint8_t etc #include // size_t #include // memmove @@ -45,12 +46,12 @@ Searching: The main finding function is: #include #include +#include #include #include #include +#include #include -#include -#include /* MMX: mmintrin.h @@ -63,12 +64,12 @@ Searching: The main finding function is: SSE4.2: nmmintrin.h */ #ifdef TIGHTDB_COMPILER_SSE - #include // SSE2 - #include // SSE42 +# include // SSE2 +# include // SSE42 #endif #ifdef TIGHTDB_DEBUG -#include +# include #endif namespace tightdb { @@ -157,12 +158,6 @@ class MemStats { }; #endif -enum ColumnDef { - coldef_Normal, - coldef_InnerNode, ///< Inner node of B-tree - coldef_HasRefs -}; - class ArrayParent { @@ -196,9 +191,15 @@ class Array: public ArrayParent { // void state_init(int action, QueryState *state); // bool match(int action, size_t index, int64_t value, QueryState *state); + enum ColumnDef { + coldef_Normal, + coldef_InnerNode, ///< Inner node of B-tree + coldef_HasRefs + }; + /// Create a new array, and if \a parent and \a ndx_in_parent are /// specified, update the parent to point to this new array. - explicit Array(ColumnDef type=coldef_Normal, ArrayParent* parent=0, size_t ndx_in_parent=0, + explicit Array(ColumnDef type = coldef_Normal, ArrayParent* = 0, size_t ndx_in_parent = 0, Allocator& = Allocator::get_default()); /// Initialize an array wrapper from the specified array. @@ -270,12 +271,12 @@ class Array: public ArrayParent { const Array* GetBlock(size_t ndx, Array& arr, size_t& off, bool use_retval = false) const TIGHTDB_NOEXCEPT; // FIXME: Constness is not propagated to the sub-array int64_t column_get(std::size_t ndx) const TIGHTDB_NOEXCEPT; - const char* string_column_get(std::size_t ndx) const TIGHTDB_NOEXCEPT; + StringData string_column_get(std::size_t ndx) const TIGHTDB_NOEXCEPT; size_t ColumnFind(int64_t target, size_t ref, Array& cache) const; - typedef const char*(*StringGetter)(void*, size_t); // Pre-declare getter function from string index - size_t IndexStringFindFirst(const char* value, void* column, StringGetter get_func) const; - void IndexStringFindAll(Array& result, const char* value, void* column, StringGetter get_func) const; - size_t IndexStringCount(const char* value, void* column, StringGetter get_func) const; + typedef StringData (*StringGetter)(void*, size_t); // Pre-declare getter function from string index + size_t IndexStringFindFirst(StringData value, void* column, StringGetter get_func) const; + void IndexStringFindAll(Array& result, StringData value, void* column, StringGetter get_func) const; + size_t IndexStringCount(StringData value, void* column, StringGetter get_func) const; void SetAllToZero(); void Increment(int64_t value, size_t start=0, size_t end=(size_t)-1); @@ -396,7 +397,7 @@ class Array: public ArrayParent { #ifdef TIGHTDB_DEBUG void Print() const; void Verify() const; - void ToDot(std::ostream& out, const char* title=NULL) const; + void ToDot(std::ostream& out, StringData title = StringData()) const; void Stats(MemStats& stats) const; #endif // TIGHTDB_DEBUG @@ -416,13 +417,16 @@ class Array: public ArrayParent { wtype_Ignore = 2 }; - static bool get_isnode_from_header(const char*) TIGHTDB_NOEXCEPT; + static bool get_isleaf_from_header(const char*) TIGHTDB_NOEXCEPT; static bool get_hasrefs_from_header(const char*) TIGHTDB_NOEXCEPT; static bool get_indexflag_from_header(const char*) TIGHTDB_NOEXCEPT; static WidthType get_wtype_from_header(const char*) TIGHTDB_NOEXCEPT; static int get_width_from_header(const char*) TIGHTDB_NOEXCEPT; static std::size_t get_len_from_header(const char*) TIGHTDB_NOEXCEPT; static std::size_t get_capacity_from_header(const char*) TIGHTDB_NOEXCEPT; + static bool get_isnode_from_header(const char*) TIGHTDB_NOEXCEPT; // DEPRECATED! + + static ColumnDef get_coldef_from_header(const char*) TIGHTDB_NOEXCEPT; static std::size_t get_alloc_size_from_header(const char*) TIGHTDB_NOEXCEPT; @@ -456,29 +460,32 @@ class Array: public ArrayParent { virtual size_t CalcItemCount(size_t bytes, size_t width) const TIGHTDB_NOEXCEPT; virtual WidthType GetWidthType() const { return wtype_Bits; } - bool get_isnode_from_header() const TIGHTDB_NOEXCEPT; + bool get_isleaf_from_header() const TIGHTDB_NOEXCEPT; bool get_hasrefs_from_header() const TIGHTDB_NOEXCEPT; bool get_indexflag_from_header() const TIGHTDB_NOEXCEPT; WidthType get_wtype_from_header() const TIGHTDB_NOEXCEPT; int get_width_from_header() const TIGHTDB_NOEXCEPT; std::size_t get_len_from_header() const TIGHTDB_NOEXCEPT; std::size_t get_capacity_from_header() const TIGHTDB_NOEXCEPT; + bool get_isnode_from_header() const TIGHTDB_NOEXCEPT; // DEPRECATED! - void set_header_isnode(bool value) TIGHTDB_NOEXCEPT; + void set_header_isleaf(bool value) TIGHTDB_NOEXCEPT; void set_header_hasrefs(bool value) TIGHTDB_NOEXCEPT; void set_header_indexflag(bool value) TIGHTDB_NOEXCEPT; void set_header_wtype(WidthType value) TIGHTDB_NOEXCEPT; void set_header_width(int value) TIGHTDB_NOEXCEPT; void set_header_len(std::size_t value) TIGHTDB_NOEXCEPT; void set_header_capacity(std::size_t value) TIGHTDB_NOEXCEPT; + void set_header_isnode(bool value) TIGHTDB_NOEXCEPT; // DEPRECATED! - static void set_header_isnode(bool value, char* header) TIGHTDB_NOEXCEPT; + static void set_header_isleaf(bool value, char* header) TIGHTDB_NOEXCEPT; static void set_header_hasrefs(bool value, char* header) TIGHTDB_NOEXCEPT; static void set_header_indexflag(bool value, char* header) TIGHTDB_NOEXCEPT; static void set_header_wtype(WidthType value, char* header) TIGHTDB_NOEXCEPT; static void set_header_width(int value, char* header) TIGHTDB_NOEXCEPT; static void set_header_len(std::size_t value, char* header) TIGHTDB_NOEXCEPT; static void set_header_capacity(std::size_t value, char* header) TIGHTDB_NOEXCEPT; + static void set_header_isnode(bool value, char* header) TIGHTDB_NOEXCEPT; // DEPRECATED! static void init_header(char* header, bool is_node, bool has_refs, WidthType width_type, int width, std::size_t length, std::size_t capacity) TIGHTDB_NOEXCEPT; @@ -790,10 +797,10 @@ inline bool Array::is_index_node(std::size_t ref, const Allocator& alloc) //------------------------------------------------- -inline bool Array::get_isnode_from_header(const char* header) TIGHTDB_NOEXCEPT +inline bool Array::get_isleaf_from_header(const char* header) TIGHTDB_NOEXCEPT { const uint8_t* h = reinterpret_cast(header); - return (h[0] & 0x80) != 0; + return (h[0] & 0x80) == 0; } inline bool Array::get_hasrefs_from_header(const char* header) TIGHTDB_NOEXCEPT { @@ -825,6 +832,10 @@ inline std::size_t Array::get_capacity_from_header(const char* header) TIGHTDB_N const uint8_t* h = reinterpret_cast(header); return (std::size_t(h[4]) << 16) + (std::size_t(h[5]) << 8) + h[6]; } +inline bool Array::get_isnode_from_header(const char* header) TIGHTDB_NOEXCEPT +{ + return !get_isleaf_from_header(header); +} inline char* Array::get_data_from_header(char* header) TIGHTDB_NOEXCEPT @@ -841,9 +852,9 @@ inline const char* Array::get_data_from_header(const char* header) TIGHTDB_NOEXC } -inline bool Array::get_isnode_from_header() const TIGHTDB_NOEXCEPT +inline bool Array::get_isleaf_from_header() const TIGHTDB_NOEXCEPT { - return get_isnode_from_header(get_header_from_data(m_data)); + return get_isleaf_from_header(get_header_from_data(m_data)); } inline bool Array::get_hasrefs_from_header() const TIGHTDB_NOEXCEPT { @@ -869,12 +880,16 @@ inline std::size_t Array::get_capacity_from_header() const TIGHTDB_NOEXCEPT { return get_capacity_from_header(get_header_from_data(m_data)); } +inline bool Array::get_isnode_from_header() const TIGHTDB_NOEXCEPT +{ + return get_isnode_from_header(get_header_from_data(m_data)); +} -inline void Array::set_header_isnode(bool value, char* header) TIGHTDB_NOEXCEPT +inline void Array::set_header_isleaf(bool value, char* header) TIGHTDB_NOEXCEPT { uint8_t* h = reinterpret_cast(header); - h[0] = (h[0] & ~0x80) | uint8_t(value << 7); + h[0] = (h[0] & ~0x80) | uint8_t(!value << 7); } inline void Array::set_header_hasrefs(bool value, char* header) TIGHTDB_NOEXCEPT @@ -928,10 +943,16 @@ inline void Array::set_header_capacity(std::size_t value, char* header) TIGHTDB_ h[6] = value & 0x000000FF; } +inline void Array::set_header_isnode(bool value, char* header) TIGHTDB_NOEXCEPT +{ + set_header_isleaf(!value, header); +} + -inline void Array::set_header_isnode(bool value) TIGHTDB_NOEXCEPT + +inline void Array::set_header_isleaf(bool value) TIGHTDB_NOEXCEPT { - set_header_isnode(value, get_header_from_data(m_data)); + set_header_isleaf(value, get_header_from_data(m_data)); } inline void Array::set_header_hasrefs(bool value) TIGHTDB_NOEXCEPT { @@ -957,23 +978,19 @@ inline void Array::set_header_capacity(std::size_t value) TIGHTDB_NOEXCEPT { set_header_capacity(value, get_header_from_data(m_data)); } +inline void Array::set_header_isnode(bool value) TIGHTDB_NOEXCEPT +{ + set_header_isnode(value, get_header_from_data(m_data)); +} -inline void Array::init_header(char* header, bool is_node, bool has_refs, WidthType width_type, - int width, std::size_t length, std::size_t capacity) TIGHTDB_NOEXCEPT +inline Array::ColumnDef Array::get_coldef_from_header(const char* header) TIGHTDB_NOEXCEPT { - // Note: Since the header layout contains unallocated bit and/or - // bytes, it is important that we put the entire 8 byte header - // into a well defined state initially. Note also: The C++11 - // standard does not guarantee that int64_t is available on all - // platforms. - *reinterpret_cast(header) = 0; - set_header_isnode(is_node, header); - set_header_hasrefs(has_refs, header); - set_header_wtype(width_type, header); - set_header_width(width, header); - set_header_len(length, header); - set_header_capacity(capacity, header); + if (!get_isleaf_from_header(header)) + return coldef_InnerNode; + if (get_hasrefs_from_header(header)) + return coldef_HasRefs; + return coldef_Normal; } @@ -1009,6 +1026,24 @@ inline std::size_t Array::get_alloc_size_from_header(const char* header) TIGHTDB } +inline void Array::init_header(char* header, bool is_node, bool has_refs, WidthType width_type, + int width, std::size_t length, std::size_t capacity) TIGHTDB_NOEXCEPT +{ + // Note: Since the header layout contains unallocated bit and/or + // bytes, it is important that we put the entire 8 byte header + // into a well defined state initially. Note also: The C++11 + // standard does not guarantee that int64_t is available on all + // platforms. + *reinterpret_cast(header) = 0; + set_header_isnode(is_node, header); + set_header_hasrefs(has_refs, header); + set_header_wtype(width_type, header); + set_header_width(width, header); + set_header_len(length, header); + set_header_capacity(capacity, header); +} + + //------------------------------------------------- template size_t Array::Write(S& out, bool recurse, bool persist) const diff --git a/src/tightdb/array_binary.cpp b/src/tightdb/array_binary.cpp index 60c61eb55c9..6ae4c150568 100644 --- a/src/tightdb/array_binary.cpp +++ b/src/tightdb/array_binary.cpp @@ -36,37 +36,64 @@ ArrayBinary::ArrayBinary(size_t ref, ArrayParent* parent, size_t pndx, Allocator // Creates new array (but invalid, call UpdateRef to init) //ArrayBinary::ArrayBinary(Allocator& alloc) : Array(alloc) {} -void ArrayBinary::add(const char* data, size_t size) +void ArrayBinary::add(BinaryData value) { - TIGHTDB_ASSERT(size == 0 || data); + TIGHTDB_ASSERT(value.size() == 0 || value.data()); - m_blob.add(data, size); - m_offsets.add(m_offsets.is_empty() ? size : m_offsets.back() + size); + m_blob.add(value.data(), value.size()); + m_offsets.add(m_offsets.is_empty() ? value.size() : m_offsets.back() + value.size()); } -void ArrayBinary::Set(size_t ndx, const char* data, size_t size) +void ArrayBinary::set(size_t ndx, BinaryData value) { TIGHTDB_ASSERT(ndx < m_offsets.size()); - TIGHTDB_ASSERT(size == 0 || data); + TIGHTDB_ASSERT(value.size() == 0 || value.data()); const size_t start = ndx ? m_offsets.GetAsSizeT(ndx-1) : 0; const size_t current_end = m_offsets.GetAsSizeT(ndx); - const ssize_t diff = (start + size) - current_end; + const ssize_t diff = (start + value.size()) - current_end; - m_blob.Replace(start, current_end, data, size); + m_blob.replace(start, current_end, value.data(), value.size()); m_offsets.Adjust(ndx, diff); } -void ArrayBinary::Insert(size_t ndx, const char* data, size_t size) +void ArrayBinary::insert(size_t ndx, BinaryData value) { TIGHTDB_ASSERT(ndx <= m_offsets.size()); - TIGHTDB_ASSERT(size == 0 || data); + TIGHTDB_ASSERT(value.size() == 0 || value.data()); const size_t pos = ndx ? m_offsets.GetAsSizeT(ndx-1) : 0; - m_blob.Insert(pos, data, size); - m_offsets.Insert(ndx, pos + size); - m_offsets.Adjust(ndx+1, size); + m_blob.insert(pos, value.data(), value.size()); + m_offsets.Insert(ndx, pos + value.size()); + m_offsets.Adjust(ndx+1, value.size()); +} + +void ArrayBinary::set_string(size_t ndx, StringData value) +{ + TIGHTDB_ASSERT(ndx < m_offsets.size()); + TIGHTDB_ASSERT(value.size() == 0 || value.data()); + + const size_t start = ndx ? m_offsets.GetAsSizeT(ndx-1) : 0; + const size_t current_end = m_offsets.GetAsSizeT(ndx); + const ssize_t diff = (start + value.size() + 1) - current_end; + + bool add_zero_term = true; + m_blob.replace(start, current_end, value.data(), value.size(), add_zero_term); + m_offsets.Adjust(ndx, diff); +} + +void ArrayBinary::insert_string(size_t ndx, StringData value) +{ + TIGHTDB_ASSERT(ndx <= m_offsets.size()); + TIGHTDB_ASSERT(value.size() == 0 || value.data()); + + const size_t pos = ndx ? m_offsets.GetAsSizeT(ndx-1) : 0; + + bool add_zero_term = true; + m_blob.insert(pos, value.data(), value.size(), add_zero_term); + m_offsets.Insert(ndx, pos + value.size() + 1); + m_offsets.Adjust(ndx+1, value.size() + 1); } void ArrayBinary::Delete(size_t ndx) @@ -76,7 +103,7 @@ void ArrayBinary::Delete(size_t ndx) const size_t start = ndx ? m_offsets.GetAsSizeT(ndx-1) : 0; const size_t end = m_offsets.GetAsSizeT(ndx); - m_blob.Delete(start, end); + m_blob.erase(start, end); m_offsets.Delete(ndx); m_offsets.Adjust(ndx, int64_t(start) - end); } @@ -102,7 +129,7 @@ BinaryData ArrayBinary::get_direct(Allocator& alloc, const char* header, size_t pair p = Array::get_two_as_size(header, 0); const char* offsets_header = static_cast(alloc.Translate(p.first)); const char* blob_header = static_cast(alloc.Translate(p.second)); - std::size_t begin, end; + size_t begin, end; if (ndx) { pair p2 = Array::get_two_as_size(offsets_header, ndx-1); begin = p2.first; diff --git a/src/tightdb/array_binary.hpp b/src/tightdb/array_binary.hpp index 602872dcd9a..d69599e76ab 100644 --- a/src/tightdb/array_binary.hpp +++ b/src/tightdb/array_binary.hpp @@ -32,20 +32,22 @@ class ArrayBinary : public Array { Allocator& alloc = Allocator::get_default()); ArrayBinary(size_t ref, ArrayParent* parent, size_t pndx, Allocator& alloc = Allocator::get_default()); - //ArrayBinary(Allocator& alloc); bool is_empty() const TIGHTDB_NOEXCEPT; std::size_t size() const TIGHTDB_NOEXCEPT; BinaryData get(std::size_t ndx) const TIGHTDB_NOEXCEPT; - void add(const char* data, std::size_t size); - void Set(std::size_t ndx, const char* data, std::size_t size); - void Insert(std::size_t ndx, const char* data, std::size_t size); + void add(BinaryData value); + void set(std::size_t ndx, BinaryData value); + void insert(std::size_t ndx, BinaryData value); void Delete(std::size_t ndx); void Resize(std::size_t ndx); void Clear(); + void set_string(std::size_t ndx, StringData value); + void insert_string(std::size_t ndx, StringData value); + static BinaryData column_get(const Array* root, std::size_t ndx) TIGHTDB_NOEXCEPT; static BinaryData get_direct(Allocator&, const char* header, std::size_t ndx) TIGHTDB_NOEXCEPT; @@ -56,9 +58,6 @@ class ArrayBinary : public Array { private: Array m_offsets; ArrayBlob m_blob; - - const char* Get(size_t ndx) const TIGHTDB_NOEXCEPT; // FIXME: Delete - size_t GetLen(size_t ndx) const TIGHTDB_NOEXCEPT; // FIXME: Delete }; @@ -83,7 +82,7 @@ inline BinaryData ArrayBinary::get(std::size_t ndx) const TIGHTDB_NOEXCEPT std::size_t begin = ndx ? m_offsets.GetAsSizeT(ndx-1) : 0; std::size_t end = m_offsets.GetAsSizeT(ndx); - return BinaryData(m_blob.Get(begin), end-begin); + return BinaryData(m_blob.get(begin), end-begin); } inline BinaryData ArrayBinary::column_get(const Array* root, std::size_t ndx) TIGHTDB_NOEXCEPT diff --git a/src/tightdb/array_blob.cpp b/src/tightdb/array_blob.cpp index 62410d8df55..c66f00603bc 100644 --- a/src/tightdb/array_blob.cpp +++ b/src/tightdb/array_blob.cpp @@ -6,7 +6,7 @@ using namespace std; namespace tightdb { -void ArrayBlob::Replace(size_t begin, size_t end, const char* data, size_t size) +void ArrayBlob::replace(size_t begin, size_t end, const char* data, size_t size, bool add_zero_term) { TIGHTDB_ASSERT(begin <= end); TIGHTDB_ASSERT(end <= m_len); @@ -15,64 +15,69 @@ void ArrayBlob::Replace(size_t begin, size_t end, const char* data, size_t size) CopyOnWrite(); // Throws // Reallocate if needed - const size_t gapsize = end - begin; - const size_t newsize = m_len - gapsize + size; + size_t remove_size = end - begin; + size_t add_size = size; + if (add_zero_term) + ++add_size; + size_t new_size = m_len - remove_size + add_size; // also updates header - Alloc(newsize, 1); // Throws + Alloc(new_size, 1); // Throws - char* const base = reinterpret_cast(m_data); - char* const gap_begin = base + begin; + char* base = reinterpret_cast(m_data); + char* modify_begin = base + begin; // Resize previous space to fit new data // (not needed if we append to end) if (begin != m_len) { - const char* const old_begin = base + end; - const char* const old_end = base + m_len; - if (gapsize < size) { // expand gap - char* const new_end = base + newsize; + const char* old_begin = base + end; + const char* old_end = base + m_len; + if (remove_size < add_size) { // expand gap + char* new_end = base + new_size; copy_backward(old_begin, old_end, new_end); } - else if (size < gapsize) { // shrink gap - char* const new_begin = gap_begin + size; + else if (add_size < remove_size) { // shrink gap + char* new_begin = modify_begin + add_size; copy(old_begin, old_end, new_begin); } } // Insert the data - copy(data, data+size, gap_begin); + modify_begin = copy(data, data+size, modify_begin); + if (add_zero_term) + *modify_begin = 0; - m_len = newsize; + m_len = new_size; } #ifdef TIGHTDB_DEBUG -void ArrayBlob::ToDot(std::ostream& out, const char* title) const +void ArrayBlob::ToDot(ostream& out, const char* title) const { const size_t ref = GetRef(); if (title) { - out << "subgraph cluster_" << ref << " {" << std::endl; - out << " label = \"" << title << "\";" << std::endl; - out << " color = white;" << std::endl; + out << "subgraph cluster_" << ref << " {" << endl; + out << " label = \"" << title << "\";" << endl; + out << " color = white;" << endl; } - out << "n" << std::hex << ref << std::dec << "[shape=none,label=<"; - out << "" << std::endl; + out << "n" << hex << ref << dec << "[shape=none,label=<"; + out << "
" << endl; // Header out << "" << std::endl; + out << "0x" << hex << ref << dec << "
"; + out << "" << endl; // Values out << "" << std::endl; + out << "" << endl; - out << "
"; - out << "0x" << std::hex << ref << std::dec << "
"; - out << "
"; out << size() << " bytes"; //TODO: write content - out << "
>];" << std::endl; - if (title) out << "}" << std::endl; + out << ">];" << endl; + if (title) out << "}" << endl; - out << std::endl; + out << endl; } #endif // TIGHTDB_DEBUG diff --git a/src/tightdb/array_blob.hpp b/src/tightdb/array_blob.hpp index 808eb2a0d3e..742d43c6796 100644 --- a/src/tightdb/array_blob.hpp +++ b/src/tightdb/array_blob.hpp @@ -33,12 +33,15 @@ class ArrayBlob : public Array { Allocator& alloc = Allocator::get_default()) TIGHTDB_NOEXCEPT; ArrayBlob(Allocator& alloc) TIGHTDB_NOEXCEPT; - const char* Get(size_t pos) const TIGHTDB_NOEXCEPT; + const char* get(std::size_t pos) const TIGHTDB_NOEXCEPT; - void add(const char* data, size_t size); - void Insert(size_t pos, const char* data, size_t size); - void Replace(size_t begin, size_t end, const char* data, size_t size); - void Delete(size_t begin, size_t end); + static const char* get_from_header(const char* header, std::size_t pos) TIGHTDB_NOEXCEPT; + + void add(const char* data, std::size_t size, bool add_zero_term = false); + void insert(std::size_t pos, const char* data, std::size_t size, bool add_zero_term = false); + void replace(std::size_t begin, std::size_t end, const char* data, std::size_t size, + bool add_zero_term = false); + void erase(size_t begin, size_t end); void Resize(size_t size); void Clear(); @@ -79,35 +82,41 @@ inline ArrayBlob::ArrayBlob(std::size_t ref, const ArrayParent *parent, std::siz // Creates new array (but invalid, call UpdateRef to init) inline ArrayBlob::ArrayBlob(Allocator& alloc) TIGHTDB_NOEXCEPT: Array(alloc) {} -inline const char* ArrayBlob::Get(std::size_t pos) const TIGHTDB_NOEXCEPT +inline const char* ArrayBlob::get(std::size_t pos) const TIGHTDB_NOEXCEPT { return m_data + pos; } -inline void ArrayBlob::add(const char* data, std::size_t len) +inline const char* ArrayBlob::get_from_header(const char* header, std::size_t pos) TIGHTDB_NOEXCEPT +{ + return get_data_from_header(header) + pos; +} + +inline void ArrayBlob::add(const char* data, std::size_t size, bool add_zero_term) { - Replace(m_len, m_len, data, len); + replace(m_len, m_len, data, size, add_zero_term); } -inline void ArrayBlob::Insert(std::size_t pos, const char* data, std::size_t len) +inline void ArrayBlob::insert(std::size_t pos, const char* data, std::size_t size, + bool add_zero_term) { - Replace(pos, pos, data, len); + replace(pos, pos, data, size, add_zero_term); } -inline void ArrayBlob::Delete(std::size_t start, std::size_t end) +inline void ArrayBlob::erase(std::size_t start, std::size_t end) { - Replace(start, end, 0, 0); + replace(start, end, 0, 0); } inline void ArrayBlob::Resize(std::size_t len) { TIGHTDB_ASSERT(len <= m_len); - Replace(len, m_len, 0, 0); + replace(len, m_len, 0, 0); } inline void ArrayBlob::Clear() { - Replace(0, m_len, 0, 0); + replace(0, m_len, 0, 0); } inline const char* ArrayBlob::get_direct(const char* header, std::size_t pos) TIGHTDB_NOEXCEPT diff --git a/src/tightdb/array_string.cpp b/src/tightdb/array_string.cpp index f6d5d9daa7a..f253e4698a7 100644 --- a/src/tightdb/array_string.cpp +++ b/src/tightdb/array_string.cpp @@ -11,6 +11,8 @@ using namespace std; namespace { +const int max_width = 64; + // When len = 0 returns 0 // When len = 1 returns 4 // When 2 <= len < 256, returns 2**ceil(log2(len+1)). @@ -31,144 +33,233 @@ size_t round_up(size_t len) namespace tightdb { -void ArrayString::Set(size_t ndx, const char* data, size_t size) +void ArrayString::set(size_t ndx, StringData value) { TIGHTDB_ASSERT(ndx < m_len); - TIGHTDB_ASSERT(data); - TIGHTDB_ASSERT(size < 64); // otherwise we have to use another column type + TIGHTDB_ASSERT(value.size() < size_t(max_width)); // otherwise we have to use another column type // Check if we need to copy before modifying CopyOnWrite(); // Throws - // Calc min column width (incl trailing zero-byte) - size_t min_width = ::round_up(size); + // Make room for the new value plus a zero-termination + if (m_width <= value.size()) { + if (value.size() == 0 && m_width == 0) + return; + + TIGHTDB_ASSERT(0 < value.size()); + + // Calc min column width + size_t new_width = ::round_up(value.size()); + + TIGHTDB_ASSERT(value.size() < new_width); - // Make room for the new value - if (m_width < min_width) { // FIXME: Should we try to avoid double copying when realloc fails to preserve the address? - Alloc(m_len, min_width); // Throws + Alloc(m_len, new_width); // Throws + + char* base = m_data; + char* new_end = base + m_len*new_width; // Expand the old values in reverse order - char* const base = reinterpret_cast(m_data); - const char* old_end = base + m_len*m_width; - char* new_end = base + m_len*min_width; - while (new_end != base) { - { - char* const new_begin = new_end - (min_width-m_width); - fill(new_begin, new_end, 0); // Extra zero-padding is needed - new_end = new_begin; + if (0 < m_width) { + const char* old_end = base + m_len*m_width; + while (new_end != base) { +// FIXME: The following line is temporarily commented out, but will +// soon be reinstated. See https://github.com/Tightdb/tightdb/pull/84 +// *--new_end = char(*--old_end + (new_width-m_width)); + { + char* new_begin = new_end - (new_width-m_width); + fill(new_begin, new_end, 0); // Extend zero padding + new_end = new_begin; + } + { +// FIXME: The following line is a temporary fix, and will soon be +// replaced by the commented line that follows it. See +// https://github.com/Tightdb/tightdb/pull/84 + const char* old_begin = old_end - m_width; +// const char* old_begin = old_end - (m_width-1); + new_end = copy_backward(old_begin, old_end, new_end); + old_end = old_begin; + } } - { - const char* const old_begin = old_end - m_width; - new_end = copy_backward(old_begin, old_end, new_end); - old_end = old_begin; + } + else { + while (new_end != base) { +// FIXME: The following line is temporarily commented out, but will +// soon be reinstated. See https://github.com/Tightdb/tightdb/pull/84 +// *--new_end = char(new_width-1); + { +// FIXME: The following line is a temporary fix, and will soon be +// replaced by the commented line that follows it. See +// https://github.com/Tightdb/tightdb/pull/84 + char* new_begin = new_end - new_width; +// char* new_begin = new_end - (new_width-1); + fill(new_begin, new_end, 0); // Fill with zero bytes + new_end = new_begin; + } } } - m_width = min_width; - } - // Set the value - char* begin = reinterpret_cast(m_data) + (ndx * m_width); - char* const end = begin + m_width; - begin = copy(data, data+size, begin); - fill(begin, end, 0); // Pad with zeroes -} - -// FIXME: Should be moved to header -void ArrayString::add() -{ - Insert(m_len, "", 0); // Throws -} + m_width = new_width; + } -// FIXME: Should be moved to header -void ArrayString::add(const char* value) -{ - Insert(m_len, value, strlen(value)); // Throws -} + TIGHTDB_ASSERT(0 < m_width); -// FIXME: Should be moved to header -void ArrayString::Insert(size_t ndx, const char* value) -{ - Insert(ndx, value, strlen(value)); // Throws + // Set the value + char* begin = m_data + (ndx * m_width); +// FIXME: The following line is a temporary fix, and will soon be +// replaced by the commented line that follows it. See +// https://github.com/Tightdb/tightdb/pull/84 + char* end = begin + m_width; +// char* end = begin + (m_width-1); + begin = copy(value.data(), value.data()+value.size(), begin); + fill(begin, end, 0); // Pad with zero bytes +// FIXME: The following four lines are temporarily commented out, but +// will soon be reinstated. See +// https://github.com/Tightdb/tightdb/pull/84 +// TIGHTDB_STATIC_ASSERT(max_width <= 128, "Padding size must fit in 7-bits"); +// TIGHTDB_ASSERT(end - begin < max_width); +// int pad_size = int(end - begin); +// *end = char(pad_size); } - -void ArrayString::Insert(size_t ndx, const char* data, size_t size) +void ArrayString::insert(size_t ndx, StringData value) { TIGHTDB_ASSERT(ndx <= m_len); - TIGHTDB_ASSERT(data); - TIGHTDB_ASSERT(size < 64); // otherwise we have to use another column type + TIGHTDB_ASSERT(value.size() < size_t(max_width)); // otherwise we have to use another column type // Check if we need to copy before modifying CopyOnWrite(); // Throws // Calc min column width (incl trailing zero-byte) - size_t new_width = max(m_width, ::round_up(size)); + size_t new_width = max(m_width, ::round_up(value.size())); // Make room for the new value Alloc(m_len+1, new_width); // Throws - char* const base = reinterpret_cast(m_data); - const char* old_end = base + m_len*m_width; - char* new_end = base + m_len*new_width + new_width; - - // Move values beyond insertion point (may expand) - if (ndx != m_len) { - if (TIGHTDB_UNLIKELY(m_width < new_width)) { - // Expand the old values - char* const new_begin = base + ndx*new_width + new_width; - do { - { - char* const new_begin2 = new_end - (new_width-m_width); - fill(new_begin2, new_end, 0); // Extra zero-padding is needed - new_end = new_begin2; + if (0 < value.size() || 0 < m_width) { + char* base = m_data; + const char* old_end = base + m_len*m_width; + char* new_end = base + m_len*new_width + new_width; + + // Move values after insertion point (may expand) + if (ndx != m_len) { + if (TIGHTDB_UNLIKELY(m_width < new_width)) { + char* const new_begin = base + ndx*new_width + new_width; + if (0 < m_width) { + // Expand the old values + do { +// FIXME: The following line is temporarily commented out, but will +// soon be reinstated. See https://github.com/Tightdb/tightdb/pull/84 +// *--new_end = char(*--old_end + (new_width-m_width)); + { + char* new_begin2 = new_end - (new_width-m_width); + fill(new_begin2, new_end, 0); // Extend zero padding + new_end = new_begin2; + } + { +// FIXME: The following line is a temporary fix, and will soon be +// replaced by the commented line that follows it. See +// https://github.com/Tightdb/tightdb/pull/84 + const char* old_begin = old_end - m_width; +// const char* old_begin = old_end - (m_width-1); + new_end = copy_backward(old_begin, old_end, new_end); + old_end = old_begin; + } + } + while (new_end != new_begin); } - { - const char* const old_begin = old_end - m_width; - new_end = copy_backward(old_begin, old_end, new_end); - old_end = old_begin; + else { + do { +// FIXME: The following line is temporarily commented out, but will +// soon be reinstated. See https://github.com/Tightdb/tightdb/pull/84 +// *--new_end = char(new_width-1); + { +// FIXME: The following line is a temporary fix, and will soon be +// replaced by the commented line that follows it. See +// https://github.com/Tightdb/tightdb/pull/84 + char* new_begin2 = new_end - new_width; +// char* new_begin2 = new_end - (new_width-1); + fill(new_begin2, new_end, 0); // Fill with zero bytes + new_end = new_begin2; + } + } + while (new_end != new_begin); } } - while (new_end != new_begin); - } - else { - // when no expansion just move the following entries forward - const char* const old_begin = base + ndx*m_width; - new_end = copy_backward(old_begin, old_end, new_end); - old_end = old_begin; + else { + // when no expansion just move the following entries forward + const char* old_begin = base + ndx*m_width; + new_end = copy_backward(old_begin, old_end, new_end); + old_end = old_begin; + } } - } - // Set the value - { - char* const new_begin = new_end - new_width; - char* const pad_begin = copy(data, data+size, new_begin); - fill(pad_begin, new_end, 0); // Pad with zeroes - new_end = new_begin; - } + // Set the value + { + char* new_begin = new_end - new_width; + char* pad_begin = copy(value.data(), value.data()+value.size(), new_begin); +// FIXME: The following line is temporarily commented out, but will +// soon be reinstated. See https://github.com/Tightdb/tightdb/pull/84 +// --new_end; + fill(pad_begin, new_end, 0); // Pad with zero bytes +// FIXME: The following four lines are temporarily commented out, but +// will soon be reinstated. See +// https://github.com/Tightdb/tightdb/pull/84 +// TIGHTDB_STATIC_ASSERT(max_width <= 128, "Padding size must fit in 7-bits"); +// TIGHTDB_ASSERT(new_end - pad_begin < max_width); +// int pad_size = int(new_end - pad_begin); +// *new_end = char(pad_size); + new_end = new_begin; + } - // Expand values before insertion point - if (TIGHTDB_UNLIKELY(m_width < new_width)) { - while (new_end != base) { - { - char* const new_begin = new_end - (new_width-m_width); - fill(new_begin, new_end, 0); // Extra zero-padding is needed - new_end = new_begin; + // Expand values before insertion point + if (TIGHTDB_UNLIKELY(m_width < new_width)) { + if (0 < m_width) { + while (new_end != base) { +// FIXME: The following line is temporarily commented out, but will +// soon be reinstated. See https://github.com/Tightdb/tightdb/pull/84 +// *--new_end = char(*--old_end + (new_width-m_width)); + { + char* new_begin = new_end - (new_width-m_width); + fill(new_begin, new_end, 0); // Extend zero padding + new_end = new_begin; + } + { +// FIXME: The following line is a temporary fix, and will soon be +// replaced by the commented line that follows it. See +// https://github.com/Tightdb/tightdb/pull/84 + const char* old_begin = old_end - m_width; +// const char* old_begin = old_end - (m_width-1); + new_end = copy_backward(old_begin, old_end, new_end); + old_end = old_begin; + } + } } - { - const char* const old_begin = old_end - m_width; - new_end = copy_backward(old_begin, old_end, new_end); - old_end = old_begin; + else { + while (new_end != base) { +// FIXME: The following line is temporarily commented out, but will +// soon be reinstated. See https://github.com/Tightdb/tightdb/pull/84 +// *--new_end = char(new_width-1); + { +// FIXME: The following line is a temporary fix, and will soon be +// replaced by the commented line that follows it. See +// https://github.com/Tightdb/tightdb/pull/84 + char* new_begin = new_end - new_width; +// char* new_begin = new_end - (new_width-1); + fill(new_begin, new_end, 0); // Fill with zero bytes + new_end = new_begin; + } + } } + m_width = new_width; } } - m_width = new_width; ++m_len; } -void ArrayString::Delete(size_t ndx) +void ArrayString::erase(size_t ndx) { TIGHTDB_ASSERT(ndx < m_len); @@ -177,9 +268,9 @@ void ArrayString::Delete(size_t ndx) // move data backwards after deletion if (ndx < m_len-1) { - char* const new_begin = reinterpret_cast(m_data) + ndx*m_width; + char* const new_begin = m_data + ndx*m_width; char* const old_begin = new_begin + m_width; - char* const old_end = reinterpret_cast(m_data) + m_len*m_width; + char* const old_end = m_data + m_len*m_width; copy(old_begin, old_end, new_begin); } @@ -191,7 +282,8 @@ void ArrayString::Delete(size_t ndx) size_t ArrayString::CalcByteLen(size_t count, size_t width) const { - // FIXME: This arithemtic could overflow. Consider using + // FIXME: This arithemtic could overflow. Consider using one of + // the functions in return 8 + (count * width); } @@ -203,14 +295,13 @@ size_t ArrayString::CalcItemCount(size_t bytes, size_t width) const TIGHTDB_NOEX return bytes_without_header / width; } -size_t ArrayString::count(const char* value, size_t start, size_t end) const +size_t ArrayString::count(StringData value, size_t begin, size_t end) const { - const size_t len = strlen(value); size_t count = 0; - size_t lastmatch = start - 1; + size_t lastmatch = begin - 1; for (;;) { - lastmatch = FindWithLen(value, len, lastmatch+1, end); + lastmatch = find_first(value, lastmatch+1, end); if (lastmatch != not_found) ++count; else break; @@ -219,47 +310,66 @@ size_t ArrayString::count(const char* value, size_t start, size_t end) const return count; } -size_t ArrayString::find_first(const char* value, size_t start, size_t end) const +size_t ArrayString::find_first(StringData value, size_t begin, size_t end) const { - TIGHTDB_ASSERT(value); - return FindWithLen(value, strlen(value), start, end); -} + if (end == size_t(-1)) end = m_len; + TIGHTDB_ASSERT(begin <= m_len && end <= m_len && begin <= end); -void ArrayString::find_all(Array& result, const char* value, size_t add_offset, size_t start, size_t end) -{ - TIGHTDB_ASSERT(value); + // A string can never be wider than the column width + if (m_width <= value.size()) + return size_t(-1); - const size_t len = strlen(value); + if (m_width == 0) { + return value.size() == 0 && begin < end ? begin : -1; + } - size_t first = start - 1; - for (;;) { - first = FindWithLen(value, len, first + 1, end); - if (first != (size_t)-1) - result.add(first + add_offset); - else break; + if (value.size() == 0) { +// FIXME: The following four lines are a temporary fix, and will soon +// be replaced by the commented block that follows them. See +// https://github.com/Tightdb/tightdb/pull/84 + const char* data = m_data; + for (size_t i = begin; i != end; ++i) { + if (TIGHTDB_UNLIKELY(data[i * m_width] == 0)) return i; + } +// const char* data = m_data + (m_width-1); +// for (size_t i = begin; i != end; ++i) { +// size_t size = (m_width-1) - data[i * m_width]; +// if (TIGHTDB_UNLIKELY(size == 0)) return i; +// } } + else { + for (size_t i = begin; i != end; ++i) { + const char* data = m_data + (i * m_width); + size_t j = 0; + for (;;) { + if (TIGHTDB_LIKELY(data[j] != value[j])) break; + ++j; + if (TIGHTDB_UNLIKELY(j == value.size())) { +// FIXME: The following line is a temporary fix, and will soon be +// replaced by the commented block that follows it. See +// https://github.com/Tightdb/tightdb/pull/84 + if (TIGHTDB_LIKELY(data[j] == 0)) return i; +// size_t size = (m_width-1) - data[m_width-1]; +// if (TIGHTDB_LIKELY(size == value.size())) return i; + break; + } + } + } + } + + return size_t(-1); // not found } -size_t ArrayString::FindWithLen(const char* value, size_t len, size_t start, size_t end) const +void ArrayString::find_all(Array& result, StringData value, size_t add_offset, + size_t begin, size_t end) { - TIGHTDB_ASSERT(value); - - if (end == (size_t)-1) end = m_len; - if (start == end) return (size_t)-1; - TIGHTDB_ASSERT(start < m_len && end <= m_len && start < end); - if (m_len == 0) return (size_t)-1; // empty list - if (len >= m_width) return (size_t)-1; // A string can never be wider than the column width - - // todo, ensure behaves as expected when m_width = 0 - - for (size_t i = start; i < end; ++i) { - if (value[0] == (char)m_data[i * m_width] && value[len] == (char)m_data[i * m_width + len]) { - const char* const v = (const char *)m_data + i * m_width; - if (strncmp(value, v, len) == 0) return i; - } + size_t first = begin - 1; + for (;;) { + first = find_first(value, first + 1, end); + if (first != size_t(-1)) + result.add(first + add_offset); + else break; } - - return (size_t)-1; // not found } bool ArrayString::Compare(const ArrayString& c) const @@ -267,7 +377,7 @@ bool ArrayString::Compare(const ArrayString& c) const if (c.size() != size()) return false; for (size_t i = 0; i < size(); ++i) { - if (strcmp(Get(i), c.Get(i)) != 0) return false; + if (get(i) != c.get(i)) return false; } return true; @@ -282,9 +392,8 @@ void ArrayString::StringStats() const size_t longest = 0; for (size_t i = 0; i < m_len; ++i) { - const char* str = Get(i); - const size_t len = strlen(str)+1; - + StringData str = get(i); + const size_t len = str.size() + 1; total += len; if (len > longest) longest = len; } @@ -306,25 +415,25 @@ void ArrayString::StringStats() const /* void ArrayString::ToDot(FILE* f) const { - const size_t ref = GetRef(); + const size_t ref = getRef(); fprintf(f, "n%zx [label=\"", ref); for (size_t i = 0; i < m_len; ++i) { if (i > 0) fprintf(f, " | "); - fprintf(f, "%s", Get(i)); + fprintf(f, "%s", get_c_str(i)); } fprintf(f, "\"];\n"); } */ -void ArrayString::ToDot(ostream& out, const char* title) const +void ArrayString::ToDot(ostream& out, StringData title) const { const size_t ref = GetRef(); - if (title) { + if (title.size() > 0) { out << "subgraph cluster_" << ref << " {" << endl; out << " label = \"" << title << "\";" << endl; out << " color = white;" << endl; @@ -338,11 +447,12 @@ void ArrayString::ToDot(ostream& out, const char* title) const out << "0x" << hex << ref << dec << "" << endl; for (size_t i = 0; i < m_len; ++i) { - out << "\"" << Get(i) << "\"" << endl; + out << "\"" << get(i) << "\"" << endl; } out << ">];" << endl; - if (title) out << "}" << endl; + if (title.size() > 0) + out << "}" << endl; } #endif // TIGHTDB_DEBUG diff --git a/src/tightdb/array_string.hpp b/src/tightdb/array_string.hpp index d1de935f335..fc9cd850cab 100644 --- a/src/tightdb/array_string.hpp +++ b/src/tightdb/array_string.hpp @@ -20,36 +20,37 @@ #ifndef TIGHTDB_ARRAY_STRING_HPP #define TIGHTDB_ARRAY_STRING_HPP -#include +#include #include namespace tightdb { -class ArrayString : public Array { +class ArrayString: public Array { public: - ArrayString(ArrayParent *parent=NULL, size_t pndx=0, - Allocator& alloc = Allocator::get_default()); - ArrayString(size_t ref, const ArrayParent *parent, size_t pndx, - Allocator& alloc = Allocator::get_default()); - ArrayString(Allocator& alloc); + ArrayString(ArrayParent* = 0, std::size_t ndx_in_parent = 0, + Allocator& = Allocator::get_default()); + ArrayString(size_t ref, const ArrayParent*, std::size_t ndx_in_parent, + Allocator& = Allocator::get_default()); + ArrayString(Allocator&); - const char* Get(size_t ndx) const TIGHTDB_NOEXCEPT; + StringData get(std::size_t ndx) const TIGHTDB_NOEXCEPT; void add(); - void add(const char* value); - void Set(size_t ndx, const char* c_str); - void Set(size_t ndx, const char* data, size_t size); - void Insert(size_t ndx, const char* c_str); - void Insert(size_t ndx, const char* data, size_t size); - void Delete(size_t ndx); + void add(StringData value); + void set(std::size_t ndx, StringData value); + void insert(std::size_t ndx, StringData value); + void erase(std::size_t ndx); - size_t count(const char* value, size_t start=0, size_t end=-1) const; - size_t find_first(const char* value, size_t start=0 , size_t end=-1) const; - void find_all(Array& result, const char* value, size_t add_offset = 0, size_t start = 0, size_t end = -1); + size_t count(StringData value, std::size_t begin = 0, std::size_t end = -1) const; + size_t find_first(StringData value, std::size_t begin = 0 , std::size_t end = -1) const; + void find_all(Array& result, StringData value, std::size_t add_offset = 0, + std::size_t begin = 0, std::size_t end = -1); + + static StringData get_from_header(const char* header, std::size_t ndx) TIGHTDB_NOEXCEPT; /// Construct an empty string array and return just the reference /// to the underlying memory. - static size_t create_empty_string_array(Allocator&); + static std::size_t create_empty_string_array(Allocator&); /// Compare two string arrays for equality. bool Compare(const ArrayString&) const; @@ -57,11 +58,10 @@ class ArrayString : public Array { #ifdef TIGHTDB_DEBUG void StringStats() const; //void ToDot(FILE* f) const; - void ToDot(std::ostream& out, const char* title=NULL) const; + void ToDot(std::ostream& out, StringData title = StringData()) const; #endif // TIGHTDB_DEBUG private: - size_t FindWithLen(const char* value, size_t len, size_t start , size_t end) const; size_t CalcByteLen(size_t count, size_t width) const TIGHTDB_OVERRIDE; size_t CalcItemCount(size_t bytes, size_t width) const TIGHTDB_NOEXCEPT TIGHTDB_OVERRIDE; WidthType GetWidthType() const TIGHTDB_OVERRIDE { return wtype_Multiply; } @@ -73,22 +73,22 @@ class ArrayString : public Array { // Implementation: -inline size_t ArrayString::create_empty_string_array(Allocator& alloc) +inline std::size_t ArrayString::create_empty_string_array(Allocator& alloc) { return create_empty_array(coldef_Normal, wtype_Multiply, alloc); // Throws } -inline ArrayString::ArrayString(ArrayParent *parent, size_t ndx_in_parent, +inline ArrayString::ArrayString(ArrayParent *parent, std::size_t ndx_in_parent, Allocator& alloc): Array(alloc) { - const size_t ref = create_empty_string_array(alloc); // Throws + std::size_t ref = create_empty_string_array(alloc); // Throws init_from_ref(ref); SetParent(parent, ndx_in_parent); update_ref_in_parent(); } -inline ArrayString::ArrayString(size_t ref, const ArrayParent *parent, size_t ndx_in_parent, - Allocator& alloc): Array(alloc) +inline ArrayString::ArrayString(std::size_t ref, const ArrayParent *parent, + std::size_t ndx_in_parent, Allocator& alloc): Array(alloc) { // Manually create array as doing it in initializer list // will not be able to call correct virtual functions @@ -99,20 +99,41 @@ inline ArrayString::ArrayString(size_t ref, const ArrayParent *parent, size_t nd // Creates new array (but invalid, call UpdateRef to init) inline ArrayString::ArrayString(Allocator& alloc): Array(alloc) {} -inline const char* ArrayString::Get(std::size_t ndx) const TIGHTDB_NOEXCEPT +inline StringData ArrayString::get_from_header(const char* header, std::size_t ndx) TIGHTDB_NOEXCEPT { - TIGHTDB_ASSERT(ndx < m_len); - - if (m_width == 0) return ""; - else return reinterpret_cast(m_data) + (ndx * m_width); + TIGHTDB_ASSERT(ndx < get_len_from_header(header)); + std::size_t width = get_width_from_header(header); + if (width == 0) return StringData("", 0); + const char* data = get_data_from_header(header) + (ndx * width); +// FIXME: The following line is a temporary fix, and will soon be +// replaced by the commented line that follows it. See +// https://github.com/Tightdb/tightdb/pull/84 + std::size_t size = std::char_traits::length(data); +// std::size_t size = (width-1) - data[width-1]; + return StringData(data, size); } -inline void ArrayString::Set(std::size_t ndx, const char* value) +inline StringData ArrayString::get(std::size_t ndx) const TIGHTDB_NOEXCEPT { TIGHTDB_ASSERT(ndx < m_len); - TIGHTDB_ASSERT(value); + if (m_width == 0) return StringData("", 0); + const char* data = m_data + (ndx * m_width); +// FIXME: The following line is a temporary fix, and will soon be +// replaced by the commented line that follows it. See +// https://github.com/Tightdb/tightdb/pull/84 + std::size_t size = std::char_traits::length(data); +// std::size_t size = (m_width-1) - data[m_width-1]; + return StringData(data, size); +} - Set(ndx, value, std::strlen(value)); // Throws +inline void ArrayString::add(StringData value) +{ + insert(m_len, value); // Throws +} + +inline void ArrayString::add() +{ + add(StringData()); // Throws } diff --git a/src/tightdb/array_string_long.cpp b/src/tightdb/array_string_long.cpp index 11533eed218..299c5b2264f 100644 --- a/src/tightdb/array_string_long.cpp +++ b/src/tightdb/array_string_long.cpp @@ -36,68 +36,51 @@ ArrayStringLong::ArrayStringLong(size_t ref, ArrayParent* parent, size_t pndx, A // Creates new array (but invalid, call UpdateRef to init) //ArrayStringLong::ArrayStringLong(Allocator& alloc) : Array(alloc) {} -void ArrayStringLong::add(const char* value) +void ArrayStringLong::add(StringData value) { - add(value, strlen(value)); + bool add_zero_term = true; + m_blob.add(value.data(), value.size(), add_zero_term); + size_t end = value.size() + 1; + if (!m_offsets.is_empty()) end += m_offsets.back(); + m_offsets.add(end); } -void ArrayStringLong::add(const char* value, size_t len) -{ - TIGHTDB_ASSERT(value); - - len += 1; // include trailing null byte - m_blob.add(value, len); - m_offsets.add(m_offsets.is_empty() ? len : m_offsets.back() + len); -} - -void ArrayStringLong::Set(size_t ndx, const char* value) -{ - Set(ndx, value, strlen(value)); -} - -void ArrayStringLong::Set(size_t ndx, const char* value, size_t len) +void ArrayStringLong::set(size_t ndx, StringData value) { TIGHTDB_ASSERT(ndx < m_offsets.size()); - TIGHTDB_ASSERT(value); - - const size_t start = ndx ? (size_t)m_offsets.Get(ndx-1) : 0; - const size_t current_end = (size_t)m_offsets.Get(ndx); - len += 1; // include trailing null byte - const int64_t diff = int64_t(start + len) - int64_t(current_end); + size_t begin = 0 < ndx ? m_offsets.GetAsSizeT(ndx-1) : 0; + size_t end = m_offsets.GetAsSizeT(ndx); + bool add_zero_term = true; + m_blob.replace(begin, end, value.data(), value.size(), add_zero_term); - m_blob.Replace(start, current_end, value, len); + size_t new_end = begin + value.size() + 1; + int64_t diff = int64_t(new_end) - int64_t(end); m_offsets.Adjust(ndx, diff); } -void ArrayStringLong::Insert(size_t ndx, const char* value) -{ - Insert(ndx, value, strlen(value)); -} - -void ArrayStringLong::Insert(size_t ndx, const char* value, size_t len) +void ArrayStringLong::insert(size_t ndx, StringData value) { TIGHTDB_ASSERT(ndx <= m_offsets.size()); - TIGHTDB_ASSERT(value); - const size_t pos = ndx ? (size_t)m_offsets.Get(ndx-1) : 0; - len += 1; // include trailing null byte + size_t pos = 0 < ndx ? m_offsets.GetAsSizeT(ndx-1) : 0; + bool add_zero_term = true; + m_blob.insert(pos, value.data(), value.size(), add_zero_term); - m_blob.Insert(pos, value, len); - m_offsets.Insert(ndx, pos + len); - m_offsets.Adjust(ndx+1, len); + m_offsets.Insert(ndx, pos + value.size() + 1); + m_offsets.Adjust(ndx+1, value.size() + 1); } -void ArrayStringLong::Delete(size_t ndx) +void ArrayStringLong::erase(size_t ndx) { TIGHTDB_ASSERT(ndx < m_offsets.size()); - const size_t start = ndx ? (size_t)m_offsets.Get(ndx-1) : 0; - const size_t end = (size_t)m_offsets.Get(ndx); + size_t begin = 0 < ndx ? m_offsets.GetAsSizeT(ndx-1) : 0; + size_t end = m_offsets.GetAsSizeT(ndx); - m_blob.Delete(start, end); + m_blob.erase(begin, end); m_offsets.Delete(ndx); - m_offsets.Adjust(ndx, (int64_t)start - end); + m_offsets.Adjust(ndx, int64_t(begin) - int64_t(end)); } void ArrayStringLong::Resize(size_t ndx) @@ -116,14 +99,13 @@ void ArrayStringLong::Clear() m_offsets.Clear(); } -size_t ArrayStringLong::count(const char* value, size_t start, size_t end) const +size_t ArrayStringLong::count(StringData value, size_t begin, size_t end) const { - const size_t len = strlen(value); size_t count = 0; - size_t lastmatch = start - 1; + size_t lastmatch = begin - 1; for (;;) { - lastmatch = FindWithLen(value, len, lastmatch+1, end); + lastmatch = find_first(value, lastmatch+1, end); if (lastmatch != not_found) ++count; else break; @@ -132,60 +114,45 @@ size_t ArrayStringLong::count(const char* value, size_t start, size_t end) const return count; } -size_t ArrayStringLong::find_first(const char* value, size_t start, size_t end) const +size_t ArrayStringLong::find_first(StringData value, size_t begin, size_t end) const { - TIGHTDB_ASSERT(value); - return FindWithLen(value, strlen(value), start, end); -} + const size_t n = m_offsets.size(); + if (end == size_t(-1)) end = n; + TIGHTDB_ASSERT(begin <= n && end <= n && begin <= end); -void ArrayStringLong::find_all(Array& result, const char* value, size_t add_offset, - size_t start, size_t end) const -{ - TIGHTDB_ASSERT(value); + size_t begin2 = 0 < begin ? m_offsets.GetAsSizeT(begin - 1) : 0; + for (size_t i=begin; i - friend std::basic_ostream& operator<<(std::basic_ostream&, const BinaryData&); + BinaryData() TIGHTDB_NOEXCEPT: m_data(0), m_size(0) {} + BinaryData(const char* data, std::size_t size) TIGHTDB_NOEXCEPT: m_data(data), m_size(size) {} + template explicit BinaryData(const char (&data)[N]): m_data(data), m_size(N) {} + + char operator[](std::size_t i) const TIGHTDB_NOEXCEPT { return m_data[i]; } + + const char* data() const TIGHTDB_NOEXCEPT { return m_data; } + std::size_t size() const TIGHTDB_NOEXCEPT { return m_size; } + + friend bool operator==(const BinaryData&, const BinaryData&) TIGHTDB_NOEXCEPT; + friend bool operator!=(const BinaryData&, const BinaryData&) TIGHTDB_NOEXCEPT; + + /// Trivial bytewise lexicographical comparison. + friend bool operator<(const BinaryData&, const BinaryData&) TIGHTDB_NOEXCEPT; + + bool begins_with(BinaryData) const TIGHTDB_NOEXCEPT; + bool ends_with(BinaryData) const TIGHTDB_NOEXCEPT; + bool contains(BinaryData) const TIGHTDB_NOEXCEPT; + + template + friend std::basic_ostream& operator<<(std::basic_ostream&, const BinaryData&); + +private: + const char* m_data; + std::size_t m_size; }; + // Implementation: -template -inline std::basic_ostream& operator<<(std::basic_ostream& out, const BinaryData& d) +inline bool operator==(const BinaryData& a, const BinaryData& b) TIGHTDB_NOEXCEPT +{ + return a.m_size == b.m_size && std::equal(a.m_data, a.m_data + a.m_size, b.m_data); +} + +inline bool operator!=(const BinaryData& a, const BinaryData& b) TIGHTDB_NOEXCEPT +{ + return a.m_size != b.m_size || !std::equal(a.m_data, a.m_data + a.m_size, b.m_data); +} + +inline bool operator<(const BinaryData& a, const BinaryData& b) TIGHTDB_NOEXCEPT +{ + return std::lexicographical_compare(a.m_data, a.m_data + a.m_size, + b.m_data, b.m_data + b.m_size); +} + +inline bool BinaryData::begins_with(BinaryData d) const TIGHTDB_NOEXCEPT +{ + return d.m_size <= m_size && std::equal(m_data, m_data + d.m_size, d.m_data); +} + +inline bool BinaryData::ends_with(BinaryData d) const TIGHTDB_NOEXCEPT +{ + return d.m_size <= m_size && std::equal(m_data + m_size - d.m_size, m_data + m_size, d.m_data); +} + +inline bool BinaryData::contains(BinaryData d) const TIGHTDB_NOEXCEPT +{ + return std::search(m_data, m_data + m_size, d.m_data, d.m_data + d.m_size) != m_data + m_size; +} + +template +inline std::basic_ostream& operator<<(std::basic_ostream& out, const BinaryData& d) { - out << "BinaryData("<(d.pointer)<<", "<(d.m_data)<<", "<GetAllocator()); - const Array refs(coldef_HasRefs, 0, 0, m_array->GetAllocator()); + const Array offsets(Array::coldef_Normal, 0, 0, m_array->GetAllocator()); + const Array refs(Array::coldef_HasRefs, 0, 0, m_array->GetAllocator()); m_array->add(offsets.GetRef()); m_array->add(refs.GetRef()); } @@ -353,7 +354,7 @@ void Column::UpdateParentNdx(int diff) // Used by column b-tree code to ensure all leaf having same type void Column::SetHasRefs() { - m_array->SetType(coldef_HasRefs); + m_array->SetType(Array::coldef_HasRefs); } /* @@ -378,12 +379,12 @@ void Column::Clear() { m_array->Clear(); if (m_array->IsNode()) - m_array->SetType(coldef_Normal); + m_array->SetType(Array::coldef_Normal); } -void Column::Set(size_t ndx, int64_t value) +void Column::set(size_t ndx, int64_t value) { - const int64_t oldVal = m_index ? Get(ndx) : 0; // cache oldval for index + const int64_t oldVal = m_index ? get(ndx) : 0; // cache oldval for index TreeSet(ndx, value); @@ -393,10 +394,10 @@ void Column::Set(size_t ndx, int64_t value) void Column::add(int64_t value) { - Insert(Size(), value); + insert(Size(), value); } -void Column::Insert(size_t ndx, int64_t value) +void Column::insert(size_t ndx, int64_t value) { TIGHTDB_ASSERT(ndx <= Size()); @@ -479,7 +480,7 @@ void Column::sort(size_t start, size_t end) // Todo, this is a bit slow. Add bulk insert or the like to Column const size_t count = sorted->size(); for (size_t t = 0; t < count; ++t) { - Set(t, sorted->Get(t)); + set(t, sorted->Get(t)); } sorted->Destroy(); @@ -548,7 +549,7 @@ void ColumnBase::NodeUpdateOffsets(size_t ndx) Array refs = NodeGetRefs(); TIGHTDB_ASSERT(ndx < offsets.size()); - const int64_t newSize = GetRefSize((size_t)refs.Get(ndx)); + const int64_t newSize = GetRefSize(refs.GetAsRef(ndx)); const int64_t oldSize = offsets.Get(ndx) - (ndx ? offsets.Get(ndx-1) : 0); const int64_t diff = newSize - oldSize; @@ -573,11 +574,11 @@ void ColumnBase::NodeAddKey(size_t ref) refs.add(ref); } -void Column::Delete(size_t ndx) +void Column::erase(size_t ndx) { TIGHTDB_ASSERT(ndx < Size()); - const int64_t oldVal = m_index ? Get(ndx) : 0; // cache oldval for index + const int64_t oldVal = m_index ? get(ndx) : 0; // cache oldval for index TreeDelete(ndx); @@ -595,7 +596,7 @@ void Column::Delete(size_t ndx) // Update index if (m_index) { const bool isLast = (ndx == Size()); - m_index->Delete(ndx, oldVal, isLast); + m_index->erase(ndx, oldVal, isLast); } } @@ -670,9 +671,9 @@ void Column::find_all_hamming(Array& result, uint64_t value, size_t maxdist, siz const size_t count = refs.size(); for (size_t i = 0; i < count; ++i) { - const Column col((size_t)refs.Get(i)); + const Column col(refs.GetAsRef(i)); col.find_all_hamming(result, value, maxdist, offset); - offset += (size_t)offsets.Get(i); + offset += offsets.GetAsSizeT(i); } } } @@ -694,7 +695,7 @@ size_t Column::find_pos(int64_t target) const TIGHTDB_NOEXCEPT // Finds position of largest value SMALLER than the target while (high - low > 1) { const size_t probe = (unsigned(low) + unsigned(high)) >> 1; - const int64_t v = Get(probe); + const int64_t v = get(probe); if (v > target) high = int(probe); else low = int(probe); @@ -720,7 +721,7 @@ size_t Column::find_pos2(int64_t target) const // Finds position of closest value BIGGER OR EQUAL to the target while (high - low > 1) { const size_t probe = ((unsigned int)low + (unsigned int)high) >> 1; - const int64_t v = Get(probe); + const int64_t v = get(probe); if (v < target) low = int(probe); else high = int(probe); @@ -769,7 +770,7 @@ bool Column::compare(const Column& c) const const size_t n = Size(); if (c.Size() != n) return false; for (size_t i=0; iVerify(); } -void ColumnBase::ToDot(std::ostream& out, const char* title) const +void ColumnBase::ToDot(ostream& out, StringData title) const { const size_t ref = GetRef(); - out << "subgraph cluster_column" << ref << " {" << std::endl; + out << "subgraph cluster_column" << ref << " {" << endl; out << " label = \"Column"; - if (title) out << "\\n'" << title << "'"; - out << "\";" << std::endl; + if (0 < title.size()) out << "\\n'" << title << "'"; + out << "\";" << endl; ArrayToDot(out, *m_array); - out << "}" << std::endl; + out << "}" << endl; } -void ColumnBase::ArrayToDot(std::ostream& out, const Array& array) const +void ColumnBase::ArrayToDot(ostream& out, const Array& array) const { if (array.IsNode()) { const Array offsets = array.GetSubArray(0); const Array refs = array.GetSubArray(1); const size_t ref = array.GetRef(); - out << "subgraph cluster_node" << ref << " {" << std::endl; - out << " label = \"Node\";" << std::endl; + out << "subgraph cluster_node" << ref << " {" << endl; + out << " label = \"Node\";" << endl; array.ToDot(out); offsets.ToDot(out, "offsets"); - out << "}" << std::endl; + out << "}" << endl; refs.ToDot(out, "refs"); @@ -869,7 +870,7 @@ void ColumnBase::ArrayToDot(std::ostream& out, const Array& array) const else LeafToDot(out, array); } -void ColumnBase::LeafToDot(std::ostream& out, const Array& array) const +void ColumnBase::LeafToDot(ostream& out, const Array& array) const { array.ToDot(out); } diff --git a/src/tightdb/column.hpp b/src/tightdb/column.hpp index bc43455c696..1817749d84f 100644 --- a/src/tightdb/column.hpp +++ b/src/tightdb/column.hpp @@ -47,8 +47,8 @@ class ColumnBase { virtual void add() = 0; // Add an entry to this column using the columns default value virtual void insert(size_t ndx) = 0; // Insert an entry into this column using the columns default value virtual void Clear() = 0; - virtual void Delete(size_t ndx) = 0; - void Resize(size_t ndx) {m_array->Resize(ndx);} + virtual void erase(size_t ndx) = 0; + void Resize(size_t ndx) { m_array->Resize(ndx); } // Indexing virtual bool HasIndex() const = 0; @@ -68,7 +68,7 @@ class ColumnBase { #ifdef TIGHTDB_DEBUG virtual void Verify() const = 0; // Must be upper case to avoid conflict with macro in ObjC - virtual void ToDot(std::ostream& out, const char* title=NULL) const; + virtual void ToDot(std::ostream& out, StringData title = StringData()) const; #endif // TIGHTDB_DEBUG template @@ -139,10 +139,10 @@ class ColumnBase { class Column : public ColumnBase { public: explicit Column(Allocator&); - Column(ColumnDef type, Allocator&); - Column(ColumnDef type=coldef_Normal, ArrayParent* = 0, size_t pndx = 0, + Column(Array::ColumnDef, Allocator&); + Column(Array::ColumnDef = Array::coldef_Normal, ArrayParent* = 0, size_t ndx_in_parent = 0, Allocator& = Allocator::get_default()); - Column(size_t ref, ArrayParent* = 0, size_t pndx = 0, + Column(size_t ref, ArrayParent* = 0, size_t ndx_in_parent = 0, Allocator& = Allocator::get_default()); // Throws Column(const Column&); // FIXME: Constness violation ~Column(); @@ -160,12 +160,12 @@ class Column : public ColumnBase { bool is_empty() const TIGHTDB_NOEXCEPT; // Getting and setting values - int64_t Get(size_t ndx) const TIGHTDB_NOEXCEPT; + int64_t get(size_t ndx) const TIGHTDB_NOEXCEPT; size_t GetAsRef(size_t ndx) const TIGHTDB_NOEXCEPT; - int64_t Back() const TIGHTDB_NOEXCEPT {return Get(Size()-1);} - void Set(size_t ndx, int64_t value); - void insert(size_t ndx) TIGHTDB_OVERRIDE { Insert(ndx, 0); } - void Insert(size_t ndx, int64_t value); + int64_t Back() const TIGHTDB_NOEXCEPT {return get(Size()-1);} + void set(size_t ndx, int64_t value); + void insert(size_t ndx) TIGHTDB_OVERRIDE { insert(ndx, 0); } + void insert(size_t ndx, int64_t value); void add() TIGHTDB_OVERRIDE { add(0); } void add(int64_t value); void fill(size_t count); @@ -179,10 +179,10 @@ class Column : public ColumnBase { void sort(size_t start, size_t end); void ReferenceSort(size_t start, size_t end, Column &ref); - intptr_t GetPtr(size_t ndx) const {return (intptr_t)Get(ndx);} + intptr_t GetPtr(size_t ndx) const {return intptr_t(get(ndx));} // FIXME: intptr_t is not guaranteed to exists, not even in C++11 void Clear() TIGHTDB_OVERRIDE; - void Delete(size_t ndx) TIGHTDB_OVERRIDE; + void erase(size_t ndx) TIGHTDB_OVERRIDE; //void Resize(size_t len); void Increment64(int64_t value, size_t start=0, size_t end=-1); @@ -250,14 +250,14 @@ class Column : public ColumnBase { // Implementation: -inline int64_t Column::Get(std::size_t ndx) const TIGHTDB_NOEXCEPT +inline int64_t Column::get(std::size_t ndx) const TIGHTDB_NOEXCEPT { return m_array->column_get(ndx); } inline std::size_t Column::GetAsRef(std::size_t ndx) const TIGHTDB_NOEXCEPT { - return to_ref(Get(ndx)); + return to_ref(get(ndx)); } diff --git a/src/tightdb/column_basic.hpp b/src/tightdb/column_basic.hpp index 71fdb0208a4..2a1d93df4c9 100644 --- a/src/tightdb/column_basic.hpp +++ b/src/tightdb/column_basic.hpp @@ -40,9 +40,9 @@ template<> struct AggReturnType { template class BasicColumn : public ColumnBase { public: - BasicColumn(Allocator& alloc = Allocator::get_default()); - BasicColumn(size_t ref, ArrayParent* parent = 0, size_t pndx = 0, - Allocator& alloc = Allocator::get_default()); + BasicColumn(Allocator& = Allocator::get_default()); + BasicColumn(size_t ref, ArrayParent* = 0, size_t ndx_in_parent = 0, + Allocator& = Allocator::get_default()); ~BasicColumn(); void Destroy(); @@ -50,13 +50,13 @@ class BasicColumn : public ColumnBase { size_t Size() const TIGHTDB_NOEXCEPT TIGHTDB_OVERRIDE; bool is_empty() const TIGHTDB_NOEXCEPT; - T Get(size_t ndx) const TIGHTDB_NOEXCEPT; + T get(size_t ndx) const TIGHTDB_NOEXCEPT; void add() TIGHTDB_OVERRIDE { add(0); } void add(T value); - void Set(size_t ndx, T value); - void insert(size_t ndx) TIGHTDB_OVERRIDE { Insert(ndx, 0); } - void Insert(size_t ndx, T value); - void Delete(size_t ndx) TIGHTDB_OVERRIDE; + void set(size_t ndx, T value); + void insert(size_t ndx) TIGHTDB_OVERRIDE { insert(ndx, 0); } + void insert(size_t ndx, T value); + void erase(size_t ndx) TIGHTDB_OVERRIDE; void Clear() TIGHTDB_OVERRIDE; void Resize(size_t ndx); void fill(size_t count); diff --git a/src/tightdb/column_basic_tpl.hpp b/src/tightdb/column_basic_tpl.hpp index f4b26ec46bd..8ad906e6a63 100644 --- a/src/tightdb/column_basic_tpl.hpp +++ b/src/tightdb/column_basic_tpl.hpp @@ -144,14 +144,14 @@ void BasicColumn::Resize(size_t ndx) } template -T BasicColumn::Get(size_t ndx) const TIGHTDB_NOEXCEPT +T BasicColumn::get(size_t ndx) const TIGHTDB_NOEXCEPT { TIGHTDB_ASSERT(ndx < Size()); return BasicArray::column_get(m_array, ndx); } template -void BasicColumn::Set(size_t ndx, T value) +void BasicColumn::set(size_t ndx, T value) { TIGHTDB_ASSERT(ndx < Size()); TreeSet >(ndx, value); @@ -160,11 +160,11 @@ void BasicColumn::Set(size_t ndx, T value) template void BasicColumn::add(T value) { - Insert(Size(), value); + insert(Size(), value); } template -void BasicColumn::Insert(size_t ndx, T value) +void BasicColumn::insert(size_t ndx, T value) { TIGHTDB_ASSERT(ndx <= Size()); TreeInsert >(ndx, value); @@ -194,8 +194,8 @@ bool BasicColumn::compare(const BasicColumn& c) const if (c.Size() != n) return false; for (size_t i=0; i::compare(const BasicColumn& c) const template -void BasicColumn::Delete(size_t ndx) +void BasicColumn::erase(size_t ndx) { TIGHTDB_ASSERT(ndx < Size()); TreeDelete >(ndx); diff --git a/src/tightdb/column_binary.cpp b/src/tightdb/column_binary.cpp index 5d2ed5c25c2..06b2e81c0b0 100644 --- a/src/tightdb/column_binary.cpp +++ b/src/tightdb/column_binary.cpp @@ -27,13 +27,13 @@ ColumnBinary::ColumnBinary(size_t ref, ArrayParent* parent, size_t pndx, Allocat ColumnBinary::~ColumnBinary() { if (IsNode()) delete m_array; - else delete (ArrayBinary*)m_array; + else delete static_cast(m_array); } void ColumnBinary::Destroy() { if (IsNode()) m_array->Destroy(); - else ((ArrayBinary*)m_array)->Destroy(); + else static_cast(m_array)->Destroy(); } void ColumnBinary::UpdateRef(size_t ref) @@ -62,7 +62,7 @@ bool ColumnBinary::is_empty() const TIGHTDB_NOEXCEPT return offsets.is_empty(); } else { - return (static_cast(m_array))->is_empty(); + return static_cast(m_array)->is_empty(); } } @@ -74,7 +74,7 @@ size_t ColumnBinary::Size() const TIGHTDB_NOEXCEPT return size; } else { - return (static_cast(m_array))->size(); + return static_cast(m_array)->size(); } } @@ -94,32 +94,44 @@ void ColumnBinary::Clear() m_array = array; } - else (static_cast(m_array))->Clear(); + else { + static_cast(m_array)->Clear(); + } } -void ColumnBinary::Set(size_t ndx, BinaryData bin) +void ColumnBinary::set(size_t ndx, BinaryData bin) { TIGHTDB_ASSERT(ndx < Size()); - TreeSet(ndx, bin); + TreeSet(ndx, bin); } -void ColumnBinary::Insert(size_t ndx, BinaryData bin) +void ColumnBinary::insert(size_t ndx, BinaryData bin) { TIGHTDB_ASSERT(ndx <= Size()); - TreeInsert(ndx, bin); + TreeInsert(ndx, bin); +} + +void ColumnBinary::set_string(size_t ndx, StringData value) +{ + TIGHTDB_ASSERT(ndx < Size()); + TreeSet(ndx, value); +} + +void ColumnBinary::insert_string(size_t ndx, StringData value) +{ + TIGHTDB_ASSERT(ndx <= Size()); + TreeInsert(ndx, value); } void ColumnBinary::fill(size_t count) { TIGHTDB_ASSERT(is_empty()); - BinaryData empty_bin; // default value - // Fill column with default values // TODO: this is a very naive approach // we could speedup by creating full nodes directly for (size_t i = 0; i < count; ++i) { - TreeInsert(i, empty_bin); + TreeInsert(i, BinaryData()); } #ifdef TIGHTDB_DEBUG @@ -128,7 +140,7 @@ void ColumnBinary::fill(size_t count) } -void ColumnBinary::Delete(size_t ndx) +void ColumnBinary::erase(size_t ndx) { TIGHTDB_ASSERT(ndx < Size()); TreeDelete(ndx); @@ -138,7 +150,7 @@ void ColumnBinary::Resize(size_t ndx) { TIGHTDB_ASSERT(!IsNode()); // currently only available on leaf level (used by b-tree code) TIGHTDB_ASSERT(ndx < Size()); - ((ArrayBinary*)m_array)->Resize(ndx); + static_cast(m_array)->Resize(ndx); } bool ColumnBinary::compare(const ColumnBinary& c) const @@ -146,9 +158,7 @@ bool ColumnBinary::compare(const ColumnBinary& c) const const size_t n = Size(); if (c.Size() != n) return false; for (size_t i=0; iSet(ndx, value.pointer, value.len); + static_cast(m_array)->set(ndx, value); } void ColumnBinary::LeafInsert(size_t ndx, BinaryData value) { - ((ArrayBinary*)m_array)->Insert(ndx, value.pointer, value.len); + static_cast(m_array)->insert(ndx, value); +} + +void ColumnBinary::LeafSet(size_t ndx, StringData value) +{ + static_cast(m_array)->set_string(ndx, value); +} + +void ColumnBinary::LeafInsert(size_t ndx, StringData value) +{ + static_cast(m_array)->insert_string(ndx, value); } void ColumnBinary::LeafDelete(size_t ndx) { - ((ArrayBinary*)m_array)->Delete(ndx); + static_cast(m_array)->Delete(ndx); } #ifdef TIGHTDB_DEBUG -void ColumnBinary::LeafToDot(std::ostream& out, const Array& array) const +void ColumnBinary::LeafToDot(ostream& out, const Array& array) const { // Rebuild array to get correct type const size_t ref = array.GetRef(); diff --git a/src/tightdb/column_binary.hpp b/src/tightdb/column_binary.hpp index 07fc15bb878..57dbf36d497 100644 --- a/src/tightdb/column_binary.hpp +++ b/src/tightdb/column_binary.hpp @@ -28,9 +28,9 @@ namespace tightdb { class ColumnBinary : public ColumnBase { public: - ColumnBinary(Allocator& alloc = Allocator::get_default()); - ColumnBinary(size_t ref, ArrayParent* parent=NULL, size_t pndx=0, - Allocator& alloc = Allocator::get_default()); + ColumnBinary(Allocator& = Allocator::get_default()); + ColumnBinary(size_t ref, ArrayParent* = 0, size_t ndx_in_parent = 0, + Allocator& = Allocator::get_default()); ~ColumnBinary(); void Destroy(); @@ -38,19 +38,24 @@ class ColumnBinary : public ColumnBase { size_t Size() const TIGHTDB_NOEXCEPT TIGHTDB_OVERRIDE; bool is_empty() const TIGHTDB_NOEXCEPT; - BinaryData Get(std::size_t ndx) const TIGHTDB_NOEXCEPT; - const char* get_data(std::size_t ndx) const TIGHTDB_NOEXCEPT; - std::size_t get_size(std::size_t ndx) const TIGHTDB_NOEXCEPT; - - void add() TIGHTDB_OVERRIDE { add(NULL, 0); } - void add(const char* data, std::size_t size); - void Set(std::size_t ndx, const char* data, size_t size); - void insert(size_t ndx) TIGHTDB_OVERRIDE { Insert(ndx, 0, 0); } - void Insert(size_t ndx, const char* data, size_t size); - void Delete(size_t ndx) TIGHTDB_OVERRIDE; - void Resize(size_t ndx); + BinaryData get(std::size_t ndx) const TIGHTDB_NOEXCEPT; + + void add() TIGHTDB_OVERRIDE { add(BinaryData()); } + void add(BinaryData value); + void set(std::size_t ndx, BinaryData value); + void insert(std::size_t ndx) TIGHTDB_OVERRIDE { insert(ndx, BinaryData()); } + void insert(std::size_t ndx, BinaryData value); + void erase(std::size_t ndx) TIGHTDB_OVERRIDE; + void Resize(std::size_t ndx); void Clear() TIGHTDB_OVERRIDE; - void fill(size_t count); + void fill(std::size_t count); + + // Requires that the specified entry was inserted as StringData. + StringData get_string(std::size_t ndx) const TIGHTDB_NOEXCEPT; + + void add_string(StringData value); + void set_string(std::size_t ndx, StringData value); + void insert_string(std::size_t ndx, StringData value); // Index bool HasIndex() const {return false;} @@ -72,10 +77,6 @@ class ColumnBinary : public ColumnBase { protected: friend class ColumnBase; - void add(BinaryData bin); - void Set(size_t ndx, BinaryData bin); - void Insert(size_t ndx, BinaryData bin); - void UpdateRef(size_t ref); BinaryData LeafGet(size_t ndx) const TIGHTDB_NOEXCEPT; @@ -86,6 +87,12 @@ class ColumnBinary : public ColumnBase { #ifdef TIGHTDB_DEBUG virtual void LeafToDot(std::ostream& out, const Array& array) const; #endif // TIGHTDB_DEBUG + +private: + void add(StringData value) { add_string(value); } + void set(std::size_t ndx, StringData value) { set_string(ndx, value); } + void LeafSet(size_t ndx, StringData value); + void LeafInsert(size_t ndx, StringData value); }; @@ -93,40 +100,27 @@ class ColumnBinary : public ColumnBase { // Implementation -inline BinaryData ColumnBinary::Get(std::size_t ndx) const TIGHTDB_NOEXCEPT +inline BinaryData ColumnBinary::get(std::size_t ndx) const TIGHTDB_NOEXCEPT { TIGHTDB_ASSERT(ndx < Size()); return ArrayBinary::column_get(m_array, ndx); } -inline const char* ColumnBinary::get_data(std::size_t ndx) const TIGHTDB_NOEXCEPT -{ - return Get(ndx).pointer; -} - -inline std::size_t ColumnBinary::get_size(std::size_t ndx) const TIGHTDB_NOEXCEPT -{ - return Get(ndx).len; -} - -inline void ColumnBinary::Set(std::size_t ndx, const char* data, std::size_t size) -{ - Set(ndx, BinaryData(data, size)); -} - -inline void ColumnBinary::add(const char* data, std::size_t size) +inline StringData ColumnBinary::get_string(std::size_t ndx) const TIGHTDB_NOEXCEPT { - Insert(Size(), data, size); + BinaryData bin = get(ndx); + TIGHTDB_ASSERT(0 < bin.size()); + return StringData(bin.data(), bin.size()-1); } -inline void ColumnBinary::add(BinaryData bin) +inline void ColumnBinary::add(BinaryData value) { - Insert(Size(), bin); + insert(Size(), value); } -inline void ColumnBinary::Insert(std::size_t ndx, const char* data, std::size_t size) +inline void ColumnBinary::add_string(StringData value) { - Insert(ndx, BinaryData(data, size)); + insert_string(Size(), value); } } // namespace tightdb diff --git a/src/tightdb/column_mixed.cpp b/src/tightdb/column_mixed.cpp index 61dfa0da825..baed9fe7d5a 100644 --- a/src/tightdb/column_mixed.cpp +++ b/src/tightdb/column_mixed.cpp @@ -1,5 +1,7 @@ #include +using namespace std; + namespace tightdb { ColumnMixed::~ColumnMixed() @@ -35,9 +37,9 @@ void ColumnMixed::UpdateFromParent() void ColumnMixed::Create(Allocator& alloc, const Table* table, size_t column_ndx) { - m_array = new Array(coldef_HasRefs, NULL, 0, alloc); + m_array = new Array(Array::coldef_HasRefs, NULL, 0, alloc); - m_types = new Column(coldef_Normal, alloc); + m_types = new Column(Array::coldef_Normal, alloc); m_refs = new RefsColumn(alloc, table, column_ndx); m_array->add(m_types->GetRef()); @@ -87,7 +89,7 @@ void ColumnMixed::clear_value(size_t ndx, MixedColType newtype) { TIGHTDB_ASSERT(ndx < m_types->Size()); - const MixedColType type = (MixedColType)m_types->Get(ndx); + MixedColType type = MixedColType(m_types->get(ndx)); if (type != mixcol_Int) { switch (type) { case mixcol_IntNeg: @@ -98,22 +100,23 @@ void ColumnMixed::clear_value(size_t ndx, MixedColType newtype) case mixcol_DoubleNeg: break; case mixcol_String: - case mixcol_Binary: - { + case mixcol_Binary: { // If item is in middle of the column, we just clear // it to avoid having to adjust refs to following items const size_t ref = m_refs->GetAsRef(ndx) >> 1; if (ref == m_data->Size()-1) - m_data->Delete(ref); + m_data->erase(ref); else - m_data->Set(ref, "", 0); + // FIXME: But this will lead to unbounded in-file + // leaking in for(;;) { insert_binary(i, ...); + // erase(i); } + m_data->set(ref, BinaryData()); break; } - case mixcol_Table: - { + case mixcol_Table: { // Delete entire table const size_t ref = m_refs->GetAsRef(ndx); - Array top(ref, (Array*)NULL, 0, m_array->GetAllocator()); + Array top(ref, 0, 0, m_array->GetAllocator()); top.Destroy(); break; } @@ -122,18 +125,18 @@ void ColumnMixed::clear_value(size_t ndx, MixedColType newtype) } } if (type != newtype) - m_types->Set(ndx, newtype); + m_types->set(ndx, newtype); } -void ColumnMixed::Delete(size_t ndx) +void ColumnMixed::erase(size_t ndx) { TIGHTDB_ASSERT(ndx < m_types->Size()); // Remove refs or binary data clear_value(ndx, mixcol_Int); - m_types->Delete(ndx); - m_refs->Delete(ndx); + m_types->erase(ndx); + m_refs->erase(ndx); invalidate_subtables(); } @@ -149,7 +152,7 @@ void ColumnMixed::Clear() DataType ColumnMixed::get_type(size_t ndx) const TIGHTDB_NOEXCEPT { TIGHTDB_ASSERT(ndx < m_types->Size()); - MixedColType coltype = MixedColType(m_types->Get(ndx)); + MixedColType coltype = MixedColType(m_types->get(ndx)); switch (coltype) { case mixcol_IntNeg: return type_Int; case mixcol_DoubleNeg: return type_Double; @@ -165,10 +168,10 @@ void ColumnMixed::fill(size_t count) // TODO: this is a very naive approach // we could speedup by creating full nodes directly for (size_t i = 0; i < count; ++i) { - m_types->Insert(i, mixcol_Int); + m_types->insert(i, mixcol_Int); } for (size_t i = 0; i < count; ++i) { - m_refs->Insert(i, 1); // 1 is zero shifted one and low bit set; + m_refs->insert(i, 1); // 1 is zero shifted one and low bit set; } #ifdef TIGHTDB_DEBUG @@ -177,23 +180,22 @@ void ColumnMixed::fill(size_t count) } -void ColumnMixed::set_string(size_t ndx, const char* value) +void ColumnMixed::set_string(size_t ndx, StringData value) { TIGHTDB_ASSERT(ndx < m_types->Size()); InitDataColumn(); - const MixedColType type = (MixedColType)m_types->Get(ndx); - const size_t len = strlen(value)+1; + const MixedColType type = MixedColType(m_types->get(ndx)); // See if we can reuse data position if (type == mixcol_String) { - const size_t ref = m_refs->GetAsRef(ndx) >> 1; - m_data->Set(ref, value, len); + size_t ref = m_refs->GetAsRef(ndx) >> 1; + m_data->set_string(ref, value); } else if (type == mixcol_Binary) { - const size_t ref = m_refs->GetAsRef(ndx) >> 1; - m_data->Set(ref, value, len); - m_types->Set(ndx, mixcol_String); + size_t ref = m_refs->GetAsRef(ndx) >> 1; + m_data->set_string(ref, value); + m_types->set(ndx, mixcol_String); } else { // Remove refs or binary data @@ -201,32 +203,32 @@ void ColumnMixed::set_string(size_t ndx, const char* value) // Add value to data column const size_t ref = m_data->Size(); - m_data->add(value, len); + m_data->add_string(value); // Shift value one bit and set lowest bit to indicate that this is not a ref const int64_t v = (ref << 1) + 1; - m_types->Set(ndx, mixcol_String); - m_refs->Set(ndx, v); + m_types->set(ndx, mixcol_String); + m_refs->set(ndx, v); } } -void ColumnMixed::set_binary(size_t ndx, const char* value, size_t len) +void ColumnMixed::set_binary(size_t ndx, BinaryData value) { TIGHTDB_ASSERT(ndx < m_types->Size()); InitDataColumn(); - const MixedColType type = (MixedColType)m_types->Get(ndx); + const MixedColType type = MixedColType(m_types->get(ndx)); // See if we can reuse data position if (type == mixcol_String) { const size_t ref = m_refs->GetAsRef(ndx) >> 1; - m_data->Set(ref, value, len); - m_types->Set(ndx, mixcol_Binary); + m_data->set(ref, value); + m_types->set(ndx, mixcol_Binary); } else if (type == mixcol_Binary) { const size_t ref = m_refs->GetAsRef(ndx) >> 1; - m_data->Set(ref, value, len); + m_data->set(ref, value); } else { // Remove refs or binary data @@ -234,13 +236,13 @@ void ColumnMixed::set_binary(size_t ndx, const char* value, size_t len) // Add value to data column const size_t ref = m_data->Size(); - m_data->add(value, len); + m_data->add(value); // Shift value one bit and set lowest bit to indicate that this is not a ref const int64_t v = (ref << 1) + 1; - m_types->Set(ndx, mixcol_Binary); - m_refs->Set(ndx, v); + m_types->set(ndx, mixcol_Binary); + m_refs->set(ndx, v); } } @@ -271,22 +273,15 @@ bool ColumnMixed::compare(const ColumnMixed& c) const if (get_double(i) != c.get_double(i)) return false; break; case type_String: - if (strcmp(get_string(i), c.get_string(i)) != 0) return false; + if (get_string(i) != c.get_string(i)) return false; break; case type_Binary: - { - const BinaryData d1 = get_binary(i); - const BinaryData d2 = c.get_binary(i); - if (d1.len != d2.len || !std::equal(d1.pointer, d1.pointer+d1.len, d2.pointer)) - return false; - } + if (get_binary(i) != c.get_binary(i)) return false; break; - case type_Table: - { + case type_Table: { ConstTableRef t1 = get_subtable_ptr(i)->get_table_ref(); ConstTableRef t2 = c.get_subtable_ptr(i)->get_table_ref(); - if (*t1 != *t2) - return false; + if (*t1 != *t2) return false; } break; case type_Mixed: @@ -315,28 +310,28 @@ void ColumnMixed::Verify() const // Verify each sub-table const size_t count = Size(); for (size_t i = 0; i < count; ++i) { - const int64_t v = m_refs->Get(i); + const int64_t v = m_refs->get(i); if (v == 0 || v & 0x1) continue; ConstTableRef subtable = m_refs->get_subtable(i); subtable->Verify(); } } -void ColumnMixed::ToDot(std::ostream& out, const char* title) const +void ColumnMixed::ToDot(ostream& out, StringData title) const { const size_t ref = GetRef(); - out << "subgraph cluster_columnmixed" << ref << " {" << std::endl; + out << "subgraph cluster_columnmixed" << ref << " {" << endl; out << " label = \"ColumnMixed"; - if (title) out << "\\n'" << title << "'"; - out << "\";" << std::endl; + if (0 < title.size()) out << "\\n'" << title << "'"; + out << "\";" << endl; m_array->ToDot(out, "mixed_top"); // Write sub-tables const size_t count = Size(); for (size_t i = 0; i < count; ++i) { - const MixedColType type = (MixedColType)m_types->Get(i); + const MixedColType type = MixedColType(m_types->get(i)); if (type != mixcol_Table) continue; ConstTableRef subtable = m_refs->get_subtable(i); subtable->to_dot(out); @@ -349,7 +344,7 @@ void ColumnMixed::ToDot(std::ostream& out, const char* title) const m_data->ToDot(out, "data"); } - out << "}" << std::endl; + out << "}" << endl; } #endif // TIGHTDB_DEBUG diff --git a/src/tightdb/column_mixed.hpp b/src/tightdb/column_mixed.hpp index 36ac96594a1..84eab8c6974 100644 --- a/src/tightdb/column_mixed.hpp +++ b/src/tightdb/column_mixed.hpp @@ -79,12 +79,16 @@ class ColumnMixed : public ColumnBase { int64_t get_int(size_t ndx) const; bool get_bool(size_t ndx) const; - time_t get_date(size_t ndx) const; + Date get_date(size_t ndx) const; float get_float(size_t ndx) const; double get_double(size_t ndx) const; - const char* get_string(size_t ndx) const; + StringData get_string(size_t ndx) const; BinaryData get_binary(size_t ndx) const; + /// The returned array ref is zero if the specified row does not + /// contain a subtable. + size_t get_subtable_ref(std::size_t row_idx) const TIGHTDB_NOEXCEPT; + /// The returned size is zero if the specified row does not /// contain a subtable. size_t get_subtable_size(std::size_t row_idx) const TIGHTDB_NOEXCEPT; @@ -96,26 +100,26 @@ class ColumnMixed : public ColumnBase { void set_int(size_t ndx, int64_t value); void set_bool(size_t ndx, bool value); - void set_date(size_t ndx, time_t value); + void set_date(size_t ndx, Date value); void set_float(size_t ndx, float value); void set_double(size_t ndx, double value); - void set_string(size_t ndx, const char* value); - void set_binary(size_t ndx, const char* value, size_t len); + void set_string(size_t ndx, StringData value); + void set_binary(size_t ndx, BinaryData value); void set_subtable(size_t ndx, const Table*); void insert_int(size_t ndx, int64_t value); void insert_bool(size_t ndx, bool value); - void insert_date(size_t ndx, time_t value); + void insert_date(size_t ndx, Date value); void insert_float(size_t ndx, float value); void insert_double(size_t ndx, double value); - void insert_string(size_t ndx, const char* value); - void insert_binary(size_t ndx, const char* value, size_t len); + void insert_string(size_t ndx, StringData value); + void insert_binary(size_t ndx, BinaryData value); void insert_subtable(size_t ndx, const Table*); void add() TIGHTDB_OVERRIDE { insert_int(Size(), 0); } void insert(size_t ndx) TIGHTDB_OVERRIDE { insert_int(ndx, 0); invalidate_subtables(); } void Clear() TIGHTDB_OVERRIDE; - void Delete(size_t ndx) TIGHTDB_OVERRIDE; + void erase(size_t ndx) TIGHTDB_OVERRIDE; void fill(size_t count); // Indexing @@ -135,7 +139,7 @@ class ColumnMixed : public ColumnBase { #ifdef TIGHTDB_DEBUG void Verify() const; // Must be upper case to avoid conflict with macro in ObjC - void ToDot(std::ostream& out, const char* title) const; + void ToDot(std::ostream& out, StringData title) const; #endif // TIGHTDB_DEBUG private: diff --git a/src/tightdb/column_mixed_tpl.hpp b/src/tightdb/column_mixed_tpl.hpp index 329508a363b..d88026f494e 100644 --- a/src/tightdb/column_mixed_tpl.hpp +++ b/src/tightdb/column_mixed_tpl.hpp @@ -38,14 +38,20 @@ inline ColumnMixed::ColumnMixed(Allocator& alloc, const Table* table, std::size_ Create(alloc, table, column_ndx, parent, ndx_in_parent, ref); } +inline size_t ColumnMixed::get_subtable_ref(size_t row_idx) const TIGHTDB_NOEXCEPT +{ + TIGHTDB_ASSERT(row_idx < m_types->Size()); + if (m_types->get(row_idx) != type_Table) return 0; + return m_refs->GetAsRef(row_idx); +} + inline size_t ColumnMixed::get_subtable_size(size_t row_idx) const TIGHTDB_NOEXCEPT { // FIXME: If the table object is cached, it is possible to get the // size from it. Maybe it is faster in general to check for the // the presence of the cached object and use it when available. - TIGHTDB_ASSERT(row_idx < m_types->Size()); - if (m_types->Get(row_idx) != type_Table) return 0; - const size_t top_ref = m_refs->GetAsRef(row_idx); + const size_t top_ref = get_subtable_ref(row_idx); + if (!top_ref) return 0; const size_t columns_ref = Array(top_ref, 0, 0, m_refs->GetAllocator()).GetAsRef(1); const Array columns(columns_ref, 0, 0, m_refs->GetAllocator()); if (columns.is_empty()) return 0; @@ -56,7 +62,7 @@ inline size_t ColumnMixed::get_subtable_size(size_t row_idx) const TIGHTDB_NOEXC inline Table* ColumnMixed::get_subtable_ptr(size_t row_idx) const { TIGHTDB_ASSERT(row_idx < m_types->Size()); - if (m_types->Get(row_idx) != type_Table) + if (m_types->get(row_idx) != type_Table) return 0; return m_refs->get_subtable_ptr(row_idx); } @@ -84,7 +90,7 @@ inline int64_t ColumnMixed::get_value(size_t ndx) const // Shift the unsigned value right - ensuring 0 gets in from left. // Shifting signed integers right doesn't ensure 0's. - const uint64_t value = uint64_t(m_refs->Get(ndx)) >> 1; + const uint64_t value = uint64_t(m_refs->get(ndx)) >> 1; return int64_t(value); } @@ -94,7 +100,7 @@ inline int64_t ColumnMixed::get_int(size_t ndx) const int64_t value = get_value(ndx); // restore 'sign'-bit from the column-type - const MixedColType coltype = MixedColType(m_types->Get(ndx)); + const MixedColType coltype = MixedColType(m_types->get(ndx)); if (coltype == mixcol_IntNeg) value |= TIGHTDB_BIT63; // set sign bit (63) else { @@ -105,14 +111,14 @@ inline int64_t ColumnMixed::get_int(size_t ndx) const inline bool ColumnMixed::get_bool(size_t ndx) const { - TIGHTDB_ASSERT(m_types->Get(ndx) == mixcol_Bool); + TIGHTDB_ASSERT(m_types->get(ndx) == mixcol_Bool); return (get_value(ndx) != 0); } -inline time_t ColumnMixed::get_date(size_t ndx) const +inline Date ColumnMixed::get_date(size_t ndx) const { - TIGHTDB_ASSERT(m_types->Get(ndx) == mixcol_Date); + TIGHTDB_ASSERT(m_types->get(ndx) == mixcol_Date); return time_t(get_value(ndx)); } @@ -121,7 +127,7 @@ inline float ColumnMixed::get_float(size_t ndx) const { TIGHTDB_STATIC_ASSERT(std::numeric_limits::is_iec559, "'float' is not IEEE"); TIGHTDB_STATIC_ASSERT((sizeof(float) * CHAR_BIT == 32), "Assume 32 bit float."); - TIGHTDB_ASSERT(m_types->Get(ndx) == mixcol_Float); + TIGHTDB_ASSERT(m_types->get(ndx) == mixcol_Float); return TypePunning( get_value(ndx) ); } @@ -134,7 +140,7 @@ inline double ColumnMixed::get_double(size_t ndx) const int64_t intval = get_value(ndx); // restore 'sign'-bit from the column-type - const MixedColType coltype = MixedColType(m_types->Get(ndx)); + const MixedColType coltype = MixedColType(m_types->get(ndx)); if (coltype == mixcol_DoubleNeg) intval |= TIGHTDB_BIT63; // set sign bit (63) else { @@ -143,24 +149,24 @@ inline double ColumnMixed::get_double(size_t ndx) const return TypePunning( intval ); } -inline const char* ColumnMixed::get_string(size_t ndx) const +inline StringData ColumnMixed::get_string(size_t ndx) const { TIGHTDB_ASSERT(ndx < m_types->Size()); - TIGHTDB_ASSERT(m_types->Get(ndx) == mixcol_String); + TIGHTDB_ASSERT(m_types->get(ndx) == mixcol_String); TIGHTDB_ASSERT(m_data); - const size_t offset = m_refs->GetAsRef(ndx) >> 1; - return m_data->get_data(offset); + size_t offset = m_refs->GetAsRef(ndx) >> 1; + return m_data->get_string(offset); } inline BinaryData ColumnMixed::get_binary(size_t ndx) const { TIGHTDB_ASSERT(ndx < m_types->Size()); - TIGHTDB_ASSERT(m_types->Get(ndx) == mixcol_Binary); + TIGHTDB_ASSERT(m_types->get(ndx) == mixcol_Binary); TIGHTDB_ASSERT(m_data); const size_t offset = m_refs->GetAsRef(ndx) >> 1; - return m_data->Get(offset); + return m_data->get(offset); } // @@ -182,7 +188,7 @@ inline void ColumnMixed::set_int64(size_t ndx, int64_t value, MixedColType pos_t // Shift value one bit and set lowest bit to indicate that this is not a ref value = (value << 1) + 1; - m_refs->Set(ndx, value); + m_refs->set(ndx, value); } inline void ColumnMixed::set_int(size_t ndx, int64_t value) @@ -205,7 +211,7 @@ inline void ColumnMixed::set_value(size_t ndx, int64_t value, MixedColType colty // Shift value one bit and set lowest bit to indicate that this is not a ref const int64_t v = (value << 1) + 1; - m_refs->Set(ndx, v); + m_refs->set(ndx, v); } inline void ColumnMixed::set_float(size_t ndx, float value) @@ -219,9 +225,9 @@ inline void ColumnMixed::set_bool(size_t ndx, bool value) set_value(ndx, (value ? 1 : 0), mixcol_Bool); } -inline void ColumnMixed::set_date(size_t ndx, time_t value) +inline void ColumnMixed::set_date(size_t ndx, Date value) { - set_value(ndx, int64_t(value), mixcol_Date); + set_value(ndx, int64_t(value.get_date()), mixcol_Date); } inline void ColumnMixed::set_subtable(std::size_t ndx, const Table* t) @@ -235,7 +241,7 @@ inline void ColumnMixed::set_subtable(std::size_t ndx, const Table* t) ref = Table::create_empty_table(m_array->GetAllocator()); // Throws } clear_value(ndx, mixcol_Table); // Remove any previous refs or binary data - m_refs->Set(ndx, ref); + m_refs->set(ndx, ref); } // @@ -251,13 +257,13 @@ inline void ColumnMixed::insert_int64(size_t ndx, int64_t value, MixedColType po // 'store' the sign-bit in the integer-type if ((value & TIGHTDB_BIT63) == 0) - m_types->Insert(ndx, pos_type); + m_types->insert(ndx, pos_type); else - m_types->Insert(ndx, neg_type); + m_types->insert(ndx, neg_type); // Shift value one bit and set lowest bit to indicate that this is not a ref value = (value << 1) + 1; - m_refs->Insert(ndx, value); + m_refs->insert(ndx, value); } inline void ColumnMixed::insert_int(size_t ndx, int64_t value) @@ -280,8 +286,8 @@ inline void ColumnMixed::insert_float(size_t ndx, float value) // Shift value one bit and set lowest bit to indicate that this is not a ref const int64_t val64 = (int64_t(val32) << 1) + 1; - m_refs->Insert(ndx, val64); - m_types->Insert(ndx, mixcol_Float); + m_refs->insert(ndx, val64); + m_types->insert(ndx, mixcol_Float); } inline void ColumnMixed::insert_bool(size_t ndx, bool value) @@ -291,50 +297,49 @@ inline void ColumnMixed::insert_bool(size_t ndx, bool value) // Shift value one bit and set lowest bit to indicate that this is not a ref const int64_t v = ((value ? 1 : 0) << 1) + 1; - m_types->Insert(ndx, mixcol_Bool); - m_refs->Insert(ndx, v); + m_types->insert(ndx, mixcol_Bool); + m_refs->insert(ndx, v); } -inline void ColumnMixed::insert_date(size_t ndx, time_t value) +inline void ColumnMixed::insert_date(size_t ndx, Date value) { TIGHTDB_ASSERT(ndx <= m_types->Size()); // Shift value one bit and set lowest bit to indicate that this is not a ref - const int64_t v = (value << 1) + 1; + const int64_t v = (int64_t(value.get_date()) << 1) + 1; - m_types->Insert(ndx, mixcol_Date); - m_refs->Insert(ndx, v); + m_types->insert(ndx, mixcol_Date); + m_refs->insert(ndx, v); } -inline void ColumnMixed::insert_string(size_t ndx, const char* value) +inline void ColumnMixed::insert_string(size_t ndx, StringData value) { TIGHTDB_ASSERT(ndx <= m_types->Size()); InitDataColumn(); - const size_t len = strlen(value)+1; const size_t ref = m_data->Size(); - m_data->add(value, len); + m_data->add_string(value); // Shift value one bit and set lowest bit to indicate that this is not a ref const int64_t v = (ref << 1) + 1; - m_types->Insert(ndx, mixcol_String); - m_refs->Insert(ndx, v); + m_types->insert(ndx, mixcol_String); + m_refs->insert(ndx, v); } -inline void ColumnMixed::insert_binary(size_t ndx, const char* value, size_t len) +inline void ColumnMixed::insert_binary(size_t ndx, BinaryData value) { TIGHTDB_ASSERT(ndx <= m_types->Size()); InitDataColumn(); const size_t ref = m_data->Size(); - m_data->add(value, len); + m_data->add(value); // Shift value one bit and set lowest bit to indicate that this is not a ref const int64_t v = (ref << 1) + 1; - m_types->Insert(ndx, mixcol_Binary); - m_refs->Insert(ndx, v); + m_types->insert(ndx, mixcol_Binary); + m_refs->insert(ndx, v); } inline void ColumnMixed::insert_subtable(std::size_t ndx, const Table* t) @@ -347,8 +352,8 @@ inline void ColumnMixed::insert_subtable(std::size_t ndx, const Table* t) else { ref = Table::create_empty_table(m_array->GetAllocator()); // Throws } - m_types->Insert(ndx, mixcol_Table); - m_refs->Insert(ndx, ref); + m_types->insert(ndx, mixcol_Table); + m_refs->insert(ndx, ref); } } // namespace tightdb diff --git a/src/tightdb/column_string.cpp b/src/tightdb/column_string.cpp index 32aa5cf68de..8c3b349ed85 100644 --- a/src/tightdb/column_string.cpp +++ b/src/tightdb/column_string.cpp @@ -2,31 +2,32 @@ #include #include // debug #ifdef _MSC_VER - #include +# include #endif #include #include #include -namespace { - using namespace std; -using namespace tightdb; -ColumnDef GetTypeFromArray(size_t ref, Allocator& alloc) -{ - const uint8_t* const header = reinterpret_cast(alloc.Translate(ref)); - const bool isNode = (header[0] & 0x80) != 0; - const bool hasRefs = (header[0] & 0x40) != 0; - if (isNode) return coldef_InnerNode; - else if (hasRefs) return coldef_HasRefs; - else return coldef_Normal; +namespace { + +tightdb::Array::ColumnDef get_coldef_from_ref(size_t ref, tightdb::Allocator& alloc) +{ + const char* header = static_cast(alloc.Translate(ref)); + return tightdb::Array::get_coldef_from_header(header); } +// Getter function for string index +tightdb::StringData get_string(void* column, size_t ndx) +{ + return static_cast(column)->get(ndx); } +} // anonymous namespace + namespace tightdb { @@ -37,15 +38,17 @@ AdaptiveStringColumn::AdaptiveStringColumn(Allocator& alloc) : m_index(NULL) AdaptiveStringColumn::AdaptiveStringColumn(size_t ref, ArrayParent* parent, size_t pndx, Allocator& alloc) : m_index(NULL) { - const ColumnDef type = GetTypeFromArray(ref, alloc); - if (type == coldef_InnerNode) { - m_array = new Array(ref, parent, pndx, alloc); - } - else if (type == coldef_HasRefs) { - m_array = new ArrayStringLong(ref, parent, pndx, alloc); - } - else { - m_array = new ArrayString(ref, parent, pndx, alloc); + Array::ColumnDef type = get_coldef_from_ref(ref, alloc); + switch (type) { + case Array::coldef_InnerNode: + m_array = new Array(ref, parent, pndx, alloc); + break; + case Array::coldef_HasRefs: + m_array = new ArrayStringLong(ref, parent, pndx, alloc); + break; + case Array::coldef_Normal: + m_array = new ArrayString(ref, parent, pndx, alloc); + break; } } @@ -60,9 +63,11 @@ void AdaptiveStringColumn::Destroy() { if (IsNode()) m_array->Destroy(); else if (IsLongStrings()) { - ((ArrayStringLong*)m_array)->Destroy(); + static_cast(m_array)->Destroy(); + } + else { + static_cast(m_array)->Destroy(); } - else ((ArrayString*)m_array)->Destroy(); if (m_index) m_index->Destroy(); @@ -71,7 +76,7 @@ void AdaptiveStringColumn::Destroy() void AdaptiveStringColumn::UpdateRef(size_t ref) { - TIGHTDB_ASSERT(GetTypeFromArray(ref, m_array->GetAllocator()) == coldef_InnerNode); // Can only be called when creating node + TIGHTDB_ASSERT(get_coldef_from_ref(ref, m_array->GetAllocator()) == Array::coldef_InnerNode); // Can only be called when creating node if (IsNode()) m_array->UpdateRef(ref); else { @@ -88,23 +93,17 @@ void AdaptiveStringColumn::UpdateRef(size_t ref) } } -// Getter function for string index -static const char* GetString(void* column, size_t ndx) -{ - return ((AdaptiveStringColumn*)column)->Get(ndx); -} - StringIndex& AdaptiveStringColumn::CreateIndex() { - TIGHTDB_ASSERT(m_index == NULL); + TIGHTDB_ASSERT(!m_index); // Create new index - m_index = new StringIndex(this, &GetString, m_array->GetAllocator()); + m_index = new StringIndex(this, &get_string, m_array->GetAllocator()); // Populate the index const size_t count = Size(); for (size_t i = 0; i < count; ++i) { - const char* const value = Get(i); + StringData value = get(i); m_index->Insert(i, value, true); } @@ -114,7 +113,7 @@ StringIndex& AdaptiveStringColumn::CreateIndex() void AdaptiveStringColumn::SetIndexRef(size_t ref, ArrayParent* parent, size_t pndx) { TIGHTDB_ASSERT(!m_index); - m_index = new StringIndex(ref, parent, pndx, this, &GetString, m_array->GetAllocator()); + m_index = new StringIndex(ref, parent, pndx, this, &get_string, m_array->GetAllocator()); } bool AdaptiveStringColumn::is_empty() const TIGHTDB_NOEXCEPT @@ -124,10 +123,10 @@ bool AdaptiveStringColumn::is_empty() const TIGHTDB_NOEXCEPT return offsets.is_empty(); } else if (IsLongStrings()) { - return (static_cast(m_array))->is_empty(); + return static_cast(m_array)->is_empty(); } else { - return (static_cast(m_array))->is_empty(); + return static_cast(m_array)->is_empty(); } } @@ -139,10 +138,10 @@ size_t AdaptiveStringColumn::Size() const TIGHTDB_NOEXCEPT return size; } else if (IsLongStrings()) { - return (static_cast(m_array))->size(); + return static_cast(m_array)->size(); } else { - return (static_cast(m_array))->size(); + return static_cast(m_array)->size(); } } @@ -156,9 +155,11 @@ void AdaptiveStringColumn::Clear() m_array = array; } else if (IsLongStrings()) { - (static_cast(m_array))->Clear(); + static_cast(m_array)->Clear(); + } + else { + static_cast(m_array)->Clear(); } - else (static_cast(m_array))->Clear(); if (m_index) m_index->Clear(); @@ -169,13 +170,15 @@ void AdaptiveStringColumn::Resize(size_t ndx) TIGHTDB_ASSERT(!IsNode()); // currently only available on leaf level (used by b-tree code) if (IsLongStrings()) { - (static_cast(m_array))->Resize(ndx); + static_cast(m_array)->Resize(ndx); + } + else { + static_cast(m_array)->Resize(ndx); } - else (static_cast(m_array))->Resize(ndx); } -void AdaptiveStringColumn::Set(size_t ndx, const char* value) +void AdaptiveStringColumn::set(size_t ndx, StringData str) { TIGHTDB_ASSERT(ndx < Size()); @@ -184,22 +187,22 @@ void AdaptiveStringColumn::Set(size_t ndx, const char* value) // the value, or the index would not be able to find the correct // position to update (as it looks for the old value)) if (m_index) { - const char* const oldVal = Get(ndx); - m_index->Set(ndx, oldVal, value); + StringData oldVal = get(ndx); + m_index->Set(ndx, oldVal, str); } - TreeSet(ndx, value); + TreeSet(ndx, str); } -void AdaptiveStringColumn::Insert(size_t ndx, const char* value) +void AdaptiveStringColumn::insert(size_t ndx, StringData str) { TIGHTDB_ASSERT(ndx <= Size()); - TreeInsert(ndx, value); + TreeInsert(ndx, str); if (m_index) { const bool isLast = (ndx+1 == Size()); - m_index->Insert(ndx, value, isLast); + m_index->Insert(ndx, str, isLast); } } @@ -212,7 +215,7 @@ void AdaptiveStringColumn::fill(size_t count) // TODO: this is a very naive approach // we could speedup by creating full nodes directly for (size_t i = 0; i < count; ++i) { - TreeInsert(i, ""); + TreeInsert(i, StringData()); } #ifdef TIGHTDB_DEBUG @@ -220,7 +223,7 @@ void AdaptiveStringColumn::fill(size_t count) #endif } -void AdaptiveStringColumn::Delete(size_t ndx) +void AdaptiveStringColumn::erase(size_t ndx) { TIGHTDB_ASSERT(ndx < Size()); @@ -229,20 +232,19 @@ void AdaptiveStringColumn::Delete(size_t ndx) // the value, or the index would not be able to find the correct // position to update (as it looks for the old value)) if (m_index) { - const char* const oldVal = Get(ndx); + StringData oldVal = get(ndx); const bool isLast = (ndx == Size()); - m_index->Delete(ndx, oldVal, isLast); + m_index->erase(ndx, oldVal, isLast); } - TreeDelete(ndx); + TreeDelete(ndx); } -size_t AdaptiveStringColumn::count(const char* target) const +size_t AdaptiveStringColumn::count(StringData target) const { - TIGHTDB_ASSERT(target); - - if (m_index) + if (m_index) { return m_index->count(target); + } size_t count = 0; @@ -259,67 +261,65 @@ size_t AdaptiveStringColumn::count(const char* target) const } else { if (IsLongStrings()) - count += ((ArrayStringLong*)m_array)->count(target); + count += static_cast(m_array)->count(target); else - count +=((ArrayString*)m_array)->count(target); + count += static_cast(m_array)->count(target); } return count; } -size_t AdaptiveStringColumn::find_first(const char* value, size_t start, size_t end) const +size_t AdaptiveStringColumn::find_first(StringData value, size_t begin, size_t end) const { - TIGHTDB_ASSERT(value); - - if (m_index && start == 0 && end == (size_t)-1) + if (m_index && begin == 0 && end == size_t(-1)) { return m_index->find_first(value); + } - return TreeFind(value, start, end); + return TreeFind(value, begin, end); } -void AdaptiveStringColumn::find_all(Array &result, const char* value, size_t start, size_t end) const +void AdaptiveStringColumn::find_all(Array &result, StringData value, size_t begin, size_t end) const { - TIGHTDB_ASSERT(value); - - if (m_index && start == 0 && end == (size_t)-1) + if (m_index && begin == 0 && end == size_t(-1)) { return m_index->find_all(result, value); + } - TreeFindAll(result, value, 0, start, end); + TreeFindAll(result, value, 0, begin, end); } -const char* AdaptiveStringColumn::LeafGet(size_t ndx) const TIGHTDB_NOEXCEPT +StringData AdaptiveStringColumn::LeafGet(size_t ndx) const TIGHTDB_NOEXCEPT { if (IsLongStrings()) { - return static_cast(m_array)->Get(ndx); + return static_cast(m_array)->get(ndx); } else { - return static_cast(m_array)->Get(ndx); + return static_cast(m_array)->get(ndx); } } -void AdaptiveStringColumn::LeafSet(size_t ndx, const char* value) +void AdaptiveStringColumn::LeafSet(size_t ndx, StringData value) { // Easy to set if the strings fit - const size_t len = strlen(value); if (IsLongStrings()) { - ((ArrayStringLong*)m_array)->Set(ndx, value, len); + static_cast(m_array)->set(ndx, value); return; } - else if (len < 16) { - ((ArrayString*)m_array)->Set(ndx, value); + if (value.size() < 16) { + static_cast(m_array)->set(ndx, value); return; } // Replace string array with long string array - ArrayStringLong* const newarray = new ArrayStringLong((Array*)NULL, 0, m_array->GetAllocator()); + ArrayStringLong* const newarray = + new ArrayStringLong(static_cast(0), 0, m_array->GetAllocator()); // Copy strings to new array - ArrayString* const oldarray = (ArrayString*)m_array; + ArrayString* const oldarray = static_cast(m_array); for (size_t i = 0; i < oldarray->size(); ++i) { - newarray->add(oldarray->Get(i)); + newarray->add(oldarray->get(i)); } - newarray->Set(ndx, value, len); + newarray->set(ndx, value); // Update parent to point to new array ArrayParent *const parent = oldarray->GetParent(); @@ -335,29 +335,29 @@ void AdaptiveStringColumn::LeafSet(size_t ndx, const char* value) delete oldarray; } -void AdaptiveStringColumn::LeafInsert(size_t ndx, const char* value) +void AdaptiveStringColumn::LeafInsert(size_t ndx, StringData value) { // Easy to insert if the strings fit - const size_t len = strlen(value); if (IsLongStrings()) { - ((ArrayStringLong*)m_array)->Insert(ndx, value, len); + static_cast(m_array)->insert(ndx, value); return; } - else if (len < 16) { - ((ArrayString*)m_array)->Insert(ndx, value); + if (value.size() < 16) { + static_cast(m_array)->insert(ndx, value); return; } // Replace string array with long string array - ArrayStringLong* const newarray = new ArrayStringLong((Array*)NULL, 0, m_array->GetAllocator()); + ArrayStringLong* const newarray = + new ArrayStringLong(static_cast(0), 0, m_array->GetAllocator()); // Copy strings to new array - ArrayString* const oldarray = (ArrayString*)m_array; + ArrayString* const oldarray = static_cast(m_array); const size_t n = oldarray->size(); for (size_t i=0; iadd(oldarray->Get(i)); + newarray->add(oldarray->get(i)); } - newarray->Insert(ndx, value, len); + newarray->insert(ndx, value); // Update parent to point to new array ArrayParent *const parent = oldarray->GetParent(); @@ -373,98 +373,61 @@ void AdaptiveStringColumn::LeafInsert(size_t ndx, const char* value) delete oldarray; } -template -size_t AdaptiveStringColumn::LeafFind(const char* value, size_t start, size_t end) const +template size_t AdaptiveStringColumn::LeafFind(StringData value, size_t begin, size_t end) const { if (IsLongStrings()) { - return ((ArrayStringLong*)m_array)->find_first(value, start, end); - } - else { - return ((ArrayString*)m_array)->find_first(value, start, end); + return static_cast(m_array)->find_first(value, begin, end); } + return static_cast(m_array)->find_first(value, begin, end); } -void AdaptiveStringColumn::LeafFindAll(Array &result, const char* value, size_t add_offset, size_t start, size_t end) const +void AdaptiveStringColumn::LeafFindAll(Array &result, StringData value, size_t add_offset, size_t begin, size_t end) const { if (IsLongStrings()) { - return ((ArrayStringLong*)m_array)->find_all(result, value, add_offset, start, end); - } - else { - return ((ArrayString*)m_array)->find_all(result, value, add_offset, start, end); + return static_cast(m_array)->find_all(result, value, add_offset, begin, end); } + return static_cast(m_array)->find_all(result, value, add_offset, begin, end); } void AdaptiveStringColumn::LeafDelete(size_t ndx) { if (IsLongStrings()) { - ((ArrayStringLong*)m_array)->Delete(ndx); + static_cast(m_array)->erase(ndx); } else { - ((ArrayString*)m_array)->Delete(ndx); + static_cast(m_array)->erase(ndx); } } -bool AdaptiveStringColumn::FindKeyPos(const char* target, size_t& pos) const -{ - const int len = (int)Size(); - bool found = false; - ssize_t low = -1; - ssize_t high = len; - - // Binary search based on: - // http://www.tbray.org/ongoing/When/200x/2003/03/22/Binary - // Finds position of closest value BIGGER OR EQUAL to the target (for - // lookups in indexes) - while (high - low > 1) { - const ssize_t probe = ((size_t)low + (size_t)high) >> 1; - const char* v = Get(probe); - - const int cmp = strcmp(v, target); - - if (cmp < 0) low = probe; - else { - high = probe; - if (cmp == 0) found = true; - } - } - - pos = high; - return found; -} - bool AdaptiveStringColumn::AutoEnumerate(size_t& ref_keys, size_t& ref_values) const { AdaptiveStringColumn keys(m_array->GetAllocator()); // Generate list of unique values (keys) - const size_t count = Size(); - for (size_t i = 0; i < count; ++i) { - const char* v = Get(i); + size_t n = Size(); + for (size_t i=0; i (count / 2)) { - keys.Destroy(); // cleanup - return false; - } - - keys.Insert(pos, v); + size_t pos = keys.lower_bound(v); + if (pos != keys.Size() && keys.get(pos) == v) continue; + + // Don't bother auto enumerating if there are too few duplicates + if (n/2 < keys.Size()) { + keys.Destroy(); // cleanup + return false; } + + keys.insert(pos, v); } // Generate enumerated list of entries Column values(m_array->GetAllocator()); - for (size_t i = 0; i < count; ++i) { - const char* v = Get(i); - - size_t pos; - const bool res = keys.FindKeyPos(v, pos); // todo/fixme, res isn't used - TIGHTDB_ASSERT(res); - static_cast(res); - + for (size_t i=0; i(0), 0, array.GetAllocator()); str_array.ToDot(out); } else { - ((ArrayString&)array).ToDot(out); + static_cast(array).ToDot(out); } } diff --git a/src/tightdb/column_string.hpp b/src/tightdb/column_string.hpp index 6f6528cd469..60ca03a8c8b 100644 --- a/src/tightdb/column_string.hpp +++ b/src/tightdb/column_string.hpp @@ -29,32 +29,39 @@ namespace tightdb { // Pre-declarations class StringIndex; -class AdaptiveStringColumn : public ColumnBase { +class AdaptiveStringColumn: public ColumnBase { public: - AdaptiveStringColumn(Allocator& alloc=Allocator::get_default()); - AdaptiveStringColumn(size_t ref, ArrayParent* parent=NULL, size_t pndx=0, - Allocator& alloc=Allocator::get_default()); + AdaptiveStringColumn(Allocator& = Allocator::get_default()); + AdaptiveStringColumn(std::size_t ref, ArrayParent* = 0, std::size_t ndx_in_parent = 0, + Allocator& = Allocator::get_default()); ~AdaptiveStringColumn(); void Destroy(); - size_t Size() const TIGHTDB_NOEXCEPT TIGHTDB_OVERRIDE; + std::size_t Size() const TIGHTDB_NOEXCEPT TIGHTDB_OVERRIDE; bool is_empty() const TIGHTDB_NOEXCEPT; - const char* Get(size_t ndx) const TIGHTDB_NOEXCEPT; - void add() TIGHTDB_OVERRIDE {return add("");} - void add(const char* value); - void Set(size_t ndx, const char* value); - void insert(size_t ndx) TIGHTDB_OVERRIDE { Insert(ndx, ""); } - void Insert(size_t ndx, const char* value); - void Delete(size_t ndx) TIGHTDB_OVERRIDE; + StringData get(std::size_t ndx) const TIGHTDB_NOEXCEPT; + void add() TIGHTDB_OVERRIDE {return add(StringData());} + void add(StringData); + void set(std::size_t ndx, StringData); + void insert(std::size_t ndx) TIGHTDB_OVERRIDE { insert(ndx, StringData()); } + void insert(std::size_t ndx, StringData); + void erase(std::size_t ndx) TIGHTDB_OVERRIDE; void Clear() TIGHTDB_OVERRIDE; - void Resize(size_t ndx); - void fill(size_t count); + void Resize(std::size_t ndx); + void fill(std::size_t count); - size_t count(const char* value) const; - size_t find_first(const char* value, size_t start=0 , size_t end=-1) const; - void find_all(Array& result, const char* value, size_t start = 0, size_t end = -1) const; + std::size_t count(StringData value) const; + std::size_t find_first(StringData value, std::size_t begin = 0 , std::size_t end = -1) const; + void find_all(Array& result, StringData value, std::size_t start = 0, + std::size_t end = -1) const; + + /// Find the lower bound for the specified value assuming that the + /// elements are already sorted according to + /// StringData::operator<(). This operation is semantically + /// identical to std::lower_bound(). + std::size_t lower_bound(StringData value) const TIGHTDB_NOEXCEPT; // Index bool HasIndex() const {return m_index != NULL;} @@ -111,7 +118,7 @@ class AdaptiveStringColumn : public ColumnBase { void Verify() const; // Must be upper case to avoid conflict with macro in ObjC #endif // TIGHTDB_DEBUG - // Assumes that this column has only a single leaf node, no + // Assumes that this column has only a single leaf node, no // internal nodes. In this case HasRefs indicates a long string // array. bool IsLongStrings() const TIGHTDB_NOEXCEPT {return m_array->HasRefs();} @@ -120,16 +127,15 @@ class AdaptiveStringColumn : public ColumnBase { friend class ColumnBase; void UpdateRef(size_t ref); - const char* LeafGet(size_t ndx) const TIGHTDB_NOEXCEPT; - void LeafSet(size_t ndx, const char* value); - void LeafInsert(size_t ndx, const char* value); - template size_t LeafFind(const char* value, size_t start, size_t end) const; - void LeafFindAll(Array& result, const char* value, size_t add_offset = 0, size_t start = 0, size_t end = -1) const; + StringData LeafGet(size_t ndx) const TIGHTDB_NOEXCEPT; + void LeafSet(size_t ndx, StringData value); + void LeafInsert(size_t ndx, StringData value); + template size_t LeafFind(StringData value, size_t begin, size_t end) const; + void LeafFindAll(Array& result, StringData value, size_t add_offset = 0, + size_t begin = 0, size_t end = -1) const; void LeafDelete(size_t ndx); - bool FindKeyPos(const char* target, size_t& pos) const; - #ifdef TIGHTDB_DEBUG virtual void LeafToDot(std::ostream& out, const Array& array) const; #endif // TIGHTDB_DEBUG @@ -144,15 +150,35 @@ class AdaptiveStringColumn : public ColumnBase { // Implementation: -inline const char* AdaptiveStringColumn::Get(std::size_t ndx) const TIGHTDB_NOEXCEPT +inline StringData AdaptiveStringColumn::get(std::size_t ndx) const TIGHTDB_NOEXCEPT { TIGHTDB_ASSERT(ndx < Size()); return m_array->string_column_get(ndx); } -inline void AdaptiveStringColumn::add(const char* value) +inline void AdaptiveStringColumn::add(StringData str) +{ + insert(Size(), str); +} + +inline std::size_t AdaptiveStringColumn::lower_bound(StringData value) const TIGHTDB_NOEXCEPT { - Insert(Size(), value); + std::size_t i = 0; + std::size_t size = Size(); + + while (0 < size) { + std::size_t half = size / 2; + std::size_t mid = i + half; + StringData probe = get(mid); + if (probe < value) { + i = mid + 1; + size -= half + 1; + } + else { + size = half; + } + } + return i; } diff --git a/src/tightdb/column_string_enum.cpp b/src/tightdb/column_string_enum.cpp index 294c8eedea0..57dd864d050 100644 --- a/src/tightdb/column_string_enum.cpp +++ b/src/tightdb/column_string_enum.cpp @@ -1,6 +1,19 @@ #include #include +using namespace std; + +namespace { + +// Getter function for string index +tightdb::StringData get_string(void* column, size_t ndx) +{ + return static_cast(column)->get(ndx); +} + +} // anonymous namespace + + namespace tightdb { ColumnStringEnum::ColumnStringEnum(size_t ref_keys, size_t ref_values, ArrayParent* parent, @@ -34,51 +47,49 @@ void ColumnStringEnum::UpdateFromParent() m_keys.UpdateFromParent(); } -const char* ColumnStringEnum::Get(size_t ndx) const TIGHTDB_NOEXCEPT +StringData ColumnStringEnum::get(size_t ndx) const TIGHTDB_NOEXCEPT { TIGHTDB_ASSERT(ndx < Column::Size()); - const size_t key_ndx = Column::GetAsRef(ndx); - return m_keys.Get(key_ndx); + size_t key_ndx = Column::GetAsRef(ndx); + return m_keys.get(key_ndx); } -void ColumnStringEnum::add(const char* value) +void ColumnStringEnum::add(StringData value) { - Insert(Column::Size(), value); + insert(Column::Size(), value); } -void ColumnStringEnum::Set(size_t ndx, const char* value) +void ColumnStringEnum::set(size_t ndx, StringData value) { TIGHTDB_ASSERT(ndx < Column::Size()); - TIGHTDB_ASSERT(value); // Update index // (it is important here that we do it before actually setting // the value, or the index would not be able to find the correct // position to update (as it looks for the old value)) if (m_index) { - const char* const oldVal = Get(ndx); + StringData oldVal = get(ndx); m_index->Set(ndx, oldVal, value); } - const size_t key_ndx = GetKeyNdxOrAdd(value); - Column::Set(ndx, key_ndx); + size_t key_ndx = GetKeyNdxOrAdd(value); + Column::set(ndx, key_ndx); } -void ColumnStringEnum::Insert(size_t ndx, const char* value) +void ColumnStringEnum::insert(size_t ndx, StringData value) { TIGHTDB_ASSERT(ndx <= Column::Size()); - TIGHTDB_ASSERT(value); const size_t key_ndx = GetKeyNdxOrAdd(value); - Column::Insert(ndx, key_ndx); + Column::insert(ndx, key_ndx); if (m_index) { - const bool isLast = (ndx+1 == Size()); + const bool isLast = ndx+1 == Size(); m_index->Insert(ndx, value, isLast); } } -void ColumnStringEnum::Delete(size_t ndx) +void ColumnStringEnum::erase(size_t ndx) { TIGHTDB_ASSERT(ndx < Column::Size()); @@ -87,12 +98,12 @@ void ColumnStringEnum::Delete(size_t ndx) // the value, or the index would not be able to find the correct // position to update (as it looks for the old value)) if (m_index) { - const char* const oldVal = Get(ndx); - const bool isLast = (ndx == Size()); - m_index->Delete(ndx, oldVal, isLast); + StringData oldVal = get(ndx); + const bool isLast = ndx == Size(); + m_index->erase(ndx, oldVal, isLast); } - Column::Delete(ndx); + Column::erase(ndx); } void ColumnStringEnum::Clear() @@ -109,64 +120,64 @@ size_t ColumnStringEnum::count(size_t key_ndx) const return Column::count(key_ndx); } -size_t ColumnStringEnum::count(const char* value) const +size_t ColumnStringEnum::count(StringData value) const { if (m_index) return m_index->count(value); - const size_t key_ndx = m_keys.find_first(value); + size_t key_ndx = m_keys.find_first(value); if (key_ndx == not_found) return 0; return Column::count(key_ndx); } -void ColumnStringEnum::find_all(Array& res, const char* value, size_t start, size_t end) const +void ColumnStringEnum::find_all(Array& res, StringData value, size_t begin, size_t end) const { - if (m_index && start == 0 && end == (size_t)-1) + if (m_index && begin == 0 && end == size_t(-1)) return m_index->find_all(res, value); - const size_t key_ndx = m_keys.find_first(value); - if (key_ndx == (size_t)-1) return; - Column::find_all(res, key_ndx, 0, start, end); + size_t key_ndx = m_keys.find_first(value); + if (key_ndx == size_t(-1)) return; + Column::find_all(res, key_ndx, 0, begin, end); return; } -void ColumnStringEnum::find_all(Array& res, size_t key_ndx, size_t start, size_t end) const +void ColumnStringEnum::find_all(Array& res, size_t key_ndx, size_t begin, size_t end) const { - if (key_ndx == (size_t)-1) return; - Column::find_all(res, key_ndx, 0, start, end); + if (key_ndx == size_t(-1)) return; + Column::find_all(res, key_ndx, 0, begin, end); return; } -size_t ColumnStringEnum::find_first(size_t key_ndx, size_t start, size_t end) const +size_t ColumnStringEnum::find_first(size_t key_ndx, size_t begin, size_t end) const { // Find key - if (key_ndx == (size_t)-1) return (size_t)-1; + if (key_ndx == size_t(-1)) return size_t(-1); - return Column::find_first(key_ndx, start, end); + return Column::find_first(key_ndx, begin, end); } -size_t ColumnStringEnum::find_first(const char* value, size_t start, size_t end) const +size_t ColumnStringEnum::find_first(StringData value, size_t begin, size_t end) const { - if (m_index && start == 0 && end == (size_t)-1) + if (m_index && begin == 0 && end == size_t(-1)) return m_index->find_first(value); // Find key - const size_t key_ndx = m_keys.find_first(value); - if (key_ndx == (size_t)-1) return (size_t)-1; + size_t key_ndx = m_keys.find_first(value); + if (key_ndx == size_t(-1)) return size_t(-1); - return Column::find_first(key_ndx, start, end); + return Column::find_first(key_ndx, begin, end); } -size_t ColumnStringEnum::GetKeyNdx(const char* value) const +size_t ColumnStringEnum::GetKeyNdx(StringData value) const { return m_keys.find_first(value); } -size_t ColumnStringEnum::GetKeyNdxOrAdd(const char* value) +size_t ColumnStringEnum::GetKeyNdxOrAdd(StringData value) { const size_t res = m_keys.find_first(value); - if (res != (size_t)-1) return res; + if (res != size_t(-1)) return res; else { // Add key if it does not exist const size_t pos = m_keys.Size(); @@ -180,9 +191,7 @@ bool ColumnStringEnum::compare(const AdaptiveStringColumn& c) const const size_t n = Size(); if (c.Size() != n) return false; for (size_t i=0; i(column)->Get(ndx); -} - - StringIndex& ColumnStringEnum::CreateIndex() { TIGHTDB_ASSERT(m_index == NULL); // Create new index - m_index = new StringIndex(this, &GetString, m_array->GetAllocator()); + m_index = new StringIndex(this, &get_string, m_array->GetAllocator()); // Populate the index const size_t count = Size(); for (size_t i = 0; i < count; ++i) { - const char* const value = Get(i); + StringData value = get(i); m_index->Insert(i, value, true); } @@ -227,14 +227,14 @@ StringIndex& ColumnStringEnum::CreateIndex() void ColumnStringEnum::SetIndexRef(size_t ref, ArrayParent* parent, size_t pndx) { TIGHTDB_ASSERT(m_index == NULL); - m_index = new StringIndex(ref, parent, pndx, this, &GetString, m_array->GetAllocator()); + m_index = new StringIndex(ref, parent, pndx, this, &get_string, m_array->GetAllocator()); } void ColumnStringEnum::ReuseIndex(StringIndex& index) { TIGHTDB_ASSERT(m_index == NULL); - index.SetTarget(this, &GetString); + index.SetTarget(this, &get_string); m_index = &index; // we now own this index } @@ -247,19 +247,19 @@ void ColumnStringEnum::Verify() const Column::Verify(); } -void ColumnStringEnum::ToDot(std::ostream& out, const char* title) const +void ColumnStringEnum::ToDot(ostream& out, StringData title) const { const size_t ref = m_keys.GetRef(); - out << "subgraph cluster_columnstringenum" << ref << " {" << std::endl; + out << "subgraph cluster_columnstringenum" << ref << " {" << endl; out << " label = \"ColumnStringEnum"; - if (title) out << "\\n'" << title << "'"; - out << "\";" << std::endl; + if (0 < title.size()) out << "\\n'" << title << "'"; + out << "\";" << endl; m_keys.ToDot(out, "keys"); Column::ToDot(out, "values"); - out << "}" << std::endl; + out << "}" << endl; } #endif // TIGHTDB_DEBUG diff --git a/src/tightdb/column_string_enum.hpp b/src/tightdb/column_string_enum.hpp index 2f0df8cf762..bb109a936ce 100644 --- a/src/tightdb/column_string_enum.hpp +++ b/src/tightdb/column_string_enum.hpp @@ -27,29 +27,30 @@ namespace tightdb { // Pre-declarations class StringIndex; -class ColumnStringEnum : public Column { +class ColumnStringEnum: public Column { public: ColumnStringEnum(size_t ref_keys, size_t ref_values, ArrayParent* parent=NULL, size_t pndx=0, Allocator& alloc = Allocator::get_default()); ~ColumnStringEnum(); void Destroy(); - const char* Get(size_t ndx) const TIGHTDB_NOEXCEPT; - void add(const char* value); - void Set(size_t ndx, const char* value); - void Insert(size_t ndx, const char* value); - void Delete(size_t ndx) TIGHTDB_OVERRIDE; + StringData get(std::size_t ndx) const TIGHTDB_NOEXCEPT; + void add(StringData value); + void set(std::size_t ndx, StringData value); + void insert(std::size_t ndx, StringData value); + void erase(std::size_t ndx) TIGHTDB_OVERRIDE; void Clear() TIGHTDB_OVERRIDE; using Column::add; + using Column::insert; - size_t count(const char* value) const; - size_t find_first(const char* value, size_t start=0, size_t end=-1) const; - void find_all(Array& res, const char* value, size_t start=0, size_t end=-1) const; + size_t count(StringData value) const; + size_t find_first(StringData value, size_t begin=0, size_t end=-1) const; + void find_all(Array& res, StringData value, size_t begin=0, size_t end=-1) const; size_t count(size_t key_index) const; - size_t find_first(size_t key_index, size_t start=0, size_t end=-1) const; - void find_all(Array& res, size_t key_index, size_t start=0, size_t end=-1) const; + size_t find_first(size_t key_index, size_t begin=0, size_t end=-1) const; + void find_all(Array& res, size_t key_index, size_t begin=0, size_t end=-1) const; void UpdateParentNdx(int diff); void UpdateFromParent(); @@ -70,11 +71,11 @@ class ColumnStringEnum : public Column { #ifdef TIGHTDB_DEBUG void Verify() const; // Must be upper case to avoid conflict with macro in ObjC - void ToDot(std::ostream& out, const char* title) const; + void ToDot(std::ostream& out, StringData title) const; #endif // TIGHTDB_DEBUG - size_t GetKeyNdx(const char* value) const; - size_t GetKeyNdxOrAdd(const char* value); + size_t GetKeyNdx(StringData value) const; + size_t GetKeyNdxOrAdd(StringData value); private: // Member variables diff --git a/src/tightdb/column_table.cpp b/src/tightdb/column_table.cpp index b84d2df139e..481a474f2cb 100644 --- a/src/tightdb/column_table.cpp +++ b/src/tightdb/column_table.cpp @@ -54,7 +54,7 @@ void ColumnTable::insert(size_t ndx, const Table* subtable) if (subtable) columns_ref = clone_table_columns(subtable); - Column::Insert(ndx, columns_ref); + Column::insert(ndx, columns_ref); } void ColumnTable::fill(size_t count) @@ -69,7 +69,7 @@ void ColumnTable::fill(size_t count) } } -void ColumnTable::Delete(size_t ndx) +void ColumnTable::erase(size_t ndx) { TIGHTDB_ASSERT(ndx < Size()); @@ -78,11 +78,11 @@ void ColumnTable::Delete(size_t ndx) // Delete sub-tree if (ref_columns != 0) { Allocator& alloc = GetAllocator(); - Array columns(ref_columns, (Array*)NULL, 0, alloc); + Array columns(ref_columns, 0, 0, alloc); columns.Destroy(); } - Column::Delete(ndx); + Column::erase(ndx); invalidate_subtables(); } @@ -96,11 +96,11 @@ void ColumnTable::ClearTable(size_t ndx) // Delete sub-tree Allocator& alloc = GetAllocator(); - Array columns(ref_columns, (Array*)NULL, 0, alloc); + Array columns(ref_columns, 0, 0, alloc); columns.Destroy(); // Mark as empty table - Set(ndx, 0); + set(ndx, 0); } bool ColumnTable::compare(const ColumnTable& c) const @@ -132,7 +132,7 @@ void ColumnTable::Verify() const } } -void ColumnTable::LeafToDot(std::ostream& out, const Array& array) const +void ColumnTable::LeafToDot(ostream& out, const Array& array) const { array.ToDot(out); diff --git a/src/tightdb/column_table.hpp b/src/tightdb/column_table.hpp index 46121854cfc..eaf0fbc75f9 100644 --- a/src/tightdb/column_table.hpp +++ b/src/tightdb/column_table.hpp @@ -36,7 +36,7 @@ class ColumnSubtableParent: public Column, public Table::Parent { void Clear() TIGHTDB_OVERRIDE { m_array->Clear(); - if (m_array->IsNode()) m_array->SetType(coldef_HasRefs); + if (m_array->IsNode()) m_array->SetType(Array::coldef_HasRefs); invalidate_subtables(); } @@ -184,7 +184,7 @@ class ColumnTable: public ColumnSubtableParent { void add(const Table*); void insert(std::size_t ndx) TIGHTDB_OVERRIDE; void insert(std::size_t ndx, const Table*); - void Delete(size_t ndx) TIGHTDB_OVERRIDE; + void erase(size_t ndx) TIGHTDB_OVERRIDE; void ClearTable(size_t ndx); void fill(size_t count); @@ -276,8 +276,8 @@ inline Table* ColumnSubtableParent::SubtableMap::find(size_t subtable_ndx) const inline void ColumnSubtableParent::SubtableMap::insert(size_t subtable_ndx, Table* wrapper) { if (!m_indices.IsValid()) { - m_indices.SetType(coldef_Normal); - m_wrappers.SetType(coldef_Normal); + m_indices.SetType(Array::coldef_Normal); + m_wrappers.SetType(Array::coldef_Normal); } m_indices.add(subtable_ndx); m_wrappers.add(reinterpret_cast(wrapper)); @@ -322,21 +322,21 @@ inline void ColumnSubtableParent::SubtableMap::invalidate_subtables() inline ColumnSubtableParent::ColumnSubtableParent(Allocator& alloc, const Table* table, std::size_t column_ndx): - Column(coldef_HasRefs, alloc), - m_table(table), m_index(column_ndx), - m_subtable_map(Allocator::get_default()) {} + Column(Array::coldef_HasRefs, alloc), + m_table(table), m_index(column_ndx), + m_subtable_map(Allocator::get_default()) {} inline ColumnSubtableParent::ColumnSubtableParent(Allocator& alloc, const Table* table, std::size_t column_ndx, ArrayParent* parent, std::size_t ndx_in_parent, std::size_t ref): - Column(ref, parent, ndx_in_parent, alloc), - m_table(table), m_index(column_ndx), - m_subtable_map(Allocator::get_default()) {} + Column(ref, parent, ndx_in_parent, alloc), + m_table(table), m_index(column_ndx), + m_subtable_map(Allocator::get_default()) {} inline void ColumnSubtableParent::update_child_ref(size_t subtable_ndx, size_t new_ref) { - Set(subtable_ndx, new_ref); + set(subtable_ndx, new_ref); } inline size_t ColumnSubtableParent::get_child_ref(size_t subtable_ndx) const TIGHTDB_NOEXCEPT diff --git a/src/tightdb/column_tpl.hpp b/src/tightdb/column_tpl.hpp index 17bf238d51f..cbadc334634 100644 --- a/src/tightdb/column_tpl.hpp +++ b/src/tightdb/column_tpl.hpp @@ -124,7 +124,7 @@ template void ColumnBase::TreeSet(size_t ndx, T value) // Set item C target = GetColumnFromRef(refs, node_ndx); - target.Set(local_ndx, value); + target.set(local_ndx, value); } else { static_cast(this)->LeafSet(ndx, value); @@ -141,21 +141,21 @@ template void ColumnBase::TreeInsert(size_t ndx, T value) case NodeChange::none: return; case NodeChange::insert_before: { - Column newNode(coldef_InnerNode, m_array->GetAllocator()); + Column newNode(Array::coldef_InnerNode, m_array->GetAllocator()); newNode.NodeAdd(nc.ref1); newNode.NodeAdd(GetRef()); static_cast(this)->UpdateRef(newNode.GetRef()); return; } case NodeChange::insert_after: { - Column newNode(coldef_InnerNode, m_array->GetAllocator()); + Column newNode(Array::coldef_InnerNode, m_array->GetAllocator()); newNode.NodeAdd(GetRef()); newNode.NodeAdd(nc.ref1); static_cast(this)->UpdateRef(newNode.GetRef()); return; } case NodeChange::split: { - Column newNode(coldef_InnerNode, m_array->GetAllocator()); + Column newNode(Array::coldef_InnerNode, m_array->GetAllocator()); newNode.NodeAdd(nc.ref1); newNode.NodeAdd(nc.ref2); static_cast(this)->UpdateRef(newNode.GetRef()); @@ -203,7 +203,7 @@ template Column::NodeChange ColumnBase::DoInsert(size_t ndx } // Else create new node - Column newNode(coldef_InnerNode, m_array->GetAllocator()); + Column newNode(Array::coldef_InnerNode, m_array->GetAllocator()); if (nc.type == NodeChange::split) { // update offset for left node const size_t newsize = target.Size(); diff --git a/src/tightdb/data_type.hpp b/src/tightdb/data_type.hpp index 0acabcbbce1..908fe2843d9 100644 --- a/src/tightdb/data_type.hpp +++ b/src/tightdb/data_type.hpp @@ -29,11 +29,11 @@ namespace tightdb { enum DataType { type_Int = 0, type_Bool = 1, - type_Date = 7, type_Float = 9, type_Double = 10, type_String = 2, type_Binary = 4, + type_Date = 7, type_Table = 5, type_Mixed = 6 }; diff --git a/src/tightdb/date.hpp b/src/tightdb/date.hpp index a4eb519f0df..67163188536 100644 --- a/src/tightdb/date.hpp +++ b/src/tightdb/date.hpp @@ -37,8 +37,9 @@ class Date { /// Return the time as seconds since Jan 1 00:00:00 UTC 1970. std::time_t get_date() const TIGHTDB_NOEXCEPT { return m_time; } - bool operator==(const Date& d) const TIGHTDB_NOEXCEPT { return m_time == d.m_time; } - bool operator!=(const Date& d) const TIGHTDB_NOEXCEPT { return m_time != d.m_time; } + friend bool operator==(const Date&, const Date&) TIGHTDB_NOEXCEPT; + friend bool operator!=(const Date&, const Date&) TIGHTDB_NOEXCEPT; + friend bool operator< (const Date&, const Date&) TIGHTDB_NOEXCEPT; /// Construct from broken down local time. /// @@ -59,34 +60,61 @@ class Date { /// /// \param seconds Seconds after the minute in the range [0, /// 60]. Note that the range allows for leap seconds. - Date(int year, int month, int day, int hours = 0, int minutes = 0, int seconds = 0): - m_time(assemble(year, month, day, hours, minutes, seconds)) {} + Date(int year, int month, int day, int hours = 0, int minutes = 0, int seconds = 0); template - friend std::basic_ostream& operator<<(std::basic_ostream& out, const Date& d) - { - out << "Date("<& operator<<(std::basic_ostream& out, const Date&); private: std::time_t m_time; // Seconds since Jan 1 00:00:00 UTC 1970. - static std::time_t assemble(int year, int month, int day, int hours, int minutes, int seconds) - { - std::tm local_time; - local_time.tm_year = year - 1900; - local_time.tm_mon = month - 1; - local_time.tm_mday = day; - local_time.tm_hour = hours; - local_time.tm_min = minutes; - local_time.tm_sec = seconds; - local_time.tm_isdst = -1; - return std::mktime(&local_time); - } + static std::time_t assemble(int year, int month, int day, int hours, int minutes, int seconds); }; + + +// Implementation: + +inline bool operator==(const Date& a, const Date& b) TIGHTDB_NOEXCEPT +{ + return a.m_time == b.m_time; +} + +inline bool operator!=(const Date& a, const Date& b) TIGHTDB_NOEXCEPT +{ + return a.m_time != b.m_time; +} + +inline bool operator<(const Date& a, const Date& b) TIGHTDB_NOEXCEPT +{ + return a.m_time < b.m_time; +} + +inline Date::Date(int year, int month, int day, int hours, int minutes, int seconds): + m_time(assemble(year, month, day, hours, minutes, seconds)) {} + +template +inline std::basic_ostream& operator<<(std::basic_ostream& out, const Date& d) +{ + out << "Date("<size(); @@ -543,18 +544,18 @@ void Group::to_string(std::ostream& out) const // Print tables for (size_t i = 0; i < count; ++i) { - const char* const name = get_table_name(i); + StringData name = get_table_name(i); ConstTableRef table = get_table(name); const size_t row_count = table->size(); out << i << " "; out.width(name_width); - out.setf(std::ostream::left, std::ostream::adjustfield); + out.setf(ostream::left, ostream::adjustfield); out << name; out << " "; out.width(rows_width); - out.unsetf(std::ostream::adjustfield); - out << row_count << std::endl; + out.unsetf(ostream::adjustfield); + out << row_count << endl; } } @@ -658,7 +659,7 @@ void Group::print_free() const printf("\n"); } -void Group::to_dot(std::ostream& out) const +void Group::to_dot(ostream& out) const { out << "digraph G {" << endl; @@ -672,7 +673,7 @@ void Group::to_dot(std::ostream& out) const // Tables for (size_t i = 0; i < m_tables.size(); ++i) { const Table* table = get_table_ptr(i); - const char* const name = get_table_name(i); + StringData name = get_table_name(i); table->to_dot(out, name); } @@ -682,7 +683,7 @@ void Group::to_dot(std::ostream& out) const void Group::to_dot() const { - to_dot(std::cerr); + to_dot(cerr); } void Group::zero_free_space(size_t file_size, size_t readlock_version) diff --git a/src/tightdb/group.hpp b/src/tightdb/group.hpp index 07224d0f68b..3426adac8f1 100644 --- a/src/tightdb/group.hpp +++ b/src/tightdb/group.hpp @@ -52,19 +52,9 @@ class Group: private Table::Parent { /// default constructed instance. explicit Group(const std::string& file, OpenMode = mode_Normal); - /// Specification of a memory buffer. The purpose of this class is - /// neither to allocate nor to deallocate memory. Its only purpose - /// is to specify the buffer. - struct BufferSpec { - const char* m_data; - std::size_t m_size; - BufferSpec() {} - BufferSpec(const char* d, std::size_t s): m_data(d), m_size(s) {} - }; - - /// Equivalent to calling open(BufferSpec, bool) on a default + /// Equivalent to calling open(BinaryData, bool) on a default /// constructed instance. - explicit Group(BufferSpec, bool take_ownership = true); + explicit Group(BinaryData, bool take_ownership = true); struct unattached_tag {}; @@ -128,7 +118,7 @@ class Group: private Table::Parent { /// /// \throw InvalidDatabase If the specified buffer does not appear /// to contain a valid database. - void open(BufferSpec, bool take_ownership = true); + void open(BinaryData, bool take_ownership = true); /// A group may be created in the unattached state, and then later /// attached to a file with a call to open(). Calling any method @@ -143,17 +133,17 @@ class Group: private Table::Parent { /// Returns the number of tables in this group. size_t size() const; - const char* get_table_name(size_t table_ndx) const; - bool has_table(const char* name) const; + StringData get_table_name(size_t table_ndx) const; + bool has_table(StringData name) const; /// Check whether this group has a table with the specified name /// and type. - template bool has_table(const char* name) const; + template bool has_table(StringData name) const; - TableRef get_table(const char* name); - ConstTableRef get_table(const char* name) const; - template typename T::Ref get_table(const char* name); - template typename T::ConstRef get_table(const char* name) const; + TableRef get_table(StringData name); + ConstTableRef get_table(StringData name) const; + template typename T::Ref get_table(StringData name); + template typename T::ConstRef get_table(StringData name) const; // Serialization @@ -166,15 +156,19 @@ class Group: private Table::Parent { /// reason corresponds to one of the exception types that are /// derived from File::OpenError, the derived exception type is /// thrown. - void write(const std::string& file); + void write(const std::string& file) const; /// Write this database to a memory buffer. /// /// Ownership of the returned buffer is transferred to the /// caller. The memory will have been allocated using /// std::malloc(). - BufferSpec write_to_mem(); + BinaryData write_to_mem() const; + // FIXME: What does this one do? Exactly how is it different from + // calling write()? There is no documentation to be found anywhere + // and it looks like it leaves the group in an invalid state. You + // should probably not use it. void commit(); // Conversion @@ -242,7 +236,7 @@ class Group: private Table::Parent { void create_from_ref(size_t top_ref); // May throw WriteError - template size_t write_to_stream(S& out); + template size_t write_to_stream(S& out) const; // Member variables SlabAlloc m_alloc; @@ -260,15 +254,18 @@ class Group: private Table::Parent { struct shared_tag {}; Group(shared_tag) TIGHTDB_NOEXCEPT; - Table* get_table_ptr(const char* name); - Table* get_table_ptr(const char* name, bool& was_created); - const Table* get_table_ptr(const char* name) const; - template T* get_table_ptr(const char* name); - template const T* get_table_ptr(const char* name) const; + // FIXME: Implement a proper copy constructor (fairly trivial). + Group(const Group&); // Disable copying + + Table* get_table_ptr(StringData name); + Table* get_table_ptr(StringData name, bool& was_created); + const Table* get_table_ptr(StringData name) const; + template T* get_table_ptr(StringData name); + template const T* get_table_ptr(StringData name) const; Table* get_table_ptr(size_t ndx); const Table* get_table_ptr(size_t ndx) const; - Table* create_new_table(const char* name); + Table* create_new_table(StringData name); void clear_cache(); @@ -293,10 +290,10 @@ class Group: private Table::Parent { // ownership of the underlying memory, causes lots of problems with // robustness both here and in other places. inline Group::Group(): - m_top(coldef_HasRefs, NULL, 0, m_alloc), m_tables(m_alloc), m_tableNames(NULL, 0, m_alloc), - m_freePositions(coldef_Normal, NULL, 0, m_alloc), - m_freeLengths(coldef_Normal, NULL, 0, m_alloc), - m_freeVersions(coldef_Normal, NULL, 0, m_alloc), m_is_shared(false) + m_top(Array::coldef_HasRefs, NULL, 0, m_alloc), m_tables(m_alloc), m_tableNames(NULL, 0, m_alloc), + m_freePositions(Array::coldef_Normal, NULL, 0, m_alloc), + m_freeLengths(Array::coldef_Normal, NULL, 0, m_alloc), + m_freeVersions(Array::coldef_Normal, NULL, 0, m_alloc), m_is_shared(false) { // FIXME: Arrays are leaked when create() throws create(); @@ -318,7 +315,7 @@ inline Group::Group(const std::string& file, OpenMode mode): } } -inline Group::Group(BufferSpec buffer, bool take_ownership): +inline Group::Group(BinaryData buffer, bool take_ownership): m_top(m_alloc), m_tables(m_alloc), m_tableNames(m_alloc), m_freePositions(m_alloc), m_freeLengths(m_alloc), m_freeVersions(m_alloc), m_is_shared(false) { @@ -348,11 +345,11 @@ inline void Group::open(const std::string& file, OpenMode mode) create_from_file(file, mode, true); } -inline void Group::open(BufferSpec buffer, bool take_ownership) +inline void Group::open(BinaryData buffer, bool take_ownership) { TIGHTDB_ASSERT(!is_attached()); - TIGHTDB_ASSERT(buffer.m_data); - m_alloc.attach_buffer(buffer.m_data, buffer.m_size, take_ownership); + TIGHTDB_ASSERT(buffer.data()); + m_alloc.attach_buffer(buffer.data(), buffer.size(), take_ownership); create_from_ref(m_alloc.GetTopRef()); // FIXME: Throws and leaves the Group in peril } @@ -378,11 +375,11 @@ inline std::size_t Group::size() const return m_tableNames.size(); } -inline const char* Group::get_table_name(std::size_t table_ndx) const +inline StringData Group::get_table_name(std::size_t table_ndx) const { TIGHTDB_ASSERT(m_top.IsValid()); TIGHTDB_ASSERT(table_ndx < m_tableNames.size()); - return m_tableNames.Get(table_ndx); + return m_tableNames.get(table_ndx); } inline const Table* Group::get_table_ptr(std::size_t ndx) const @@ -390,14 +387,14 @@ inline const Table* Group::get_table_ptr(std::size_t ndx) const return const_cast(this)->get_table_ptr(ndx); } -inline bool Group::has_table(const char* name) const +inline bool Group::has_table(StringData name) const { if (!m_top.IsValid()) return false; const size_t i = m_tableNames.find_first(name); return i != size_t(-1); } -template inline bool Group::has_table(const char* name) const +template inline bool Group::has_table(StringData name) const { if (!m_top.IsValid()) return false; const size_t i = m_tableNames.find_first(name); @@ -406,7 +403,7 @@ template inline bool Group::has_table(const char* name) const return T::matches_dynamic_spec(&table->get_spec()); } -inline Table* Group::get_table_ptr(const char* name) +inline Table* Group::get_table_ptr(StringData name) { TIGHTDB_ASSERT(m_top.IsValid()); const size_t ndx = m_tableNames.find_first(name); @@ -418,7 +415,7 @@ inline Table* Group::get_table_ptr(const char* name) return create_new_table(name); } -inline Table* Group::get_table_ptr(const char* name, bool& was_created) +inline Table* Group::get_table_ptr(StringData name, bool& was_created) { TIGHTDB_ASSERT(m_top.IsValid()); const size_t ndx = m_tableNames.find_first(name); @@ -432,13 +429,13 @@ inline Table* Group::get_table_ptr(const char* name, bool& was_created) return create_new_table(name); } -inline const Table* Group::get_table_ptr(const char* name) const +inline const Table* Group::get_table_ptr(StringData name) const { TIGHTDB_ASSERT(has_table(name)); return const_cast(this)->get_table_ptr(name); } -template inline T* Group::get_table_ptr(const char* name) +template inline T* Group::get_table_ptr(StringData name) { TIGHTDB_STATIC_ASSERT(IsBasicTable::value, "Invalid table type"); TIGHTDB_ASSERT(!has_table(name) || has_table(name)); @@ -455,28 +452,28 @@ template inline T* Group::get_table_ptr(const char* name) return table; } -template inline const T* Group::get_table_ptr(const char* name) const +template inline const T* Group::get_table_ptr(StringData name) const { TIGHTDB_ASSERT(has_table(name)); return const_cast(this)->get_table_ptr(name); } -inline TableRef Group::get_table(const char* name) +inline TableRef Group::get_table(StringData name) { return get_table_ptr(name)->get_table_ref(); } -inline ConstTableRef Group::get_table(const char* name) const +inline ConstTableRef Group::get_table(StringData name) const { return get_table_ptr(name)->get_table_ref(); } -template inline typename T::Ref Group::get_table(const char* name) +template inline typename T::Ref Group::get_table(StringData name) { return get_table_ptr(name)->get_table_ref(); } -template inline typename T::ConstRef Group::get_table(const char* name) const +template inline typename T::ConstRef Group::get_table(StringData name) const { return get_table_ptr(name)->get_table_ref(); } @@ -486,7 +483,7 @@ inline void Group::commit() commit(-1, -1, true); } -template size_t Group::write_to_stream(S& out) +template size_t Group::write_to_stream(S& out) const { // Space for file header out.write(SlabAlloc::default_header, sizeof SlabAlloc::default_header); @@ -494,7 +491,7 @@ template size_t Group::write_to_stream(S& out) // When serializing to disk we dont want // to include free space tracking as serialized // files are written without any free space. - Array top(coldef_HasRefs, NULL, 0, m_alloc); + Array top(Array::coldef_HasRefs, NULL, 0, const_cast(m_alloc)); // FIXME: Another aspect of the poor constness behavior in Array class. What can we do? top.add(m_top.Get(0)); top.add(m_top.Get(1)); @@ -506,7 +503,7 @@ template size_t Group::write_to_stream(S& out) // (since we initially set the last bit in the file header to // zero, it is the first ref block that is valid) out.seek(0); - out.write((const char*)&topPos, 8); + out.write(reinterpret_cast(&topPos), 8); // FIXME: To be 100% robust with respect to being able to detect // afterwards whether the file was completely written, we would @@ -538,8 +535,8 @@ void Group::to_json(S& out) const out << "{"; for (size_t i = 0; i < m_tables.size(); ++i) { - const char* const name = m_tableNames.Get(i); - const Table* const table = get_table_ptr(i); + StringData name = m_tableNames.get(i); + const Table* table = get_table_ptr(i); if (i) out << ","; out << "\"" << name << "\""; diff --git a/src/tightdb/group_shared.hpp b/src/tightdb/group_shared.hpp index 073e14059da..1cf23c0c7ae 100644 --- a/src/tightdb/group_shared.hpp +++ b/src/tightdb/group_shared.hpp @@ -205,12 +205,12 @@ class ReadTransaction { m_shared_group.end_read(); } - ConstTableRef get_table(const char* name) const + ConstTableRef get_table(StringData name) const { return get_group().get_table(name); } - template typename T::ConstRef get_table(const char* name) const + template typename T::ConstRef get_table(StringData name) const { return get_group().get_table(name); } @@ -237,12 +237,12 @@ class WriteTransaction { if (m_shared_group) m_shared_group->rollback(); } - TableRef get_table(const char* name) const + TableRef get_table(StringData name) const { return get_group().get_table(name); } - template typename T::Ref get_table(const char* name) const + template typename T::Ref get_table(StringData name) const { return get_group().get_table(name); } diff --git a/src/tightdb/group_writer.cpp b/src/tightdb/group_writer.cpp index fde4ba8969a..66fdf696b34 100644 --- a/src/tightdb/group_writer.cpp +++ b/src/tightdb/group_writer.cpp @@ -65,7 +65,7 @@ size_t GroupWriter::Commit() // (64bit width + one possible ekstra entry per alloc and header) const size_t free_count = fpositions.size() + 5; const size_t top_max_size = (5 + 1) * 8; - const size_t flist_max_size = (free_count) * 8; + const size_t flist_max_size = free_count * 8; const size_t total_reserve = top_max_size + (flist_max_size * (isShared ? 3 : 2)); // Reserve space for each block. We explicitly ask for a bigger space than diff --git a/src/tightdb/index.cpp b/src/tightdb/index.cpp index 666c4315297..72ad892fcd2 100644 --- a/src/tightdb/index.cpp +++ b/src/tightdb/index.cpp @@ -25,16 +25,16 @@ const Index GetIndexFromRef(const Array& parent, size_t ndx) namespace tightdb { -Index::Index(): Column(coldef_HasRefs) +Index::Index(): Column(Array::coldef_HasRefs) { // Add subcolumns for leafs - const Array values(coldef_Normal); - const Array refs(coldef_Normal); // we do not own these refs (to column positions), so no COLUMN_HASREF + const Array values(Array::coldef_Normal); + const Array refs(Array::coldef_Normal); // we do not own these refs (to column positions), so no COLUMN_HASREF m_array->add(intptr_t(values.GetRef())); m_array->add(intptr_t(refs.GetRef())); } -Index::Index(ColumnDef type, Array* parent, size_t pndx): Column(type, parent, pndx) {} +Index::Index(Array::ColumnDef type, Array* parent, size_t pndx): Column(type, parent, pndx) {} Index::Index(size_t ref): Column(ref) {} @@ -53,7 +53,7 @@ void Index::BuildIndex(const Column& src) // Brute-force build-up // TODO: sort and merge for (size_t i = 0; i < src.Size(); ++i) { - Insert(i, src.Get(i), true); + Insert(i, src.get(i), true); } #ifdef TIGHTDB_DEBUG @@ -63,11 +63,11 @@ void Index::BuildIndex(const Column& src) void Index::Set(size_t ndx, int64_t oldValue, int64_t newValue) { - Delete(ndx, oldValue, true); // set isLast to avoid updating refs + erase(ndx, oldValue, true); // set isLast to avoid updating refs Insert(ndx, newValue, true); // set isLast to avoid updating refs } -void Index::Delete(size_t ndx, int64_t value, bool isLast) +void Index::erase(size_t ndx, int64_t value, bool isLast) { DoDelete(ndx, value); @@ -139,21 +139,21 @@ void Index::Insert(size_t ndx, int64_t value, bool isLast) case NodeChange::none: return; case NodeChange::insert_before: { - Index newNode(coldef_InnerNode); + Index newNode(Array::coldef_InnerNode); newNode.NodeAdd(nc.ref1); newNode.NodeAdd(GetRef()); m_array->UpdateRef(newNode.GetRef()); return; } case NodeChange::insert_after: { - Index newNode(coldef_InnerNode); + Index newNode(Array::coldef_InnerNode); newNode.NodeAdd(GetRef()); newNode.NodeAdd(nc.ref1); m_array->UpdateRef(newNode.GetRef()); return; } case NodeChange::split: { - Index newNode(coldef_InnerNode); + Index newNode(Array::coldef_InnerNode); newNode.NodeAdd(nc.ref1); newNode.NodeAdd(nc.ref2); m_array->UpdateRef(newNode.GetRef()); @@ -251,7 +251,7 @@ Column::NodeChange Index::DoInsert(size_t ndx, int64_t value) } // Else create new node - Index newNode(coldef_InnerNode); + Index newNode(Array::coldef_InnerNode); newNode.NodeAdd(nc.ref1); switch (node_ndx) { diff --git a/src/tightdb/index.hpp b/src/tightdb/index.hpp index bcb6af9938e..6c4d4350e92 100644 --- a/src/tightdb/index.hpp +++ b/src/tightdb/index.hpp @@ -24,10 +24,10 @@ namespace tightdb { -class Index : public Column { +class Index: public Column { public: Index(); - Index(ColumnDef type, Array* parent=NULL, size_t pndx=0); + Index(Array::ColumnDef, Array* = 0, size_t pndx=0); Index(size_t ref); Index(size_t ref, Array* parent, size_t pndx); @@ -36,10 +36,10 @@ class Index : public Column { void BuildIndex(const Column& c); void Insert(size_t ndx, int64_t value, bool isLast=false); - void Delete(size_t ndx, int64_t value, bool isLast=false); + void erase(size_t ndx, int64_t value, bool isLast=false); void Set(size_t ndx, int64_t oldValue, int64_t newValue); - using Column::Delete; + using Column::erase; size_t find_first(int64_t value) const; bool find_all(Column& result, int64_t value) const; diff --git a/src/tightdb/index_string.cpp b/src/tightdb/index_string.cpp index 1d3236390e9..4cd7bc9e072 100644 --- a/src/tightdb/index_string.cpp +++ b/src/tightdb/index_string.cpp @@ -1,38 +1,38 @@ -#include #include +#include + +using namespace std; using namespace tightdb; namespace { -// Pre-declaration -int32_t CreateKey(const char* v); - -int32_t CreateKey(const char* v) +int32_t create_key(const char* begin, const char* end) { // Create 4 byte index key // (encoded like this to allow literal comparisons // independently of endianness) int32_t key = 0; - if (*v) key = (int32_t(*v++) << 24); - if (*v) key |= (int32_t(*v++) << 16); - if (*v) key |= (int32_t(*v++) << 8); - if (*v) key |= int32_t(*v++); + if (begin != end) key = (int32_t(*begin++) << 24); + if (begin != end) key |= (int32_t(*begin++) << 16); + if (begin != end) key |= (int32_t(*begin++) << 8); + if (begin != end) key |= int32_t(*begin++); return key; } -} // namespace +} // anonymous namespace + -StringIndex::StringIndex(void* target_column, StringGetter get_func, Allocator& alloc) -: Column(coldef_HasRefs, NULL, 0, alloc), m_target_column(target_column), m_get_func(get_func) +StringIndex::StringIndex(void* target_column, StringGetter get_func, Allocator& alloc): + Column(Array::coldef_HasRefs, NULL, 0, alloc), m_target_column(target_column), m_get_func(get_func) { Create(); } -StringIndex::StringIndex(ColumnDef type, Allocator& alloc) -: Column(type, NULL, 0, alloc), m_target_column(NULL), m_get_func(NULL) +StringIndex::StringIndex(Array::ColumnDef type, Allocator& alloc): + Column(type, NULL, 0, alloc), m_target_column(NULL), m_get_func(NULL) { - TIGHTDB_ASSERT(type == coldef_InnerNode); // only used for node creation at this point + TIGHTDB_ASSERT(type == Array::coldef_InnerNode); // only used for node creation at this point // Mark that this is part of index // (as opposed to columns under leafs) @@ -55,8 +55,8 @@ void StringIndex::Create() // Add subcolumns for leafs Allocator& alloc = m_array->GetAllocator(); - Array values(coldef_Normal, NULL, 0, alloc); - Array refs(coldef_HasRefs, NULL, 1, alloc); + Array values(Array::coldef_Normal, NULL, 0, alloc); + Array refs(Array::coldef_HasRefs, NULL, 1, alloc); m_array->add(values.GetRef()); m_array->add(refs.GetRef()); values.SetParent((ArrayParent*)m_array, 0); @@ -76,13 +76,13 @@ int32_t StringIndex::GetLastKey() const return (int32_t)offsets.back(); } -void StringIndex::Set(size_t ndx, const char* oldValue, const char* newValue) +void StringIndex::Set(size_t ndx, StringData oldValue, StringData newValue) { - Delete(ndx, oldValue, true); // set isLast to avoid updating refs + erase(ndx, oldValue, true); // set isLast to avoid updating refs Insert(ndx, newValue, true); // set isLast to avoid updating refs } -void StringIndex::Insert(size_t row_ndx, const char* value, bool isLast) +void StringIndex::Insert(size_t row_ndx, StringData value, bool isLast) { // If it is last item in column, we don't have to update refs if (!isLast) UpdateRefs(row_ndx, 1); @@ -90,22 +90,22 @@ void StringIndex::Insert(size_t row_ndx, const char* value, bool isLast) InsertWithOffset(row_ndx, 0, value); } -void StringIndex::InsertWithOffset(size_t row_ndx, size_t offset, const char* value) +void StringIndex::InsertWithOffset(size_t row_ndx, size_t offset, StringData value) { // Create 4 byte index key - const char* const v = value + offset; - const int32_t key = CreateKey(v); + const char* const v = value.data() + offset; + const int32_t key = create_key(v, value.data() + value.size()); TreeInsert(row_ndx, key, offset, value); } -void StringIndex::InsertRowList(size_t ref, size_t offset, const char* value) +void StringIndex::InsertRowList(size_t ref, size_t offset, StringData value) { TIGHTDB_ASSERT(!m_array->IsNode()); // only works in leafs // Create 4 byte index key - const char* const v = value + offset; - const int32_t key = CreateKey(v); + const char* const v = value.data() + offset; + const int32_t key = create_key(v, value.data() + value.size()); // Get subnode table Array values = m_array->GetSubArray(0); @@ -123,7 +123,7 @@ void StringIndex::InsertRowList(size_t ref, size_t offset, const char* value) #ifdef TIGHTDB_DEBUG // Since we only use this for moving existing values to new // sub-indexes, there should never be an existing match. - const int32_t k = (int32_t)values.Get(ins_pos); + const int32_t k = int32_t(values.Get(ins_pos)); TIGHTDB_ASSERT(k != key); #endif @@ -132,28 +132,28 @@ void StringIndex::InsertRowList(size_t ref, size_t offset, const char* value) refs.Insert(ins_pos, ref); } -void StringIndex::TreeInsert(size_t row_ndx, int32_t key, size_t offset, const char* value) +void StringIndex::TreeInsert(size_t row_ndx, int32_t key, size_t offset, StringData value) { const NodeChange nc = DoInsert(row_ndx, key, offset, value); switch (nc.type) { case NodeChange::none: return; case NodeChange::insert_before: { - StringIndex newNode(coldef_InnerNode, m_array->GetAllocator()); + StringIndex newNode(Array::coldef_InnerNode, m_array->GetAllocator()); newNode.NodeAddKey(nc.ref1); newNode.NodeAddKey(GetRef()); UpdateRef(newNode.GetRef()); return; } case NodeChange::insert_after: { - StringIndex newNode(coldef_InnerNode, m_array->GetAllocator()); + StringIndex newNode(Array::coldef_InnerNode, m_array->GetAllocator()); newNode.NodeAddKey(GetRef()); newNode.NodeAddKey(nc.ref1); UpdateRef(newNode.GetRef()); return; } case NodeChange::split: { - StringIndex newNode(coldef_InnerNode, m_array->GetAllocator()); + StringIndex newNode(Array::coldef_InnerNode, m_array->GetAllocator()); newNode.NodeAddKey(nc.ref1); newNode.NodeAddKey(nc.ref2); UpdateRef(newNode.GetRef()); @@ -163,7 +163,7 @@ void StringIndex::TreeInsert(size_t row_ndx, int32_t key, size_t offset, const c TIGHTDB_ASSERT(false); } -Column::NodeChange StringIndex::DoInsert(size_t row_ndx, int32_t key, size_t offset, const char* value) +Column::NodeChange StringIndex::DoInsert(size_t row_ndx, int32_t key, size_t offset, StringData value) { if (IsNode()) { // Get subnode table @@ -172,7 +172,7 @@ Column::NodeChange StringIndex::DoInsert(size_t row_ndx, int32_t key, size_t off // Find the subnode containing the item size_t node_ndx = offsets.FindPos2(key); - if (node_ndx == (size_t)-1) { + if (node_ndx == size_t(-1)) { // node can never be empty, so try to fit in last item node_ndx = offsets.size()-1; } @@ -200,7 +200,7 @@ Column::NodeChange StringIndex::DoInsert(size_t row_ndx, int32_t key, size_t off } // Else create new node - StringIndex newNode(coldef_InnerNode, m_array->GetAllocator()); + StringIndex newNode(Array::coldef_InnerNode, m_array->GetAllocator()); if (nc.type == NodeChange::split) { // update offset for left node const int32_t lastKey = target.GetLastKey(); @@ -322,7 +322,7 @@ void StringIndex::NodeInsert(size_t ndx, size_t ref) refs.Insert(ndx, ref); } -bool StringIndex::LeafInsert(size_t row_ndx, int32_t key, size_t offset, const char* value, bool noextend) +bool StringIndex::LeafInsert(size_t row_ndx, int32_t key, size_t offset, StringData value, bool noextend) { TIGHTDB_ASSERT(!IsNode()); @@ -361,10 +361,10 @@ bool StringIndex::LeafInsert(size_t row_ndx, int32_t key, size_t offset, const c // Single match (lowest bit set indicates literal row_ndx) if (ref & 1) { const size_t row_ndx2 = ref >> 1; - const char* const v2 = Get(row_ndx2); - if (strcmp(v2, value) == 0) { + StringData v2 = Get(row_ndx2); + if (v2 == value) { // convert to list (in sorted order) - Array row_list(coldef_Normal, NULL, 0, alloc); + Array row_list(Array::coldef_Normal, NULL, 0, alloc); row_list.add(row_ndx < row_ndx2 ? row_ndx : row_ndx2); row_list.add(row_ndx < row_ndx2 ? row_ndx2 : row_ndx); refs.Set(ins_pos, row_list.GetRef()); @@ -384,13 +384,13 @@ bool StringIndex::LeafInsert(size_t row_ndx, int32_t key, size_t offset, const c if (!Array::is_index_node(ref, alloc)) { Column sub(ref, &refs, ins_pos, alloc); - const size_t r1 = (size_t)sub.Get(0); - const char* const v2 = Get(r1); - if (strcmp(v2, value) == 0) { + const size_t r1 = (size_t)sub.get(0); + StringData v2 = Get(r1); + if (v2 == value) { // find insert position (the list has to be kept in sorted order) // In most cases we refs will be added to the end. So we test for that // first to see if we can avoid the binary search for insert position - const size_t lastRef = (size_t)sub.Back(); + const size_t lastRef = size_t(sub.Back()); if (row_ndx > lastRef) sub.add(row_ndx); else { @@ -398,7 +398,7 @@ bool StringIndex::LeafInsert(size_t row_ndx, int32_t key, size_t offset, const c if (pos == not_found) sub.add(row_ndx); else - sub.Insert(pos, row_ndx); + sub.insert(pos, row_ndx); } } else { @@ -417,19 +417,19 @@ bool StringIndex::LeafInsert(size_t row_ndx, int32_t key, size_t offset, const c return true; } -size_t StringIndex::find_first(const char* value) const +size_t StringIndex::find_first(StringData value) const { // Use direct access method return m_array->IndexStringFindFirst(value, m_target_column, m_get_func); } -void StringIndex::find_all(Array& result, const char* value) const +void StringIndex::find_all(Array& result, StringData value) const { // Use direct access method return m_array->IndexStringFindAll(result, value, m_target_column, m_get_func); } -size_t StringIndex::count(const char* value) const +size_t StringIndex::count(StringData value) const { // Use direct access method return m_array->IndexStringCount(value, m_target_column, m_get_func); @@ -467,7 +467,7 @@ void StringIndex::distinct(Array& result) const } else { const Column sub(to_size_t(ref), &refs, i, alloc); - const size_t r = to_size_t(sub.Get(0)); // get first match + const size_t r = to_size_t(sub.get(0)); // get first match result.add(r); } } @@ -526,7 +526,7 @@ void StringIndex::Clear() refs.Clear(); } -void StringIndex::Delete(size_t row_ndx, const char* value, bool isLast) +void StringIndex::erase(size_t row_ndx, StringData value, bool isLast) { DoDelete(row_ndx, value, 0); @@ -536,7 +536,7 @@ void StringIndex::Delete(size_t row_ndx, const char* value, bool isLast) TIGHTDB_ASSERT(refs.size() != 0); // node cannot be empty if (refs.size() > 1) break; - const size_t ref = (size_t)refs.Get(0); + const size_t ref = refs.GetAsRef(0); refs.Delete(0); // avoid deleting subtree m_array->Destroy(); m_array->UpdateRef(ref); @@ -546,15 +546,15 @@ void StringIndex::Delete(size_t row_ndx, const char* value, bool isLast) if (!isLast) UpdateRefs(row_ndx, -1); } -void StringIndex::DoDelete(size_t row_ndx, const char* value, size_t offset) +void StringIndex::DoDelete(size_t row_ndx, StringData value, size_t offset) { Array values = m_array->GetSubArray(0); Array refs = m_array->GetSubArray(1); Allocator& alloc = m_array->GetAllocator(); // Create 4 byte index key - const char* const v = value + offset; - const int32_t key = CreateKey(v); + const char* const v = value.data() + offset; + const int32_t key = create_key(v, value.data() + value.size()); const size_t pos = values.FindPos2(key); TIGHTDB_ASSERT(pos != not_found); @@ -579,14 +579,14 @@ void StringIndex::DoDelete(size_t row_ndx, const char* value, size_t offset) else { const int64_t ref = refs.Get(pos); if (ref & 1) { - TIGHTDB_ASSERT((uint64_t(ref) >> 1) == (int64_t)row_ndx); + TIGHTDB_ASSERT((uint64_t(ref) >> 1) == uint64_t(row_ndx)); values.Delete(pos); refs.Delete(pos); } else { // A real ref either points to a list or a sub-index if (Array::is_index_node(to_size_t(ref), alloc)) { - StringIndex subNdx((size_t)ref, &refs, pos, m_target_column, m_get_func, alloc); + StringIndex subNdx(size_t(ref), &refs, pos, m_target_column, m_get_func, alloc); subNdx.DoDelete(row_ndx, value, offset+4); if (subNdx.is_empty()) { @@ -599,7 +599,7 @@ void StringIndex::DoDelete(size_t row_ndx, const char* value, size_t offset) Column sub(to_size_t(ref), &refs, pos, alloc); const size_t r = sub.find_first(row_ndx); TIGHTDB_ASSERT(r != not_found); - sub.Delete(r); + sub.erase(r); if (sub.is_empty()) { values.Delete(pos); @@ -625,7 +625,7 @@ void StringIndex::verify_entries(const AdaptiveStringColumn& column) const const size_t count = column.Size(); for (size_t i = 0; i < count; ++i) { - const char* const value = column.Get(i); + StringData value = column.get(i); find_all(results, value); @@ -638,31 +638,31 @@ void StringIndex::verify_entries(const AdaptiveStringColumn& column) const results.Destroy(); // clean-up } -void StringIndex::to_dot(std::ostream& out) const +void StringIndex::to_dot(ostream& out) const { - out << "digraph G {" << std::endl; + out << "digraph G {" << endl; ToDot(out); - out << "}" << std::endl; + out << "}" << endl; } -void StringIndex::ToDot(std::ostream& out, const char* title) const +void StringIndex::ToDot(ostream& out, StringData title) const { const size_t ref = GetRef(); - out << "subgraph cluster_stringindex" << ref << " {" << std::endl; + out << "subgraph cluster_stringindex" << ref << " {" << endl; out << " label = \"StringIndex"; - if (title) out << "\\n'" << title << "'"; - out << "\";" << std::endl; + if (0 < title.size()) out << "\\n'" << title << "'"; + out << "\";" << endl; ArrayToDot(out, *m_array); - out << "}" << std::endl; + out << "}" << endl; } -void StringIndex::ArrayToDot(std::ostream& out, const Array& array) const +void StringIndex::ArrayToDot(ostream& out, const Array& array) const { if (array.HasRefs()) { const Array offsets = array.GetSubArray(0); @@ -670,18 +670,18 @@ void StringIndex::ArrayToDot(std::ostream& out, const Array& array) const const size_t ref = array.GetRef(); if (array.IsNode()) { - out << "subgraph cluster_stringindex_node" << ref << " {" << std::endl; - out << " label = \"Node\";" << std::endl; + out << "subgraph cluster_stringindex_node" << ref << " {" << endl; + out << " label = \"Node\";" << endl; } else { - out << "subgraph cluster_stringindex_leaf" << ref << " {" << std::endl; - out << " label = \"Leaf\";" << std::endl; + out << "subgraph cluster_stringindex_leaf" << ref << " {" << endl; + out << " label = \"Leaf\";" << endl; } array.ToDot(out); KeysToDot(out, offsets, "keys"); - out << "}" << std::endl; + out << "}" << endl; refs.ToDot(out, "refs"); @@ -699,25 +699,25 @@ void StringIndex::ArrayToDot(std::ostream& out, const Array& array) const } } -void StringIndex::KeysToDot(std::ostream& out, const Array& array, const char* title) const +void StringIndex::KeysToDot(ostream& out, const Array& array, StringData title) const { const size_t ref = array.GetRef(); - if (title) { - out << "subgraph cluster_" << ref << " {" << std::endl; - out << " label = \"" << title << "\";" << std::endl; - out << " color = white;" << std::endl; + if (0 < title.size()) { + out << "subgraph cluster_" << ref << " {" << endl; + out << " label = \"" << title << "\";" << endl; + out << " color = white;" << endl; } - out << "n" << std::hex << ref << std::dec << "[shape=none,label=<"; - out << "" << std::endl; + out << "n" << hex << ref << dec << "[shape=none,label=<"; + out << "
" << endl; // Header out << "" << std::endl; + out << "" << endl; // Values const size_t count = array.size(); @@ -731,13 +731,13 @@ void StringIndex::KeysToDot(std::ostream& out, const Array& array, const char* t str[0] = char((v >> 24) & 0xFF); const char* s = str; - out << "" << std::endl; + out << "" << endl; } - out << "
"; - out << "0x" << std::hex << ref << std::dec << "
"; + out << "0x" << hex << ref << dec << "
"; if (array.IsNode()) out << "IsNode
"; if (array.HasRefs()) out << "HasRefs
"; - out << "
" << s << "" << s << "
>];" << std::endl; - if (title) out << "}" << std::endl; + out << ">];" << endl; + if (0 < title.size()) out << "}" << endl; - out << std::endl; + out << endl; } diff --git a/src/tightdb/index_string.hpp b/src/tightdb/index_string.hpp index 1036025ab88..3f608b18a19 100644 --- a/src/tightdb/index_string.hpp +++ b/src/tightdb/index_string.hpp @@ -26,27 +26,27 @@ namespace tightdb { -typedef const char*(*StringGetter)(void*, size_t); +typedef StringData (*StringGetter)(void*, size_t); -class StringIndex : public Column { +class StringIndex: public Column { public: - StringIndex(void* target_column, StringGetter get_func, Allocator& alloc); - StringIndex(ColumnDef type, Allocator& alloc); - StringIndex(size_t ref, ArrayParent* parent, size_t pndx, void* target_column, StringGetter get_func, Allocator& alloc); + StringIndex(void* target_column, StringGetter get_func, Allocator&); + StringIndex(Array::ColumnDef, Allocator&); + StringIndex(size_t ref, ArrayParent*, size_t pndx, void* target_column, StringGetter get_func, Allocator&); void SetTarget(void* target_column, StringGetter get_func); bool is_empty() const; - void Insert(size_t row_ndx, const char* value, bool isLast=false); - void Set(size_t row_ndx, const char* oldValue, const char* newValue); - void Delete(size_t row_ndx, const char* value, bool isLast=false); + void Insert(size_t row_ndx, StringData value, bool isLast=false); + void Set(size_t row_ndx, StringData oldValue, StringData newValue); + void erase(size_t row_ndx, StringData value, bool isLast=false); void Clear() TIGHTDB_OVERRIDE; - using Column::Delete; + using Column::erase; - size_t count(const char* value) const; - size_t find_first(const char* value) const; - void find_all(Array& result, const char* value) const; + size_t count(StringData value) const; + size_t find_first(StringData value) const; + void find_all(Array& result, StringData value) const; void distinct(Array& result) const; #ifdef TIGHTDB_DEBUG @@ -58,30 +58,30 @@ class StringIndex : public Column { protected: void Create(); - void InsertWithOffset(size_t row_ndx, size_t offset, const char* value); - void InsertRowList(size_t ref, size_t offset, const char* value); + void InsertWithOffset(size_t row_ndx, size_t offset, StringData value); + void InsertRowList(size_t ref, size_t offset, StringData value); int32_t GetLastKey() const; void UpdateRefs(size_t pos, int diff); // B-Tree functions - void TreeInsert(size_t row_ndx, int32_t key, size_t offset, const char* value); - NodeChange DoInsert(size_t ndx, int32_t key, size_t offset, const char* value); + void TreeInsert(size_t row_ndx, int32_t key, size_t offset, StringData value); + NodeChange DoInsert(size_t ndx, int32_t key, size_t offset, StringData value); /// Returns true if there is room or it can join existing entries - bool LeafInsert(size_t row_ndx, int32_t key, size_t offset, const char* value, bool noextend=false); + bool LeafInsert(size_t row_ndx, int32_t key, size_t offset, StringData value, bool noextend=false); void NodeInsertSplit(size_t ndx, size_t new_ref); void NodeInsert(size_t ndx, size_t ref); - void DoDelete(size_t ndx, const char* value, size_t offset); + void DoDelete(size_t ndx, StringData, size_t offset); - const char* Get(size_t ndx) {return (*m_get_func)(m_target_column, ndx);} + StringData Get(size_t ndx) {return (*m_get_func)(m_target_column, ndx);} // Member variables void* m_target_column; StringGetter m_get_func; #ifdef TIGHTDB_DEBUG - void ToDot(std::ostream& out, const char* title=NULL) const; + void ToDot(std::ostream& out, StringData title = StringData()) const; void ArrayToDot(std::ostream& out, const Array& array) const; - void KeysToDot(std::ostream& out, const Array& array, const char* title=NULL) const; + void KeysToDot(std::ostream& out, const Array& array, StringData title = StringData()) const; #endif }; diff --git a/src/tightdb/lang_bind_helper.hpp b/src/tightdb/lang_bind_helper.hpp index 8da3dcce307..0e54614969f 100644 --- a/src/tightdb/lang_bind_helper.hpp +++ b/src/tightdb/lang_bind_helper.hpp @@ -30,13 +30,14 @@ namespace tightdb { /// These functions are only to be used by language bindings to gain -/// access to certain otherwise private memebers. +/// access to certain memebers that are othewise private. /// -/// \note An application must never call these functions directly. +/// \note Applications are not supposed to call any of these functions +/// directly. /// -/// All the get_*_ptr() functions as well as new_table() in this class -/// will return a Table pointer where the reference count has already been -/// incremented. +/// All the get_*_ptr() functions as well as new_table() and +/// copy_table() will return a pointer to a Table whose reference +/// count has already been incremented. /// /// The application must make sure that the unbind_table_ref() function is /// called to decrement the reference count when it no longer needs @@ -64,9 +65,9 @@ class LangBindHelper { static const Table* get_subtable_ptr(const ConstTableView*, std::size_t column_ndx, std::size_t row_ndx); - static Table* get_table_ptr(Group* grp, const char* name); - static Table* get_table_ptr(Group* grp, const char* name, bool& was_created); - static const Table* get_table_ptr(const Group* grp, const char* name); + static Table* get_table_ptr(Group* grp, StringData name); + static Table* get_table_ptr(Group* grp, StringData name, bool& was_created); + static const Table* get_table_ptr(const Group* grp, StringData name); static void unbind_table_ref(const Table*); static void bind_table_ref(const Table*); @@ -141,21 +142,21 @@ inline const Table* LangBindHelper::get_subtable_ptr(const ConstTableView* tv, return get_subtable_ptr(&tv->get_parent(), column_ndx, tv->get_source_ndx(row_ndx)); } -inline Table* LangBindHelper::get_table_ptr(Group* grp, const char* name) +inline Table* LangBindHelper::get_table_ptr(Group* grp, StringData name) { Table* subtab = grp->get_table_ptr(name); subtab->bind_ref(); return subtab; } -inline Table* LangBindHelper::get_table_ptr(Group* grp, const char* name, bool& was_created) +inline Table* LangBindHelper::get_table_ptr(Group* grp, StringData name, bool& was_created) { Table* subtab = grp->get_table_ptr(name, was_created); subtab->bind_ref(); return subtab; } -inline const Table* LangBindHelper::get_table_ptr(const Group* grp, const char* name) +inline const Table* LangBindHelper::get_table_ptr(const Group* grp, StringData name) { const Table* subtab = grp->get_table_ptr(name); subtab->bind_ref(); diff --git a/src/tightdb/mixed.hpp b/src/tightdb/mixed.hpp index f0459c37726..dff7eced4ff 100644 --- a/src/tightdb/mixed.hpp +++ b/src/tightdb/mixed.hpp @@ -29,44 +29,113 @@ #include #include #include +#include #include namespace tightdb { +/// This class represents a polymorphic TightDB value. +/// +/// At any particular moment an instance of this class stores a +/// definite value of a definite type. If, for instance, that is an +/// integer value, you may call get_int() to extract that value. You +/// may call get_type() to discover what type of value is currently +/// stored. Calling get_int() on an instance that does not store an +/// integer, has undefined behavior, and likewise for all the other +/// types that can be stored. +/// +/// It is crucial to understand that the act of extracting a value of +/// a particular type requires definite knowledge about the stored +/// type. Calling a getter method for any particular type, that is not +/// the same type as the stored value, has undefined behavior. +/// +/// While values of numeric types are contained directly in a Mixed +/// instance, character and binary data are merely referenced. A Mixed +/// instance never owns the referenced data, nor does it in any other +/// way attempt to manage its lifetime. +/// +/// For compatibility with C style strings, when a string (character +/// data) is stored in a TightDB database, it is always followed by a +/// terminating null character. This is also true when strings are +/// stored in a mixed type column. This means that in the following +/// code if the 'mixed' value of the 8th row stores a string, then \c +/// c_str will always point to a null-terminated string: +/// +/// \code{.cpp} +/// +/// const char* c_str = my_table[7].mixed.data(); // Always null-terminated +/// +/// \endcode +/// +/// Note that this assumption does not hold in general for strings in +/// instances of Mixed. Indeed there is nothing stopping you from +/// constructing a new Mixed instance that refers to a string without +/// a terminating null character. +/// +/// At the present time no soultion has been found that would allow +/// for a Mixed instance to directly store a reference to a table. The +/// problem is roughly as follows: From most points of view, the +/// desirable thing to do, would be to store the table reference in a +/// Mixed instance as a plain pointer without any ownership +/// semantics. This would have no negative impact on the performance +/// of copying and destroying Mixed instances, and it would serve just +/// fine for passing a table as argument when setting the value of an +/// entry in a mixed column. In that case a copy of the referenced +/// table would inserted into the mixed column. +/// +/// On the other hand, when retrieving a table reference from a mixed +/// column, storing it as a plain pointer in a Mixed instance is no +/// longer an acceptable option. The complex rules for managing the +/// lifetime of a Table instance, that represents a subtable, +/// necessitates the use of a "smart pointer" such as +/// TableRef. Enhancing the Mixed class to be able to act as a +/// TableRef would be possible, but would also lead to several new +/// problems. One problem is the risk of a Mixed instance outliving a +/// stack allocated Table instance that it references. This would be a +/// fatal error. Another problem is the impact that the nontrivial +/// table reference has on the performance of copying and detroying +/// Mixed instances. +/// +/// \sa StringData class Mixed { public: Mixed() TIGHTDB_NOEXCEPT; - Mixed(bool) TIGHTDB_NOEXCEPT; - Mixed(int64_t) TIGHTDB_NOEXCEPT; - Mixed(float) TIGHTDB_NOEXCEPT; - Mixed(double) TIGHTDB_NOEXCEPT; - Mixed(const char*) TIGHTDB_NOEXCEPT; + Mixed(bool) TIGHTDB_NOEXCEPT; + Mixed(int64_t) TIGHTDB_NOEXCEPT; + Mixed(float) TIGHTDB_NOEXCEPT; + Mixed(double) TIGHTDB_NOEXCEPT; + Mixed(StringData) TIGHTDB_NOEXCEPT; Mixed(BinaryData) TIGHTDB_NOEXCEPT; - Mixed(Date) TIGHTDB_NOEXCEPT; + Mixed(Date) TIGHTDB_NOEXCEPT; + + // These are shortcuts for Mixed(StringData(c_str)), and are + // needed to avoid unwanted implicit conversion of char* to bool. + Mixed( char* c_str) TIGHTDB_NOEXCEPT { set_string(c_str); } + Mixed(const char* c_str) TIGHTDB_NOEXCEPT { set_string(c_str); } struct subtable_tag {}; Mixed(subtable_tag) TIGHTDB_NOEXCEPT: m_type(type_Table) {} DataType get_type() const TIGHTDB_NOEXCEPT { return m_type; } - bool get_bool() const TIGHTDB_NOEXCEPT; - int64_t get_int() const TIGHTDB_NOEXCEPT; - float get_float() const TIGHTDB_NOEXCEPT; - double get_double() const TIGHTDB_NOEXCEPT; - const char* get_string() const TIGHTDB_NOEXCEPT; - BinaryData get_binary() const TIGHTDB_NOEXCEPT; - std::time_t get_date() const TIGHTDB_NOEXCEPT; + int64_t get_int() const TIGHTDB_NOEXCEPT; + bool get_bool() const TIGHTDB_NOEXCEPT; + float get_float() const TIGHTDB_NOEXCEPT; + double get_double() const TIGHTDB_NOEXCEPT; + StringData get_string() const TIGHTDB_NOEXCEPT; + BinaryData get_binary() const TIGHTDB_NOEXCEPT; + Date get_date() const TIGHTDB_NOEXCEPT; - void set_bool(bool) TIGHTDB_NOEXCEPT; void set_int(int64_t) TIGHTDB_NOEXCEPT; + void set_bool(bool) TIGHTDB_NOEXCEPT; void set_float(float) TIGHTDB_NOEXCEPT; void set_double(double) TIGHTDB_NOEXCEPT; - void set_string(const char*) TIGHTDB_NOEXCEPT; + void set_string(StringData) TIGHTDB_NOEXCEPT; void set_binary(BinaryData) TIGHTDB_NOEXCEPT; void set_binary(const char* data, std::size_t size) TIGHTDB_NOEXCEPT; - void set_date(std::time_t) TIGHTDB_NOEXCEPT; + void set_date(Date) TIGHTDB_NOEXCEPT; template friend std::basic_ostream& operator<<(std::basic_ostream&, const Mixed&); @@ -78,10 +147,10 @@ class Mixed { bool m_bool; float m_float; double m_double; - const char* m_str; + const char* m_data; std::time_t m_date; }; - std::size_t m_len; + std::size_t m_size; }; // Note: We cannot compare two mixed values, since when the type of @@ -93,18 +162,18 @@ class Mixed { // vs int64_t, and cause ambiguity. This is because the constructors // of Mixed are not explicit. -// Compare mixed with boolean -bool operator==(Wrap, bool) TIGHTDB_NOEXCEPT; -bool operator!=(Wrap, bool) TIGHTDB_NOEXCEPT; -bool operator==(bool, Wrap) TIGHTDB_NOEXCEPT; -bool operator!=(bool, Wrap) TIGHTDB_NOEXCEPT; - // Compare mixed with integer template bool operator==(Wrap, const T&) TIGHTDB_NOEXCEPT; template bool operator!=(Wrap, const T&) TIGHTDB_NOEXCEPT; template bool operator==(const T&, Wrap) TIGHTDB_NOEXCEPT; template bool operator!=(const T&, Wrap) TIGHTDB_NOEXCEPT; +// Compare mixed with boolean +bool operator==(Wrap, bool) TIGHTDB_NOEXCEPT; +bool operator!=(Wrap, bool) TIGHTDB_NOEXCEPT; +bool operator==(bool, Wrap) TIGHTDB_NOEXCEPT; +bool operator!=(bool, Wrap) TIGHTDB_NOEXCEPT; + // Compare mixed with float bool operator==(Wrap, float); bool operator!=(Wrap, float); @@ -117,15 +186,19 @@ bool operator!=(Wrap, double); bool operator==(double, Wrap); bool operator!=(double, Wrap); -// Compare mixed with zero-terminated string -bool operator==(Wrap, const char*) TIGHTDB_NOEXCEPT; -bool operator!=(Wrap, const char*) TIGHTDB_NOEXCEPT; -bool operator==(const char*, Wrap) TIGHTDB_NOEXCEPT; -bool operator!=(const char*, Wrap) TIGHTDB_NOEXCEPT; -bool operator==(Wrap, char*) TIGHTDB_NOEXCEPT; -bool operator!=(Wrap, char*) TIGHTDB_NOEXCEPT; -bool operator==(char*, Wrap) TIGHTDB_NOEXCEPT; -bool operator!=(char*, Wrap) TIGHTDB_NOEXCEPT; +// Compare mixed with string +bool operator==(Wrap, StringData) TIGHTDB_NOEXCEPT; +bool operator!=(Wrap, StringData) TIGHTDB_NOEXCEPT; +bool operator==(StringData, Wrap) TIGHTDB_NOEXCEPT; +bool operator!=(StringData, Wrap) TIGHTDB_NOEXCEPT; +bool operator==(Wrap, const char* c_str) TIGHTDB_NOEXCEPT; +bool operator!=(Wrap, const char* c_str) TIGHTDB_NOEXCEPT; +bool operator==(const char* c_str, Wrap) TIGHTDB_NOEXCEPT; +bool operator!=(const char* c_str, Wrap) TIGHTDB_NOEXCEPT; +bool operator==(Wrap, char* c_str) TIGHTDB_NOEXCEPT; +bool operator!=(Wrap, char* c_str) TIGHTDB_NOEXCEPT; +bool operator==(char* c_str, Wrap) TIGHTDB_NOEXCEPT; +bool operator!=(char* c_str, Wrap) TIGHTDB_NOEXCEPT; // Compare mixed with binary data bool operator==(Wrap, BinaryData) TIGHTDB_NOEXCEPT; @@ -150,18 +223,18 @@ inline Mixed::Mixed() TIGHTDB_NOEXCEPT m_int = 0; } -inline Mixed::Mixed(bool v) TIGHTDB_NOEXCEPT -{ - m_type = type_Bool; - m_bool = v; -} - inline Mixed::Mixed(int64_t v) TIGHTDB_NOEXCEPT { m_type = type_Int; m_int = v; } +inline Mixed::Mixed(bool v) TIGHTDB_NOEXCEPT +{ + m_type = type_Bool; + m_bool = v; +} + inline Mixed::Mixed(float v) TIGHTDB_NOEXCEPT { m_type = type_Float; @@ -174,17 +247,18 @@ inline Mixed::Mixed(double v) TIGHTDB_NOEXCEPT m_double = v; } -inline Mixed::Mixed(const char* v) TIGHTDB_NOEXCEPT +inline Mixed::Mixed(StringData v) TIGHTDB_NOEXCEPT { m_type = type_String; - m_str = v; + m_data = v.data(); + m_size = v.size(); } inline Mixed::Mixed(BinaryData v) TIGHTDB_NOEXCEPT { m_type = type_Binary; - m_str = v.pointer; - m_len = v.len; + m_data = v.data(); + m_size = v.size(); } inline Mixed::Mixed(Date v) TIGHTDB_NOEXCEPT @@ -193,11 +267,6 @@ inline Mixed::Mixed(Date v) TIGHTDB_NOEXCEPT m_date = v.get_date(); } -inline bool Mixed::get_bool() const TIGHTDB_NOEXCEPT -{ - TIGHTDB_ASSERT(m_type == type_Bool); - return m_bool; -} inline int64_t Mixed::get_int() const TIGHTDB_NOEXCEPT { @@ -205,6 +274,12 @@ inline int64_t Mixed::get_int() const TIGHTDB_NOEXCEPT return m_int; } +inline bool Mixed::get_bool() const TIGHTDB_NOEXCEPT +{ + TIGHTDB_ASSERT(m_type == type_Bool); + return m_bool; +} + inline float Mixed::get_float() const TIGHTDB_NOEXCEPT { TIGHTDB_ASSERT(m_type == type_Float); @@ -217,29 +292,24 @@ inline double Mixed::get_double() const TIGHTDB_NOEXCEPT return m_double; } -inline const char* Mixed::get_string() const TIGHTDB_NOEXCEPT +inline StringData Mixed::get_string() const TIGHTDB_NOEXCEPT { TIGHTDB_ASSERT(m_type == type_String); - return m_str; + return StringData(m_data, m_size); } inline BinaryData Mixed::get_binary() const TIGHTDB_NOEXCEPT { TIGHTDB_ASSERT(m_type == type_Binary); - return BinaryData(m_str, m_len); + return BinaryData(m_data, m_size); } -inline std::time_t Mixed::get_date() const TIGHTDB_NOEXCEPT +inline Date Mixed::get_date() const TIGHTDB_NOEXCEPT { TIGHTDB_ASSERT(m_type == type_Date); return m_date; } -inline void Mixed::set_bool(bool v) TIGHTDB_NOEXCEPT -{ - m_type = type_Bool; - m_bool = v; -} inline void Mixed::set_int(int64_t v) TIGHTDB_NOEXCEPT { @@ -247,6 +317,12 @@ inline void Mixed::set_int(int64_t v) TIGHTDB_NOEXCEPT m_int = v; } +inline void Mixed::set_bool(bool v) TIGHTDB_NOEXCEPT +{ + m_type = type_Bool; + m_bool = v; +} + inline void Mixed::set_float(float v) TIGHTDB_NOEXCEPT { m_type = type_Float; @@ -259,28 +335,29 @@ inline void Mixed::set_double(double v) TIGHTDB_NOEXCEPT m_double = v; } -inline void Mixed::set_string(const char* v) TIGHTDB_NOEXCEPT +inline void Mixed::set_string(StringData v) TIGHTDB_NOEXCEPT { m_type = type_String; - m_str = v; + m_data = v.data(); + m_size = v.size(); } inline void Mixed::set_binary(BinaryData v) TIGHTDB_NOEXCEPT { - set_binary(v.pointer, v.len); + set_binary(v.data(), v.size()); } inline void Mixed::set_binary(const char* data, std::size_t size) TIGHTDB_NOEXCEPT { m_type = type_Binary; - m_str = data; - m_len = size; + m_data = data; + m_size = size; } -inline void Mixed::set_date(std::time_t v) TIGHTDB_NOEXCEPT +inline void Mixed::set_date(Date v) TIGHTDB_NOEXCEPT { m_type = type_Date; - m_date = v; + m_date = v.get_date(); } @@ -289,64 +366,64 @@ inline std::basic_ostream& operator<<(std::basic_ostream& out, c { out << "Mixed("; switch (m.m_type) { - case type_Bool: out << m.m_bool; break; - case type_Int: out << m.m_int; break; - case type_String: out << m.m_str; break; - case type_Float: out << m.m_float; break; - case type_Double: out << m.m_double; break; - case type_Binary: out << BinaryData(m.m_str, m.m_len); break; - case type_Date: out << Date(m.m_date); break; - case type_Table: out << "subtable"; break; - default: TIGHTDB_ASSERT(false); break; // FIXME: Remove + case type_Int: out << m.m_int; break; + case type_Bool: out << m.m_bool; break; + case type_Float: out << m.m_float; break; + case type_Double: out << m.m_double; break; + case type_String: out << StringData(m.m_data, m.m_size); break; + case type_Binary: out << BinaryData(m.m_data, m.m_size); break; + case type_Date: out << Date(m.m_date); break; + case type_Table: out << "subtable"; break; + case type_Mixed: TIGHTDB_ASSERT(false); break; } out << ")"; return out; } -// Compare mixed with boolean +// Compare mixed with integer -inline bool operator==(Wrap a, bool b) TIGHTDB_NOEXCEPT +template inline bool operator==(Wrap a, const T& b) TIGHTDB_NOEXCEPT { - return Mixed(a).get_type() == type_Bool && Mixed(a).get_bool() == b; + return Mixed(a).get_type() == type_Int && Mixed(a).get_int() == b; } -inline bool operator!=(Wrap a, bool b) TIGHTDB_NOEXCEPT +template inline bool operator!=(Wrap a, const T& b) TIGHTDB_NOEXCEPT { - return Mixed(a).get_type() == type_Bool && Mixed(a).get_bool() != b; + return Mixed(a).get_type() != type_Int || Mixed(a).get_int() != b; } -inline bool operator==(bool a, Wrap b) TIGHTDB_NOEXCEPT +template inline bool operator==(const T& a, Wrap b) TIGHTDB_NOEXCEPT { - return Mixed(b).get_type() == type_Bool && a == Mixed(b).get_bool(); + return type_Int == Mixed(b).get_type() && a == Mixed(b).get_int(); } -inline bool operator!=(bool a, Wrap b) TIGHTDB_NOEXCEPT +template inline bool operator!=(const T& a, Wrap b) TIGHTDB_NOEXCEPT { - return Mixed(b).get_type() == type_Bool && a != Mixed(b).get_bool(); + return type_Int != Mixed(b).get_type() || a != Mixed(b).get_int(); } -// Compare mixed with integer +// Compare mixed with boolean -template inline bool operator==(Wrap a, const T& b) TIGHTDB_NOEXCEPT +inline bool operator==(Wrap a, bool b) TIGHTDB_NOEXCEPT { - return Mixed(a).get_type() == type_Int && Mixed(a).get_int() == b; + return Mixed(a).get_type() == type_Bool && Mixed(a).get_bool() == b; } -template inline bool operator!=(Wrap a, const T& b) TIGHTDB_NOEXCEPT +inline bool operator!=(Wrap a, bool b) TIGHTDB_NOEXCEPT { - return Mixed(a).get_type() == type_Int && Mixed(a).get_int() != b; + return Mixed(a).get_type() != type_Bool || Mixed(a).get_bool() != b; } -template inline bool operator==(const T& a, Wrap b) TIGHTDB_NOEXCEPT +inline bool operator==(bool a, Wrap b) TIGHTDB_NOEXCEPT { - return Mixed(b).get_type() == type_Int && a == Mixed(b).get_int(); + return type_Bool == Mixed(b).get_type() && a == Mixed(b).get_bool(); } -template inline bool operator!=(const T& a, Wrap b) TIGHTDB_NOEXCEPT +inline bool operator!=(bool a, Wrap b) TIGHTDB_NOEXCEPT { - return Mixed(b).get_type() == type_Int && a != Mixed(b).get_int(); + return type_Bool != Mixed(b).get_type() || a != Mixed(b).get_bool(); } @@ -359,17 +436,17 @@ inline bool operator==(Wrap a, float b) inline bool operator!=(Wrap a, float b) { - return Mixed(a).get_type() == type_Float && Mixed(a).get_float() != b; + return Mixed(a).get_type() != type_Float || Mixed(a).get_float() != b; } inline bool operator==(float a, Wrap b) { - return Mixed(b).get_type() == type_Float && a == Mixed(b).get_float(); + return type_Float == Mixed(b).get_type() && a == Mixed(b).get_float(); } inline bool operator!=(float a, Wrap b) { - return Mixed(b).get_type() == type_Float && a != Mixed(b).get_float(); + return type_Float != Mixed(b).get_type() || a != Mixed(b).get_float(); } @@ -382,60 +459,80 @@ inline bool operator==(Wrap a, double b) inline bool operator!=(Wrap a, double b) { - return Mixed(a).get_type() == type_Double && Mixed(a).get_double() != b; + return Mixed(a).get_type() != type_Double || Mixed(a).get_double() != b; } inline bool operator==(double a, Wrap b) { - return Mixed(b).get_type() == type_Double && a == Mixed(b).get_double(); + return type_Double == Mixed(b).get_type() && a == Mixed(b).get_double(); } inline bool operator!=(double a, Wrap b) { - return Mixed(b).get_type() == type_Double && a != Mixed(b).get_double(); + return type_Double != Mixed(b).get_type() || a != Mixed(b).get_double(); } -// Compare mixed with zero-terminated string +// Compare mixed with string + +inline bool operator==(Wrap a, StringData b) TIGHTDB_NOEXCEPT +{ + return Mixed(a).get_type() == type_String && Mixed(a).get_string() == b; +} + +inline bool operator!=(Wrap a, StringData b) TIGHTDB_NOEXCEPT +{ + return Mixed(a).get_type() != type_String || Mixed(a).get_string() != b; +} + +inline bool operator==(StringData a, Wrap b) TIGHTDB_NOEXCEPT +{ + return type_String == Mixed(b).get_type() && a == Mixed(b).get_string(); +} + +inline bool operator!=(StringData a, Wrap b) TIGHTDB_NOEXCEPT +{ + return type_String != Mixed(b).get_type() || a != Mixed(b).get_string(); +} inline bool operator==(Wrap a, const char* b) TIGHTDB_NOEXCEPT { - return Mixed(a).get_type() == type_String && std::strcmp(Mixed(a).get_string(), b) == 0; + return a == StringData(b); } inline bool operator!=(Wrap a, const char* b) TIGHTDB_NOEXCEPT { - return Mixed(a).get_type() == type_String && std::strcmp(Mixed(a).get_string(), b) != 0; + return a != StringData(b); } inline bool operator==(const char* a, Wrap b) TIGHTDB_NOEXCEPT { - return Mixed(b).get_type() == type_String && std::strcmp(a, Mixed(b).get_string()) == 0; + return StringData(a) == b; } inline bool operator!=(const char* a, Wrap b) TIGHTDB_NOEXCEPT { - return Mixed(b).get_type() == type_String && std::strcmp(a, Mixed(b).get_string()) != 0; + return StringData(a) != b; } inline bool operator==(Wrap a, char* b) TIGHTDB_NOEXCEPT { - return Mixed(a).get_type() == type_String && std::strcmp(Mixed(a).get_string(), b) == 0; + return a == StringData(b); } inline bool operator!=(Wrap a, char* b) TIGHTDB_NOEXCEPT { - return Mixed(a).get_type() == type_String && std::strcmp(Mixed(a).get_string(), b) != 0; + return a != StringData(b); } inline bool operator==(char* a, Wrap b) TIGHTDB_NOEXCEPT { - return Mixed(b).get_type() == type_String && std::strcmp(a, Mixed(b).get_string()) == 0; + return StringData(a) == b; } inline bool operator!=(char* a, Wrap b) TIGHTDB_NOEXCEPT { - return Mixed(b).get_type() == type_String && std::strcmp(a, Mixed(b).get_string()) != 0; + return StringData(a) != b; } @@ -443,22 +540,22 @@ inline bool operator!=(char* a, Wrap b) TIGHTDB_NOEXCEPT inline bool operator==(Wrap a, BinaryData b) TIGHTDB_NOEXCEPT { - return Mixed(a).get_type() == type_Binary && Mixed(a).get_binary().compare_payload(b); + return Mixed(a).get_type() == type_Binary && Mixed(a).get_binary() == b; } inline bool operator!=(Wrap a, BinaryData b) TIGHTDB_NOEXCEPT { - return Mixed(a).get_type() == type_Binary && !Mixed(a).get_binary().compare_payload(b); + return Mixed(a).get_type() != type_Binary || Mixed(a).get_binary() != b; } inline bool operator==(BinaryData a, Wrap b) TIGHTDB_NOEXCEPT { - return Mixed(b).get_type() == type_Binary && a.compare_payload(Mixed(b).get_binary()); + return type_Binary == Mixed(b).get_type() && a == Mixed(b).get_binary(); } inline bool operator!=(BinaryData a, Wrap b) TIGHTDB_NOEXCEPT { - return Mixed(b).get_type() == type_Binary && !a.compare_payload(Mixed(b).get_binary()); + return type_Binary != Mixed(b).get_type() || a != Mixed(b).get_binary(); } @@ -471,17 +568,17 @@ inline bool operator==(Wrap a, Date b) TIGHTDB_NOEXCEPT inline bool operator!=(Wrap a, Date b) TIGHTDB_NOEXCEPT { - return Mixed(a).get_type() == type_Date && Date(Mixed(a).get_date()) != b; + return Mixed(a).get_type() != type_Date || Date(Mixed(a).get_date()) != b; } inline bool operator==(Date a, Wrap b) TIGHTDB_NOEXCEPT { - return Mixed(b).get_type() == type_Date && a == Date(Mixed(b).get_date()); + return type_Date == Mixed(b).get_type() && a == Date(Mixed(b).get_date()); } inline bool operator!=(Date a, Wrap b) TIGHTDB_NOEXCEPT { - return Mixed(b).get_type() == type_Date && a != Date(Mixed(b).get_date()); + return type_Date != Mixed(b).get_type() || a != Date(Mixed(b).get_date()); } diff --git a/src/tightdb/query.cpp b/src/tightdb/query.cpp index a2fc03a5091..eba3e37f9e0 100644 --- a/src/tightdb/query.cpp +++ b/src/tightdb/query.cpp @@ -84,7 +84,31 @@ Query& Query::tableview(const Array &arr) // Binary Query& Query::equal(size_t column_ndx, BinaryData b) { - ParentNode* const p = new BinaryNode(b.pointer, b.len, column_ndx); + ParentNode* const p = new BinaryNode(b, column_ndx); + UpdatePointers(p, &p->m_child); + return *this; +} +Query& Query::not_equal(size_t column_ndx, BinaryData b) +{ + ParentNode* const p = new BinaryNode(b, column_ndx); + UpdatePointers(p, &p->m_child); + return *this; +} +Query& Query::begins_with(size_t column_ndx, BinaryData b) +{ + ParentNode* p = new BinaryNode(b, column_ndx); + UpdatePointers(p, &p->m_child); + return *this; +} +Query& Query::ends_with(size_t column_ndx, BinaryData b) +{ + ParentNode* p = new BinaryNode(b, column_ndx); + UpdatePointers(p, &p->m_child); + return *this; +} +Query& Query::contains(size_t column_ndx, BinaryData b) +{ + ParentNode* p = new BinaryNode(b, column_ndx); UpdatePointers(p, &p->m_child); return *this; } @@ -219,50 +243,50 @@ Query& Query::between(size_t column_ndx, double from, double to) } // STRINGS -Query& Query::equal(size_t column_ndx, const char* value, bool caseSensitive) +Query& Query::equal(size_t column_ndx, StringData value, bool case_sensitive) { ParentNode* p; - if (caseSensitive) + if (case_sensitive) p = new StringNode(value, column_ndx); else p = new StringNode(value, column_ndx); UpdatePointers(p, &p->m_child); return *this; } -Query& Query::begins_with(size_t column_ndx, const char* value, bool caseSensitive) +Query& Query::begins_with(size_t column_ndx, StringData value, bool case_sensitive) { ParentNode* p; - if (caseSensitive) + if (case_sensitive) p = new StringNode(value, column_ndx); else p = new StringNode(value, column_ndx); UpdatePointers(p, &p->m_child); return *this; } -Query& Query::ends_with(size_t column_ndx, const char* value, bool caseSensitive) +Query& Query::ends_with(size_t column_ndx, StringData value, bool case_sensitive) { ParentNode* p; - if (caseSensitive) + if (case_sensitive) p = new StringNode(value, column_ndx); else p = new StringNode(value, column_ndx); UpdatePointers(p, &p->m_child); return *this; } -Query& Query::contains(size_t column_ndx, const char* value, bool caseSensitive) +Query& Query::contains(size_t column_ndx, StringData value, bool case_sensitive) { ParentNode* p; - if (caseSensitive) + if (case_sensitive) p = new StringNode(value, column_ndx); else p = new StringNode(value, column_ndx); UpdatePointers(p, &p->m_child); return *this; } -Query& Query::not_equal(size_t column_ndx, const char* value, bool caseSensitive) +Query& Query::not_equal(size_t column_ndx, StringData value, bool case_sensitive) { ParentNode* p; - if (caseSensitive) + if (case_sensitive) p = new StringNode(value, column_ndx); else p = new StringNode(value, column_ndx); @@ -553,7 +577,7 @@ TableView Query::find_all_multi(size_t start, size_t end) TableView tv(*m_table); // Sort search results because user expects ascending order - std::sort (ts.chunks.begin(), ts.chunks.end(), &Query::comp); + sort(ts.chunks.begin(), ts.chunks.end(), &Query::comp); for (size_t i = 0; i < ts.chunks.size(); ++i) { const size_t from = ts.chunks[i].first; const size_t upto = (i == ts.chunks.size() - 1) ? size_t(-1) : ts.chunks[i + 1].first; @@ -599,8 +623,8 @@ void* Query::query_thread(void* arg) static_cast(arg); thread_state* ts = static_cast(arg); - std::vector res; - std::vector > chunks; + vector res; + vector > chunks; for (;;) { // Main waiting loop that waits for a query to start @@ -634,7 +658,7 @@ void* Query::query_thread(void* arg) pthread_mutex_lock(&ts->result_mutex); ts->done_job += chunk; if (res.size() > 0) { - ts->chunks.push_back(std::pair(mine, ts->results.size())); + ts->chunks.push_back(pair(mine, ts->results.size())); ts->count += res.size(); for (size_t i = 0; i < res.size(); i++) { ts->results.push_back(res[i]); @@ -656,7 +680,7 @@ void* Query::query_thread(void* arg) #ifdef TIGHTDB_DEBUG -std::string Query::Verify() +string Query::Verify() { if (first.size() == 0) return ""; @@ -676,7 +700,7 @@ void Query::Init(const Table& table) const if (first[0] != NULL) { ParentNode* const top = (ParentNode*)first[0]; top->Init(table); - std::vectorv; + vectorv; top->gather_children(v); } } @@ -712,7 +736,7 @@ void Query::UpdatePointers(ParentNode* p, ParentNode** newnode) update[update.size()-1] = newnode; } -bool Query::comp(const std::pair& a, const std::pair& b) +bool Query::comp(const pair& a, const pair& b) { return a.first < b.first; } diff --git a/src/tightdb/query.hpp b/src/tightdb/query.hpp index f56c1e2fd7d..010af16a4e9 100644 --- a/src/tightdb/query.hpp +++ b/src/tightdb/query.hpp @@ -87,31 +87,28 @@ class Query { // Conditions: bool Query& equal(size_t column_ndx, bool value); - // Conditions: strings - Query& equal(size_t column_ndx, const char* value, bool case_sensitive=true); - Query& begins_with(size_t column_ndx, const char* value, bool case_sensitive=true); - Query& ends_with(size_t column_ndx, const char* value, bool case_sensitive=true); - Query& contains(size_t column_ndx, const char* value, bool case_sensitive=true); - Query& not_equal(size_t column_ndx, const char* value, bool case_sensitive=true); - // Conditions: date - Query& equal_date(size_t column_ndx, time_t value) { return equal(column_ndx, int64_t(value)); } - Query& not_equal_date(size_t column_ndx, time_t value) { return not_equal(column_ndx, int64_t(value)); } - Query& greater_date(size_t column_ndx, time_t value) { return greater(column_ndx, int64_t(value)); } - Query& greater_equal_date(size_t column_ndx, time_t value) { return greater_equal(column_ndx, int64_t(value)); } - Query& less_date(size_t column_ndx, time_t value) { return less(column_ndx, int64_t(value)); } - Query& less_equal_date(size_t column_ndx, time_t value) { return less_equal(column_ndx, int64_t(value)); } - Query& between_date(size_t column_ndx, time_t from, time_t to) { return between(column_ndx, int64_t(from), int64_t(to)); } + Query& equal_date(size_t column_ndx, Date value) { return equal(column_ndx, int64_t(value.get_date())); } + Query& not_equal_date(size_t column_ndx, Date value) { return not_equal(column_ndx, int64_t(value.get_date())); } + Query& greater_date(size_t column_ndx, Date value) { return greater(column_ndx, int64_t(value.get_date())); } + Query& greater_equal_date(size_t column_ndx, Date value) { return greater_equal(column_ndx, int64_t(value.get_date())); } + Query& less_date(size_t column_ndx, Date value) { return less(column_ndx, int64_t(value.get_date())); } + Query& less_equal_date(size_t column_ndx, Date value) { return less_equal(column_ndx, int64_t(value.get_date())); } + Query& between_date(size_t column_ndx, Date from, Date to) { return between(column_ndx, int64_t(from.get_date()), int64_t(to.get_date())); } + + // Conditions: strings + Query& equal(size_t column_ndx, StringData value, bool case_sensitive=true); + Query& not_equal(size_t column_ndx, StringData value, bool case_sensitive=true); + Query& begins_with(size_t column_ndx, StringData value, bool case_sensitive=true); + Query& ends_with(size_t column_ndx, StringData value, bool case_sensitive=true); + Query& contains(size_t column_ndx, StringData value, bool case_sensitive=true); // Conditions: binary data - // Only BinaryData prototype can exist, else it would conflict with equal() for strings - Query& equal(size_t column_ndx, BinaryData); -/* - Query& equal_binary(size_t column_ndx, const char* ptr, size_t len); - Query& begins_with_binary(size_t column_ndx, const char* ptr, size_t len); - Query& ends_with_binary(size_t column_ndx, const char* ptr, size_t len); - Query& contains_binary(size_t column_ndx, const char* ptr, size_t len); -*/ + Query& equal(size_t column_ndx, BinaryData value); + Query& not_equal(size_t column_ndx, BinaryData value); + Query& begins_with(size_t column_ndx, BinaryData value); + Query& ends_with(size_t column_ndx, BinaryData value); + Query& contains(size_t column_ndx, BinaryData value); // Grouping Query& group(); diff --git a/src/tightdb/query_conditions.hpp b/src/tightdb/query_conditions.hpp index d0155048df4..41c97c38716 100644 --- a/src/tightdb/query_conditions.hpp +++ b/src/tightdb/query_conditions.hpp @@ -21,9 +21,9 @@ #define TIGHTDB_QUERY_CONDITIONS_HPP #include -#include #include +#include #include namespace tightdb { @@ -31,69 +31,32 @@ namespace tightdb { enum {cond_Equal, cond_NotEqual, cond_Greater, cond_GreaterEqual, cond_Less, cond_LessEqual, cond_None, cond_Count}; +// Does v2 contain v1? struct Contains { - bool operator()(const char* v1, const char* v1_upper, const char* v1_lower, const char* v2) const - { - static_cast(v1_lower); - static_cast(v1_upper); - return std::strstr(v2, v1) != 0; - } + bool operator()(StringData v1, const char*, const char*, StringData v2) const { return v2.contains(v1); } + bool operator()(BinaryData v1, BinaryData v2) const { return v2.contains(v1); } }; -// is v2 a prefix of v1? +// Does v2 begin with v1? struct BeginsWith { - bool operator()(const char* v1, const char* v1_upper, const char* v1_lower, const char* v2) const - { - static_cast(v1_lower); - static_cast(v1_upper); - return std::strstr(v2, v1) == v2; // FIXME: Not the most efficient way to do this - } + bool operator()(StringData v1, const char*, const char*, StringData v2) const { return v2.begins_with(v1); } + bool operator()(BinaryData v1, BinaryData v2) const { return v2.begins_with(v1); } }; -// does v1 end with s2? +// Does v2 end with v1? struct EndsWith { - bool operator()(const char* v1, const char* v1_upper, const char* v1_lower, const char* v2) const - { - static_cast(v1_lower); - static_cast(v1_upper); - const size_t l1 = std::strlen(v1); - const size_t l2 = std::strlen(v2); - if (l1 > l2) - return false; - - return std::strcmp(v1, v2 + l2 - l1) == 0; - } + bool operator()(StringData v1, const char*, const char*, StringData v2) const { return v2.ends_with(v1); } + bool operator()(BinaryData v1, BinaryData v2) const { return v2.ends_with(v1); } }; struct Equal { - bool operator()(const bool v1, const bool v2) const - { - return v1 == v2; - } + bool operator()(const bool v1, const bool v2) const { return v1 == v2; } // To avoid a "performance warning" in VC++ - bool operator()(const int64_t v1, const bool v2) const - { - return (v1 != 0) == v2; - } + bool operator()(const int64_t v1, const bool v2) const { return (v1 != 0) == v2; } - bool operator()(const char *v1, const char* v1_upper, const char* v1_lower, const char* v2) const - { - static_cast(v1_lower); - static_cast(v1_upper); - return std::strcmp(v1, v2) == 0; - } - bool operator()(const char *v1, size_t len1, const char* v2, size_t len2) const - { - if (len1 != len2) - return false; - if (len1 == 0) - return true; - if (v1[len1 - 1] != v2[len1 - 1]) - return false; - int i = memcmp(v1, v2, len1); - return (i == 0); - } + bool operator()(StringData v1, const char*, const char*, StringData v2) const { return v1 == v2; } + bool operator()(BinaryData v1, BinaryData v2) const { return v1 == v2; } template bool operator()(const T& v1, const T& v2) const {return v1 == v2;} int condition() {return cond_Equal;} @@ -102,68 +65,53 @@ struct Equal { }; struct NotEqual { - bool operator()(const char *v1, const char* v1_upper, const char* v1_lower, const char* v2) const - { - static_cast(v1_lower); - static_cast(v1_upper); - return std::strcmp(v1, v2) != 0; - } + bool operator()(StringData v1, const char*, const char*, StringData v2) const { return v1 != v2; } + bool operator()(BinaryData v1, BinaryData v2) const { return v1 != v2; } template bool operator()(const T& v1, const T& v2) const { return v1 != v2; } int condition() {return cond_NotEqual;} bool can_match(int64_t v, int64_t lbound, int64_t ubound) { return !(v == 0 && ubound == 0 && lbound == 0); } bool will_match(int64_t v, int64_t lbound, int64_t ubound) { return (v > ubound || v < lbound); } }; -// does v1 contain v2? +// Does v2 contain v1? struct ContainsIns { - bool operator()(const char* v1, const char* v1_upper, const char* v1_lower, const char* v2) const + bool operator()(StringData v1, const char* v1_upper, const char* v1_lower, StringData v2) const { - static_cast(v1); - return case_strstr(v1_upper, v1_lower, v2); + return search_case_fold(v2, v1_upper, v1_lower, v1.size()) != v2.size(); } int condition() {return -1;} }; -// is v2 a prefix of v1? +// Does v2 begin with v1? struct BeginsWithIns { - bool operator()(const char* v1, const char* v1_upper, const char* v1_lower, const char* v2) const + bool operator()(StringData v1, const char* v1_upper, const char* v1_lower, StringData v2) const { - static_cast(v1); - return case_prefix(v1_upper, v1_lower, v2) != (size_t)-1; + return v1.size() <= v2.size() && equal_case_fold(v2.prefix(v1.size()), v1_upper, v1_lower); } int condition() {return -1;} }; -// does v1 end with s2? +// Does v2 end with v1? struct EndsWithIns { - bool operator()(const char* v1, const char* v1_upper, const char* v1_lower, const char* v2) const + bool operator()(StringData v1, const char* v1_upper, const char* v1_lower, StringData v2) const { - const size_t l1 = std::strlen(v1); - const size_t l2 = std::strlen(v2); - if (l1 > l2) - return false; - - bool r = case_cmp(v1_upper, v1_lower, v2 + l2 - l1); - return r; + return v1.size() <= v2.size() && equal_case_fold(v2.suffix(v1.size()), v1_upper, v1_lower); } int condition() {return -1;} }; struct EqualIns { - bool operator()(const char* v1, const char* v1_upper, const char* v1_lower, const char* v2) const + bool operator()(StringData v1, const char* v1_upper, const char* v1_lower, StringData v2) const { - static_cast(v1); - return case_cmp(v1_upper, v1_lower, v2); + return v1.size() == v2.size() && equal_case_fold(v2, v1_upper, v1_lower); } int condition() {return -1;} }; struct NotEqualIns { - bool operator()(const char* v1, const char* v1_upper, const char* v1_lower, const char* v2) const + bool operator()(StringData v1, const char* v1_upper, const char* v1_lower, StringData v2) const { - static_cast(v1_lower); - static_cast(v1); - return !case_cmp(v1_upper, v1_lower, v2); + return v1.size() != v2.size() || !equal_case_fold(v2, v1_upper, v1_lower); } int condition() {return -1;} }; @@ -204,6 +152,3 @@ struct GreaterEqual { } // namespace tightdb #endif // TIGHTDB_QUERY_CONDITIONS_HPP - - - diff --git a/src/tightdb/query_engine.hpp b/src/tightdb/query_engine.hpp index b51585be61e..5ed6ede46f8 100644 --- a/src/tightdb/query_engine.hpp +++ b/src/tightdb/query_engine.hpp @@ -88,8 +88,9 @@ AggregateState State of the aggregate - contains a state variable that stor #include #include -#include "meta.hpp" +#include +#include #include #include #include @@ -818,27 +819,34 @@ template class StringNode: public ParentNode { return 0; } - StringNode(const char* v, size_t column) + StringNode(StringData v, size_t column) { m_condition_column_idx = column; m_child = 0; m_dT = 10.0; m_leaf = NULL; - // todo, see if we can store in std::string instead - m_value = new char[strlen(v)*6]; - memcpy(m_value, v, strlen(v) + 1); - m_ucase = new char[strlen(v)*6]; - m_lcase = new char[strlen(v)*6]; - - const bool b1 = utf8case(v, m_lcase, false); - const bool b2 = utf8case(v, m_ucase, true); - if (!b1 || !b2) - error_code = "Malformed UTF-8: " + std::string(m_value); + + // FIXME: Store these in std::string instead. + // FIXME: Why are these sizes 6 times the required size? + char* data = new char[6 * v.size()]; // FIXME: Arithmetic is prone to overflow + std::copy(v.data(), v.data()+v.size(), data); + m_value = StringData(data, v.size()); + char* upper = new char[6 * v.size()]; + char* lower = new char[6 * v.size()]; + + bool b1 = case_map(v, lower, false); + bool b2 = case_map(v, upper, true); + if (!b1 || !b2) error_code = "Malformed UTF-8: " + std::string(v); + + m_ucase = upper; + m_lcase = lower; } ~StringNode() { - delete[] m_value; delete[] m_ucase; delete[] m_lcase; + delete[] m_value.data(); + delete[] m_ucase; + delete[] m_lcase; m_long ? delete(static_cast(m_leaf)) : delete(static_cast(m_leaf)); } @@ -861,11 +869,11 @@ template class StringNode: public ParentNode { TConditionFunction cond; for (size_t s = start; s < end; ++s) { - const char* t; + StringData t; #if 1 if (m_column_type == col_type_StringEnum) { // enum - t = static_cast(m_condition_column)->Get(s); + t = static_cast(m_condition_column)->get(s); } else { // short or long @@ -879,16 +887,16 @@ template class StringNode: public ParentNode { m_end_s = m_leaf_start + (m_long ? static_cast(m_leaf)->size() : static_cast(m_leaf)->size()); } - t = (m_long ? static_cast(m_leaf)->Get(s - m_leaf_start) : static_cast(m_leaf)->Get(s - m_leaf_start)); + t = (m_long ? static_cast(m_leaf)->get(s - m_leaf_start) : static_cast(m_leaf)->get(s - m_leaf_start)); } #else // old legacy, to track bugs - enable to see if bug was caused by above optimization // todo, can be optimized by placing outside loop if (m_column_type == col_type_String) - t = static_cast(m_condition_column)->Get(s); + t = static_cast(m_condition_column)->get(s); else { //TODO: First check if string is in key list - t = static_cast(m_condition_column)->Get(s); + t = static_cast(m_condition_column)->get(s); } #endif if (cond(m_value, m_ucase, m_lcase, t)) @@ -898,9 +906,11 @@ template class StringNode: public ParentNode { } protected: - char* m_value; - char* m_lcase; - char* m_ucase; +private: + StringData m_value; + const char* m_lcase; + const char* m_ucase; +protected: const ColumnBase* m_condition_column; ColumnType m_column_type; @@ -969,19 +979,21 @@ template class BinaryNode: public ParentNode { public: template int64_t find_all(Array* /*res*/, size_t /*start*/, size_t /*end*/, size_t /*limit*/, size_t /*source_column*/) {TIGHTDB_ASSERT(false); return 0;} - BinaryNode(const char* v, size_t len, size_t column) + BinaryNode(BinaryData v, size_t column) { m_dT = 100.0; m_condition_column_idx = column; m_child = 0; - m_len = len; - m_value = new char[len]; - memcpy(m_value, v, len); + + // FIXME: Store this in std::string instead. + char* data = new char[v.size()]; + std::copy(v.data(), v.data()+v.size(), data); + m_value = BinaryData(data, v.size()); } ~BinaryNode() { - delete(m_value); + delete[] m_value.data(); } void Init(const Table& table) @@ -998,26 +1010,23 @@ template class BinaryNode: public ParentNode { size_t find_first_local(size_t start, size_t end) { TConditionFunction condition; - for (size_t s = start; s < end; ++s) { - const char* value = m_condition_column->Get(s).pointer; - size_t len = m_condition_column->Get(s).len; - - if (condition(m_value, m_len, value, len)) - return s; + BinaryData value = m_condition_column->get(s); + if (condition(m_value, value)) return s; } return end; } protected: - char* m_value; - size_t m_len; +private: + BinaryData m_value; +protected: const ColumnBinary* m_condition_column; ColumnType m_column_type; }; -template <> class StringNode: public ParentNode { +template<> class StringNode: public ParentNode { public: template int64_t find_all(Array*, size_t, size_t, size_t, size_t) @@ -1026,16 +1035,20 @@ template <> class StringNode: public ParentNode { return 0; } - StringNode(const char* v, size_t column): m_key_ndx((size_t)-1) -{ + StringNode(StringData v, size_t column): m_key_ndx(size_t(-1)) + { m_condition_column_idx = column; m_child = 0; - m_value = new char[strlen(v)*6]; - memcpy(m_value, v, strlen(v) + 1); + // FIXME: Store this in std::string instead. + // FIXME: Why are the sizes 6 times the required size? + char* data = new char[6 * v.size()]; // FIXME: Arithmetic is prone to overflow + std::copy(v.data(), v.data()+v.size(), data); + m_value = StringData(data, v.size()); m_leaf = NULL; } - ~StringNode() { - delete(m_value); + ~StringNode() + { + delete[] m_value.data(); m_long ? delete(static_cast(m_leaf)) : delete(static_cast(m_leaf)); m_index.Destroy(); } @@ -1152,7 +1165,8 @@ template <> class StringNode: public ParentNode { } protected: - char* m_value; +private: + StringData m_value; private: const ColumnBase* m_condition_column; diff --git a/src/tightdb/replication.cpp b/src/tightdb/replication.cpp index a3b60f530d0..289ea3f7c0f 100644 --- a/src/tightdb/replication.cpp +++ b/src/tightdb/replication.cpp @@ -308,7 +308,8 @@ bool Replication::grant_write_access_and_wait_for_completion(TransactLog& transa shared_state->m_write_transact_available = true; shared_state->m_cond_write_transact_available.notify_all(); while (!shared_state->m_write_transact_finished) { - if (m_interrupt) return false; + if (m_interrupt) + return false; shared_state->m_cond_write_transact_finished.wait(ml); } shared_state->m_write_transact_finished = false; @@ -427,8 +428,10 @@ void Replication::transact_log_reserve_contig(size_t n) // logs gets transmitted to other clients. So in that case // we will simply wait. if (shared_state->m_transact_log_used_begin == - shared_state->m_transact_log_used_end) break; - if (m_interrupt) throw Interrupted(); + shared_state->m_transact_log_used_end) + break; + if (m_interrupt) + throw Interrupted(); shared_state->m_cond_transact_log_free.wait(ml); } } @@ -448,7 +451,7 @@ void Replication::transact_log_reserve_contig(size_t n) } -void Replication::transact_log_append_overflow(const char* data, std::size_t size) +void Replication::transact_log_append_overflow(const char* data, size_t size) { // FIXME: During write access, it should be possible to use m_file_map.get_size() instead of SharedState::m_size. bool need_expand = false; @@ -464,7 +467,8 @@ void Replication::transact_log_append_overflow(const char* data, std::size_t siz // the end of the buffer. size_t avail = shared_state->m_size - used_end; // Require one unused byte. - if (sizeof(SharedState) < used_begin) avail += used_begin - sizeof(SharedState) - 1; // FIXME: Use static const memeber + if (sizeof(SharedState) < used_begin) + avail += used_begin - sizeof(SharedState) - 1; // FIXME: Use static const memeber if (size <= avail) { m_transact_log_free_end = base + shared_state->m_size; break; @@ -541,16 +545,19 @@ void Replication::transact_log_expand(size_t free, bool contig) if (used_lower < used_upper) { // Move lower section min_size = used_wrap; - if (int_add_with_overflow_detect(min_size, used_lower)) goto transact_log_too_big; + if (int_add_with_overflow_detect(min_size, used_lower)) + goto transact_log_too_big; const size_t avail_lower = used_begin - buffer_begin; if (avail_lower <= free) { // Require one unused byte - if (int_add_with_overflow_detect(min_size, free)) goto transact_log_too_big; + if (int_add_with_overflow_detect(min_size, free)) + goto transact_log_too_big; } } else { // Move upper section min_size = used_end + 1 + used_upper; // Require one unused byte - if (int_add_with_overflow_detect(min_size, free)) goto transact_log_too_big; + if (int_add_with_overflow_detect(min_size, free)) + goto transact_log_too_big; } } else { @@ -562,7 +569,8 @@ void Replication::transact_log_expand(size_t free, bool contig) // Require one unused byte min_size = buffer_begin + (used_end-used_begin) + 1; } - if (int_add_with_overflow_detect(min_size, free)) goto transact_log_too_big; + if (int_add_with_overflow_detect(min_size, free)) + goto transact_log_too_big; } new_size = shared_state->m_size; @@ -635,7 +643,8 @@ void Replication::select_table(const Table* table) for (;;) { begin = m_subtab_path_buf.m_data; end = table->record_subtable_path(begin, begin+m_subtab_path_buf.m_size); - if (end) break; + if (end) + break; size_t new_size = m_subtab_path_buf.m_size; if (int_multiply_with_overflow_detect(new_size, 2)) throw runtime_error("To many subtable nesting levels"); @@ -651,7 +660,8 @@ void Replication::select_table(const Table* table) for (;;) { for (int i=0; i T Replication::TransactLogApplier::read_int() { T value = 0; int part; - const int max_bytes = (std::numeric_limits::digits+1+6)/7; + const int max_bytes = (numeric_limits::digits+1+6)/7; for (int i=0; i(c); - if (0xFF < part) goto bad_transact_log; // Only the first 8 bits may be used in each byte + if (0xFF < part) + goto bad_transact_log; // Only the first 8 bits may be used in each byte if ((part & 0x80) == 0) { T p = part & 0x3F; - if (int_shift_left_with_overflow_detect(p, i*7)) goto bad_transact_log; + if (int_shift_left_with_overflow_detect(p, i*7)) + goto bad_transact_log; value |= p; break; } - if (i == max_bytes-1) goto bad_transact_log; // Two many bytes + if (i == max_bytes-1) + goto bad_transact_log; // Two many bytes value |= T(part & 0x7F) << (i*7); } if (part & 0x40) { @@ -817,7 +836,8 @@ template T Replication::TransactLogApplier::read_int() // this point, the following negation is guaranteed by the // standard to never overflow. value = -value; - if (int_subtract_with_overflow_detect(value, 1)) goto bad_transact_log; + if (int_subtract_with_overflow_detect(value, 1)) + goto bad_transact_log; } return value; @@ -834,10 +854,12 @@ void Replication::TransactLogApplier::read_string(StringBuffer& buf) char* str_end = buf.data(); for (;;) { const size_t avail = m_input_end - m_input_begin; - if (size <= avail) break; + if (size <= avail) + break; const char* to = m_input_begin + avail; copy(m_input_begin, to, str_end); - if (!fill_input_buffer()) throw BadTransactLog(); + if (!fill_input_buffer()) + throw BadTransactLog(); str_end += avail; size -= avail; } @@ -872,251 +894,305 @@ template void Replication::TransactLogApplier::set_or_insert(int column_ndx, size_t ndx) { switch (m_table->get_column_type(column_ndx)) { - case type_Int: - { + case type_Int: { int64_t value = read_int(); // Throws - if (insert) m_table->insert_int(column_ndx, ndx, value); // FIXME: Memory allocation failure!!! - else m_table->set_int(column_ndx, ndx, value); // FIXME: Memory allocation failure!!! + if (insert) + m_table->insert_int(column_ndx, ndx, value); // FIXME: Memory allocation failure!!! + else + m_table->set_int(column_ndx, ndx, value); // FIXME: Memory allocation failure!!! #ifdef TIGHTDB_DEBUG if (m_log) { - if (insert) *m_log << "table->insert_int("<set_int("<insert_int("<set_int("<(); // Throws - if (insert) m_table->insert_bool(column_ndx, ndx, value); // FIXME: Memory allocation failure!!! - else m_table->set_bool(column_ndx, ndx, value); // FIXME: Memory allocation failure!!! + if (insert) + m_table->insert_bool(column_ndx, ndx, value); // FIXME: Memory allocation failure!!! + else + m_table->set_bool(column_ndx, ndx, value); // FIXME: Memory allocation failure!!! #ifdef TIGHTDB_DEBUG if (m_log) { - if (insert) *m_log << "table->insert_bool("<set_bool("<insert_bool("<set_bool("<(); // Throws - if (insert) m_table->insert_date(column_ndx, ndx, value); // FIXME: Memory allocation failure!!! - else m_table->set_date(column_ndx, ndx, value); // FIXME: Memory allocation failure!!! + if (insert) + m_table->insert_date(column_ndx, ndx, value); // FIXME: Memory allocation failure!!! + else + m_table->set_date(column_ndx, ndx, value); // FIXME: Memory allocation failure!!! #ifdef TIGHTDB_DEBUG if (m_log) { - if (insert) *m_log << "table->insert_date("<set_date("<insert_date("<set_date("<insert_string(column_ndx, ndx, value); // FIXME: Memory allocation failure!!! - else m_table->set_string(column_ndx, ndx, value); // FIXME: Memory allocation failure!!! + StringData value(m_string_buffer.data(), m_string_buffer.size()); + if (insert) + m_table->insert_string(column_ndx, ndx, value); // FIXME: Memory allocation failure!!! + else + m_table->set_string(column_ndx, ndx, value); // FIXME: Memory allocation failure!!! #ifdef TIGHTDB_DEBUG if (m_log) { - if (insert) *m_log << "table->insert_string("<set_string("<insert_string("<set_string("<insert_binary(column_ndx, ndx, m_string_buffer.data(), - m_string_buffer.size()); // FIXME: Memory allocation failure!!! - else m_table->set_binary(column_ndx, ndx, m_string_buffer.data(), - m_string_buffer.size()); // FIXME: Memory allocation failure!!! + BinaryData value(m_string_buffer.data(), m_string_buffer.size()); + if (insert) + m_table->insert_binary(column_ndx, ndx, value); // FIXME: Memory allocation failure!!! + else + m_table->set_binary(column_ndx, ndx, value); // FIXME: Memory allocation failure!!! #ifdef TIGHTDB_DEBUG if (m_log) { - if (insert) *m_log << "table->insert_binary("<set_binary("<insert_binary("<set_binary("<insert_subtable(column_ndx, ndx); // FIXME: Memory allocation failure!!! - else m_table->clear_subtable(column_ndx, ndx); // FIXME: Memory allocation failure!!! + case type_Table: { + if (insert) + m_table->insert_subtable(column_ndx, ndx); // FIXME: Memory allocation failure!!! + else + m_table->clear_subtable(column_ndx, ndx); // FIXME: Memory allocation failure!!! #ifdef TIGHTDB_DEBUG - if (m_log) { - if (insert) *m_log << "table->insert_subtable("<clear_subtable("<insert_subtable("<clear_subtable("<(); // Throws switch (type) { - case type_Int: - { + case type_Int: { int64_t value = read_int(); // Throws - if (insert) m_table->insert_mixed(column_ndx, ndx, value); // FIXME: Memory allocation failure!!! - else m_table->set_mixed(column_ndx, ndx, value); // FIXME: Memory allocation failure!!! + if (insert) + m_table->insert_mixed(column_ndx, ndx, value); // FIXME: Memory allocation failure!!! + else + m_table->set_mixed(column_ndx, ndx, value); // FIXME: Memory allocation failure!!! #ifdef TIGHTDB_DEBUG if (m_log) { - if (insert) *m_log << "table->insert_mixed("<set_mixed("<insert_mixed("<set_mixed("<(); // Throws - if (insert) m_table->insert_mixed(column_ndx, ndx, value); // FIXME: Memory allocation failure!!! - else m_table->set_mixed(column_ndx, ndx, value); // FIXME: Memory allocation failure!!! + if (insert) + m_table->insert_mixed(column_ndx, ndx, value); // FIXME: Memory allocation failure!!! + else + m_table->set_mixed(column_ndx, ndx, value); // FIXME: Memory allocation failure!!! #ifdef TIGHTDB_DEBUG if (m_log) { - if (insert) *m_log << "table->insert_mixed("<set_mixed("<insert_mixed("<set_mixed("<(); // Throws - if (insert) m_table->insert_mixed(column_ndx, ndx, Date(value)); // FIXME: Memory allocation failure!!! - else m_table->set_mixed(column_ndx, ndx, Date(value)); // FIXME: Memory allocation failure!!! + if (insert) + m_table->insert_mixed(column_ndx, ndx, Date(value)); // FIXME: Memory allocation failure!!! + else + m_table->set_mixed(column_ndx, ndx, Date(value)); // FIXME: Memory allocation failure!!! #ifdef TIGHTDB_DEBUG if (m_log) { - if (insert) *m_log << "table->insert_mixed("<set_mixed("<insert_mixed("<set_mixed("<insert_mixed(column_ndx, ndx, value); // FIXME: Memory allocation failure!!! - else m_table->set_mixed(column_ndx, ndx, value); // FIXME: Memory allocation failure!!! + StringData value(m_string_buffer.data(), m_string_buffer.size()); + if (insert) + m_table->insert_mixed(column_ndx, ndx, value); // FIXME: Memory allocation failure!!! + else + m_table->set_mixed(column_ndx, ndx, value); // FIXME: Memory allocation failure!!! #ifdef TIGHTDB_DEBUG if (m_log) { - if (insert) *m_log << "table->insert_mixed("<set_mixed("<insert_mixed("<set_mixed("<insert_mixed(column_ndx, ndx, value); // FIXME: Memory allocation failure!!! - else m_table->set_mixed(column_ndx, ndx, value); // FIXME: Memory allocation failure!!! + BinaryData value(m_string_buffer.data(), m_string_buffer.size()); + if (insert) + m_table->insert_mixed(column_ndx, ndx, value); // FIXME: Memory allocation failure!!! + else + m_table->set_mixed(column_ndx, ndx, value); // FIXME: Memory allocation failure!!! #ifdef TIGHTDB_DEBUG if (m_log) { - if (insert) *m_log << "table->insert_mixed("<set_mixed("<insert_mixed("<set_mixed("<insert_mixed(column_ndx, ndx, Mixed::subtable_tag()); // FIXME: Memory allocation failure!!! - else m_table->set_mixed(column_ndx, ndx, Mixed::subtable_tag()); // FIXME: Memory allocation failure!!! + case type_Table: { + if (insert) + m_table->insert_mixed(column_ndx, ndx, Mixed::subtable_tag()); // FIXME: Memory allocation failure!!! + else + m_table->set_mixed(column_ndx, ndx, Mixed::subtable_tag()); // FIXME: Memory allocation failure!!! #ifdef TIGHTDB_DEBUG - if (m_log) { - if (insert) *m_log << "table->insert_mixed("<set_mixed("<insert_mixed("<set_mixed("<(); // Throws size_t ndx = read_int(); // Throws - if (!m_table) goto bad_transact_log; + if (!m_table) + goto bad_transact_log; if (column_ndx < 0 || int(m_table->get_column_count()) <= column_ndx) goto bad_transact_log; - if (m_table->size() <= ndx) goto bad_transact_log; + if (m_table->size() <= ndx) + goto bad_transact_log; const bool insert = false; set_or_insert(column_ndx, ndx); // Throws break; } case 'i': { // Insert value - if (m_dirty_spec) finalize_spec(); + if (m_dirty_spec) + finalize_spec(); int column_ndx = read_int(); // Throws size_t ndx = read_int(); // Throws - if (!m_table) goto bad_transact_log; + if (!m_table) + goto bad_transact_log; if (column_ndx < 0 || int(m_table->get_column_count()) <= column_ndx) goto bad_transact_log; - if (m_table->size() < ndx) goto bad_transact_log; + if (m_table->size() < ndx) + goto bad_transact_log; const bool insert = true; set_or_insert(column_ndx, ndx); // Throws break; } case 'c': { // Row insert complete - if (m_dirty_spec) finalize_spec(); - if (!m_table) goto bad_transact_log; + if (m_dirty_spec) + finalize_spec(); + if (!m_table) + goto bad_transact_log; m_table->insert_done(); // FIXME: May fail #ifdef TIGHTDB_DEBUG - if (m_log) *m_log << "table->insert_done()\n"; + if (m_log) + *m_log << "table->insert_done()\n"; #endif break; } case 'I': { // Insert empty rows - if (m_dirty_spec) finalize_spec(); + if (m_dirty_spec) + finalize_spec(); size_t ndx = read_int(); // Throws size_t num_rows = read_int(); // Throws - if (!m_table || m_table->size() < ndx) goto bad_transact_log; + if (!m_table || m_table->size() < ndx) + goto bad_transact_log; m_table->insert_empty_row(ndx, num_rows); // FIXME: May fail #ifdef TIGHTDB_DEBUG - if (m_log) *m_log << "table->insert_empty_row("<insert_empty_row("<(); // Throws - if (!m_table || m_table->size() < ndx) goto bad_transact_log; + if (!m_table || m_table->size() < ndx) + goto bad_transact_log; m_table->remove(ndx); // FIXME: May fail #ifdef TIGHTDB_DEBUG - if (m_log) *m_log << "table->remove("<remove("<(); // Throws - if (!m_table) goto bad_transact_log; + if (!m_table) + goto bad_transact_log; if (column_ndx < 0 || int(m_table->get_column_count()) <= column_ndx) goto bad_transact_log; int64_t value = read_int(); // Throws @@ -1128,13 +1204,16 @@ void Replication::TransactLogApplier::apply() } case 'T': { // Select table - if (m_dirty_spec) finalize_spec(); + if (m_dirty_spec) + finalize_spec(); int levels = read_int(); // Throws size_t ndx = read_int(); // Throws - if (m_group.size() <= ndx) goto bad_transact_log; + if (m_group.size() <= ndx) + goto bad_transact_log; m_table = m_group.get_table_ptr(ndx)->get_table_ref(); #ifdef TIGHTDB_DEBUG - if (m_log) *m_log << "table = group->get_table_by_ndx("<get_table_by_ndx("<(); // Throws if (column_ndx < 0 || int(m_table->get_column_count()) <= column_ndx) goto bad_transact_log; - if (m_table->size() <= ndx) goto bad_transact_log; - switch (m_table->get_column_type(column_ndx)) { - case type_Table: - m_table = m_table->get_subtable(column_ndx, ndx); - break; - case type_Mixed: - m_table = m_table->get_subtable(column_ndx, ndx); - if (!m_table) goto bad_transact_log; - break; - default: + if (m_table->size() <= ndx) goto bad_transact_log; + switch (m_table->get_column_type(column_ndx)) { + case type_Table: + m_table = m_table->get_subtable(column_ndx, ndx); + break; + case type_Mixed: + m_table = m_table->get_subtable(column_ndx, ndx); + if (!m_table) + goto bad_transact_log; + break; + default: + goto bad_transact_log; } #ifdef TIGHTDB_DEBUG - if (m_log) *m_log << "table = table->get_subtable("<get_subtable("<clear(); // FIXME: Can probably fail! #ifdef TIGHTDB_DEBUG - if (m_log) *m_log << "table->clear()\n"; + if (m_log) + *m_log << "table->clear()\n"; #endif break; } @@ -1174,27 +1259,33 @@ void Replication::TransactLogApplier::apply() case 'x': { // Add index to column if (m_dirty_spec) finalize_spec(); int column_ndx = read_int(); // Throws - if (!m_table) goto bad_transact_log; + if (!m_table) + goto bad_transact_log; if (column_ndx < 0 || int(m_table->get_column_count()) <= column_ndx) goto bad_transact_log; m_table->set_index(column_ndx); // FIXME: Memory allocation failure!!! #ifdef TIGHTDB_DEBUG - if (m_log) *m_log << "table->set_index("<set_index("<(); // Throws - if (!is_valid_column_type(type)) goto bad_transact_log; + if (!is_valid_column_type(type)) + goto bad_transact_log; read_string(m_string_buffer); // Throws - const char* const name = m_string_buffer.c_str(); - if (!spec) goto bad_transact_log; + StringData name(m_string_buffer.data(), m_string_buffer.size()); + if (!spec) + goto bad_transact_log; // FIXME: Is it legal to have multiple columns with the same name? - if (spec->get_column_index(name) != size_t(-1)) goto bad_transact_log; + if (spec->get_column_index(name) != size_t(-1)) + goto bad_transact_log; spec->add_column(DataType(type), name); #ifdef TIGHTDB_DEBUG - if (m_log) *m_log << "spec->add_column("<add_column("<get_spec(); #ifdef TIGHTDB_DEBUG - if (m_log) *m_log << "spec = table->get_spec()\n"; + if (m_log) + *m_log << "spec = table->get_spec()\n"; #endif int levels = read_int(); // Throws for (int i=0; iget_subspec_by_ndx("<get_subspec_by_ndx("<create_new_table(\""<create_new_table(\""<optimize(); // FIXME: May fail #ifdef TIGHTDB_DEBUG - if (m_log) *m_log << "table->optimize()\n"; + if (m_log) + *m_log << "table->optimize()\n"; #endif break; } @@ -1248,7 +1347,8 @@ void Replication::TransactLogApplier::apply() } } - if (m_dirty_spec) finalize_spec(); // FIXME: Why is this necessary? + if (m_dirty_spec) + finalize_spec(); // FIXME: Why is this necessary? return; bad_transact_log: diff --git a/src/tightdb/replication.hpp b/src/tightdb/replication.hpp index d146f358d1f..b77f4f5edf2 100644 --- a/src/tightdb/replication.hpp +++ b/src/tightdb/replication.hpp @@ -236,17 +236,19 @@ class Replication { struct subtable_tag {}; - void new_top_level_table(const char* name); - void add_column(const Table*, const Spec*, DataType, const char* name); + void new_top_level_table(StringData name); + void add_column(const Table*, const Spec*, DataType, StringData name); template void set_value(const Table*, std::size_t column_ndx, std::size_t ndx, T value); + void set_value(const Table*, std::size_t column_ndx, std::size_t ndx, StringData value); void set_value(const Table*, std::size_t column_ndx, std::size_t ndx, BinaryData value); void set_value(const Table*, std::size_t column_ndx, std::size_t ndx, const Mixed& value); void set_value(const Table*, std::size_t column_ndx, std::size_t ndx, subtable_tag); template void insert_value(const Table*, std::size_t column_ndx, std::size_t ndx, T value); + void insert_value(const Table*, std::size_t column_ndx, std::size_t ndx, StringData value); void insert_value(const Table*, std::size_t column_ndx, std::size_t ndx, BinaryData value); void insert_value(const Table*, std::size_t column_ndx, std::size_t ndx, const Mixed& value); void insert_value(const Table*, std::size_t column_ndx, std::size_t ndx, subtable_tag); @@ -311,12 +313,11 @@ class Replication { char* m_transact_log_free_end; template struct Buffer { - T* m_data; + UniquePtr m_data; std::size_t m_size; T& operator[](std::size_t i) TIGHTDB_NOEXCEPT { return m_data[i]; } const T& operator[](std::size_t i) const TIGHTDB_NOEXCEPT { return m_data[i]; } Buffer() TIGHTDB_NOEXCEPT: m_data(0), m_size(0) {} - ~Buffer() TIGHTDB_NOEXCEPT { delete[] m_data; } void set_size(std::size_t); }; Buffer m_subtab_path_buf; @@ -350,7 +351,7 @@ class Replication { void select_spec(const Table*, const Spec*); void string_cmd(char cmd, std::size_t column_ndx, std::size_t ndx, - const char* data,std::size_t size); + const char* data, std::size_t size); void mixed_cmd(char cmd, std::size_t column_ndx, std::size_t ndx, const Mixed& value); @@ -530,24 +531,23 @@ inline void Replication::mixed_cmd(char cmd, std::size_t column_ndx, transact_log_advance(buf); break; case type_Date: - buf = encode_int(buf, value.get_date()); + buf = encode_int(buf, value.get_date().get_date()); transact_log_advance(buf); break; case type_String: { - const char* data = value.get_string(); - std::size_t size = std::strlen(data); - buf = encode_int(buf, size); + StringData data = value.get_string(); + buf = encode_int(buf, data.size()); transact_log_advance(buf); - transact_log_append(data, size); // Throws + transact_log_append(data.data(), data.size()); // Throws } break; case type_Binary: { BinaryData data = value.get_binary(); - buf = encode_int(buf, data.len); + buf = encode_int(buf, data.size()); transact_log_advance(buf); - transact_log_append(data.pointer, data.len); // Throws + transact_log_append(data.data(), data.size()); // Throws } break; case type_Table: @@ -559,21 +559,19 @@ inline void Replication::mixed_cmd(char cmd, std::size_t column_ndx, } -inline void Replication::new_top_level_table(const char* name) +inline void Replication::new_top_level_table(StringData name) { - size_t length = std::strlen(name); - simple_cmd('N', tuple(length)); // Throws - transact_log_append(name, length); // Throws + simple_cmd('N', tuple(name.size())); // Throws + transact_log_append(name.data(), name.size()); // Throws } inline void Replication::add_column(const Table* table, const Spec* spec, - DataType type, const char* name) + DataType type, StringData name) { check_spec(table, spec); // Throws - size_t length = std::strlen(name); - simple_cmd('A', tuple(int(type), length)); // Throws - transact_log_append(name, length); // Throws + simple_cmd('A', tuple(int(type), name.size())); // Throws + transact_log_append(name.data(), name.size()); // Throws } @@ -585,11 +583,18 @@ inline void Replication::set_value(const Table* t, std::size_t column_ndx, simple_cmd('s', tuple(column_ndx, ndx, value)); // Throws } +inline void Replication::set_value(const Table* t, std::size_t column_ndx, + std::size_t ndx, StringData value) +{ + check_table(t); // Throws + string_cmd('s', column_ndx, ndx, value.data(), value.size()); // Throws +} + inline void Replication::set_value(const Table* t, std::size_t column_ndx, std::size_t ndx, BinaryData value) { check_table(t); // Throws - string_cmd('s', column_ndx, ndx, value.pointer, value.len); // Throws + string_cmd('s', column_ndx, ndx, value.data(), value.size()); // Throws } inline void Replication::set_value(const Table* t, std::size_t column_ndx, @@ -615,11 +620,18 @@ inline void Replication::insert_value(const Table* t, std::size_t column_ndx, simple_cmd('i', tuple(column_ndx, ndx, value)); // Throws } +inline void Replication::insert_value(const Table* t, std::size_t column_ndx, + std::size_t ndx, StringData value) +{ + check_table(t); // Throws + string_cmd('i', column_ndx, ndx, value.data(), value.size()); // Throws +} + inline void Replication::insert_value(const Table* t, std::size_t column_ndx, std::size_t ndx, BinaryData value) { check_table(t); // Throws - string_cmd('i', column_ndx, ndx, value.pointer, value.len); // Throws + string_cmd('i', column_ndx, ndx, value.data(), value.size()); // Throws } inline void Replication::insert_value(const Table* t, std::size_t column_ndx, @@ -699,12 +711,10 @@ inline void Replication::on_spec_destroyed(const Spec* s) TIGHTDB_NOEXCEPT } -template void Replication::Buffer::set_size(std::size_t new_size) +template void Replication::Buffer::set_size(std::size_t size) { - T* const new_data = new T[new_size]; - delete[] m_data; - m_data = new_data; - m_size = new_size; + m_data.reset(new T[size]); + m_size = size; } diff --git a/src/tightdb/spec.cpp b/src/tightdb/spec.cpp index 107a1d55a12..940ce9e86f5 100644 --- a/src/tightdb/spec.cpp +++ b/src/tightdb/spec.cpp @@ -67,10 +67,8 @@ bool Spec::update_from_parent() else return false; } -size_t Spec::add_column(DataType type, const char* name, ColumnType attr) +size_t Spec::add_column(DataType type, StringData name, ColumnType attr) { - TIGHTDB_ASSERT(name); - m_names.add(name); m_spec.add(type); @@ -84,7 +82,7 @@ size_t Spec::add_column(DataType type, const char* name, ColumnType attr) if (type == type_Table) { // SubSpecs array is only there when there are subtables if (m_specSet.size() == 2) { - m_subSpecs.SetType(coldef_HasRefs); + m_subSpecs.SetType(Array::coldef_HasRefs); //m_subSpecs.SetType((ColumnDef)4); //return; m_specSet.add(m_subSpecs.GetRef()); @@ -94,9 +92,9 @@ size_t Spec::add_column(DataType type, const char* name, ColumnType attr) Allocator& alloc = m_specSet.GetAllocator(); // Create spec for new subtable - Array spec(coldef_Normal, NULL, 0, alloc); + Array spec(Array::coldef_Normal, NULL, 0, alloc); ArrayString names(NULL, 0, alloc); - Array specSet(coldef_HasRefs, NULL, 0, alloc); + Array specSet(Array::coldef_HasRefs, NULL, 0, alloc); specSet.add(spec.GetRef()); specSet.add(names.GetRef()); @@ -113,13 +111,13 @@ size_t Spec::add_column(DataType type, const char* name, ColumnType attr) return (m_names.size()-1); // column_ndx } -size_t Spec::add_subcolumn(const vector& column_path, DataType type, const char* name) +size_t Spec::add_subcolumn(const vector& column_path, DataType type, StringData name) { TIGHTDB_ASSERT(!column_path.empty()); return do_add_subcolumn(column_path, 0, type, name); } -size_t Spec::do_add_subcolumn(const vector& column_ids, size_t pos, DataType type, const char* name) +size_t Spec::do_add_subcolumn(const vector& column_ids, size_t pos, DataType type, StringData name) { const size_t column_ndx = column_ids[pos]; Spec subspec = get_subtable_spec(column_ndx); @@ -132,7 +130,7 @@ size_t Spec::do_add_subcolumn(const vector& column_ids, size_t pos, Data } } -Spec Spec::add_subtable_column(const char* name) +Spec Spec::add_subtable_column(StringData name) { const size_t column_ndx = m_names.size(); add_column(type_Table, name); @@ -140,20 +138,21 @@ Spec Spec::add_subtable_column(const char* name) return get_subtable_spec(column_ndx); } -void Spec::rename_column(size_t column_ndx, const char* newname) +void Spec::rename_column(size_t column_ndx, StringData newname) { TIGHTDB_ASSERT(column_ndx < m_spec.size()); //TODO: Verify that new name is valid - m_names.Set(column_ndx, newname); + m_names.set(column_ndx, newname); } -void Spec::rename_column(const vector& column_ids, const char* name) { +void Spec::rename_column(const vector& column_ids, StringData name) +{ do_rename_column(column_ids, 0, name); } -void Spec::do_rename_column(const vector& column_ids, size_t pos, const char* name) +void Spec::do_rename_column(const vector& column_ids, size_t pos, StringData name) { const size_t column_ndx = column_ids[pos]; @@ -185,7 +184,7 @@ void Spec::remove_column(size_t column_ndx) } // Delete the actual name and type entries - m_names.Delete(column_ndx); + m_names.erase(column_ndx); m_spec.Delete(type_ndx); // If there are an attribute, we have to delete that as well @@ -252,7 +251,7 @@ size_t Spec::get_subspec_ndx(size_t column_ndx) const return pos; } -size_t Spec::get_subspec_ref(std::size_t subspec_ndx) const +size_t Spec::get_subspec_ref(size_t subspec_ndx) const { TIGHTDB_ASSERT(subspec_ndx < m_subSpecs.size()); @@ -320,7 +319,7 @@ DataType Spec::get_column_type(size_t ndx) const TIGHTDB_NOEXCEPT return DataType(type); } -void Spec::set_column_type(std::size_t column_ndx, ColumnType type) +void Spec::set_column_type(size_t column_ndx, ColumnType type) { TIGHTDB_ASSERT(column_ndx < get_column_count()); @@ -388,13 +387,13 @@ void Spec::set_column_attr(size_t ndx, ColumnType attr) } } -const char* Spec::get_column_name(size_t ndx) const TIGHTDB_NOEXCEPT +StringData Spec::get_column_name(size_t ndx) const TIGHTDB_NOEXCEPT { TIGHTDB_ASSERT(ndx < get_column_count()); - return m_names.Get(ndx); + return m_names.get(ndx); } -size_t Spec::get_column_index(const char* name) const +size_t Spec::get_column_index(StringData name) const { return m_names.find_first(name); } @@ -434,7 +433,7 @@ void Spec::Verify() const TIGHTDB_ASSERT(column_count <= m_spec.size()); } -void Spec::to_dot(std::ostream& out, const char*) const +void Spec::to_dot(ostream& out, StringData) const { const size_t ref = m_specSet.GetRef(); diff --git a/src/tightdb/spec.hpp b/src/tightdb/spec.hpp index 245b8453850..3fac6dea170 100644 --- a/src/tightdb/spec.hpp +++ b/src/tightdb/spec.hpp @@ -37,12 +37,12 @@ class Spec { Spec(const Spec& s); ~Spec(); - size_t add_column(DataType type, const char* name, ColumnType attr=col_attr_None); - size_t add_subcolumn(const vector& column_path, DataType type, const char* name); - Spec add_subtable_column(const char* name); + size_t add_column(DataType type, StringData name, ColumnType attr=col_attr_None); + size_t add_subcolumn(const vector& column_path, DataType type, StringData name); + Spec add_subtable_column(StringData name); - void rename_column(size_t column_ndx, const char* newname); - void rename_column(const vector& column_ids, const char* newname); + void rename_column(size_t column_ndx, StringData newname); + void rename_column(const vector& column_ids, StringData newname); void remove_column(size_t column_ndx); void remove_column(const vector& column_ids); @@ -63,10 +63,10 @@ class Spec { size_t get_column_count() const TIGHTDB_NOEXCEPT; DataType get_column_type(size_t column_ndx) const TIGHTDB_NOEXCEPT; ColumnType get_real_column_type(size_t column_ndx) const TIGHTDB_NOEXCEPT; - const char* get_column_name(size_t column_ndx) const TIGHTDB_NOEXCEPT; + StringData get_column_name(size_t column_ndx) const TIGHTDB_NOEXCEPT; /// Returns std::size_t(-1) if the specified column is not found. - size_t get_column_index(const char* name) const; + size_t get_column_index(StringData name) const; // Column Attributes ColumnType get_column_attr(size_t column_ndx) const; @@ -79,7 +79,7 @@ class Spec { #ifdef TIGHTDB_DEBUG void Verify() const; // Must be upper case to avoid conflict with macro in ObjC - void to_dot(std::ostream& out, const char* title=NULL) const; + void to_dot(std::ostream& out, StringData title = StringData()) const; #endif // TIGHTDB_DEBUG private: @@ -114,9 +114,9 @@ class Spec { /// underlying memory. static size_t create_empty_spec(Allocator&); - size_t do_add_subcolumn(const vector& column_ids, size_t pos, DataType type, const char* name); + size_t do_add_subcolumn(const vector& column_ids, size_t pos, DataType type, StringData name); void do_remove_column(const vector& column_ids, size_t pos); - void do_rename_column(const vector& column_ids, size_t pos, const char* name); + void do_rename_column(const vector& column_ids, size_t pos, StringData name); #ifdef TIGHTDB_ENABLE_REPLICATION // Precondition: 1 <= end - begin @@ -142,8 +142,8 @@ inline size_t Spec::create_empty_spec(Allocator& alloc) { // The 'spec_set' contains the specification (types and names) of // all columns and sub-tables - Array spec_set(coldef_HasRefs, 0, 0, alloc); - spec_set.add(Array::create_empty_array(coldef_Normal, alloc)); // One type for each column + Array spec_set(Array::coldef_HasRefs, 0, 0, alloc); + spec_set.add(Array::create_empty_array(Array::coldef_Normal, alloc)); // One type for each column spec_set.add(ArrayString::create_empty_string_array(alloc)); // One name for each column return spec_set.GetRef(); } diff --git a/src/tightdb/string_buffer.cpp b/src/tightdb/string_buffer.cpp index c8b0332e7b7..c4517c0bcec 100644 --- a/src/tightdb/string_buffer.cpp +++ b/src/tightdb/string_buffer.cpp @@ -26,7 +26,7 @@ void StringBuffer::append(const char* data, size_t size) } -void StringBuffer::reallocate(std::size_t capacity) +void StringBuffer::reallocate(size_t capacity) { size_t min_allocated = capacity; // Make space for zero termination diff --git a/src/tightdb/string_data.hpp b/src/tightdb/string_data.hpp new file mode 100644 index 00000000000..b10ee0fa818 --- /dev/null +++ b/src/tightdb/string_data.hpp @@ -0,0 +1,177 @@ +/************************************************************************* + * + * TIGHTDB CONFIDENTIAL + * __________________ + * + * [2011] - [2012] TightDB Inc + * All Rights Reserved. + * + * NOTICE: All information contained herein is, and remains + * the property of TightDB Incorporated and its suppliers, + * if any. The intellectual and technical concepts contained + * herein are proprietary to TightDB Incorporated + * and its suppliers and may be covered by U.S. and Foreign Patents, + * patents in process, and are protected by trade secret or copyright law. + * Dissemination of this information or reproduction of this material + * is strictly forbidden unless prior written permission is obtained + * from TightDB Incorporated. + * + **************************************************************************/ +#ifndef TIGHTDB_STRING_HPP +#define TIGHTDB_STRING_HPP + +#include +#include +#include +#include + +#include + +namespace tightdb { + +/// A reference to a chunk of character data. +/// +/// This class does not own the referenced memory, nor does it in any +/// other way attempt to manage the lifetime of it. +/// +/// For compatibility with C style strings, when a string is stored in +/// a TightDB database, it is always followed by a terminating null +/// character. This means that all of the following forms are +/// guaranteed to return a pointer to a null-terminated string: +/// +/// \code{.cpp} +/// +/// group.get_table_name(...).data() +/// table.get_column_name().data() +/// table.get_string(...).data() +/// table.get_mixed(...).get_string().data() +/// +/// \endcode +/// +/// Note that this assumption does not hold in general for strings +/// referenced by instances of StringData. Indeed there is nothing +/// stopping you from constructing a new StringData instance that +/// refers to a string without a terminating null character. +/// +/// \sa BinaryData +/// \sa Mixed +class StringData { +public: + StringData() TIGHTDB_NOEXCEPT: m_data(0), m_size(0) {} + StringData(const char* d, std::size_t s) TIGHTDB_NOEXCEPT: m_data(d), m_size(s) {} + + template StringData(const std::basic_string&); + template operator std::basic_string() const; + + /// Initialize from a zero terminated C style string. + StringData(const char* c_str) TIGHTDB_NOEXCEPT; + + char operator[](std::size_t i) const TIGHTDB_NOEXCEPT { return m_data[i]; } + + const char* data() const TIGHTDB_NOEXCEPT { return m_data; } + std::size_t size() const TIGHTDB_NOEXCEPT { return m_size; } + + friend bool operator==(const StringData&, const StringData&) TIGHTDB_NOEXCEPT; + friend bool operator!=(const StringData&, const StringData&) TIGHTDB_NOEXCEPT; + + /// Trivial bytewise lexicographical comparison. + friend bool operator<(const StringData&, const StringData&) TIGHTDB_NOEXCEPT; + + bool begins_with(StringData) const TIGHTDB_NOEXCEPT; + bool ends_with(StringData) const TIGHTDB_NOEXCEPT; + bool contains(StringData) const TIGHTDB_NOEXCEPT; + + //@{ + /// Undefined behavior if \a n, \a i, or i+n is greater + /// than size(). + StringData prefix(std::size_t n) const TIGHTDB_NOEXCEPT; + StringData suffix(std::size_t n) const TIGHTDB_NOEXCEPT; + StringData substr(std::size_t i, std::size_t n) const TIGHTDB_NOEXCEPT; + StringData substr(std::size_t i) const TIGHTDB_NOEXCEPT; + //@} + + template + friend std::basic_ostream& operator<<(std::basic_ostream&, const StringData&); + +private: + const char* m_data; + std::size_t m_size; +}; + + + +// Implementation: + +template inline StringData::StringData(const std::basic_string& s): + m_data(s.data()), m_size(s.size()) {} + +template inline StringData::operator std::basic_string() const +{ + return std::basic_string(m_data, m_size); +} + +inline StringData::StringData(const char* c_str) TIGHTDB_NOEXCEPT: + m_data(c_str), m_size(std::char_traits::length(c_str)) {} + +inline bool operator==(const StringData& a, const StringData& b) TIGHTDB_NOEXCEPT +{ + return a.m_size == b.m_size && std::equal(a.m_data, a.m_data + a.m_size, b.m_data); +} + +inline bool operator!=(const StringData& a, const StringData& b) TIGHTDB_NOEXCEPT +{ + return a.m_size != b.m_size || !std::equal(a.m_data, a.m_data + a.m_size, b.m_data); +} + +inline bool operator<(const StringData& a, const StringData& b) TIGHTDB_NOEXCEPT +{ + return std::lexicographical_compare(a.m_data, a.m_data + a.m_size, + b.m_data, b.m_data + b.m_size); +} + +inline bool StringData::begins_with(StringData d) const TIGHTDB_NOEXCEPT +{ + return d.m_size <= m_size && std::equal(m_data, m_data + d.m_size, d.m_data); +} + +inline bool StringData::ends_with(StringData d) const TIGHTDB_NOEXCEPT +{ + return d.m_size <= m_size && std::equal(m_data + m_size - d.m_size, m_data + m_size, d.m_data); +} + +inline bool StringData::contains(StringData d) const TIGHTDB_NOEXCEPT +{ + return std::search(m_data, m_data + m_size, d.m_data, d.m_data + d.m_size) != m_data + m_size; +} + +inline StringData StringData::prefix(std::size_t n) const TIGHTDB_NOEXCEPT +{ + return substr(0,n); +} + +inline StringData StringData::suffix(std::size_t n) const TIGHTDB_NOEXCEPT +{ + return substr(m_size - n); +} + +inline StringData StringData::substr(std::size_t i, std::size_t n) const TIGHTDB_NOEXCEPT +{ + return StringData(m_data + i, n); +} + +inline StringData StringData::substr(std::size_t i) const TIGHTDB_NOEXCEPT +{ + return substr(i, m_size - i); +} + +template +inline std::basic_ostream& operator<<(std::basic_ostream& out, const StringData& d) +{ + for (const char* i = d.m_data; i != d.m_data + d.m_size; ++i) + out << *i; + return out; +} + +} // namespace tightdb + +#endif // TIGHTDB_STRING_HPP diff --git a/src/tightdb/table.cpp b/src/tightdb/table.cpp index 680b14e9b21..418014a7958 100644 --- a/src/tightdb/table.cpp +++ b/src/tightdb/table.cpp @@ -66,7 +66,7 @@ void Table::CreateColumns() // Instantiate first if we have an empty table (from zero-ref) if (!m_columns.IsValid()) { - m_columns.SetType(coldef_HasRefs); + m_columns.SetType(Array::coldef_HasRefs); } size_t subtable_count = 0; @@ -85,7 +85,7 @@ void Table::CreateColumns() case type_Bool: case type_Date: { - Column* c = new Column(coldef_Normal, alloc); + Column* c = new Column(Array::coldef_Normal, alloc); m_columns.add(c->GetRef()); c->SetParent(&m_columns, ref_pos); new_col = c; @@ -415,7 +415,7 @@ size_t Table::GetColumnRefPos(size_t column_ndx) const return (size_t)-1; } -size_t Table::add_subcolumn(const vector& column_path, DataType type, const char* name) +size_t Table::add_subcolumn(const vector& column_path, DataType type, StringData name) { TIGHTDB_ASSERT(!column_path.empty()); @@ -459,7 +459,7 @@ void Table::do_add_subcolumn(const vector& column_path, size_t pos, Data } } -size_t Table::add_column(DataType type, const char* name) +size_t Table::add_column(DataType type, StringData name) { // Create column and add cached instance const size_t column_ndx = do_add_column(type); @@ -494,7 +494,7 @@ size_t Table::do_add_column(DataType type) case type_Bool: case type_Date: { - Column* c = new Column(coldef_Normal, alloc); + Column* c = new Column(Array::coldef_Normal, alloc); m_columns.add(c->GetRef()); c->SetParent(&m_columns, m_columns.size()-1); new_col = c; @@ -639,11 +639,13 @@ void Table::do_remove_column(const vector& column_path, size_t pos) } } -void Table::rename_column(size_t column_ndx, const char* name) { +void Table::rename_column(size_t column_ndx, StringData name) +{ m_spec_set.rename_column(column_ndx, name); } -void Table::rename_column(const vector& column_path, const char* name) { +void Table::rename_column(const vector& column_path, StringData name) +{ m_spec_set.rename_column(column_path, name); } @@ -732,7 +734,7 @@ void Table::validate_column_type(const ColumnBase& column, ColumnType coltype, s size_t Table::clone_columns(Allocator& alloc) const { - Array new_columns(coldef_HasRefs, 0, 0, alloc); + Array new_columns(Array::coldef_HasRefs, 0, 0, alloc); size_t n = get_column_count(); for (size_t i=0; iSize(); for (size_t i2=0; i2Get(i)); + new_col.add(enum_col->get(i)); new_col_ref = new_col.GetRef(); } else { @@ -767,7 +769,7 @@ size_t Table::clone(Allocator& alloc) const return new_top.GetRef(); } - Array new_top(coldef_HasRefs, 0, 0, alloc); + Array new_top(Array::coldef_HasRefs, 0, 0, alloc); { Array new_spec(alloc); new_spec.Copy(m_spec_set.m_specSet); @@ -872,7 +874,7 @@ void Table::remove(size_t ndx) const size_t count = get_column_count(); for (size_t i = 0; i < count; ++i) { ColumnBase& column = GetColumnBase(i); - column.Delete(ndx); + column.erase(ndx); } --m_size; @@ -1023,7 +1025,7 @@ int64_t Table::get_int(size_t column_ndx, size_t ndx) const TIGHTDB_NOEXCEPT TIGHTDB_ASSERT(ndx < m_size); const Column& column = GetColumn(column_ndx); - return column.Get(ndx); + return column.get(ndx); } void Table::set_int(size_t column_ndx, size_t ndx, int64_t value) @@ -1032,7 +1034,7 @@ void Table::set_int(size_t column_ndx, size_t ndx, int64_t value) TIGHTDB_ASSERT(ndx < m_size); Column& column = GetColumn(column_ndx); - column.Set(ndx, value); + column.set(ndx, value); #ifdef TIGHTDB_ENABLE_REPLICATION transact_log().set_value(column_ndx, ndx, value); // Throws @@ -1058,7 +1060,7 @@ bool Table::get_bool(size_t column_ndx, size_t ndx) const TIGHTDB_NOEXCEPT TIGHTDB_ASSERT(ndx < m_size); const Column& column = GetColumn(column_ndx); - return column.Get(ndx) != 0; + return column.get(ndx) != 0; } void Table::set_bool(size_t column_ndx, size_t ndx, bool value) @@ -1068,34 +1070,34 @@ void Table::set_bool(size_t column_ndx, size_t ndx, bool value) TIGHTDB_ASSERT(ndx < m_size); Column& column = GetColumn(column_ndx); - column.Set(ndx, value ? 1 : 0); + column.set(ndx, value ? 1 : 0); #ifdef TIGHTDB_ENABLE_REPLICATION transact_log().set_value(column_ndx, ndx, int(value)); // Throws #endif } -time_t Table::get_date(size_t column_ndx, size_t ndx) const TIGHTDB_NOEXCEPT +Date Table::get_date(size_t column_ndx, size_t ndx) const TIGHTDB_NOEXCEPT { TIGHTDB_ASSERT(column_ndx < get_column_count()); TIGHTDB_ASSERT(get_real_column_type(column_ndx) == col_type_Date); TIGHTDB_ASSERT(ndx < m_size); const Column& column = GetColumn(column_ndx); - return time_t(column.Get(ndx)); + return time_t(column.get(ndx)); } -void Table::set_date(size_t column_ndx, size_t ndx, time_t value) +void Table::set_date(size_t column_ndx, size_t ndx, Date value) { TIGHTDB_ASSERT(column_ndx < get_column_count()); TIGHTDB_ASSERT(get_real_column_type(column_ndx) == col_type_Date); TIGHTDB_ASSERT(ndx < m_size); Column& column = GetColumn(column_ndx); - column.Set(ndx, int64_t(value)); + column.set(ndx, int64_t(value.get_date())); #ifdef TIGHTDB_ENABLE_REPLICATION - transact_log().set_value(column_ndx, ndx, value); // Throws + transact_log().set_value(column_ndx, ndx, value.get_date()); // Throws #endif } @@ -1105,7 +1107,7 @@ void Table::insert_int(size_t column_ndx, size_t ndx, int64_t value) TIGHTDB_ASSERT(ndx <= m_size); Column& column = GetColumn(column_ndx); - column.Insert(ndx, value); + column.insert(ndx, value); #ifdef TIGHTDB_ENABLE_REPLICATION transact_log().insert_value(column_ndx, ndx, value); // Throws @@ -1119,7 +1121,7 @@ float Table::get_float(size_t column_ndx, size_t ndx) const TIGHTDB_NOEXCEPT TIGHTDB_ASSERT(ndx < m_size); const ColumnFloat& column = GetColumnFloat(column_ndx); - return column.Get(ndx); + return column.get(ndx); } void Table::set_float(size_t column_ndx, size_t ndx, float value) @@ -1128,7 +1130,7 @@ void Table::set_float(size_t column_ndx, size_t ndx, float value) TIGHTDB_ASSERT(ndx < m_size); ColumnFloat& column = GetColumnFloat(column_ndx); - column.Set(ndx, value); + column.set(ndx, value); #ifdef TIGHTDB_ENABLE_REPLICATION transact_log().set_value(column_ndx, ndx, value); // Throws @@ -1141,7 +1143,7 @@ void Table::insert_float(size_t column_ndx, size_t ndx, float value) TIGHTDB_ASSERT(ndx <= m_size); ColumnFloat& column = GetColumnFloat(column_ndx); - column.Insert(ndx, value); + column.insert(ndx, value); #ifdef TIGHTDB_ENABLE_REPLICATION transact_log().insert_value(column_ndx, ndx, value); // Throws @@ -1155,7 +1157,7 @@ double Table::get_double(size_t column_ndx, size_t ndx) const TIGHTDB_NOEXCEPT TIGHTDB_ASSERT(ndx < m_size); const ColumnDouble& column = GetColumnDouble(column_ndx); - return column.Get(ndx); + return column.get(ndx); } void Table::set_double(size_t column_ndx, size_t ndx, double value) @@ -1164,7 +1166,7 @@ void Table::set_double(size_t column_ndx, size_t ndx, double value) TIGHTDB_ASSERT(ndx < m_size); ColumnDouble& column = GetColumnDouble(column_ndx); - column.Set(ndx, value); + column.set(ndx, value); #ifdef TIGHTDB_ENABLE_REPLICATION transact_log().set_value(column_ndx, ndx, value); // Throws @@ -1177,7 +1179,7 @@ void Table::insert_double(size_t column_ndx, size_t ndx, double value) TIGHTDB_ASSERT(ndx <= m_size); ColumnDouble& column = GetColumnDouble(column_ndx); - column.Insert(ndx, value); + column.insert(ndx, value); #ifdef TIGHTDB_ENABLE_REPLICATION transact_log().insert_value(column_ndx, ndx, value); // Throws @@ -1185,7 +1187,7 @@ void Table::insert_double(size_t column_ndx, size_t ndx, double value) } -const char* Table::get_string(size_t column_ndx, size_t ndx) const TIGHTDB_NOEXCEPT +StringData Table::get_string(size_t column_ndx, size_t ndx) const TIGHTDB_NOEXCEPT { TIGHTDB_ASSERT(column_ndx < m_columns.size()); TIGHTDB_ASSERT(ndx < m_size); @@ -1193,21 +1195,15 @@ const char* Table::get_string(size_t column_ndx, size_t ndx) const TIGHTDB_NOEXC const ColumnType type = get_real_column_type(column_ndx); if (type == col_type_String) { const AdaptiveStringColumn& column = GetColumnString(column_ndx); - return column.Get(ndx); + return column.get(ndx); } TIGHTDB_ASSERT(type == col_type_StringEnum); const ColumnStringEnum& column = GetColumnStringEnum(column_ndx); - return column.Get(ndx); + return column.get(ndx); } -size_t Table::get_string_length(size_t column_ndx, size_t ndx) const TIGHTDB_NOEXCEPT -{ - // TODO: Implement faster get_string_length() - return strlen( get_string(column_ndx, ndx) ); -} - -void Table::set_string(size_t column_ndx, size_t ndx, const char* value) +void Table::set_string(size_t column_ndx, size_t ndx, StringData value) { TIGHTDB_ASSERT(column_ndx < get_column_count()); TIGHTDB_ASSERT(ndx < m_size); @@ -1216,20 +1212,20 @@ void Table::set_string(size_t column_ndx, size_t ndx, const char* value) if (type == col_type_String) { AdaptiveStringColumn& column = GetColumnString(column_ndx); - column.Set(ndx, value); + column.set(ndx, value); } else { TIGHTDB_ASSERT(type == col_type_StringEnum); ColumnStringEnum& column = GetColumnStringEnum(column_ndx); - column.Set(ndx, value); + column.set(ndx, value); } #ifdef TIGHTDB_ENABLE_REPLICATION - transact_log().set_value(column_ndx, ndx, BinaryData(value, std::strlen(value))); // Throws + transact_log().set_value(column_ndx, ndx, value); // Throws #endif } -void Table::insert_string(size_t column_ndx, size_t ndx, const char* value) +void Table::insert_string(size_t column_ndx, size_t ndx, StringData value) { TIGHTDB_ASSERT(column_ndx < get_column_count()); TIGHTDB_ASSERT(ndx <= m_size); @@ -1238,16 +1234,16 @@ void Table::insert_string(size_t column_ndx, size_t ndx, const char* value) if (type == col_type_String) { AdaptiveStringColumn& column = GetColumnString(column_ndx); - column.Insert(ndx, value); + column.insert(ndx, value); } else { TIGHTDB_ASSERT(type == col_type_StringEnum); ColumnStringEnum& column = GetColumnStringEnum(column_ndx); - column.Insert(ndx, value); + column.insert(ndx, value); } #ifdef TIGHTDB_ENABLE_REPLICATION - transact_log().insert_value(column_ndx, ndx, BinaryData(value, std::strlen(value))); // Throws + transact_log().insert_value(column_ndx, ndx, value); // Throws #endif } @@ -1258,32 +1254,32 @@ BinaryData Table::get_binary(size_t column_ndx, size_t ndx) const TIGHTDB_NOEXCE TIGHTDB_ASSERT(ndx < m_size); const ColumnBinary& column = GetColumnBinary(column_ndx); - return column.Get(ndx); + return column.get(ndx); } -void Table::set_binary(size_t column_ndx, size_t ndx, const char* data, size_t size) +void Table::set_binary(size_t column_ndx, size_t ndx, BinaryData value) { TIGHTDB_ASSERT(column_ndx < get_column_count()); TIGHTDB_ASSERT(ndx < m_size); ColumnBinary& column = GetColumnBinary(column_ndx); - column.Set(ndx, data, size); + column.set(ndx, value); #ifdef TIGHTDB_ENABLE_REPLICATION - transact_log().set_value(column_ndx, ndx, BinaryData(data, size)); // Throws + transact_log().set_value(column_ndx, ndx, value); // Throws #endif } -void Table::insert_binary(size_t column_ndx, size_t ndx, const char* data, size_t size) +void Table::insert_binary(size_t column_ndx, size_t ndx, BinaryData value) { TIGHTDB_ASSERT(column_ndx < get_column_count()); TIGHTDB_ASSERT(ndx <= m_size); ColumnBinary& column = GetColumnBinary(column_ndx); - column.Insert(ndx, data, size); + column.insert(ndx, value); #ifdef TIGHTDB_ENABLE_REPLICATION - transact_log().insert_value(column_ndx, ndx, BinaryData(data, size)); // Throws + transact_log().insert_value(column_ndx, ndx, value); // Throws #endif } @@ -1358,11 +1354,9 @@ void Table::set_mixed(size_t column_ndx, size_t ndx, Mixed value) case type_String: column.set_string(ndx, value.get_string()); break; - case type_Binary: { - const BinaryData b = value.get_binary(); - column.set_binary(ndx, b.pointer, b.len); + case type_Binary: + column.set_binary(ndx, value.get_binary()); break; - } case type_Table: column.set_subtable(ndx, 0); break; @@ -1405,11 +1399,9 @@ void Table::insert_mixed(size_t column_ndx, size_t ndx, Mixed value) case type_String: column.insert_string(ndx, value.get_string()); break; - case type_Binary: { - const BinaryData b = value.get_binary(); - column.insert_binary(ndx, b.pointer, b.len); + case type_Binary: + column.insert_binary(ndx, value.get_binary()); break; - } case type_Table: column.insert_subtable(ndx, 0); break; @@ -1439,25 +1431,24 @@ void Table::insert_done() // count ---------------------------------------------- -size_t Table::count_int(size_t column_ndx, int64_t target) const +size_t Table::count_int(size_t column_ndx, int64_t value) const { const Column& column = GetColumn(column_ndx); - return column.count(target); + return column.count(value); } -size_t Table::count_float(size_t column_ndx, float target) const +size_t Table::count_float(size_t column_ndx, float value) const { const ColumnFloat& column = GetColumn(column_ndx); - return column.count(target); + return column.count(value); } -size_t Table::count_double(size_t column_ndx, double target) const +size_t Table::count_double(size_t column_ndx, double value) const { const ColumnDouble& column = GetColumn(column_ndx); - return column.count(target); + return column.count(value); } -size_t Table::count_string(size_t column_ndx, const char* value) const +size_t Table::count_string(size_t column_ndx, StringData value) const { TIGHTDB_ASSERT(column_ndx < get_column_count()); - TIGHTDB_ASSERT(value); const ColumnType type = get_real_column_type(column_ndx); @@ -1577,7 +1568,7 @@ double Table::maximum_double(size_t column_ndx) const -size_t Table::lookup(const char* value) const +size_t Table::lookup(StringData value) const { // First time we do a lookup we check if we can cache the index if (!m_lookup_index) { @@ -1627,13 +1618,13 @@ size_t Table::find_first_bool(size_t column_ndx, bool value) const return column.find_first(value ? 1 : 0); } -size_t Table::find_first_date(size_t column_ndx, time_t value) const +size_t Table::find_first_date(size_t column_ndx, Date value) const { TIGHTDB_ASSERT(column_ndx < m_columns.size()); TIGHTDB_ASSERT(get_real_column_type(column_ndx) == col_type_Date); const Column& column = GetColumn(column_ndx); - return column.find_first((int64_t)value); + return column.find_first(int64_t(value.get_date())); } size_t Table::find_first_float(size_t column_ndx, float value) const @@ -1654,7 +1645,7 @@ size_t Table::find_first_double(size_t column_ndx, double value) const return column.find_first(value); } -size_t Table::find_first_string(size_t column_ndx, const char* value) const +size_t Table::find_first_string(size_t column_ndx, StringData value) const { TIGHTDB_ASSERT(column_ndx < m_columns.size()); @@ -1671,12 +1662,9 @@ size_t Table::find_first_string(size_t column_ndx, const char* value) const } } -size_t Table::find_first_binary(size_t column_ndx, const char* value, size_t len) const +size_t Table::find_first_binary(size_t, BinaryData) const { // FIXME: Implement this! - static_cast(column_ndx); - static_cast(value); - static_cast(len); throw runtime_error("Not implemented"); } @@ -1774,29 +1762,29 @@ ConstTableView Table::find_all_double(size_t column_ndx, double value) const return move(tv); } -TableView Table::find_all_date(size_t column_ndx, time_t value) +TableView Table::find_all_date(size_t column_ndx, Date value) { TIGHTDB_ASSERT(column_ndx < m_columns.size()); const Column& column = GetColumn(column_ndx); TableView tv(*this); - column.find_all(tv.get_ref_column(), int64_t(value)); + column.find_all(tv.get_ref_column(), int64_t(value.get_date())); return move(tv); } -ConstTableView Table::find_all_date(size_t column_ndx, time_t value) const +ConstTableView Table::find_all_date(size_t column_ndx, Date value) const { TIGHTDB_ASSERT(column_ndx < m_columns.size()); const Column& column = GetColumn(column_ndx); ConstTableView tv(*this); - column.find_all(tv.get_ref_column(), int64_t(value)); + column.find_all(tv.get_ref_column(), int64_t(value.get_date())); return move(tv); } -TableView Table::find_all_string(size_t column_ndx, const char *value) +TableView Table::find_all_string(size_t column_ndx, StringData value) { TIGHTDB_ASSERT(column_ndx < m_columns.size()); @@ -1815,7 +1803,7 @@ TableView Table::find_all_string(size_t column_ndx, const char *value) return move(tv); } -ConstTableView Table::find_all_string(size_t column_ndx, const char *value) const +ConstTableView Table::find_all_string(size_t column_ndx, StringData value) const { TIGHTDB_ASSERT(column_ndx < m_columns.size()); @@ -1834,21 +1822,15 @@ ConstTableView Table::find_all_string(size_t column_ndx, const char *value) cons return move(tv); } -TableView Table::find_all_binary(size_t column_ndx, const char* value, size_t len) +TableView Table::find_all_binary(size_t, BinaryData) { // FIXME: Implement this! - static_cast(column_ndx); - static_cast(value); - static_cast(len); throw runtime_error("Not implemented"); } -ConstTableView Table::find_all_binary(size_t column_ndx, const char* value, size_t len) const +ConstTableView Table::find_all_binary(size_t, BinaryData) const { // FIXME: Implement this! - static_cast(column_ndx); - static_cast(value); - static_cast(len); throw runtime_error("Not implemented"); } @@ -2060,7 +2042,7 @@ void Table::update_from_spec() // to JSON: ------------------------------------------ -void Table::to_json(std::ostream& out) +void Table::to_json(ostream& out) { // Represent table as list of objects out << "["; @@ -2077,8 +2059,9 @@ void Table::to_json(std::ostream& out) namespace { -inline void out_date(std::ostream& out, time_t rawtime) +inline void out_date(ostream& out, Date value) { + time_t rawtime = value.get_date(); struct tm* const t = gmtime(&rawtime); if (t) { // We need a buffer for formatting dates (and binary to hex). Max @@ -2090,14 +2073,14 @@ inline void out_date(std::ostream& out, time_t rawtime) } } -inline void out_binary(std::ostream& out, const BinaryData bin) +inline void out_binary(ostream& out, const BinaryData bin) { - const char* const p = (char*)bin.pointer; - for (size_t i = 0; i < bin.len; ++i) - out << setw(2) << setfill('0') << hex << (unsigned int)p[i] << dec; + const char* p = bin.data(); + for (size_t i = 0; i < bin.size(); ++i) + out << setw(2) << setfill('0') << hex << static_cast(p[i]) << dec; } -template void out_floats(std::ostream& out, T value) +template void out_floats(ostream& out, T value) { streamsize old = out.precision(); out.precision(numeric_limits::digits10 + 1); @@ -2107,7 +2090,7 @@ template void out_floats(std::ostream& out, T value) } // anonymous namespace -void Table::to_json_row(size_t row_ndx, std::ostream& out) +void Table::to_json_row(size_t row_ndx, ostream& out) { out << "{"; const size_t column_count = get_column_count(); @@ -2115,7 +2098,7 @@ void Table::to_json_row(size_t row_ndx, std::ostream& out) if (i > 0) out << ","; - const char* const name = get_column_name(i); + StringData name = get_column_name(i); out << "\"" << name << "\":"; const DataType type = get_column_type(i); @@ -2201,15 +2184,15 @@ size_t chars_in_int(int64_t v) } } -void Table::to_string(std::ostream& out, size_t limit) const +void Table::to_string(ostream& out, size_t limit) const { // Print header (will also calculate widths) - std::vector widths; + vector widths; to_string_header(out, widths); // Set limit=-1 to print all rows, otherwise only print to limit const size_t row_count = size(); - const size_t out_count = (limit == (size_t)-1) ? row_count + const size_t out_count = (limit == size_t(-1)) ? row_count : (row_count < limit) ? row_count : limit; // Print rows @@ -2223,19 +2206,19 @@ void Table::to_string(std::ostream& out, size_t limit) const } } -void Table::row_to_string(size_t row_ndx, std::ostream& out) const +void Table::row_to_string(size_t row_ndx, ostream& out) const { TIGHTDB_ASSERT(row_ndx < size()); // Print header (will also calculate widths) - std::vector widths; + vector widths; to_string_header(out, widths); // Print row contents to_string_row(row_ndx, out, widths); } -void Table::to_string_header(std::ostream& out, std::vector& widths) const +void Table::to_string_header(ostream& out, vector& widths) const { const size_t column_count = get_column_count(); const size_t row_count = size(); @@ -2248,7 +2231,7 @@ void Table::to_string_header(std::ostream& out, std::vector& widths) con // Write header for (size_t col = 0; col < column_count; ++col) { - const char* const name = get_column_name(col); + StringData name = get_column_name(col); const DataType type = get_column_type(col); size_t width = 0; switch (type) { @@ -2277,7 +2260,7 @@ void Table::to_string_header(std::ostream& out, std::vector& widths) con break; case type_Binary: for (size_t row = 0; row < row_count; ++row) { - size_t len = chars_in_int( get_binary(col, row).len ) + 2; + size_t len = chars_in_int( get_binary(col, row).size() ) + 2; width = max(width, len); } width += 6; // space for " bytes" @@ -2285,10 +2268,10 @@ void Table::to_string_header(std::ostream& out, std::vector& widths) con case type_String: { // Find max length of the strings for (size_t row = 0; row < row_count; ++row) { - size_t len = get_string_length(col, row); + size_t len = get_string(col, row).size(); width = max(width, len); } - if (width > 20) + if (width > 20) width = 23; // cut strings longer than 20 chars break; } @@ -2320,10 +2303,10 @@ void Table::to_string_header(std::ostream& out, std::vector& widths) con width = max(width, size_t(14)); break; case type_Binary: - width = max(width, chars_in_int(m.get_binary().len) + 6); + width = max(width, chars_in_int(m.get_binary().size()) + 6); break; case type_String: { - size_t len = strlen(m.get_string()); + size_t len = m.get_string().size(); if (len > 20) len = 23; width = max(width, len); @@ -2338,7 +2321,7 @@ void Table::to_string_header(std::ostream& out, std::vector& widths) con break; } // Set width to max of column name and the longest value - const size_t name_len = strlen(name); + const size_t name_len = name.size(); if (name_len > width) width = name_len; @@ -2346,24 +2329,24 @@ void Table::to_string_header(std::ostream& out, std::vector& widths) con out << " "; // spacing out.width(width); - out << name; + out << string(name); } out << "\n"; } namespace { -inline void out_string(std::ostream& out, const std::string text, const size_t max_len) +inline void out_string(ostream& out, const string text, const size_t max_len) { - out.setf(std::ostream::left, std::ostream::adjustfield); + out.setf(ostream::left, ostream::adjustfield); if (text.size() > max_len) out << text.substr(0, max_len) + "..."; else out << text; - out.unsetf(std::ostream::adjustfield); + out.unsetf(ostream::adjustfield); } -inline void out_table(std::ostream& out, const size_t len) +inline void out_table(ostream& out, const size_t len) { const size_t width = out.width() - chars_in_int(len) - 1; out.width(width); @@ -2372,7 +2355,7 @@ inline void out_table(std::ostream& out, const size_t len) } -void Table::to_string_row(size_t row_ndx, std::ostream& out, const std::vector& widths) const +void Table::to_string_row(size_t row_ndx, ostream& out, const vector& widths) const { const size_t column_count = get_column_count(); const size_t row_ndx_width = widths[0]; @@ -2410,7 +2393,7 @@ void Table::to_string_row(size_t row_ndx, std::ostream& out, const std::vector& column_path, DataType type, const char* name); + size_t add_column(DataType type, StringData name); // Add a column dynamically + size_t add_subcolumn(const std::vector& column_path, DataType type, StringData name); void remove_column(size_t column_ndx); - void remove_column(const vector& column_path); - void rename_column(size_t column_ndx, const char* name); - void rename_column(const vector& column_path, const char* name); + void remove_column(const std::vector& column_path); + void rename_column(size_t column_ndx, StringData name); + void rename_column(const std::vector& column_path, StringData name); // Table size and deletion bool is_empty() const TIGHTDB_NOEXCEPT {return m_size == 0;} @@ -151,8 +149,8 @@ class Table { // Column information size_t get_column_count() const TIGHTDB_NOEXCEPT; - const char* get_column_name(size_t column_ndx) const TIGHTDB_NOEXCEPT; - size_t get_column_index(const char* name) const; + StringData get_column_name(size_t column_ndx) const TIGHTDB_NOEXCEPT; + size_t get_column_index(StringData name) const; DataType get_column_type(size_t column_ndx) const TIGHTDB_NOEXCEPT; // Row handling @@ -165,12 +163,12 @@ class Table { // NOTE: You have to insert values in ALL columns followed by insert_done(). void insert_int(size_t column_ndx, size_t row_ndx, int64_t value); void insert_bool(size_t column_ndx, size_t row_ndx, bool value); - void insert_date(size_t column_ndx, size_t row_ndx, time_t value); + void insert_date(size_t column_ndx, size_t row_ndx, Date value); template void insert_enum(size_t column_ndx, size_t row_ndx, E value); void insert_float(size_t column_ndx, size_t row_ndx, float value); void insert_double(size_t column_ndx, size_t row_ndx, double value); - void insert_string(size_t column_ndx, size_t row_ndx, const char* value); - void insert_binary(size_t column_ndx, size_t row_ndx, const char* data, size_t size); + void insert_string(size_t column_ndx, size_t row_ndx, StringData value); + void insert_binary(size_t column_ndx, size_t row_ndx, BinaryData value); void insert_subtable(size_t column_ndx, size_t row_ndx); // Insert empty table void insert_mixed(size_t column_ndx, size_t row_ndx, Mixed value); void insert_done(); @@ -178,11 +176,10 @@ class Table { // Get cell values int64_t get_int(size_t column_ndx, size_t row_ndx) const TIGHTDB_NOEXCEPT; bool get_bool(size_t column_ndx, size_t row_ndx) const TIGHTDB_NOEXCEPT; - time_t get_date(size_t column_ndx, size_t row_ndx) const TIGHTDB_NOEXCEPT; + Date get_date(size_t column_ndx, size_t row_ndx) const TIGHTDB_NOEXCEPT; float get_float(size_t column_ndx, size_t row_ndx) const TIGHTDB_NOEXCEPT; double get_double(size_t column_ndx, size_t row_ndx) const TIGHTDB_NOEXCEPT; - const char* get_string(size_t column_ndx, size_t row_ndx) const TIGHTDB_NOEXCEPT; - size_t get_string_length(size_t column_ndx, size_t row_ndx) const TIGHTDB_NOEXCEPT; + StringData get_string(size_t column_ndx, size_t row_ndx) const TIGHTDB_NOEXCEPT; BinaryData get_binary(size_t column_ndx, size_t row_ndx) const TIGHTDB_NOEXCEPT; Mixed get_mixed(size_t column_ndx, size_t row_ndx) const; // FIXME: Should be modified so it never throws DataType get_mixed_type(size_t column_ndx, size_t row_ndx) const TIGHTDB_NOEXCEPT; @@ -190,12 +187,12 @@ class Table { // Set cell values void set_int(size_t column_ndx, size_t row_ndx, int64_t value); void set_bool(size_t column_ndx, size_t row_ndx, bool value); - void set_date(size_t column_ndx, size_t row_ndx, time_t value); + void set_date(size_t column_ndx, size_t row_ndx, Date value); template void set_enum(size_t column_ndx, size_t row_ndx, E value); void set_float(size_t column_ndx, size_t row_ndx, float value); void set_double(size_t column_ndx, size_t row_ndx, double value); - void set_string(size_t column_ndx, size_t row_ndx, const char* value); - void set_binary(size_t column_ndx, size_t row_ndx, const char* value, size_t len); + void set_string(size_t column_ndx, size_t row_ndx, StringData value); + void set_binary(size_t column_ndx, size_t row_ndx, BinaryData value); void set_mixed(size_t column_ndx, size_t row_ndx, Mixed value); void add_int(size_t column_ndx, int64_t value); @@ -213,10 +210,10 @@ class Table { void set_index(size_t column_ndx) {set_index(column_ndx, true);} // Aggregate functions - size_t count_int(size_t column_ndx, int64_t target) const; - size_t count_string(size_t column_ndx, const char* target) const; - size_t count_float(size_t column_ndx, float target) const; - size_t count_double(size_t column_ndx, double target) const; + size_t count_int(size_t column_ndx, int64_t value) const; + size_t count_string(size_t column_ndx, StringData value) const; + size_t count_float(size_t column_ndx, float value) const; + size_t count_double(size_t column_ndx, double value) const; int64_t sum(size_t column_ndx) const; double sum_float(size_t column_ndx) const; @@ -233,29 +230,29 @@ class Table { double average_double(size_t column_ndx) const; // Searching - size_t lookup(const char* value) const; + size_t lookup(StringData value) const; size_t find_first_int(size_t column_ndx, int64_t value) const; size_t find_first_bool(size_t column_ndx, bool value) const; - size_t find_first_date(size_t column_ndx, time_t value) const; + size_t find_first_date(size_t column_ndx, Date value) const; size_t find_first_float(size_t column_ndx, float value) const; size_t find_first_double(size_t column_ndx, double value) const; - size_t find_first_string(size_t column_ndx, const char* value) const; - size_t find_first_binary(size_t column_ndx, const char* value, size_t len) const; + size_t find_first_string(size_t column_ndx, StringData value) const; + size_t find_first_binary(size_t column_ndx, BinaryData value) const; TableView find_all_int(size_t column_ndx, int64_t value); ConstTableView find_all_int(size_t column_ndx, int64_t value) const; TableView find_all_bool(size_t column_ndx, bool value); ConstTableView find_all_bool(size_t column_ndx, bool value) const; - TableView find_all_date(size_t column_ndx, time_t value); - ConstTableView find_all_date(size_t column_ndx, time_t value) const; + TableView find_all_date(size_t column_ndx, Date value); + ConstTableView find_all_date(size_t column_ndx, Date value) const; TableView find_all_float(size_t column_ndx, float value); ConstTableView find_all_float(size_t column_ndx, float value) const; TableView find_all_double(size_t column_ndx, double value); ConstTableView find_all_double(size_t column_ndx, double value) const; - TableView find_all_string(size_t column_ndx, const char* value); - ConstTableView find_all_string(size_t column_ndx, const char* value) const; - TableView find_all_binary(size_t column_ndx, const char* value, size_t len); - ConstTableView find_all_binary(size_t column_ndx, const char* value, size_t len) const; + TableView find_all_string(size_t column_ndx, StringData value); + ConstTableView find_all_string(size_t column_ndx, StringData value) const; + TableView find_all_binary(size_t column_ndx, BinaryData value); + ConstTableView find_all_binary(size_t column_ndx, BinaryData value) const; TableView distinct(size_t column_ndx); ConstTableView distinct(size_t column_ndx) const; @@ -293,7 +290,7 @@ class Table { // Debug #ifdef TIGHTDB_DEBUG void Verify() const; // Must be upper case to avoid conflict with macro in ObjC - void to_dot(std::ostream& out, const char* title=NULL) const; + void to_dot(std::ostream& out, StringData title = StringData()) const; void print() const; MemStats stats() const; #endif // TIGHTDB_DEBUG @@ -360,10 +357,10 @@ class Table { size_t GetColumnRefPos(size_t column_ndx) const; void UpdateColumnRefs(size_t column_ndx, int diff); void UpdateFromParent(); - void do_remove_column(const vector& column_ids, size_t pos); + void do_remove_column(const std::vector& column_ids, size_t pos); void do_remove_column(size_t column_ndx); size_t do_add_column(DataType type); - void do_add_subcolumn(const vector& column_path, size_t pos, DataType type); + void do_add_subcolumn(const std::vector& column_path, size_t pos, DataType type); void set_index(size_t column_ndx, bool update_spec); @@ -523,13 +520,13 @@ inline std::size_t Table::get_column_count() const TIGHTDB_NOEXCEPT return m_spec_set.get_column_count(); } -inline const char* Table::get_column_name(std::size_t ndx) const TIGHTDB_NOEXCEPT +inline StringData Table::get_column_name(std::size_t ndx) const TIGHTDB_NOEXCEPT { TIGHTDB_ASSERT(ndx < get_column_count()); return m_spec_set.get_column_name(ndx); } -inline std::size_t Table::get_column_index(const char* name) const +inline std::size_t Table::get_column_index(StringData name) const { return m_spec_set.get_column_index(name); } @@ -588,9 +585,9 @@ struct Table::UnbindGuard { inline std::size_t Table::create_empty_table(Allocator& alloc) { - Array top(coldef_HasRefs, 0, 0, alloc); + Array top(Array::coldef_HasRefs, 0, 0, alloc); top.add(Spec::create_empty_spec(alloc)); - top.add(Array::create_empty_array(coldef_HasRefs, alloc)); // Columns + top.add(Array::create_empty_array(Array::coldef_HasRefs, alloc)); // Columns return top.GetRef(); } @@ -642,9 +639,9 @@ inline void Table::insert_bool(size_t column_ndx, size_t row_ndx, bool value) insert_int(column_ndx, row_ndx, value); } -inline void Table::insert_date(size_t column_ndx, size_t row_ndx, time_t value) +inline void Table::insert_date(size_t column_ndx, size_t row_ndx, Date value) { - insert_int(column_ndx, row_ndx, value); + insert_int(column_ndx, row_ndx, value.get_date()); } template inline void Table::insert_enum(size_t column_ndx, size_t row_ndx, E value) @@ -741,7 +738,7 @@ struct Table::LocalTransactLog { if (m_repl) m_repl->optimize_table(m_table); // Throws } - void add_column(DataType type, const char* name) + void add_column(DataType type, StringData name) { if (m_repl) m_repl->add_column(m_table, &m_table->m_spec_set, type, name); // Throws } diff --git a/src/tightdb/table_accessors.hpp b/src/tightdb/table_accessors.hpp index 2698240a8b5..38d5be05214 100644 --- a/src/tightdb/table_accessors.hpp +++ b/src/tightdb/table_accessors.hpp @@ -43,7 +43,7 @@ struct SpecBase { typedef tightdb::Date Date; typedef float Float; typedef double Double; - typedef const char* String; + typedef tightdb::StringData String; typedef tightdb::BinaryData Binary; typedef tightdb::Mixed Mixed; @@ -93,7 +93,7 @@ struct SpecBase { /// FIXME: Currently we do not support absence of dynamic column /// names. - static const char* const* dyn_col_names() { return 0; } + static const StringData* dyn_col_names() { return 0; } /// This is the fallback class that is used when no convenience /// methods are specified in the users Spec class. @@ -392,18 +392,18 @@ class FieldAccessor: public FieldAccessorBase< typedef FieldAccessorBase Base; public: - std::time_t get() const TIGHTDB_NOEXCEPT + Date get() const TIGHTDB_NOEXCEPT { return Base::m_table->get_impl()->get_date(col_idx, Base::m_row_idx); } - void set(const std::time_t& value) const + void set(Date value) const { Base::m_table->get_impl()->set_date(col_idx, Base::m_row_idx, value); } - operator std::time_t() const TIGHTDB_NOEXCEPT { return get(); } - const FieldAccessor& operator=(const std::time_t& value) const { set(value); return *this; } + operator Date() const TIGHTDB_NOEXCEPT { return get(); } + const FieldAccessor& operator=(Date value) const { set(value); return *this; } explicit FieldAccessor(typename Base::Init i) TIGHTDB_NOEXCEPT: Base(i) {} @@ -412,43 +412,28 @@ class FieldAccessor: public FieldAccessorBase< /// Field accessor specialization for strings. template -class FieldAccessor: public FieldAccessorBase { +class FieldAccessor: public FieldAccessorBase { private: typedef FieldAccessorBase Base; public: - const char* get() const TIGHTDB_NOEXCEPT + StringData get() const TIGHTDB_NOEXCEPT { return Base::m_table->get_impl()->get_string(col_idx, Base::m_row_idx); } - void set(const char* value) const + void set(StringData value) const { Base::m_table->get_impl()->set_string(col_idx, Base::m_row_idx, value); } - operator const char*() const TIGHTDB_NOEXCEPT { return get(); } - const FieldAccessor& operator=(const char* value) const { set(value); return *this; } + operator StringData() const TIGHTDB_NOEXCEPT { return get(); } + const FieldAccessor& operator=(StringData value) const { set(value); return *this; } - friend bool operator==(const FieldAccessor& a, const char* b) TIGHTDB_NOEXCEPT - { - return std::strcmp(a.get(), b) == 0; - } - - friend bool operator!=(const FieldAccessor& a, const char* b) TIGHTDB_NOEXCEPT - { - return std::strcmp(a.get(), b) != 0; - } - - friend bool operator==(const char* a, const FieldAccessor& b) TIGHTDB_NOEXCEPT - { - return std::strcmp(a, b.get()) == 0; - } + const char* data() const TIGHTDB_NOEXCEPT { return get().data(); } + std::size_t size() const TIGHTDB_NOEXCEPT { return get().size(); } - friend bool operator!=(const char* a, const FieldAccessor& b) TIGHTDB_NOEXCEPT - { - return std::strcmp(a, b.get()) != 0; - } + const char* c_str() const TIGHTDB_NOEXCEPT { return data(); } explicit FieldAccessor(typename Base::Init i) TIGHTDB_NOEXCEPT: Base(i) {} @@ -469,34 +454,36 @@ class FieldAccessor: public FieldAccesso void set(const BinaryData& value) const { - Base::m_table->get_impl()->set_binary(col_idx, Base::m_row_idx, value.pointer, value.len); + Base::m_table->get_impl()->set_binary(col_idx, Base::m_row_idx, value); } operator BinaryData() const { return get(); } // FIXME: Should be modified so it never throws const FieldAccessor& operator=(const BinaryData& value) const { set(value); return *this; } +/* friend bool operator==(const FieldAccessor& a, const BinaryData& b) // FIXME: Should be modified so it never throws { - return a.get().compare_payload(b); + return a.get() == b; } friend bool operator!=(const FieldAccessor& a, const BinaryData& b) // FIXME: Should be modified so it never throws { - return !a.get().compare_payload(b); + return a.get() != b; } friend bool operator==(const BinaryData& a, const FieldAccessor& b) // FIXME: Should be modified so it never throws { - return a.compare_payload(b.get()); + return a == b.get(); } friend bool operator!=(const BinaryData& a, const FieldAccessor& b) // FIXME: Should be modified so it never throws { - return !a.compare_payload(b.get()); + return a != b.get(); } +*/ - const char* get_pointer() const { return get().pointer; } // FIXME: Should be modified so it never throws - std::size_t get_len() const { return get().len; } // FIXME: Should be modified so it never throws + const char* data() const { return get().data(); } // FIXME: Should be modified so it never throws + std::size_t size() const { return get().size(); } // FIXME: Should be modified so it never throws explicit FieldAccessor(typename Base::Init i) TIGHTDB_NOEXCEPT: Base(i) {} @@ -633,13 +620,13 @@ class MixedFieldAccessorBase: public FieldAccessorBase { bool get_bool() const { return get().get_bool(); } // FIXME: Should be modified so it never throws - std::time_t get_date() const { return get().get_date(); } // FIXME: Should be modified so it never throws + Date get_date() const { return get().get_date(); } // FIXME: Should be modified so it never throws float get_float() const { return get().get_float(); } // FIXME: Should be modified so it never throws double get_double() const { return get().get_double(); } // FIXME: Should be modified so it never throws - const char* get_string() const { return get().get_string(); } // FIXME: Should be modified so it never throws + StringData get_string() const { return get().get_string(); } // FIXME: Should be modified so it never throws BinaryData get_binary() const { return get().get_binary(); } // FIXME: Should be modified so it never throws @@ -1063,12 +1050,12 @@ class ColumnAccessor: public ColumnAccessorBaseget_impl()->find_first_date(col_idx, value); } - BasicTableView find_all(std::time_t value) const + BasicTableView find_all(Date value) const { return Base::m_table->get_impl()->find_all_date(col_idx, value); } @@ -1077,25 +1064,25 @@ class ColumnAccessor: public ColumnAccessorBase -class ColumnAccessor: - public ColumnAccessorBase { +class ColumnAccessor: + public ColumnAccessorBase { private: - typedef ColumnAccessorBase Base; + typedef ColumnAccessorBase Base; public: explicit ColumnAccessor(Taboid* t) TIGHTDB_NOEXCEPT: Base(t) {} - size_t count(const char* target) const + size_t count(StringData value) const { - return Base::m_table->get_impl()->count_string(col_idx, target); + return Base::m_table->get_impl()->count_string(col_idx, value); } - std::size_t find_first(const char* value) const + std::size_t find_first(StringData value) const { return Base::m_table->get_impl()->find_first_string(col_idx, value); } - BasicTableView find_all(const char* value) const + BasicTableView find_all(StringData value) const { return Base::m_table->get_impl()->find_all_string(col_idx, value); } @@ -1119,12 +1106,12 @@ class ColumnAccessor: std::size_t find_first(const BinaryData &value) const { - return Base::m_table->get_impl()->find_first_binary(col_idx, value.pointer, value.len); + return Base::m_table->get_impl()->find_first_binary(col_idx, value.data(), value.size()); } BasicTableView find_all(const BinaryData &value) const { - return Base::m_table->get_impl()->find_all_date(col_idx, value.pointer, value.len); + return Base::m_table->get_impl()->find_all_binary(col_idx, value.data(), value.size()); } }; @@ -1431,56 +1418,56 @@ class QueryColumn: public QueryColumnBasem_impl.equal_date(col_idx, value); return *Base::m_query; } - Query& not_equal(std::time_t value) const + Query& not_equal(Date value) const { Base::m_query->m_impl.not_equal_date(col_idx, value); return *Base::m_query; } - Query& greater(std::time_t value) const + Query& greater(Date value) const { Base::m_query->m_impl.greater_date(col_idx, value); return *Base::m_query; } - Query& greater_equal(std::time_t value) const + Query& greater_equal(Date value) const { Base::m_query->m_impl.greater_equal_date(col_idx, value); return *Base::m_query; } - Query& less(std::time_t value) const + Query& less(Date value) const { Base::m_query->m_impl.less_date(col_idx, value); return *Base::m_query; } - Query& less_equal(std::time_t value) const + Query& less_equal(Date value) const { Base::m_query->m_impl.less_equal_date(col_idx, value); return *Base::m_query; } - Query& between(std::time_t from, std::time_t to) const + Query& between(Date from, Date to) const { Base::m_query->m_impl.between_date(col_idx, from, to); return *Base::m_query; }; - std::time_t maximum(const Taboid& tab, std::size_t* resultcount=NULL, std::size_t start=0, - std::size_t end = std::size_t(-1), std::size_t limit=std::size_t(-1)) const + Date maximum(const Taboid& tab, std::size_t* resultcount=NULL, std::size_t start=0, + std::size_t end = std::size_t(-1), std::size_t limit=std::size_t(-1)) const { return Base::m_query->m_impl.maximum_date(tab, col_idx, resultcount, start, end, limit); } - std::time_t minimum(const Taboid& tab, std::size_t* resultcount=NULL, std::size_t start=0, - std::size_t end = std::size_t(-1), std::size_t limit=std::size_t(-1)) const + Date minimum(const Taboid& tab, std::size_t* resultcount=NULL, std::size_t start=0, + std::size_t end = std::size_t(-1), std::size_t limit=std::size_t(-1)) const { return Base::m_query->m_impl.minimum_date(tab, col_idx, resultcount, start, end, limit); } @@ -1489,40 +1476,40 @@ class QueryColumn: public QueryColumnBase -class QueryColumn: - public QueryColumnBase { +class QueryColumn: + public QueryColumnBase { private: - typedef QueryColumnBase Base; + typedef QueryColumnBase Base; typedef typename Taboid::Query Query; public: explicit QueryColumn(Query* q) TIGHTDB_NOEXCEPT: Base(q) {} - Query& equal(const char* value, bool case_sensitive=true) const + Query& equal(StringData value, bool case_sensitive=true) const { Base::m_query->m_impl.equal(col_idx, value, case_sensitive); return *Base::m_query; } - Query& not_equal(const char* value, bool case_sensitive=true) const + Query& not_equal(StringData value, bool case_sensitive=true) const { Base::m_query->m_impl.not_equal(col_idx, value, case_sensitive); return *Base::m_query; } - Query& begins_with(const char* value, bool case_sensitive=true) const + Query& begins_with(StringData value, bool case_sensitive=true) const { Base::m_query->m_impl.begins_with(col_idx, value, case_sensitive); return *Base::m_query; } - Query& ends_with(const char* value, bool case_sensitive=true) const + Query& ends_with(StringData value, bool case_sensitive=true) const { Base::m_query->m_impl.ends_with(col_idx, value, case_sensitive); return *Base::m_query; } - Query& contains(const char* value, bool case_sensitive=true) const + Query& contains(StringData value, bool case_sensitive=true) const { Base::m_query->m_impl.contains(col_idx, value, case_sensitive); return *Base::m_query; @@ -1541,34 +1528,33 @@ class QueryColumn: public: explicit QueryColumn(Query* q) TIGHTDB_NOEXCEPT: Base(q) {} - Query& equal(const BinaryData& value) const + Query& equal(BinaryData value) const { - Base::m_query->m_impl.equal_binary(col_idx, value.pointer, value.len); + Base::m_query->m_impl.equal(col_idx, value); return *Base::m_query; } - Query& not_equal(const BinaryData& value, bool case_sensitive=true) const + Query& not_equal(BinaryData value) const { - Base::m_query->m_impl.not_equal_binary(col_idx, value.pointer, value.len, case_sensitive); + Base::m_query->m_impl.not_equal(col_idx, value); return *Base::m_query; } - Query& begins_with(const BinaryData& value, bool case_sensitive=true) const + Query& begins_with(BinaryData value) const { - Base::m_query->m_impl.begins_with_binary(col_idx, value.pointer, value.len, - case_sensitive); + Base::m_query->m_impl.begins_with(col_idx, value); return *Base::m_query; } - Query& ends_with(const BinaryData& value, bool case_sensitive=true) const + Query& ends_with(BinaryData value) const { - Base::m_query->m_impl.ends_with_binary(col_idx, value.pointer, value.len, case_sensitive); + Base::m_query->m_impl.ends_with(col_idx, value); return *Base::m_query; } - Query& contains(const BinaryData& value, bool case_sensitive=true) const + Query& contains(BinaryData value) const { - Base::m_query->m_impl.contains_binary(col_idx, value.pointer, value.len, case_sensitive); + Base::m_query->m_impl.contains(col_idx, value); return *Base::m_query; } }; diff --git a/src/tightdb/table_basic.hpp b/src/tightdb/table_basic.hpp index 64e7899b8f6..c2f1a4a45ba 100644 --- a/src/tightdb/table_basic.hpp +++ b/src/tightdb/table_basic.hpp @@ -22,8 +22,6 @@ #include // unint8_t etc #include -#include // strcmp() -#include #include #include @@ -396,6 +394,9 @@ namespace _impl template<> struct GetColumnTypeId { static const DataType id = type_Int; }; + template struct GetColumnTypeId > { + static const DataType id = type_Int; + }; template<> struct GetColumnTypeId { static const DataType id = type_Bool; }; @@ -405,25 +406,22 @@ namespace _impl template<> struct GetColumnTypeId { static const DataType id = type_Double; }; - template<> struct GetColumnTypeId { + template<> struct GetColumnTypeId { static const DataType id = type_String; }; - template struct GetColumnTypeId > { - static const DataType id = type_Int; + template<> struct GetColumnTypeId { + static const DataType id = type_Binary; }; template<> struct GetColumnTypeId { static const DataType id = type_Date; }; - template<> struct GetColumnTypeId { - static const DataType id = type_Binary; - }; template<> struct GetColumnTypeId { static const DataType id = type_Mixed; }; template struct AddCol { - static void exec(Spec* spec, const char* const* col_names) + static void exec(Spec* spec, const StringData* col_names) { TIGHTDB_ASSERT(col_idx == spec->get_column_count()); spec->add_column(GetColumnTypeId::id, col_names[col_idx]); @@ -432,12 +430,12 @@ namespace _impl // AddCol specialization for subtables template struct AddCol, col_idx> { - static void exec(Spec* spec, const char* const* col_names) + static void exec(Spec* spec, const StringData* col_names) { TIGHTDB_ASSERT(col_idx == spec->get_column_count()); typedef typename Subtab::Columns Subcolumns; Spec subspec = spec->add_subtable_column(col_names[col_idx]); - const char* const* const subcol_names = Subtab::spec_type::dyn_col_names(); + const StringData* const subcol_names = Subtab::spec_type::dyn_col_names(); ForEachType::exec(&subspec, subcol_names); } }; @@ -445,19 +443,19 @@ namespace _impl template struct DiffColType { - static bool exec(const Spec* spec, const char* const* col_names) + static bool exec(const Spec* spec, const StringData* col_names) { return GetColumnTypeId::id != spec->get_column_type(col_idx) || - std::strcmp(col_names[col_idx], spec->get_column_name(col_idx)) != 0; + col_names[col_idx] != spec->get_column_name(col_idx); } }; // DiffColType specialization for subtables template struct DiffColType, col_idx> { - static bool exec(const Spec* spec, const char* const* col_names) + static bool exec(const Spec* spec, const StringData* col_names) { if (spec->get_column_type(col_idx) != type_Table || - std::strcmp(col_names[col_idx], spec->get_column_name(col_idx)) != 0) return true; + col_names[col_idx] != spec->get_column_name(col_idx)) return true; Spec subspec = spec->get_subtable_spec(col_idx); return !Subtab::matches_dynamic_spec(&subspec); } @@ -498,7 +496,7 @@ namespace _impl }; // InsertIntoCol specialization for strings - template struct InsertIntoCol { + template struct InsertIntoCol { template static void exec(Table* t, std::size_t row_idx, Tuple tuple) { t->insert_string(col_idx, row_idx, at(tuple)); @@ -517,8 +515,7 @@ namespace _impl template struct InsertIntoCol { template static void exec(Table* t, std::size_t row_idx, Tuple tuple) { - const Date d(at(tuple)); - t->insert_date(col_idx, row_idx, d.get_date()); + t->insert_date(col_idx, row_idx, at(tuple)); } }; @@ -526,8 +523,7 @@ namespace _impl template struct InsertIntoCol { template static void exec(Table* t, std::size_t row_idx, Tuple tuple) { - const BinaryData b(at(tuple)); - t->insert_binary(col_idx, row_idx, b.pointer, b.len); + t->insert_binary(col_idx, row_idx, at(tuple)); } }; @@ -582,7 +578,7 @@ namespace _impl }; // AssignIntoCol specialization for strings - template struct AssignIntoCol { + template struct AssignIntoCol { template static void exec(Table* t, std::size_t row_idx, Tuple tuple) { t->set_string(col_idx, row_idx, at(tuple)); @@ -601,8 +597,7 @@ namespace _impl template struct AssignIntoCol { template static void exec(Table* t, std::size_t row_idx, Tuple tuple) { - const Date d(at(tuple)); - t->set_date(col_idx, row_idx, d.get_date()); + t->set_date(col_idx, row_idx, at(tuple)); } }; @@ -610,8 +605,7 @@ namespace _impl template struct AssignIntoCol { template static void exec(Table* t, std::size_t row_idx, Tuple tuple) { - const BinaryData b(at(tuple)); - t->set_binary(col_idx, row_idx, b.pointer, b.len); + t->set_binary(col_idx, row_idx, at(tuple)); } }; diff --git a/src/tightdb/table_macros.hpp b/src/tightdb/table_macros.hpp index c50dca84b27..88ea771599a 100644 --- a/src/tightdb/table_macros.hpp +++ b/src/tightdb/table_macros.hpp @@ -32,9 +32,9 @@ struct Table##Spec: ::tightdb::SpecBase { \ ColNames(Init i) TIGHTDB_NOEXCEPT: name1(i) {} \ }; \ \ - static const char* const* dyn_col_names() \ + static const tightdb::StringData* dyn_col_names() \ { \ - static const char* names[] = { #name1 }; \ + static tightdb::StringData names[] = { tightdb::StringData(#name1, sizeof(#name1)-1) }; \ return names; \ } \ \ @@ -73,9 +73,9 @@ struct Table##Spec: ::tightdb::SpecBase { \ ColNames(Init i) TIGHTDB_NOEXCEPT: name1(i), name2(i) {} \ }; \ \ - static const char* const* dyn_col_names() \ + static const tightdb::StringData* dyn_col_names() \ { \ - static const char* names[] = { #name1, #name2 }; \ + static tightdb::StringData names[] = { tightdb::StringData(#name1, sizeof(#name1)-1), tightdb::StringData(#name2, sizeof(#name2)-1) }; \ return names; \ } \ \ @@ -116,9 +116,9 @@ struct Table##Spec: ::tightdb::SpecBase { \ ColNames(Init i) TIGHTDB_NOEXCEPT: name1(i), name2(i), name3(i) {} \ }; \ \ - static const char* const* dyn_col_names() \ + static const tightdb::StringData* dyn_col_names() \ { \ - static const char* names[] = { #name1, #name2, #name3 }; \ + static tightdb::StringData names[] = { tightdb::StringData(#name1, sizeof(#name1)-1), tightdb::StringData(#name2, sizeof(#name2)-1), tightdb::StringData(#name3, sizeof(#name3)-1) }; \ return names; \ } \ \ @@ -161,9 +161,9 @@ struct Table##Spec: ::tightdb::SpecBase { \ ColNames(Init i) TIGHTDB_NOEXCEPT: name1(i), name2(i), name3(i), name4(i) {} \ }; \ \ - static const char* const* dyn_col_names() \ + static const tightdb::StringData* dyn_col_names() \ { \ - static const char* names[] = { #name1, #name2, #name3, #name4 }; \ + static tightdb::StringData names[] = { tightdb::StringData(#name1, sizeof(#name1)-1), tightdb::StringData(#name2, sizeof(#name2)-1), tightdb::StringData(#name3, sizeof(#name3)-1), tightdb::StringData(#name4, sizeof(#name4)-1) }; \ return names; \ } \ \ @@ -208,9 +208,9 @@ struct Table##Spec: ::tightdb::SpecBase { \ ColNames(Init i) TIGHTDB_NOEXCEPT: name1(i), name2(i), name3(i), name4(i), name5(i) {} \ }; \ \ - static const char* const* dyn_col_names() \ + static const tightdb::StringData* dyn_col_names() \ { \ - static const char* names[] = { #name1, #name2, #name3, #name4, #name5 }; \ + static tightdb::StringData names[] = { tightdb::StringData(#name1, sizeof(#name1)-1), tightdb::StringData(#name2, sizeof(#name2)-1), tightdb::StringData(#name3, sizeof(#name3)-1), tightdb::StringData(#name4, sizeof(#name4)-1), tightdb::StringData(#name5, sizeof(#name5)-1) }; \ return names; \ } \ \ @@ -257,9 +257,9 @@ struct Table##Spec: ::tightdb::SpecBase { \ ColNames(Init i) TIGHTDB_NOEXCEPT: name1(i), name2(i), name3(i), name4(i), name5(i), name6(i) {} \ }; \ \ - static const char* const* dyn_col_names() \ + static const tightdb::StringData* dyn_col_names() \ { \ - static const char* names[] = { #name1, #name2, #name3, #name4, #name5, #name6 }; \ + static tightdb::StringData names[] = { tightdb::StringData(#name1, sizeof(#name1)-1), tightdb::StringData(#name2, sizeof(#name2)-1), tightdb::StringData(#name3, sizeof(#name3)-1), tightdb::StringData(#name4, sizeof(#name4)-1), tightdb::StringData(#name5, sizeof(#name5)-1), tightdb::StringData(#name6, sizeof(#name6)-1) }; \ return names; \ } \ \ @@ -308,9 +308,9 @@ struct Table##Spec: ::tightdb::SpecBase { \ ColNames(Init i) TIGHTDB_NOEXCEPT: name1(i), name2(i), name3(i), name4(i), name5(i), name6(i), name7(i) {} \ }; \ \ - static const char* const* dyn_col_names() \ + static const tightdb::StringData* dyn_col_names() \ { \ - static const char* names[] = { #name1, #name2, #name3, #name4, #name5, #name6, #name7 }; \ + static tightdb::StringData names[] = { tightdb::StringData(#name1, sizeof(#name1)-1), tightdb::StringData(#name2, sizeof(#name2)-1), tightdb::StringData(#name3, sizeof(#name3)-1), tightdb::StringData(#name4, sizeof(#name4)-1), tightdb::StringData(#name5, sizeof(#name5)-1), tightdb::StringData(#name6, sizeof(#name6)-1), tightdb::StringData(#name7, sizeof(#name7)-1) }; \ return names; \ } \ \ @@ -361,9 +361,9 @@ struct Table##Spec: ::tightdb::SpecBase { \ ColNames(Init i) TIGHTDB_NOEXCEPT: name1(i), name2(i), name3(i), name4(i), name5(i), name6(i), name7(i), name8(i) {} \ }; \ \ - static const char* const* dyn_col_names() \ + static const tightdb::StringData* dyn_col_names() \ { \ - static const char* names[] = { #name1, #name2, #name3, #name4, #name5, #name6, #name7, #name8 }; \ + static tightdb::StringData names[] = { tightdb::StringData(#name1, sizeof(#name1)-1), tightdb::StringData(#name2, sizeof(#name2)-1), tightdb::StringData(#name3, sizeof(#name3)-1), tightdb::StringData(#name4, sizeof(#name4)-1), tightdb::StringData(#name5, sizeof(#name5)-1), tightdb::StringData(#name6, sizeof(#name6)-1), tightdb::StringData(#name7, sizeof(#name7)-1), tightdb::StringData(#name8, sizeof(#name8)-1) }; \ return names; \ } \ \ @@ -416,9 +416,9 @@ struct Table##Spec: ::tightdb::SpecBase { \ ColNames(Init i) TIGHTDB_NOEXCEPT: name1(i), name2(i), name3(i), name4(i), name5(i), name6(i), name7(i), name8(i), name9(i) {} \ }; \ \ - static const char* const* dyn_col_names() \ + static const tightdb::StringData* dyn_col_names() \ { \ - static const char* names[] = { #name1, #name2, #name3, #name4, #name5, #name6, #name7, #name8, #name9 }; \ + static tightdb::StringData names[] = { tightdb::StringData(#name1, sizeof(#name1)-1), tightdb::StringData(#name2, sizeof(#name2)-1), tightdb::StringData(#name3, sizeof(#name3)-1), tightdb::StringData(#name4, sizeof(#name4)-1), tightdb::StringData(#name5, sizeof(#name5)-1), tightdb::StringData(#name6, sizeof(#name6)-1), tightdb::StringData(#name7, sizeof(#name7)-1), tightdb::StringData(#name8, sizeof(#name8)-1), tightdb::StringData(#name9, sizeof(#name9)-1) }; \ return names; \ } \ \ @@ -473,9 +473,9 @@ struct Table##Spec: ::tightdb::SpecBase { \ ColNames(Init i) TIGHTDB_NOEXCEPT: name1(i), name2(i), name3(i), name4(i), name5(i), name6(i), name7(i), name8(i), name9(i), name10(i) {} \ }; \ \ - static const char* const* dyn_col_names() \ + static const tightdb::StringData* dyn_col_names() \ { \ - static const char* names[] = { #name1, #name2, #name3, #name4, #name5, #name6, #name7, #name8, #name9, #name10 }; \ + static tightdb::StringData names[] = { tightdb::StringData(#name1, sizeof(#name1)-1), tightdb::StringData(#name2, sizeof(#name2)-1), tightdb::StringData(#name3, sizeof(#name3)-1), tightdb::StringData(#name4, sizeof(#name4)-1), tightdb::StringData(#name5, sizeof(#name5)-1), tightdb::StringData(#name6, sizeof(#name6)-1), tightdb::StringData(#name7, sizeof(#name7)-1), tightdb::StringData(#name8, sizeof(#name8)-1), tightdb::StringData(#name9, sizeof(#name9)-1), tightdb::StringData(#name10, sizeof(#name10)-1) }; \ return names; \ } \ \ @@ -532,9 +532,9 @@ struct Table##Spec: ::tightdb::SpecBase { \ ColNames(Init i) TIGHTDB_NOEXCEPT: name1(i), name2(i), name3(i), name4(i), name5(i), name6(i), name7(i), name8(i), name9(i), name10(i), name11(i) {} \ }; \ \ - static const char* const* dyn_col_names() \ + static const tightdb::StringData* dyn_col_names() \ { \ - static const char* names[] = { #name1, #name2, #name3, #name4, #name5, #name6, #name7, #name8, #name9, #name10, #name11 }; \ + static tightdb::StringData names[] = { tightdb::StringData(#name1, sizeof(#name1)-1), tightdb::StringData(#name2, sizeof(#name2)-1), tightdb::StringData(#name3, sizeof(#name3)-1), tightdb::StringData(#name4, sizeof(#name4)-1), tightdb::StringData(#name5, sizeof(#name5)-1), tightdb::StringData(#name6, sizeof(#name6)-1), tightdb::StringData(#name7, sizeof(#name7)-1), tightdb::StringData(#name8, sizeof(#name8)-1), tightdb::StringData(#name9, sizeof(#name9)-1), tightdb::StringData(#name10, sizeof(#name10)-1), tightdb::StringData(#name11, sizeof(#name11)-1) }; \ return names; \ } \ \ @@ -593,9 +593,9 @@ struct Table##Spec: ::tightdb::SpecBase { \ ColNames(Init i) TIGHTDB_NOEXCEPT: name1(i), name2(i), name3(i), name4(i), name5(i), name6(i), name7(i), name8(i), name9(i), name10(i), name11(i), name12(i) {} \ }; \ \ - static const char* const* dyn_col_names() \ + static const tightdb::StringData* dyn_col_names() \ { \ - static const char* names[] = { #name1, #name2, #name3, #name4, #name5, #name6, #name7, #name8, #name9, #name10, #name11, #name12 }; \ + static tightdb::StringData names[] = { tightdb::StringData(#name1, sizeof(#name1)-1), tightdb::StringData(#name2, sizeof(#name2)-1), tightdb::StringData(#name3, sizeof(#name3)-1), tightdb::StringData(#name4, sizeof(#name4)-1), tightdb::StringData(#name5, sizeof(#name5)-1), tightdb::StringData(#name6, sizeof(#name6)-1), tightdb::StringData(#name7, sizeof(#name7)-1), tightdb::StringData(#name8, sizeof(#name8)-1), tightdb::StringData(#name9, sizeof(#name9)-1), tightdb::StringData(#name10, sizeof(#name10)-1), tightdb::StringData(#name11, sizeof(#name11)-1), tightdb::StringData(#name12, sizeof(#name12)-1) }; \ return names; \ } \ \ @@ -656,9 +656,9 @@ struct Table##Spec: ::tightdb::SpecBase { \ ColNames(Init i) TIGHTDB_NOEXCEPT: name1(i), name2(i), name3(i), name4(i), name5(i), name6(i), name7(i), name8(i), name9(i), name10(i), name11(i), name12(i), name13(i) {} \ }; \ \ - static const char* const* dyn_col_names() \ + static const tightdb::StringData* dyn_col_names() \ { \ - static const char* names[] = { #name1, #name2, #name3, #name4, #name5, #name6, #name7, #name8, #name9, #name10, #name11, #name12, #name13 }; \ + static tightdb::StringData names[] = { tightdb::StringData(#name1, sizeof(#name1)-1), tightdb::StringData(#name2, sizeof(#name2)-1), tightdb::StringData(#name3, sizeof(#name3)-1), tightdb::StringData(#name4, sizeof(#name4)-1), tightdb::StringData(#name5, sizeof(#name5)-1), tightdb::StringData(#name6, sizeof(#name6)-1), tightdb::StringData(#name7, sizeof(#name7)-1), tightdb::StringData(#name8, sizeof(#name8)-1), tightdb::StringData(#name9, sizeof(#name9)-1), tightdb::StringData(#name10, sizeof(#name10)-1), tightdb::StringData(#name11, sizeof(#name11)-1), tightdb::StringData(#name12, sizeof(#name12)-1), tightdb::StringData(#name13, sizeof(#name13)-1) }; \ return names; \ } \ \ @@ -721,9 +721,9 @@ struct Table##Spec: ::tightdb::SpecBase { \ ColNames(Init i) TIGHTDB_NOEXCEPT: name1(i), name2(i), name3(i), name4(i), name5(i), name6(i), name7(i), name8(i), name9(i), name10(i), name11(i), name12(i), name13(i), name14(i) {} \ }; \ \ - static const char* const* dyn_col_names() \ + static const tightdb::StringData* dyn_col_names() \ { \ - static const char* names[] = { #name1, #name2, #name3, #name4, #name5, #name6, #name7, #name8, #name9, #name10, #name11, #name12, #name13, #name14 }; \ + static tightdb::StringData names[] = { tightdb::StringData(#name1, sizeof(#name1)-1), tightdb::StringData(#name2, sizeof(#name2)-1), tightdb::StringData(#name3, sizeof(#name3)-1), tightdb::StringData(#name4, sizeof(#name4)-1), tightdb::StringData(#name5, sizeof(#name5)-1), tightdb::StringData(#name6, sizeof(#name6)-1), tightdb::StringData(#name7, sizeof(#name7)-1), tightdb::StringData(#name8, sizeof(#name8)-1), tightdb::StringData(#name9, sizeof(#name9)-1), tightdb::StringData(#name10, sizeof(#name10)-1), tightdb::StringData(#name11, sizeof(#name11)-1), tightdb::StringData(#name12, sizeof(#name12)-1), tightdb::StringData(#name13, sizeof(#name13)-1), tightdb::StringData(#name14, sizeof(#name14)-1) }; \ return names; \ } \ \ @@ -788,9 +788,9 @@ struct Table##Spec: ::tightdb::SpecBase { \ ColNames(Init i) TIGHTDB_NOEXCEPT: name1(i), name2(i), name3(i), name4(i), name5(i), name6(i), name7(i), name8(i), name9(i), name10(i), name11(i), name12(i), name13(i), name14(i), name15(i) {} \ }; \ \ - static const char* const* dyn_col_names() \ + static const tightdb::StringData* dyn_col_names() \ { \ - static const char* names[] = { #name1, #name2, #name3, #name4, #name5, #name6, #name7, #name8, #name9, #name10, #name11, #name12, #name13, #name14, #name15 }; \ + static tightdb::StringData names[] = { tightdb::StringData(#name1, sizeof(#name1)-1), tightdb::StringData(#name2, sizeof(#name2)-1), tightdb::StringData(#name3, sizeof(#name3)-1), tightdb::StringData(#name4, sizeof(#name4)-1), tightdb::StringData(#name5, sizeof(#name5)-1), tightdb::StringData(#name6, sizeof(#name6)-1), tightdb::StringData(#name7, sizeof(#name7)-1), tightdb::StringData(#name8, sizeof(#name8)-1), tightdb::StringData(#name9, sizeof(#name9)-1), tightdb::StringData(#name10, sizeof(#name10)-1), tightdb::StringData(#name11, sizeof(#name11)-1), tightdb::StringData(#name12, sizeof(#name12)-1), tightdb::StringData(#name13, sizeof(#name13)-1), tightdb::StringData(#name14, sizeof(#name14)-1), tightdb::StringData(#name15, sizeof(#name15)-1) }; \ return names; \ } \ \ diff --git a/src/tightdb/table_view.cpp b/src/tightdb/table_view.cpp index fc003fd623e..24bf945bef2 100644 --- a/src/tightdb/table_view.cpp +++ b/src/tightdb/table_view.cpp @@ -2,6 +2,8 @@ #include #include +using namespace std; + namespace tightdb { // Searching @@ -16,13 +18,12 @@ size_t TableViewBase::find_first_integer(size_t column_ndx, int64_t value) const return size_t(-1); } -size_t TableViewBase::find_first_string(size_t column_ndx, const char* value) const +size_t TableViewBase::find_first_string(size_t column_ndx, StringData value) const { TIGHTDB_ASSERT_COLUMN_AND_TYPE(column_ndx, type_String); for (size_t i = 0; i < m_refs.size(); i++) - if (strcmp(get_string(column_ndx, i), value) == 0) - return i; + if (get_string(column_ndx, i) == value) return i; return size_t(-1); } @@ -162,21 +163,21 @@ void TableViewBase::sort(size_t column, bool Ascending) // with rand access (we have ~log(n) accesses to each element, so using 1 additional read to speed up the rest is faster) if (m_table->get_column_type(column) == type_Int) { for (size_t t = 0; t < m_refs.size(); t++) { - const int64_t v = m_table->get_int(column, size_t(m_refs.Get(t))); + int64_t v = m_table->get_int(column, size_t(m_refs.Get(t))); vals.add(v); } } else if (m_table->get_column_type(column) == type_Date) { for (size_t t = 0; t < m_refs.size(); t++) { - const size_t idx = size_t(m_refs.Get(t)); - const int64_t v = int64_t(m_table->get_date(column, idx)); + size_t idx = size_t(m_refs.Get(t)); + int64_t v = int64_t(m_table->get_date(column, idx).get_date()); vals.add(v); } } else if (m_table->get_column_type(column) == type_Bool) { for (size_t t = 0; t < m_refs.size(); t++) { - const size_t idx = size_t(m_refs.Get(t)); - const int64_t v = int64_t(m_table->get_bool(column, idx)); + size_t idx = size_t(m_refs.Get(t)); + int64_t v = int64_t(m_table->get_bool(column, idx)); vals.add(v); } } @@ -185,8 +186,8 @@ void TableViewBase::sort(size_t column, bool Ascending) vals.Destroy(); for (size_t t = 0; t < m_refs.size(); t++) { - const size_t r = (size_t)ref.Get(t); - const size_t rr = (size_t)m_refs.Get(r); + size_t r = ref.GetAsSizeT(t); + size_t rr = m_refs.GetAsSizeT(r); result.add(rr); } @@ -196,20 +197,20 @@ void TableViewBase::sort(size_t column, bool Ascending) m_refs.Clear(); if (Ascending) { for (size_t t = 0; t < ref.size(); t++) { - const size_t v = (size_t)result.Get(t); + size_t v = result.GetAsSizeT(t); m_refs.add(v); } } else { for (size_t t = 0; t < ref.size(); t++) { - const size_t v = (size_t)result.Get(ref.size() - t - 1); + size_t v = result.GetAsSizeT(ref.size() - t - 1); m_refs.add(v); } } result.Destroy(); } -void TableViewBase::to_json(std::ostream& out) +void TableViewBase::to_json(ostream& out) { // Represent table as list of objects out << "["; @@ -225,15 +226,15 @@ void TableViewBase::to_json(std::ostream& out) out << "]"; } -void TableViewBase::to_string(std::ostream& out, size_t limit) const +void TableViewBase::to_string(ostream& out, size_t limit) const { // Print header (will also calculate widths) - std::vector widths; + vector widths; m_table->to_string_header(out, widths); // Set limit=-1 to print all rows, otherwise only print to limit const size_t row_count = size(); - const size_t out_count = (limit == (size_t)-1) ? row_count + const size_t out_count = (limit == size_t(-1)) ? row_count : (row_count < limit) ? row_count : limit; // Print rows diff --git a/src/tightdb/table_view.hpp b/src/tightdb/table_view.hpp index 199b31a878c..306581fe5ba 100644 --- a/src/tightdb/table_view.hpp +++ b/src/tightdb/table_view.hpp @@ -28,7 +28,6 @@ namespace tightdb { using std::size_t; -using std::time_t; /** @@ -41,17 +40,17 @@ class TableViewBase { // Column information size_t get_column_count() const TIGHTDB_NOEXCEPT; - const char* get_column_name(size_t column_ndx) const TIGHTDB_NOEXCEPT; - size_t get_column_index(const char* name) const; + StringData get_column_name(size_t column_ndx) const TIGHTDB_NOEXCEPT; + size_t get_column_index(StringData name) const; DataType get_column_type(size_t column_ndx) const TIGHTDB_NOEXCEPT; // Getting values int64_t get_int(size_t column_ndx, size_t row_ndx) const TIGHTDB_NOEXCEPT; bool get_bool(size_t column_ndx, size_t row_ndx) const TIGHTDB_NOEXCEPT; - time_t get_date(size_t column_ndx, size_t row_ndx) const TIGHTDB_NOEXCEPT; + Date get_date(size_t column_ndx, size_t row_ndx) const TIGHTDB_NOEXCEPT; float get_float(size_t column_ndx, size_t row_ndx) const; // FIXME: Should be modified so it never throws double get_double(size_t column_ndx, size_t row_ndx) const; // FIXME: Should be modified so it never throws - const char* get_string(size_t column_ndx, size_t row_ndx) const TIGHTDB_NOEXCEPT; + StringData get_string(size_t column_ndx, size_t row_ndx) const TIGHTDB_NOEXCEPT; BinaryData get_binary(size_t column_ndx, size_t row_ndx) const; // FIXME: Should be modified so it never throws Mixed get_mixed(size_t column_ndx, size_t row_ndx) const; // FIXME: Should be modified so it never throws DataType get_mixed_type(size_t column_ndx, size_t row_ndx) const TIGHTDB_NOEXCEPT; @@ -62,15 +61,15 @@ class TableViewBase { // Searching (Int and String) size_t find_first_int(size_t column_ndx, int64_t value) const; size_t find_first_bool(size_t column_ndx, bool value) const; - size_t find_first_date(size_t column_ndx, time_t value) const; + size_t find_first_date(size_t column_ndx, Date value) const; size_t find_first_float(size_t column_ndx, float value) const; size_t find_first_double(size_t column_ndx, double value) const; - size_t find_first_string(size_t column_ndx, const char* value) const; - // FIXME: Need: size_t find_first_binary(size_t column_ndx, const char* value, size_t len) const; + size_t find_first_string(size_t column_ndx, StringData value) const; + // FIXME: Need: size_t find_first_binary(size_t column_ndx, BinaryData value) const; // Aggregate functions template - R aggregate(R (ColType::*aggregateMethod)(size_t, size_t) const, size_t column_ndx) const; + R aggregate(R (ColType::*aggregateMethod)(size_t, size_t) const, size_t column_ndx) const; // TODO, FIXME: rename int versions @@ -87,7 +86,8 @@ class TableViewBase { double maximum_double(size_t column_ndx) const; double minimum_double(size_t column_ndx) const; - // Sort the view according to the specified column and the specified direction. + // Sort the view according to the specified column and the + // specified direction. void sort(size_t column, bool ascending = true); // Get row index in the source table this view is "looking" at. @@ -107,7 +107,7 @@ class TableViewBase { template static R find_all_integer(V*, size_t, int64_t); template static R find_all_float(V*, size_t, float); template static R find_all_double(V*, size_t, double); - template static R find_all_string(V*, size_t, const char*); + template static R find_all_string(V*, size_t, StringData); Table* m_table; Array m_refs; @@ -196,12 +196,12 @@ class TableView: public TableViewBase { // Setting values void set_int(size_t column_ndx, size_t row_ndx, int64_t value); void set_bool(size_t column_ndx, size_t row_ndx, bool value); - void set_date(size_t column_ndx, size_t row_ndx, time_t value); + void set_date(size_t column_ndx, size_t row_ndx, Date value); template void set_enum(size_t column_ndx, size_t row_ndx, E value); void set_float(size_t column_ndx, size_t row_ndx, float value); void set_double(size_t column_ndx, size_t row_ndx, double value); - void set_string(size_t column_ndx, size_t row_ndx, const char* value); - void set_binary(size_t column_ndx, size_t row_ndx, const char* value, size_t len); + void set_string(size_t column_ndx, size_t row_ndx, StringData value); + void set_binary(size_t column_ndx, size_t row_ndx, BinaryData value); void set_mixed(size_t column_ndx, size_t row_ndx, Mixed value); void add_int(size_t column_ndx, int64_t value); @@ -215,16 +215,16 @@ class TableView: public TableViewBase { ConstTableView find_all_int(size_t column_ndx, int64_t value) const; TableView find_all_bool(size_t column_ndx, bool value); ConstTableView find_all_bool(size_t column_ndx, bool value) const; - TableView find_all_date(size_t column_ndx, time_t value); - ConstTableView find_all_date(size_t column_ndx, time_t value) const; + TableView find_all_date(size_t column_ndx, Date value); + ConstTableView find_all_date(size_t column_ndx, Date value) const; TableView find_all_float(size_t column_ndx, float value); ConstTableView find_all_float(size_t column_ndx, float value) const; TableView find_all_double(size_t column_ndx, double value); ConstTableView find_all_double(size_t column_ndx, double value) const; - TableView find_all_string(size_t column_ndx, const char *value); - ConstTableView find_all_string(size_t column_ndx, const char *value) const; - // FIXME: Need: TableView find_all_binary(size_t column_ndx, const char* value, size_t len); - // FIXME: Need: ConstTableView find_all_binary(size_t column_ndx, const char* value, size_t len) const; + TableView find_all_string(size_t column_ndx, StringData value); + ConstTableView find_all_string(size_t column_ndx, StringData value) const; + // FIXME: Need: TableView find_all_binary(size_t column_ndx, BinaryData value); + // FIXME: Need: ConstTableView find_all_binary(size_t column_ndx, BinaryData value) const; Table& get_parent() TIGHTDB_NOEXCEPT { return *m_table; } const Table& get_parent() const TIGHTDB_NOEXCEPT { return *m_table; } @@ -272,10 +272,10 @@ class ConstTableView: public TableViewBase { // Searching (Int and String) ConstTableView find_all_int(size_t column_ndx, int64_t value) const; ConstTableView find_all_bool(size_t column_ndx, bool value) const; - ConstTableView find_all_date(size_t column_ndx, time_t value) const; + ConstTableView find_all_date(size_t column_ndx, Date value) const; ConstTableView find_all_float(size_t column_ndx, float value) const; ConstTableView find_all_double(size_t column_ndx, double value) const; - ConstTableView find_all_string(size_t column_ndx, const char *value) const; + ConstTableView find_all_string(size_t column_ndx, StringData value) const; const Table& get_parent() const TIGHTDB_NOEXCEPT { return *m_table; } @@ -336,13 +336,13 @@ inline size_t TableViewBase::get_column_count() const TIGHTDB_NOEXCEPT return m_table->get_column_count(); } -inline const char* TableViewBase::get_column_name(size_t column_ndx) const TIGHTDB_NOEXCEPT +inline StringData TableViewBase::get_column_name(size_t column_ndx) const TIGHTDB_NOEXCEPT { TIGHTDB_ASSERT(m_table); return m_table->get_column_name(column_ndx); } -inline size_t TableViewBase::get_column_index(const char* name) const +inline size_t TableViewBase::get_column_index(StringData name) const { TIGHTDB_ASSERT(m_table); return m_table->get_column_index(name); @@ -374,7 +374,7 @@ inline bool TableViewBase::get_bool(size_t column_ndx, size_t row_ndx) const TIG return m_table->get_bool(column_ndx, real_ndx); } -inline time_t TableViewBase::get_date(size_t column_ndx, size_t row_ndx) const TIGHTDB_NOEXCEPT +inline Date TableViewBase::get_date(size_t column_ndx, size_t row_ndx) const TIGHTDB_NOEXCEPT { TIGHTDB_ASSERT_INDEX_AND_TYPE(column_ndx, row_ndx, type_Date); @@ -398,7 +398,7 @@ inline double TableViewBase::get_double(size_t column_ndx, size_t row_ndx) const return m_table->get_double(column_ndx, real_ndx); } -inline const char* TableViewBase::get_string(size_t column_ndx, size_t row_ndx) const +inline StringData TableViewBase::get_string(size_t column_ndx, size_t row_ndx) const TIGHTDB_NOEXCEPT { TIGHTDB_ASSERT_INDEX_AND_TYPE(column_ndx, row_ndx, type_String); @@ -457,10 +457,10 @@ inline size_t TableViewBase::find_first_bool(size_t column_ndx, bool value) cons return find_first_integer(column_ndx, value ? 1 : 0); } -inline size_t TableViewBase::find_first_date(size_t column_ndx, time_t value) const +inline size_t TableViewBase::find_first_date(size_t column_ndx, Date value) const { TIGHTDB_ASSERT_COLUMN_AND_TYPE(column_ndx, type_Date); - return find_first_integer(column_ndx, (int64_t)value); + return find_first_integer(column_ndx, int64_t(value.get_date())); } @@ -495,16 +495,17 @@ R TableViewBase::find_all_double(V* view, size_t column_ndx, double value) } template -R TableViewBase::find_all_string(V* view, size_t column_ndx, const char* value) +R TableViewBase::find_all_string(V* view, size_t column_ndx, StringData value) { TIGHTDB_ASSERT(view->m_table); TIGHTDB_ASSERT(column_ndx < view->m_table->get_column_count()); TIGHTDB_ASSERT(view->m_table->get_column_type(column_ndx) == type_String); R tv(*view->m_table); - for (size_t i = 0; i < view->m_refs.size(); i++) - if (strcmp(view->get_string(column_ndx, i), value) == 0) + for (size_t i = 0; i < view->m_refs.size(); i++) { + if (view->get_string(column_ndx, i) == value) tv.get_ref_column().add(i); + } return move(tv); } @@ -512,17 +513,17 @@ R TableViewBase::find_all_string(V* view, size_t column_ndx, const char* value) //-------------------------- TableView, ConstTableView implementation: // - string -inline TableView TableView::find_all_string(size_t column_ndx, const char* value) +inline TableView TableView::find_all_string(size_t column_ndx, StringData value) { return TableViewBase::find_all_string(this, column_ndx, value); } -inline ConstTableView TableView::find_all_string(size_t column_ndx, const char* value) const +inline ConstTableView TableView::find_all_string(size_t column_ndx, StringData value) const { return TableViewBase::find_all_string(this, column_ndx, value); } -inline ConstTableView ConstTableView::find_all_string(size_t column_ndx, const char* value) const +inline ConstTableView ConstTableView::find_all_string(size_t column_ndx, StringData value) const { return TableViewBase::find_all_string(this, column_ndx, value); } @@ -592,10 +593,10 @@ inline TableView TableView::find_all_bool(size_t column_ndx, bool value) return find_all_integer(column_ndx, value ? 1 : 0); } -inline TableView TableView::find_all_date(size_t column_ndx, time_t value) +inline TableView TableView::find_all_date(size_t column_ndx, Date value) { TIGHTDB_ASSERT_COLUMN_AND_TYPE(column_ndx, type_Date); - return find_all_integer(column_ndx, (int64_t)value); + return find_all_integer(column_ndx, int64_t(value.get_date())); } @@ -611,10 +612,10 @@ inline ConstTableView TableView::find_all_bool(size_t column_ndx, bool value) co return find_all_integer(column_ndx, value ? 1 : 0); } -inline ConstTableView TableView::find_all_date(size_t column_ndx, time_t value) const +inline ConstTableView TableView::find_all_date(size_t column_ndx, Date value) const { TIGHTDB_ASSERT_COLUMN_AND_TYPE(column_ndx, type_Date); - return find_all_integer(column_ndx, (int64_t)value); + return find_all_integer(column_ndx, int64_t(value.get_date())); } @@ -630,10 +631,10 @@ inline ConstTableView ConstTableView::find_all_bool(size_t column_ndx, bool valu return find_all_integer(column_ndx, value ? 1 : 0); } -inline ConstTableView ConstTableView::find_all_date(size_t column_ndx, time_t value) const +inline ConstTableView ConstTableView::find_all_date(size_t column_ndx, Date value) const { TIGHTDB_ASSERT_COLUMN_AND_TYPE(column_ndx, type_Date); - return find_all_integer(column_ndx, (int64_t)value); + return find_all_integer(column_ndx, int64_t(value.get_date())); } @@ -692,7 +693,7 @@ inline void TableView::set_bool(size_t column_ndx, size_t row_ndx, bool value) m_table->set_bool(column_ndx, real_ndx, value); } -inline void TableView::set_date(size_t column_ndx, size_t row_ndx, time_t value) +inline void TableView::set_date(size_t column_ndx, size_t row_ndx, Date value) { TIGHTDB_ASSERT_INDEX_AND_TYPE(column_ndx, row_ndx, type_Date); @@ -722,7 +723,7 @@ template inline void TableView::set_enum(size_t column_ndx, size_t row_ m_table->set_int(column_ndx, real_ndx, value); } -inline void TableView::set_string(size_t column_ndx, size_t row_ndx, const char* value) +inline void TableView::set_string(size_t column_ndx, size_t row_ndx, StringData value) { TIGHTDB_ASSERT_INDEX_AND_TYPE(column_ndx, row_ndx, type_String); @@ -730,12 +731,12 @@ inline void TableView::set_string(size_t column_ndx, size_t row_ndx, const char* m_table->set_string(column_ndx, real_ndx, value); } -inline void TableView::set_binary(size_t column_ndx, size_t row_ndx, const char* value, size_t len) +inline void TableView::set_binary(size_t column_ndx, size_t row_ndx, BinaryData value) { TIGHTDB_ASSERT_INDEX_AND_TYPE(column_ndx, row_ndx, type_Binary); const size_t real_ndx = size_t(m_refs.Get(row_ndx)); - m_table->set_binary(column_ndx, real_ndx, value, len); + m_table->set_binary(column_ndx, real_ndx, value); } inline void TableView::set_mixed(size_t column_ndx, size_t row_ndx, Mixed value) diff --git a/src/tightdb/unique_ptr.hpp b/src/tightdb/unique_ptr.hpp index bccafdf49ff..5425808037d 100644 --- a/src/tightdb/unique_ptr.hpp +++ b/src/tightdb/unique_ptr.hpp @@ -19,7 +19,7 @@ template class DefaultDelete { /// std::unique_ptr (as it exists in C++11). It reproduces /// only a small subset of the features of /// std::unique_ptr. In particular, it neither provides copy -/// not move semantics. +/// nor move semantics. template > class UniquePtr { public: typedef T* pointer; @@ -50,9 +50,39 @@ template > class UniquePtr { bool operator!=(const UniquePtr&); // Hide T* m_ptr; + + friend class UniquePtr; +}; + + +// Specialization for arrays +template class DefaultDelete { +public: + void operator()(T* p) const { delete[] p; } +}; + +// Specialization for arrays +template class UniquePtr: private UniquePtr { +public: + typedef T* pointer; + typedef T element_type; + typedef D deleter_type; + + explicit UniquePtr(T* = 0) TIGHTDB_NOEXCEPT; + + T& operator[](std::size_t) const TIGHTDB_NOEXCEPT; + + void swap(UniquePtr&) TIGHTDB_NOEXCEPT; + + using UniquePtr::get; + using UniquePtr::operator*; + using UniquePtr::reset; + using UniquePtr::release; + using UniquePtr::operator typename UniquePtr::unspecified_bool_type; }; + template void swap(UniquePtr& p, UniquePtr& q) TIGHTDB_NOEXCEPT; @@ -62,6 +92,9 @@ template void swap(UniquePtr& p, UniquePtr& q) TIGHT template inline UniquePtr::UniquePtr(T* p) TIGHTDB_NOEXCEPT: m_ptr(p) {} +template inline UniquePtr::UniquePtr(T* p) TIGHTDB_NOEXCEPT: + UniquePtr(p) {} + template inline UniquePtr::~UniquePtr() { D()(m_ptr); @@ -77,6 +110,12 @@ template inline T& UniquePtr::operator*() const TIGHTDB_N return *m_ptr; } +template +inline T& UniquePtr::operator[](std::size_t i) const TIGHTDB_NOEXCEPT +{ + return (&**this)[i]; +} + template inline T* UniquePtr::operator->() const TIGHTDB_NOEXCEPT { return m_ptr; @@ -87,6 +126,11 @@ template inline void UniquePtr::swap(UniquePtr& p) TIGHTD using std::swap; swap(m_ptr, p.m_ptr); } +template inline void UniquePtr::swap(UniquePtr& p) TIGHTDB_NOEXCEPT +{ + UniquePtr::swap(p); +} + template inline void UniquePtr::reset(T* p) { UniquePtr(p).swap(*this); diff --git a/src/tightdb/utf8.cpp b/src/tightdb/utf8.cpp index 534881d9593..15c9adc9242 100644 --- a/src/tightdb/utf8.cpp +++ b/src/tightdb/utf8.cpp @@ -1,177 +1,256 @@ #include +#include + #ifdef _WIN32 #include #else #include #endif +#include #include -namespace tightdb { - -// Return size in bytes of one utf8 character -size_t sequence_length(const char *lead) -{ - unsigned char lead2 = *lead; - if (lead2 < 0x80) - return 1; - else if ((lead2 >> 5) == 0x6) - return 2; - else if ((lead2 >> 4) == 0xe) - return 3; - else if ((lead2 >> 3) == 0x1e) - return 4; - else - return 0; -} +using namespace std; +namespace { -// assumes both chars have same lengths. Assumes both chars are in 0-terminated strings -size_t comparechars(const char* c1, const char* c2) +#ifdef _WIN32 +// Returns the number of bytes in a UTF-8 sequence whose leading byte +// is as specified. +inline int sequence_length(char lead) { - size_t p = 0; - do { - if (c1[p] != c2[p]) - return 0; - p++; - } while ((c1[p] & 0x80) == 0x80); - - return p; + int lead2 = char_traits::to_int_type(lead); + if ((lead2 & 0x80) == 0) return 1; + if ((lead2 & 0x40) == 0) return 0; // Error + if ((lead2 & 0x20) == 0) return 2; + if ((lead2 & 0x10) == 0) return 3; + if ((lead2 & 0x08) == 0) return 4; + if ((lead2 & 0x04) == 0) return 5; + if ((lead2 & 0x02) == 0) return 6; + return 0; // Error } +#endif -// If constant == source, return 1. -// Else, if constant is a prefix of source, return 0 -// Else return -1 -size_t case_prefix(const char* constant_upper, const char* constant_lower, const char* source) +// Check if the next UTF-8 sequence in [begin, end) is identical to +// the one beginning at begin2. If it is, 'begin' is advanced +// accordingly. +inline bool equal_sequence(const char*& begin, const char* end, const char* begin2) { - size_t matchlen = 0; - do { - size_t m = comparechars(&constant_lower[matchlen], &source[matchlen]); - if (m == 0) - m = comparechars(&constant_upper[matchlen], &source[matchlen]); - if (m != 0) - matchlen += m; - else - return (size_t)-1; - } - while (constant_lower[matchlen] != 0 && source[matchlen] != 0); + if (begin[0] != begin2[0]) return false; - if (constant_lower[matchlen] == 0 && source[matchlen] != 0) - return 0; - else if (constant_lower[matchlen] == 0 && source[matchlen] == 0) - return 1; + size_t i = 1; + if (int(char_traits::to_int_type(begin[0])) & 0x80) { + // All following bytes matching '10xxxxxx' will be considered + // as part of this character. + while (begin + i != end) { + if ((int(char_traits::to_int_type(begin[i])) & (0x80 + 0x40)) != 0x80) break; + if (begin[i] != begin2[i]) return false; + ++i; + } + } - return (size_t)-1; + begin += i; + return true; } -// If constant == source, return true. NOTE: This function first performs a case insensitive *byte* -// compare instead of one whole UTF-8 character at a time. This is very fast, but enough to guarantee -// that the strings are identical, so we need a slower character compare later (we use case_prefix() -// for this). -bool case_cmp(const char* constant_upper, const char* constant_lower, const char *source) +} // anonymous namespace + + +namespace tightdb { + + + +// Here is a version for Windows that may be closer to what is ultimately needed. +/* +bool case_map(const char* begin, const char* end, StringBuffer& dest, bool upper) { - size_t matchlen = 0; - do { - if (constant_lower[matchlen] == source[matchlen] || constant_upper[matchlen] == source[matchlen]) - matchlen++; - else + const int wide_buffer_size = 32; + wchar_t wide_buffer[wide_buffer_size]; + + dest.resize(end-begin); + size_t dest_offset = 0; + + for (;;) { + int num_out; + + // Decode + { + size_t num_in = end - begin; + if (size_t(32) <= num_in) { + num_out = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, begin, 32, wide_buffer, wide_buffer_size); + if (num_out != 0) { + begin += 32; + goto convert; + } + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return false; + } + if (num_in == 0) break; + int n = num_in < size_t(8) ? int(num_in) : 8; + num_out = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, begin, n, wide_buffer, wide_buffer_size); + if (num_out != 0) { + begin += n; + goto convert; + } return false; - } - while (constant_lower[matchlen] != 0 && source[matchlen] != 0); - if (constant_lower[matchlen] != 0 || source[matchlen] != 0) - return false; - - if (case_prefix(constant_upper, constant_lower, source) != (size_t)-1) - return true; - else - return false; -} + } -// Test if constant is a substring of source -bool case_strstr(const char *constant_upper, const char *constant_lower, const char *source) { - size_t source_pos = 0; - do { - if (case_prefix(constant_upper, constant_lower, source + source_pos) != size_t(-1)) - return true; - source_pos++; - } while (source[source_pos] != 0); + convert: + if (upper) { + for (int i=0; i::max(), free)) free = numeric_limits::max(); + int n = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, wide_buffer, num_out, + dest.data() + dest_offset, int(free), 0, 0); + if (i != 0) { + dest_offset += n; + continue; + } + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return false; + size_t dest_size = dest.size(); + if (int_multiply_with_overflow_detect(dest_size, 2)) { + if (dest_size == numeric_limits::max()) return false; + dest_size = numeric_limits::max(); + } + dest.resize(dest_size); + goto encode; + } + } - return false; + dest.resize(dest_offset); + return true; } +*/ + -// Converts a single utf8 character to upper or lower case. Operating system specific function. -bool utf8case_single(const char* source, char* destination, int upper) +// Converts UTF-8 source into upper or lower case. This function +// preserves the byte length of each UTF-8 character in following way: +// If an output character differs in size, it is simply substituded by +// the original character. This may of course give wrong search +// results in very special cases. Todo. +bool case_map(StringData source, char* target, bool upper) { #ifdef _WIN32 - wchar_t tmp[2]; + const char* begin = source.data(); + const char* end = begin + source.size(); + while (begin != end) { + int n = sequence_length(*begin); + if (n == 0 || end-begin < n) return false; + + wchar_t tmp[2]; // FIXME: Why no room for UTF-16 surrogate? + + int n2 = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, begin, n, tmp, 1); + if (n2 == 0) return false; - int i = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)source, (int)sequence_length(source), &tmp[0], 1); - if (i == 0) - return false; + TIGHTDB_ASSERT(0 < n2 && n2 <= 1); + tmp[n2] = 0; - tmp[1] = 0; + // Note: If tmp[0] == 0, it is because the string contains a + // null-chacarcter, which is perfectly fine. - if (upper) - CharUpperW((LPWSTR)&tmp); - else - CharLowerW((LPWSTR)&tmp); + if (upper) + CharUpperW(static_cast(tmp)); + else + CharLowerW(static_cast(tmp)); + + // FIXME: The intention is to use flag 'WC_ERR_INVALID_CHARS' + // to catch invalid UTF-8. Even though the documentation says + // unambigously that it is supposed to work, it doesn't. When + // the flag is specified, the function fails with error + // ERROR_INVALID_FLAGS. + DWORD flags = 0; + int n3 = WideCharToMultiByte(CP_UTF8, flags, tmp, 1, target, end-begin, 0, 0); + if (n3 == 0 && GetLastError() != ERROR_INSUFFICIENT_BUFFER) return false; + if (n3 != n) { + copy(begin, begin+n, target); // Cannot handle different size, copy source + } - i = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)&tmp, 1, (LPSTR)destination, 6, 0, 0); - if (i == 0) - return false; + begin += n; + target += n; + } return true; #else + // FIXME: Implement this! Note that this is trivial in C++11 due + // to its built-in support for UTF-8. In C++03 it is trivial when + // __STDC_ISO_10646__ is defined. Also consider using ICU. Maybe + // GNU has something to offer too. + + // For now we handle just the ASCII subset + typedef char_traits traits; + if (upper) { + size_t n = source.size(); + for (size_t i=0; i(upper); return true; #endif } -// Converts utf8 source into upper or lower case. This function preserves the byte length of each utf8 -// character in following way: If an output character differs in size, it is simply substituded by the -// original character. This may of course give wrong search results in very special cases. Todo. -bool utf8case(const char* source, char* destination, int upper) -{ - while (*source != 0) { - if (sequence_length(source) == 0) - return false; - bool b = utf8case_single(source, destination, upper); - if (!b) { - return false; - } - - if (sequence_length(destination) != sequence_length(source)) { - memcpy(destination, source, sequence_length(source)); - destination += sequence_length(source); - } - else - destination += sequence_length(destination); - - source += sequence_length(source); +// If needle == haystack, return true. NOTE: This function first +// performs a case insensitive *byte* compare instead of one whole +// UTF-8 character at a time. This is very fast, but not enough to +// guarantee that the strings are identical, so we need to finish off +// with a slower but rigorous comparison. The signature is similar in +// spirit to std::equal(). +bool equal_case_fold(StringData haystack, const char* needle_upper, const char* needle_lower) +{ + for (size_t i=0; i!=haystack.size(); ++i) { + char c = haystack[i]; + if (needle_lower[i] != c && needle_upper[i] != c) return false; } - *destination = 0; + const char* begin = haystack.data(); + const char* end = begin + haystack.size(); + const char* i = begin; + while (i != end) { + if (!equal_sequence(i, end, needle_lower + (i - begin)) && + !equal_sequence(i, end, needle_upper + (i - begin))) return false; + } return true; } + +// Test if needle is a substring of haystack. The signature is similar +// in spirit to std::search(). +size_t search_case_fold(StringData haystack, const char* needle_upper, const char* needle_lower, + size_t needle_size) +{ + // FIXME: This solution is terribly inefficient. Consider deploying the Boyer-Moore algorithm. + size_t i = 0; + while (needle_size <= haystack.size() - i) { + if (equal_case_fold(haystack.substr(i, needle_size), needle_upper, needle_lower)) { + return i; + } + ++i; + } + return haystack.size(); // Not found } + + +} // namespace tightdb diff --git a/src/tightdb/utf8.hpp b/src/tightdb/utf8.hpp index 71530272983..520226d81fa 100644 --- a/src/tightdb/utf8.hpp +++ b/src/tightdb/utf8.hpp @@ -20,16 +20,408 @@ #ifndef TIGHTDB_UTF8_HPP #define TIGHTDB_UTF8_HPP +#include +#include + +#include +#include + namespace tightdb { -bool case_cmp(const char* constant_upper, const char* constant_lower, const char* source); -bool case_strstr(const char* constant_upper, const char* constant_lower, const char* source); -bool utf8case(const char* source, char* destination, int upper); -size_t case_prefix(const char* constant_upper, const char* constant_lower, const char* source); -bool utf8case_single(const char** source, char** destination, int upper); -size_t sequence_length(const char* lead); -size_t comparechars(const char* c1, const char* c2); -bool utf8case_single(const char* source, char* destination, int upper); +// FIXME: The current approach to case insensitive comparison requires +// that case mappings can be done in a way that does not change he +// number of bytes used to encode the individual Unicode +// character. This is not generally the case, so, as far as I can see, +// this approach has no future. +// +// FIXME: The current approach to case insensitive comparison relies +// on checking each "haystack" character against the corresponding +// character in both a lower cased and an upper cased version of the +// "needle". While this leads to efficient comparison, it ignores the +// fact that "case folding" is the only correct approach to case +// insensitive comparison in a locale agnostic Unicode +// environment. +// +// See +// http://www.w3.org/International/wiki/Case_folding +// http://userguide.icu-project.org/transforms/casemappings#TOC-Case-Folding. +// +// The ideal API would probably be something like this: +// +// case_fold: utf_8 -> case_folded +// equal_case_fold: (needle_case_folded, single_haystack_entry_utf_8) -> found +// search_case_fold: (needle_case_folded, huge_haystack_string_utf_8) -> found_at_position +// +// The case folded form would probably be using UTF-32 or UTF-16. + + +/// If successfull, writes a string to \a target of the same size as +/// \a source, and returns true. Returns false if invalid UTF-8 +/// encoding was encountered. +bool case_map(StringData source, char* target, bool upper); + +/// Assumes that the sizes of \a needle_upper and \a needle_lower are +/// identical to the size of \a haystack. Returns false if the needle +/// is different from the haystack. +bool equal_case_fold(StringData haystack, const char* needle_upper, const char* needle_lower); + +/// Assumes that the sizes of \a needle_upper and \a needle_lower are +/// both equal to \a needle_size. Returns haystack.size() if the +/// needle was not found. +std::size_t search_case_fold(StringData haystack, const char* needle_upper, + const char* needle_lower, std::size_t needle_size); + + + +/// Transcode between UTF-8 and UTF-16. +/// +/// \tparam Char16 Must be an integral type with at least 16 bits. +/// +/// \tparam Traits16 Must define to_int_type() and to_char_type() for +/// \a Char16. +template > struct Utf8x16 { + /// Transcode as much as possible of the specified UTF-8 input, to + /// UTF-16. Returns true if all input characters were transcoded, + /// or transcoding stopped because the next character did not fit + /// into the output buffer. Returns false if transcoding stopped + /// due to invalid input. It is not specified whether this + /// function returns true or false if invalid input occurs at the + /// same time that the output buffer runs full. In any case, upon + /// return, \a in_begin and \a out_begin are advanced to the + /// position where the transcoding stopped. + /// + /// Throws only if Traits16::to_char_type() throws. + static bool to_utf16(const char*& in_begin, const char* in_end, + Char16*& out_begin, Char16* out_end); + + /// Same as to_utf16(), but in reverse. + /// + /// Throws only if Traits16::to_int_type() throws. + static bool to_utf8(const Char16*& in_begin, const Char16* in_end, + char*& out_begin, char* out_end); + + /// Summarize the number of UTF-16 elements needed to hold the + /// result of transcoding the specified UTF-8 string. Upon return, + /// if \a in_begin != \a in_end, then the summation stopped due to + /// invalid UTF-8 input. The returned size then reflects the + /// number of UTF-16 elements needed to hold the result of + /// transcoding the part of the input that was examined. This + /// function will only detect a few UTF-8 validity issues, and can + /// therefore not be used for general UTF-8 validation. + static std::size_t find_utf16_buf_size(const char*& in_begin, const char* in_end); + + /// Summarize the number of UTF-8 bytes needed to hold the result + /// of transcoding the specified UTF-16 string. Upon return, if \a + /// in_begin != \a in_end, then the summation stopped due to + /// invalid UTF-16 input, or to prevent the returned \c size_t + /// value from overflowing. The returned size then reflects the + /// number of UTF-8 bytes needed to hold the result of transcoding + /// the part of the input that was examined. This function will + /// only detect a few UTF-16 validity issues, and can therefore + /// not be used for general UTF-16 validation. + static std::size_t find_utf8_buf_size(const Char16*& in_begin, const Char16* in_end); +}; + + + + + +// ------------------------------------------------------------------- + +// Implementation: + +// Adapted from reference implementation. +// http://www.unicode.org/resources/utf8.html +// http://www.bsdua.org/files/unicode.tar.gz +template +inline bool Utf8x16::to_utf16(const char*& in_begin, const char* in_end, + Char16*& out_begin, Char16* out_end) +{ + using namespace std; + typedef char_traits Traits8; + bool invalid = false; + const char* in = in_begin; + Char16* out = out_begin; + while (in != in_end) { + if (TIGHTDB_UNLIKELY(out == out_end)) { + break; // Need space in output buffer + } + uint_fast16_t v1 = Traits8::to_int_type(in[0]); + if (TIGHTDB_LIKELY(v1 < 0x80)) { // One byte + // UTF-8 layout: 0xxxxxxx + *out++ = Traits16::to_char_type(v1); + in += 1; + continue; + } + if (TIGHTDB_UNLIKELY(v1 < 0xC0)) { + invalid = true; + break; // Invalid first byte of UTF-8 sequence + } + if (TIGHTDB_LIKELY(v1 < 0xE0)) { // Two bytes + if (TIGHTDB_UNLIKELY(in_end - in < 2)) { + invalid = true; + break; // Incomplete UTF-8 sequence + } + uint_fast16_t v2 = Traits8::to_int_type(in[1]); + // UTF-8 layout: 110xxxxx 10xxxxxx + if (TIGHTDB_UNLIKELY((v2 & 0xC0) != 0x80)) { + invalid = true; + break; // Invalid continuation byte + } + uint_fast16_t v = + ((v1 & 0x1F) << 6) | + ((v2 & 0x3F) << 0); + if (TIGHTDB_UNLIKELY(v < 0x80)) { + invalid = true; + break; // Overlong encoding is invalid + } + *out++ = Traits16::to_char_type(v); + in += 2; + continue; + } + if (TIGHTDB_LIKELY(v1 < 0xF0)) { // Three bytes + if (TIGHTDB_UNLIKELY(in_end - in < 3)) { + invalid = true; + break; // Incomplete UTF-8 sequence + } + uint_fast16_t v2 = Traits8::to_int_type(in[1]); + uint_fast16_t v3 = Traits8::to_int_type(in[2]); + // UTF-8 layout: 1110xxxx 10xxxxxx 10xxxxxx + if (TIGHTDB_UNLIKELY((v2 & 0xC0) != 0x80 || (v3 & 0xC0) != 0x80)) { + invalid = true; + break; // Invalid continuation byte + } + uint_fast16_t v = + ((v1 & 0x0F) << 12) | + ((v2 & 0x3F) << 6) | + ((v3 & 0x3F) << 0); + if (TIGHTDB_UNLIKELY(v < 0x800)) { + invalid = true; + break; // Overlong encoding is invalid + } + if (TIGHTDB_UNLIKELY(0xD800 <= v && v < 0xE000)) { + invalid = true; + break; // Illegal code point range (reserved for UTF-16 surrogate pairs) + } + *out++ = Traits16::to_char_type(v); + in += 3; + continue; + } + if (TIGHTDB_UNLIKELY(out + 1 == out_end)) { + break; // Need space in output buffer for surrogate pair + } + if (TIGHTDB_LIKELY(v1 < 0xF8)) { // Four bytes + if (TIGHTDB_UNLIKELY(in_end - in < 4)) { + invalid = true; + break; // Incomplete UTF-8 sequence + } + uint_fast32_t w1 = v1; // 16 bit -> 32 bit + uint_fast32_t v2 = Traits8::to_int_type(in[1]); // 32 bit intended + uint_fast16_t v3 = Traits8::to_int_type(in[2]); // 16 bit intended + uint_fast16_t v4 = Traits8::to_int_type(in[3]); // 16 bit intended + // UTF-8 layout: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + if (TIGHTDB_UNLIKELY((v2 & 0xC0) != 0x80 || (v3 & 0xC0) != 0x80 || + (v4 & 0xC0) != 0x80)) { + invalid = true; + break; // Invalid continuation byte + } + uint_fast32_t v = + ((w1 & 0x07) << 18) | // Parenthesis is 32 bit partial result + ((v2 & 0x3F) << 12) | // Parenthesis is 32 bit partial result + ((v3 & 0x3F) << 6) | // Parenthesis is 16 bit partial result + ((v4 & 0x3F) << 0); // Parenthesis is 16 bit partial result + if (TIGHTDB_UNLIKELY(v < 0x10000)) { + invalid = true; + break; // Overlong encoding is invalid + } + if (TIGHTDB_UNLIKELY(0x110000 <= v)) { + invalid = true; + break; // Code point too big for UTF-16 + } + v -= 0x10000l; + *out++ = Traits16::to_char_type(0xD800 + (v / 0x400)); + *out++ = Traits16::to_char_type(0xDC00 + (v % 0x400)); + in += 4; + continue; + } + // Invalid first byte of UTF-8 sequence, or code point too big for UTF-16 + invalid = true; + break; + } + + in_begin = in; + out_begin = out; + return !invalid; +} + + +template +inline std::size_t Utf8x16::find_utf16_buf_size(const char*& in_begin, + const char* in_end) +{ + using namespace std; + typedef char_traits Traits8; + size_t num_out = 0; + const char* in = in_begin; + while (in != in_end) { + uint_fast16_t v1 = Traits8::to_int_type(in[0]); + if (TIGHTDB_LIKELY(v1 < 0x80)) { // One byte + num_out += 1; + in += 1; + continue; + } + if (TIGHTDB_UNLIKELY(v1 < 0xC0)) { + break; // Invalid first byte of UTF-8 sequence + } + if (TIGHTDB_LIKELY(v1 < 0xE0)) { // Two bytes + if (TIGHTDB_UNLIKELY(in_end - in < 2)) { + break; // Incomplete UTF-8 sequence + } + num_out += 1; + in += 2; + continue; + } + if (TIGHTDB_LIKELY(v1 < 0xF0)) { // Three bytes + if (TIGHTDB_UNLIKELY(in_end - in < 3)) { + break; // Incomplete UTF-8 sequence + } + num_out += 1; + in += 3; + continue; + } + if (TIGHTDB_LIKELY(v1 < 0xF8)) { // Four bytes + if (TIGHTDB_UNLIKELY(in_end - in < 4)) { + break; // Incomplete UTF-8 sequence + } + num_out += 2; // Surrogate pair + in += 4; + continue; + } + // Invalid first byte of UTF-8 sequence, or code point too big for UTF-16 + break; + } + + in_begin = in; + return num_out; +} + + + +// Adapted from reference implementation. +// http://www.unicode.org/resources/utf8.html +// http://www.bsdua.org/files/unicode.tar.gz +template +inline bool Utf8x16::to_utf8(const Char16*& in_begin, const Char16* in_end, + char*& out_begin, char* out_end) +{ + using namespace std; + typedef char_traits Traits8; + bool invalid = false; + const Char16* in = in_begin; + char* out = out_begin; + while (in != in_end) { + uint_fast16_t v1 = Traits16::to_int_type(in[0]); + if (TIGHTDB_LIKELY(v1 < 0x80)) { + if (TIGHTDB_UNLIKELY(out == out_end)) { + break; // Not enough output buffer space + } + // UTF-8 layout: 0xxxxxxx + *out++ = Traits8::to_char_type(v1); + in += 1; + continue; + } + if (TIGHTDB_LIKELY(v1 < 0x800)) { + if (TIGHTDB_UNLIKELY(out_end - out < 2)) { + break; // Not enough output buffer space + } + // UTF-8 layout: 110xxxxx 10xxxxxx + *out++ = Traits8::to_char_type(0xC0 + v1 / 0x40); + *out++ = Traits8::to_char_type(0x80 + v1 % 0x40); + in += 1; + continue; + } + if (TIGHTDB_LIKELY(v1 < 0xD800 || 0xE000 <= v1)) { + if (TIGHTDB_UNLIKELY(out_end - out < 3)) { + break; // Not enough output buffer space + } + // UTF-8 layout: 1110xxxx 10xxxxxx 10xxxxxx + *out++ = Traits8::to_char_type(0xE0 + v1 / 0x1000); + *out++ = Traits8::to_char_type(0x80 + v1 / 0x40 % 0x40); + *out++ = Traits8::to_char_type(0x80 + v1 % 0x40); + in += 1; + continue; + } + + // Surrogate pair + if (TIGHTDB_UNLIKELY(out_end - out < 4)) { + break; // Not enough output buffer space + } + if (TIGHTDB_UNLIKELY(0xDC00 <= v1)) { + invalid = true; + break; // Invalid first half of surrogate pair + } + if (TIGHTDB_UNLIKELY(in + 1 == in_end)) { + invalid = true; + break; // Incomplete surrogate pair + } + uint_fast16_t v2 = Traits16::to_int_type(in[1]); + if (TIGHTDB_UNLIKELY(v2 < 0xDC00 || 0xE000 <= v2)) { + invalid = true; + break; // Invalid second half of surrogate pair + } + uint_fast32_t v = 0x10000l + (uint_fast32_t(v1 - 0xD800) * 0x400 + (v2 - 0xDC00)); + // UTF-8 layout: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + *out++ = Traits8::to_char_type(0xF0 + v / 0x40000); + *out++ = Traits8::to_char_type(0x80 + v / 0x1000 % 0x40); + *out++ = Traits8::to_char_type(0x80 + v / 0x40 % 0x40); + *out++ = Traits8::to_char_type(0x80 + v % 0x40); + in += 2; + } + + in_begin = in; + out_begin = out; + return !invalid; +} + + +template +inline std::size_t Utf8x16::find_utf8_buf_size(const Char16*& in_begin, + const Char16* in_end) +{ + using namespace std; + size_t num_out = 0; + const Char16* in = in_begin; + while (in != in_end) { + uint_fast16_t v = Traits16::to_int_type(in[0]); + if (TIGHTDB_LIKELY(v < 0x80)) { + if (TIGHTDB_UNLIKELY(int_add_with_overflow_detect(num_out, 1))) + break; // Avoid overflow + in += 1; + } + else if (TIGHTDB_LIKELY(v < 0x800)) { + if (TIGHTDB_UNLIKELY(int_add_with_overflow_detect(num_out, 2))) + break; // Avoid overflow + in += 1; + } + else if (TIGHTDB_LIKELY(v < 0xD800 || 0xE000 <= v)) { + if (TIGHTDB_UNLIKELY(int_add_with_overflow_detect(num_out, 3))) + break; // Avoid overflow + in += 1; + } + else { + if (TIGHTDB_UNLIKELY(in + 1 == in_end)) { + break; // Incomplete surrogate pair + } + if (TIGHTDB_UNLIKELY(int_add_with_overflow_detect(num_out, 4))) + break; // Avoid overflow + in += 2; + } + } + + in_begin = in; + return num_out; +} + } // namespace tightdb diff --git a/src/tightdb/utilities.hpp b/src/tightdb/utilities.hpp index 96b90c984a6..b781b2a356d 100644 --- a/src/tightdb/utilities.hpp +++ b/src/tightdb/utilities.hpp @@ -159,6 +159,7 @@ ReturnType TypePunning( OriginalType variable ) OriginalType in; ReturnType out; }; + out = ReturnType(); // Clear all bits in case ReturnType is larger than OriginalType in = variable; return out; } diff --git a/test/TestQuery.cpp b/test/TestQuery.cpp index 6650e63412b..ab64bf59de1 100644 --- a/test/TestQuery.cpp +++ b/test/TestQuery.cpp @@ -17,6 +17,10 @@ TIGHTDB_TABLE_2(TupleTableType, first, Int, second, String) +TIGHTDB_TABLE_2(TupleTableTypeBin, + first, Int, + second, Binary) + TIGHTDB_TABLE_2(BoolTupleTable, first, Int, second, Bool) @@ -53,7 +57,6 @@ TIGHTDB_TABLE_5(GATable, build, String, event_1, Int, event_2, Int) - } // anonymous namespace @@ -374,7 +377,7 @@ TEST(TestQueryStrIndexed_enum) { TupleTableType ttt; - for(size_t t = 0; t < 10; t++) { + for (size_t t = 0; t < 10; t++) { ttt.add(1, "a"); ttt.add(4, "b"); ttt.add(7, "c"); @@ -813,7 +816,7 @@ TEST(TestQuerySubtable) q1.subtable(2); q1.less(0, val50); q1.end_subtable(); - TableView t1 = q1.find_all(0, (size_t)-1); + TableView t1 = q1.find_all(0, size_t(-1)); CHECK_EQUAL(2, t1.size()); CHECK_EQUAL(1, t1.get_source_ndx(0)); CHECK_EQUAL(2, t1.get_source_ndx(1)); @@ -825,7 +828,7 @@ TEST(TestQuerySubtable) q2.Or(); q2.less(0, val20); q2.end_subtable(); - TableView t2 = q2.find_all(0, (size_t)-1); + TableView t2 = q2.find_all(0, size_t(-1)); CHECK_EQUAL(2, t2.size()); CHECK_EQUAL(0, t2.get_source_ndx(0)); CHECK_EQUAL(3, t2.get_source_ndx(1)); @@ -838,7 +841,7 @@ TEST(TestQuerySubtable) q3.less(0, val20); q3.end_subtable(); q3.less(0, val300); - TableView t3 = q3.find_all(0, (size_t)-1); + TableView t3 = q3.find_all(0, size_t(-1)); CHECK_EQUAL(1, t3.size()); CHECK_EQUAL(0, t3.get_source_ndx(0)); @@ -851,7 +854,7 @@ TEST(TestQuerySubtable) q4.Or(); q4.less(0, val20); q4.end_subtable(); - TableView t4 = q4.find_all(0, (size_t)-1); + TableView t4 = q4.find_all(0, size_t(-1)); @@ -1187,7 +1190,7 @@ TEST(TestQueryFindNext) CHECK_EQUAL(5, res1); CHECK_EQUAL(6, res2); - CHECK_EQUAL((size_t)-1, res3); // no more matches + CHECK_EQUAL(size_t(-1), res3); // no more matches } TEST(TestQueryFindAll1) @@ -1515,6 +1518,81 @@ TEST(TestQueryFindAll_Contains) CHECK_EQUAL(3, tv1.get_source_ndx(3)); } + +TEST(TestQuery_Binary) +{ + TupleTableTypeBin t; + + const char bin[64] = { + 6, 3, 9, 5, 9, 7, 6, 3, 2, 6, 0, 0, 5, 4, 2, 4, + 5, 7, 9, 5, 7, 1, 1, 2, 0, 8, 3, 8, 0, 9, 6, 8, + 4, 7, 3, 4, 9, 5, 2, 3, 6, 2, 7, 4, 0, 3, 7, 6, + 2, 3, 5, 9, 3, 1, 2, 1, 0, 5, 5, 2, 9, 4, 5, 9 + }; + + const char bin_2[4] = { 6, 6, 6, 6 }; // Not occuring above + + t.add(0, BinaryData(bin + 0, 16)); + t.add(0, BinaryData(bin + 0, 32)); + t.add(0, BinaryData(bin + 0, 48)); + t.add(0, BinaryData(bin + 0, 64)); + t.add(0, BinaryData(bin + 16, 48)); + t.add(0, BinaryData(bin + 32, 32)); + t.add(0, BinaryData(bin + 48, 16)); + t.add(0, BinaryData(bin + 24, 16)); // The "odd ball" + t.add(0, BinaryData(bin + 0, 32)); // Repeat an entry + + CHECK_EQUAL(0, t.where().second.equal(BinaryData(bin + 16, 16)).count()); + CHECK_EQUAL(1, t.where().second.equal(BinaryData(bin + 0, 16)).count()); + CHECK_EQUAL(1, t.where().second.equal(BinaryData(bin + 48, 16)).count()); + CHECK_EQUAL(2, t.where().second.equal(BinaryData(bin + 0, 32)).count()); + + CHECK_EQUAL(9, t.where().second.not_equal(BinaryData(bin + 16, 16)).count()); + CHECK_EQUAL(8, t.where().second.not_equal(BinaryData(bin + 0, 16)).count()); + + CHECK_EQUAL(0, t.where().second.begins_with(BinaryData(bin + 8, 16)).count()); + CHECK_EQUAL(1, t.where().second.begins_with(BinaryData(bin + 16, 16)).count()); + CHECK_EQUAL(4, t.where().second.begins_with(BinaryData(bin + 0, 32)).count()); + CHECK_EQUAL(5, t.where().second.begins_with(BinaryData(bin + 0, 16)).count()); + CHECK_EQUAL(1, t.where().second.begins_with(BinaryData(bin + 48, 16)).count()); + CHECK_EQUAL(9, t.where().second.begins_with(BinaryData(bin + 0, 0)).count()); + + CHECK_EQUAL(0, t.where().second.ends_with(BinaryData(bin + 40, 16)).count()); + CHECK_EQUAL(1, t.where().second.ends_with(BinaryData(bin + 32, 16)).count()); + CHECK_EQUAL(3, t.where().second.ends_with(BinaryData(bin + 32, 32)).count()); + CHECK_EQUAL(4, t.where().second.ends_with(BinaryData(bin + 48, 16)).count()); + CHECK_EQUAL(1, t.where().second.ends_with(BinaryData(bin + 0, 16)).count()); + CHECK_EQUAL(9, t.where().second.ends_with(BinaryData(bin + 64, 0)).count()); + + CHECK_EQUAL(0, t.where().second.contains(BinaryData(bin_2)).count()); + CHECK_EQUAL(5, t.where().second.contains(BinaryData(bin + 0, 16)).count()); + CHECK_EQUAL(5, t.where().second.contains(BinaryData(bin + 16, 16)).count()); + CHECK_EQUAL(4, t.where().second.contains(BinaryData(bin + 24, 16)).count()); + CHECK_EQUAL(4, t.where().second.contains(BinaryData(bin + 32, 16)).count()); + CHECK_EQUAL(9, t.where().second.contains(BinaryData(bin + 0, 0)).count()); + + { + TupleTableTypeBin::View tv = t.where().second.equal(BinaryData(bin + 0, 32)).find_all(); + if (tv.size() == 2) { + CHECK_EQUAL(1, tv.get_source_ndx(0)); + CHECK_EQUAL(8, tv.get_source_ndx(1)); + } + else CHECK(false); + } + + { + TupleTableTypeBin::View tv = t.where().second.contains(BinaryData(bin + 24, 16)).find_all(); + if (tv.size() == 4) { + CHECK_EQUAL(2, tv.get_source_ndx(0)); + CHECK_EQUAL(3, tv.get_source_ndx(1)); + CHECK_EQUAL(4, tv.get_source_ndx(2)); + CHECK_EQUAL(7, tv.get_source_ndx(3)); + } + else CHECK(false); + } +} + + TEST(TestQueryEnums) { TupleTableType table; @@ -1738,12 +1816,14 @@ TEST(TestQuerySyntaxCheck) #ifdef TIGHTDB_DEBUG s = q6.Verify(); CHECK(s != ""); - #endif + TupleTableType::Query q7 = ttt.where().second.equal("\xa0", false); -#ifdef TIGHTDB_DEBUG +#ifdef _WIN32 +# ifdef TIGHTDB_DEBUG s = q7.Verify(); CHECK(s != ""); +# endif #endif } diff --git a/test/experiments/testcase.cpp b/test/experiments/testcase.cpp index 3fc3be65817..2df377bc233 100644 --- a/test/experiments/testcase.cpp +++ b/test/experiments/testcase.cpp @@ -4,6 +4,9 @@ #include #include #include +#include +#include +#include //#include @@ -25,9 +28,23 @@ inline bool check_equal(const char* a, const char* b) { return strcmp(a, b) == 0 namespace { +TIGHTDB_TABLE_2(TupleTableType, + first, Int, + second, String) + } // anonymous namespace int main() { + TupleTableType ttt; + + ttt.add(1, "BLAAbaergroed"); + ttt.add(1, "BLAAbaergroedandMORE"); + ttt.add(1, "BLAAbaergroed2"); + + TupleTableType::Query q1 = ttt.where().second.equal("blaabaerGROED", false); + TupleTableType::View tv1 = q1.find_all(); + CHECK_EQUAL(1, tv1.size()); + CHECK_EQUAL(0, tv1.get_source_ndx(0)); } diff --git a/test/large_tests/verified_integer.cpp b/test/large_tests/verified_integer.cpp index c0ffd732427..3f5ab9df239 100644 --- a/test/large_tests/verified_integer.cpp +++ b/test/large_tests/verified_integer.cpp @@ -16,13 +16,13 @@ using namespace tightdb; void VerifiedInteger::VerifyNeighbours(size_t ndx) { if (v.size() > ndx) - TIGHTDB_ASSERT(v[ndx] == u.Get(ndx)); + TIGHTDB_ASSERT(v[ndx] == u.get(ndx)); if (ndx > 0) - TIGHTDB_ASSERT(v[ndx - 1] == u.Get(ndx - 1)); + TIGHTDB_ASSERT(v[ndx - 1] == u.get(ndx - 1)); if (v.size() > ndx + 1) - TIGHTDB_ASSERT(v[ndx + 1] == u.Get(ndx + 1)); + TIGHTDB_ASSERT(v[ndx + 1] == u.get(ndx + 1)); } void VerifiedInteger::add(int64_t value) @@ -37,7 +37,7 @@ void VerifiedInteger::add(int64_t value) void VerifiedInteger::Insert(size_t ndx, int64_t value) { v.insert(v.begin() + ndx, value); - u.Insert(ndx, value); + u.insert(ndx, value); TIGHTDB_ASSERT(v.size() == u.Size()); VerifyNeighbours(ndx); TIGHTDB_ASSERT(ConditionalVerify()); @@ -45,7 +45,7 @@ void VerifiedInteger::Insert(size_t ndx, int64_t value) int64_t VerifiedInteger::Get(size_t ndx) { - TIGHTDB_ASSERT(v[ndx] == u.Get(ndx)); + TIGHTDB_ASSERT(v[ndx] == u.get(ndx)); return v[ndx]; } @@ -105,7 +105,7 @@ int64_t VerifiedInteger::minimum(size_t start, size_t end) void VerifiedInteger::Set(size_t ndx, int64_t value) { v[ndx] = value; - u.Set(ndx, value); + u.set(ndx, value); VerifyNeighbours(ndx); TIGHTDB_ASSERT(ConditionalVerify()); } @@ -113,7 +113,7 @@ void VerifiedInteger::Set(size_t ndx, int64_t value) void VerifiedInteger::Delete(size_t ndx) { v.erase(v.begin() + ndx); - u.Delete(ndx); + u.erase(ndx); TIGHTDB_ASSERT(v.size() == u.Size()); VerifyNeighbours(ndx); TIGHTDB_ASSERT(ConditionalVerify()); @@ -164,7 +164,7 @@ void VerifiedInteger::find_all(Array &c, int64_t value, size_t start, size_t end if (c.size() != result.size()) TIGHTDB_ASSERT(false); for (size_t t = 0; t < result.size(); ++t) { - if (result[t] != (size_t)c.Get(t)) + if (result[t] != size_t(c.Get(t))) TIGHTDB_ASSERT(false); } @@ -178,8 +178,8 @@ bool VerifiedInteger::Verify(void) return false; for (size_t t = 0; t < v.size(); ++t) { - TIGHTDB_ASSERT(v[t] == u.Get(t)); - if (v[t] != u.Get(t)) + TIGHTDB_ASSERT(v[t] == u.get(t)); + if (v[t] != u.get(t)) return false; } return true; @@ -188,7 +188,7 @@ bool VerifiedInteger::Verify(void) // makes it run amortized the same time complexity as original, even though the row count grows bool VerifiedInteger::ConditionalVerify(void) { - if (((uint64_t)rand() * (uint64_t)rand()) % (v.size() / 10 + 1) == 0) { + if ((uint64_t(rand()) * uint64_t(rand())) % (v.size() / 10 + 1) == 0) { return Verify(); } else { diff --git a/test/large_tests/verified_string.cpp b/test/large_tests/verified_string.cpp index 23c8ec67408..8c5b6d19b77 100644 --- a/test/large_tests/verified_string.cpp +++ b/test/large_tests/verified_string.cpp @@ -14,13 +14,13 @@ using namespace tightdb; void VerifiedString::VerifyNeighbours(size_t ndx) { if (v.size() > ndx) - TIGHTDB_ASSERT(v[ndx] == u.Get(ndx)); + TIGHTDB_ASSERT(v[ndx] == u.get(ndx)); if (ndx > 0) - TIGHTDB_ASSERT(v[ndx - 1] == u.Get(ndx - 1)); + TIGHTDB_ASSERT(v[ndx - 1] == u.get(ndx - 1)); if (v.size() > ndx + 1) - TIGHTDB_ASSERT(v[ndx + 1] == u.Get(ndx + 1)); + TIGHTDB_ASSERT(v[ndx + 1] == u.get(ndx + 1)); } void VerifiedString::add(const char * value) @@ -36,7 +36,7 @@ void VerifiedString::add(const char * value) void VerifiedString::Insert(size_t ndx, const char * value) { v.insert(v.begin() + ndx, value); - u.Insert(ndx, value); + u.insert(ndx, value); TIGHTDB_ASSERT(v.size() == u.Size()); VerifyNeighbours(ndx); TIGHTDB_ASSERT(ConditionalVerify()); @@ -45,14 +45,14 @@ void VerifiedString::Insert(size_t ndx, const char * value) const char *VerifiedString::Get(size_t ndx) { - TIGHTDB_ASSERT(v[ndx] == u.Get(ndx)); + TIGHTDB_ASSERT(v[ndx] == u.get(ndx)); return v[ndx].c_str(); } void VerifiedString::Set(size_t ndx, const char *value) { v[ndx] = value; - u.Set(ndx, value); + u.set(ndx, value); VerifyNeighbours(ndx); TIGHTDB_ASSERT(ConditionalVerify()); } @@ -60,7 +60,7 @@ void VerifiedString::Set(size_t ndx, const char *value) void VerifiedString::Delete(size_t ndx) { v.erase(v.begin() + ndx); - u.Delete(ndx); + u.erase(ndx); TIGHTDB_ASSERT(v.size() == u.Size()); VerifyNeighbours(ndx); TIGHTDB_ASSERT(ConditionalVerify()); @@ -79,12 +79,12 @@ size_t VerifiedString::find_first(const char *value) std::vector::iterator it = std::find(v.begin(), v.end(), value); size_t ndx = std::distance(v.begin(), it); size_t index2 = u.find_first(value); - (void)index2; + static_cast(index2); TIGHTDB_ASSERT(ndx == index2 || (it == v.end() && index2 == size_t(-1))); return ndx; } -size_t VerifiedString::Size(void) +size_t VerifiedString::Size() { TIGHTDB_ASSERT(v.size() == u.Size()); return v.size(); @@ -112,7 +112,7 @@ void VerifiedString::find_all(Array &c, const char *value, size_t start, size_t if (cs != result.size()) TIGHTDB_ASSERT(false); for (size_t t = 0; t < result.size(); ++t) { - if (result[t] != (size_t)c.Get(t)) + if (result[t] != size_t(c.Get(t))) TIGHTDB_ASSERT(false); } @@ -126,8 +126,8 @@ bool VerifiedString::Verify() return false; for (size_t t = 0; t < v.size(); ++t) { - TIGHTDB_ASSERT(v[t] == u.Get(t)); - if (v[t] != u.Get(t)) + TIGHTDB_ASSERT(v[t] == u.get(t)); + if (v[t] != u.get(t)) return false; } return true; @@ -136,7 +136,7 @@ bool VerifiedString::Verify() // makes it run amortized the same time complexity as original, even though the row count grows bool VerifiedString::ConditionalVerify() { - if (((uint64_t)rand() * (uint64_t)rand()) % (v.size() / 10 + 1) == 0) { + if ((uint64_t(rand()) * uint64_t(rand())) % (v.size() / 10 + 1) == 0) { return Verify(); } else { diff --git a/test/main.cpp b/test/main.cpp index 58eb1df09e8..90d6412cba1 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -84,4 +84,4 @@ int main(int argc, char* argv[]) getchar(); // wait for key #endif return no_error_exit_staus ? 0 : res; -} \ No newline at end of file +} diff --git a/test/test_string_data.cpp b/test/test_string_data.cpp new file mode 100644 index 00000000000..0e036b7adb8 --- /dev/null +++ b/test/test_string_data.cpp @@ -0,0 +1,98 @@ +#include +#include +#include + +#include + +#include + + +using namespace std; +using namespace tightdb; + + +TEST(StringData_Compare) +{ + // Check lexicographic ordering + char c_11 = 11; + char c_22 = 22; + string s_8_11(8, c_11); + string s_8_22(8, c_22); + string s_9_22(9, c_22); + StringData sd_8_11(s_8_11); + StringData sd_8_22(s_8_22); + StringData sd_9_22(s_9_22); + CHECK(sd_8_11 < sd_8_22); + CHECK(sd_8_22 < sd_9_22); + CHECK(sd_8_11 < sd_9_22); + CHECK(!(sd_8_22 < sd_8_11)); + CHECK(!(sd_9_22 < sd_8_22)); + CHECK(!(sd_9_22 < sd_8_11)); +} + + +TEST(StringData_Substrings) +{ + StringData sd("Minkowski"); + CHECK(sd.begins_with("Min")); + CHECK(sd.ends_with("ski")); + CHECK(sd.contains("Min")); + CHECK(sd.contains("kow")); + CHECK(sd.contains("ski")); + CHECK(!sd.begins_with("ski")); + CHECK(!sd.ends_with("Min")); + CHECK(!sd.contains("wok")); + CHECK_EQUAL("Min", sd.prefix(3)); + CHECK_EQUAL("ski", sd.suffix(3)); + CHECK_EQUAL("kowski", sd.substr(3)); + CHECK_EQUAL("kow", sd.substr(3,3)); +} + + +TEST(StringData_STL_String) +{ + const char* pre = "hilbert"; + const char* suf_1 = "banachA"; + const char* suf_2 = "banachB"; + string s_1; + s_1 += pre; + s_1 += char(); // Null + s_1 += suf_1; + CHECK_EQUAL(strlen(pre) + 1 + strlen(suf_1), s_1.size()); + string s_2; + s_2 += pre; + s_2 += char(); // Null + s_2 += suf_2; + CHECK_EQUAL(strlen(pre) + 1 + strlen(suf_2), s_2.size()); + CHECK(s_1 != s_2); + StringData sd_1(s_1); + CHECK_EQUAL(s_1, sd_1); + // Check assignment too + StringData sd_2; + sd_2 = s_2; + CHECK_EQUAL(s_2, sd_2); + CHECK(sd_1 != sd_2); + string t_1(sd_1); + CHECK_EQUAL(sd_1, t_1); + string t_2; + t_2 = sd_2; + CHECK_EQUAL(sd_2, t_2); + CHECK(sd_1 != sd_2); + CHECK_EQUAL(s_1, t_1); + CHECK_EQUAL(s_2, t_2); +} + + +TEST(StringData_STL_Stream) +{ + const char* pre = "hilbert"; + const char* suf = "banach"; + string s; + s += pre; + s += char(); // Null + s += suf; + StringData sd(s); + ostringstream out; + out << sd; + CHECK_EQUAL(s, out.str()); +} diff --git a/test/test_utf8.cpp b/test/test_utf8.cpp new file mode 100644 index 00000000000..45c5d75f9f9 --- /dev/null +++ b/test/test_utf8.cpp @@ -0,0 +1,265 @@ +#include +#include +#include +#include + +#include + +#include +#include +#include + + +using namespace std; +using namespace tightdb; + + +namespace { + +template struct IntChar { + typedef Int int_type; + IntChar(): m_value(Int()) {} + explicit IntChar(Int v): m_value(v) {} + Int value() { return m_value; } + bool operator==(IntChar c) const { return m_value == c.m_value; } + bool operator< (IntChar c) const { return m_value < c.m_value; } +private: + Int m_value; +}; +template struct IntCharTraits: private char_traits { + typedef Char char_type; + typedef Int int_type; + typedef typename char_traits::off_type off_type; + typedef typename char_traits::pos_type pos_type; + static Int to_int_type(Char c) { return c.value(); } + static Char to_char_type(Int i) { return Char(i); } + static bool eq_int_type(Int i1, Int i2) { return i1 == i2; } + static Int eof() { return numeric_limits::max(); } + static Int not_eof(Int i) { return i != eof() ? i : Int(); } + using char_traits::assign; + using char_traits::eq; + using char_traits::lt; + using char_traits::move; + using char_traits::copy; + using char_traits::compare; + using char_traits::length; + using char_traits::find; +}; + + +// Assumes that lower case 'a', 'b', 'c', 'd', 'e', and 'f' have +// consecutive integer values. Likewise for the corresponding capital +// letters. Note that is is not guaranteed by C++11. +int decode_hex_digit(char hex_digit) +{ + typedef char_traits traits; + int v = traits::to_int_type(hex_digit); + if (traits::to_int_type('0') <= v && v <= traits::to_int_type('9')) + return v - traits::to_int_type('0'); + if (traits::to_int_type('A') <= v && v <= traits::to_int_type('F')) + return 10 + (v - traits::to_int_type('A')); + if (traits::to_int_type('a') <= v && v <= traits::to_int_type('f')) + return 10 + (v - traits::to_int_type('a')); + throw runtime_error("Bad hex digit"); +} + +char encode_hex_digit(int value) +{ + typedef char_traits traits; + if (0 <= value) { + if (value < 10) return traits::to_char_type(traits::to_int_type('0') + value); + if (value < 16) return traits::to_char_type(traits::to_int_type('A') + (value-10)); + } + throw runtime_error("Bad hex digit value"); +} + + +string decode_8bit_hex(const string& hex) +{ + string s; + s.reserve(hex.size() / 2); + const char* begin = hex.data(); + const char* end = begin + hex.size(); + for (const char* i = begin; i != end; ++i) { + char digit_1 = *i; + if (++i == end) throw runtime_error("Incomplete 8-bit element"); + char digit_2 = *i; + int value = 16 * decode_hex_digit(digit_1) + decode_hex_digit(digit_2); + s += char_traits::to_char_type(value); + } + return s; +} + +string encode_8bit_hex(const string& bin) +{ + string s; + s.reserve(bin.size() * 2); + const char* begin = bin.data(); + const char* end = begin + bin.size(); + for (const char* i = begin; i != end; ++i) { + int value = char_traits::to_int_type(*i); + s.push_back(encode_hex_digit(value / 16)); + s.push_back(encode_hex_digit(value % 16)); + } + return s; +} + + +template String16 decode_16bit_hex(const string& hex) +{ + String16 s; + s.reserve(hex.size() / 4); + const char* begin = hex.data(); + const char* end = begin + hex.size(); + for (const char* i = begin; i != end; ++i) { + char digit_1 = *i; + if (++i == end) throw runtime_error("Incomplete 16-bit element"); + char digit_2 = *i; + if (++i == end) throw runtime_error("Incomplete 16-bit element"); + char digit_3 = *i; + if (++i == end) throw runtime_error("Incomplete 16-bit element"); + char digit_4 = *i; + long value = + 4096L * decode_hex_digit(digit_1) + + 256 * decode_hex_digit(digit_2) + + 16 * decode_hex_digit(digit_3) + + 1 * decode_hex_digit(digit_4); + typedef typename String16::traits_type Traits16; + s += Traits16::to_char_type(value); + } + + return s; +} + +template string encode_16bit_hex(const String16& bin) +{ + string s; + s.reserve(bin.size() * 4); + typedef typename String16::traits_type Traits16; + typedef typename Traits16::char_type Char16; + const Char16* begin = bin.data(); + const Char16* end = begin + bin.size(); + for (const Char16* i = begin; i != end; ++i) { + long value = Traits16::to_int_type(*i); + s.push_back(encode_hex_digit(value / 4096)); + s.push_back(encode_hex_digit(value / 256 % 16)); + s.push_back(encode_hex_digit(value / 16 % 16)); + s.push_back(encode_hex_digit(value % 16)); + } + return s; +} + + +template String16 utf8_to_utf16(const string& s) +{ + typedef typename String16::traits_type Traits16; + typedef typename Traits16::char_type Char16; + typedef Utf8x16 Xcode; + const char* in_begin = s.data(); + const char* in_end = in_begin + s.size(); + size_t utf16_buf_size = Xcode::find_utf16_buf_size(in_begin, in_end); + if (in_begin != in_end) throw runtime_error("Bad UTF-8"); + in_begin = s.data(); + UniquePtr utf16_buf(new Char16[utf16_buf_size]); + Char16* out_begin = utf16_buf.get(); + Char16* out_end = out_begin + utf16_buf_size; + bool valid_utf8 = Xcode::to_utf16(in_begin, in_end, out_begin, out_end); + TIGHTDB_ASSERT(valid_utf8); + static_cast(valid_utf8); + TIGHTDB_ASSERT(in_begin == in_end); + return String16(utf16_buf.get(), out_begin); +} + +template string utf16_to_utf8(const String16& s) +{ + typedef typename String16::traits_type Traits16; + typedef typename Traits16::char_type Char16; + typedef Utf8x16 Xcode; + const Char16* in_begin = s.data(); + const Char16* in_end = in_begin + s.size(); + size_t utf8_buf_size = Xcode::find_utf8_buf_size(in_begin, in_end); + if (in_begin != in_end) throw runtime_error("Bad UTF-16"); + in_begin = s.data(); + UniquePtr utf8_buf(new char[utf8_buf_size]); + char* out_begin = utf8_buf.get(); + char* out_end = out_begin + utf8_buf_size; + bool valid_utf16 = Xcode::to_utf8(in_begin, in_end, out_begin, out_end); + TIGHTDB_ASSERT(valid_utf16); + static_cast(valid_utf16); + TIGHTDB_ASSERT(in_begin == in_end); + return string(utf8_buf.get(), out_begin); +} + + +size_t find_buf_size_utf8_to_utf16(const string& s) +{ + typedef Utf8x16 Xcode; + const char* in_begin = s.data(); + const char* in_end = in_begin + s.size(); + size_t size = Xcode::find_utf16_buf_size(in_begin, in_end); + if (in_begin != in_end) throw runtime_error("Bad UTF-8"); + return size; +} + +template size_t find_buf_size_utf16_to_utf8(const String16& s) +{ + typedef typename String16::traits_type Traits16; + typedef typename Traits16::char_type Char16; + typedef Utf8x16 Xcode; + const Char16* in_begin = s.data(); + const Char16* in_end = in_begin + s.size(); + size_t size = Xcode::find_utf8_buf_size(in_begin, in_end); + if (in_begin != in_end) throw runtime_error("Bad UTF-16"); + return size; +} + +} // anonymous namespace + + + +TEST(Utf8_Utf16_Transcode) +{ + typedef IntChar Char16; + typedef IntCharTraits Traits16; + typedef basic_string String16; + + // Try a trivial string first + { + string utf8 = "Lorem ipsum. The quick brown fox jumps over the lazy dog."; + const char* utf16_hex = + "004C006F00720065006D00200069007000730075006D002E0020005400680065" + "00200071007500690063006B002000620072006F0077006E00200066006F0078" + "0020006A0075006D007000730020006F00760065007200200074006800650020" + "006C0061007A007900200064006F0067002E"; + CHECK_EQUAL(char_traits::length(utf16_hex), + find_buf_size_utf8_to_utf16(utf8) * 4); + String16 utf16 = decode_16bit_hex(utf16_hex); + CHECK_EQUAL(utf8.size(), find_buf_size_utf16_to_utf8(utf16)); + CHECK(utf16 == utf8_to_utf16(utf8)); + CHECK(utf8 == utf16_to_utf8(utf16)); + } + + // Now try a harder one (contains characters beyond U+FFFF) + { + const char* utf8_hex = + "EFA4A5EFA49BF0A08080EFA4A7EFA491F0A08081EFA4A1C3A6C3B8C3A5EFA497" + "EFA4A3F0A08082F0A08083666F6FF0A08084EFA495F0A08085F0A08086EFA493" + "F0A08087F0A08088F0A08089F0A0808AEFA49DF0A0808BF0A0808CF0A0808DEF" + "A49FF0A0808EF0A0808FEFA48F"; + const char* utf16_hex = + "F925F91BD840DC00F927F911D840DC01F92100E600F800E5F917F923D840DC02" + "D840DC030066006F006FD840DC04F915D840DC05D840DC06F913D840DC07D840" + "DC08D840DC09D840DC0AF91DD840DC0BD840DC0CD840DC0DF91FD840DC0ED840" + "DC0FF90F"; + string utf8 = decode_8bit_hex(utf8_hex); + CHECK_EQUAL(char_traits::length(utf16_hex), + find_buf_size_utf8_to_utf16(utf8) * 4); + String16 utf16 = decode_16bit_hex(utf16_hex); + CHECK_EQUAL(char_traits::length(utf8_hex), + find_buf_size_utf16_to_utf8(utf16) * 2); + CHECK(utf16 == utf8_to_utf16(utf8)); + CHECK(utf8 == utf16_to_utf8(utf16)); + } + + CHECK_EQUAL("41", encode_8bit_hex("A")); // Avoid 'unused function' warning +} diff --git a/test/test_utf8.sh b/test/test_utf8.sh new file mode 100644 index 00000000000..6008998ff4b --- /dev/null +++ b/test/test_utf8.sh @@ -0,0 +1,9 @@ +input="$(cat)" +bin2hex() +{ + python -c 'import sys;import binascii;print binascii.hexlify("".join(sys.stdin.readlines()))' +} +echo -n "UTF-8: " +printf "%s" "$input" | bin2hex +echo -n "UTF-16: " +printf "%s" "$input" | iconv --from UTF-8 --to UTF-16BE | bin2hex diff --git a/test/testarray.cpp b/test/testarray.cpp index b4a4ba2e134..765dcae5649 100644 --- a/test/testarray.cpp +++ b/test/testarray.cpp @@ -1348,7 +1348,7 @@ TEST(ArrayCopy) CHECK_EQUAL(4, b.Get(4)); // With sub-arrays - Array c(coldef_HasRefs); + Array c(Array::coldef_HasRefs); c.add(a.GetRef()); Array d; diff --git a/test/testarrayblob.cpp b/test/testarrayblob.cpp index 52ae9ef3942..06ada735678 100644 --- a/test/testarrayblob.cpp +++ b/test/testarrayblob.cpp @@ -20,42 +20,42 @@ TEST(ArrayBlob) blob.add(t2, l2); blob.add(t3, l3); - CHECK_EQUAL(t1, blob.Get(0)); - CHECK_EQUAL(t2, blob.Get(l1)); - CHECK_EQUAL(t3, blob.Get(l1 + l2)); + CHECK_EQUAL(t1, blob.get(0)); + CHECK_EQUAL(t2, blob.get(l1)); + CHECK_EQUAL(t3, blob.get(l1 + l2)); // Test insert - blob.Insert(0, t3, l3); - blob.Insert(l3, t2, l2); + blob.insert(0, t3, l3); + blob.insert(l3, t2, l2); - CHECK_EQUAL(t3, blob.Get(0)); - CHECK_EQUAL(t2, blob.Get(l3)); - CHECK_EQUAL(t1, blob.Get(l3 + l2)); - CHECK_EQUAL(t2, blob.Get(l3 + l2 + l1)); - CHECK_EQUAL(t3, blob.Get(l3 + l2 + l1 + l2)); + CHECK_EQUAL(t3, blob.get(0)); + CHECK_EQUAL(t2, blob.get(l3)); + CHECK_EQUAL(t1, blob.get(l3 + l2)); + CHECK_EQUAL(t2, blob.get(l3 + l2 + l1)); + CHECK_EQUAL(t3, blob.get(l3 + l2 + l1 + l2)); // Test replace - blob.Replace(l3, l3 + l2, t1, l1); // replace with smaller - blob.Replace(l3 + l1 + l1, l3 + l1 + l1 + l2, t3, l3); // replace with bigger - blob.Replace(l3 + l1, l3 + l1 + l1, t4, l1); // replace with same + blob.replace(l3, l3 + l2, t1, l1); // replace with smaller + blob.replace(l3 + l1 + l1, l3 + l1 + l1 + l2, t3, l3); // replace with bigger + blob.replace(l3 + l1, l3 + l1 + l1, t4, l1); // replace with same - CHECK_EQUAL(t3, blob.Get(0)); - CHECK_EQUAL(t1, blob.Get(l3)); - CHECK_EQUAL(t4, blob.Get(l3 + l1)); - CHECK_EQUAL(t3, blob.Get(l3 + l1 + l1)); - CHECK_EQUAL(t3, blob.Get(l3 + l1 + l1 + l3)); + CHECK_EQUAL(t3, blob.get(0)); + CHECK_EQUAL(t1, blob.get(l3)); + CHECK_EQUAL(t4, blob.get(l3 + l1)); + CHECK_EQUAL(t3, blob.get(l3 + l1 + l1)); + CHECK_EQUAL(t3, blob.get(l3 + l1 + l1 + l3)); // Test delete - blob.Delete(0, l3); // top - blob.Delete(l1, l1 + l1); // middle - blob.Delete(l1 + l3, l1 + l3 + l3); // bottom + blob.erase(0, l3); // top + blob.erase(l1, l1 + l1); // middle + blob.erase(l1 + l3, l1 + l3 + l3); // bottom - CHECK_EQUAL(t1, blob.Get(0)); - CHECK_EQUAL(t3, blob.Get(l1)); + CHECK_EQUAL(t1, blob.get(0)); + CHECK_EQUAL(t3, blob.get(l1)); CHECK_EQUAL(l1 + l3, blob.size()); // Delete all - blob.Delete(0, l1 + l3); + blob.erase(0, l1 + l3); CHECK(blob.is_empty()); // Cleanup diff --git a/test/testarraystring.cpp b/test/testarraystring.cpp index b920dc6d1cd..61af507cc64 100644 --- a/test/testarraystring.cpp +++ b/test/testarraystring.cpp @@ -20,108 +20,108 @@ TEST_FIXTURE(db_setup_string, ArrayStringMultiEmpty) c.add(""); CHECK_EQUAL(6, c.size()); - CHECK_EQUAL("", c.Get(0)); - CHECK_EQUAL("", c.Get(1)); - CHECK_EQUAL("", c.Get(2)); - CHECK_EQUAL("", c.Get(3)); - CHECK_EQUAL("", c.Get(4)); - CHECK_EQUAL("", c.Get(5)); + CHECK_EQUAL("", c.get(0)); + CHECK_EQUAL("", c.get(1)); + CHECK_EQUAL("", c.get(2)); + CHECK_EQUAL("", c.get(3)); + CHECK_EQUAL("", c.get(4)); + CHECK_EQUAL("", c.get(5)); } TEST_FIXTURE(db_setup_string, ArrayStringSetExpand4) { - c.Set(0, "hey"); + c.set(0, "hey"); CHECK_EQUAL(6, c.size()); - CHECK_EQUAL("hey", c.Get(0)); - CHECK_EQUAL("", c.Get(1)); - CHECK_EQUAL("", c.Get(2)); - CHECK_EQUAL("", c.Get(3)); - CHECK_EQUAL("", c.Get(4)); - CHECK_EQUAL("", c.Get(5)); + CHECK_EQUAL("hey", c.get(0)); + CHECK_EQUAL("", c.get(1)); + CHECK_EQUAL("", c.get(2)); + CHECK_EQUAL("", c.get(3)); + CHECK_EQUAL("", c.get(4)); + CHECK_EQUAL("", c.get(5)); } TEST_FIXTURE(db_setup_string, ArrayStringSetExpand8) { - c.Set(1, "test"); + c.set(1, "test"); CHECK_EQUAL(6, c.size()); - CHECK_EQUAL("hey", c.Get(0)); - CHECK_EQUAL("test", c.Get(1)); - CHECK_EQUAL("", c.Get(2)); - CHECK_EQUAL("", c.Get(3)); - CHECK_EQUAL("", c.Get(4)); - CHECK_EQUAL("", c.Get(5)); + CHECK_EQUAL("hey", c.get(0)); + CHECK_EQUAL("test", c.get(1)); + CHECK_EQUAL("", c.get(2)); + CHECK_EQUAL("", c.get(3)); + CHECK_EQUAL("", c.get(4)); + CHECK_EQUAL("", c.get(5)); } TEST_FIXTURE(db_setup_string, ArrayArrayStringAdd0) { c.Clear(); c.add(); - CHECK_EQUAL("", c.Get(0)); + CHECK_EQUAL("", c.get(0)); CHECK_EQUAL(1, c.size()); } TEST_FIXTURE(db_setup_string, ArrayStringAdd1) { c.add("a"); - CHECK_EQUAL("", c.Get(0)); - CHECK_EQUAL("a", c.Get(1)); + CHECK_EQUAL("", c.get(0)); + CHECK_EQUAL("a", c.get(1)); CHECK_EQUAL(2, c.size()); } TEST_FIXTURE(db_setup_string, ArrayStringAdd2) { c.add("bb"); - CHECK_EQUAL("", c.Get(0)); - CHECK_EQUAL("a", c.Get(1)); - CHECK_EQUAL("bb", c.Get(2)); + CHECK_EQUAL("", c.get(0)); + CHECK_EQUAL("a", c.get(1)); + CHECK_EQUAL("bb", c.get(2)); CHECK_EQUAL(3, c.size()); } TEST_FIXTURE(db_setup_string, ArrayStringAdd3) { c.add("ccc"); - CHECK_EQUAL("", c.Get(0)); - CHECK_EQUAL("a", c.Get(1)); - CHECK_EQUAL("bb", c.Get(2)); - CHECK_EQUAL("ccc", c.Get(3)); + CHECK_EQUAL("", c.get(0)); + CHECK_EQUAL("a", c.get(1)); + CHECK_EQUAL("bb", c.get(2)); + CHECK_EQUAL("ccc", c.get(3)); CHECK_EQUAL(4, c.size()); } TEST_FIXTURE(db_setup_string, ArrayStringAdd4) { c.add("dddd"); - CHECK_EQUAL("", c.Get(0)); - CHECK_EQUAL("a", c.Get(1)); - CHECK_EQUAL("bb", c.Get(2)); - CHECK_EQUAL("ccc", c.Get(3)); - CHECK_EQUAL("dddd", c.Get(4)); + CHECK_EQUAL("", c.get(0)); + CHECK_EQUAL("a", c.get(1)); + CHECK_EQUAL("bb", c.get(2)); + CHECK_EQUAL("ccc", c.get(3)); + CHECK_EQUAL("dddd", c.get(4)); CHECK_EQUAL(5, c.size()); } TEST_FIXTURE(db_setup_string, ArrayStringAdd8) { c.add("eeeeeeee"); - CHECK_EQUAL("", c.Get(0)); - CHECK_EQUAL("a", c.Get(1)); - CHECK_EQUAL("bb", c.Get(2)); - CHECK_EQUAL("ccc", c.Get(3)); - CHECK_EQUAL("dddd", c.Get(4)); - CHECK_EQUAL("eeeeeeee", c.Get(5)); + CHECK_EQUAL("", c.get(0)); + CHECK_EQUAL("a", c.get(1)); + CHECK_EQUAL("bb", c.get(2)); + CHECK_EQUAL("ccc", c.get(3)); + CHECK_EQUAL("dddd", c.get(4)); + CHECK_EQUAL("eeeeeeee", c.get(5)); CHECK_EQUAL(6, c.size()); } TEST_FIXTURE(db_setup_string, ArrayStringAdd16) { c.add("ffffffffffffffff"); - CHECK_EQUAL("", c.Get(0)); - CHECK_EQUAL("a", c.Get(1)); - CHECK_EQUAL("bb", c.Get(2)); - CHECK_EQUAL("ccc", c.Get(3)); - CHECK_EQUAL("dddd", c.Get(4)); - CHECK_EQUAL("eeeeeeee", c.Get(5)); - CHECK_EQUAL("ffffffffffffffff", c.Get(6)); + CHECK_EQUAL("", c.get(0)); + CHECK_EQUAL("a", c.get(1)); + CHECK_EQUAL("bb", c.get(2)); + CHECK_EQUAL("ccc", c.get(3)); + CHECK_EQUAL("dddd", c.get(4)); + CHECK_EQUAL("eeeeeeee", c.get(5)); + CHECK_EQUAL("ffffffffffffffff", c.get(6)); CHECK_EQUAL(7, c.size()); } @@ -129,106 +129,106 @@ TEST_FIXTURE(db_setup_string, ArrayStringAdd32) { c.add("gggggggggggggggggggggggggggggggg"); - CHECK_EQUAL("", c.Get(0)); - CHECK_EQUAL("a", c.Get(1)); - CHECK_EQUAL("bb", c.Get(2)); - CHECK_EQUAL("ccc", c.Get(3)); - CHECK_EQUAL("dddd", c.Get(4)); - CHECK_EQUAL("eeeeeeee", c.Get(5)); - CHECK_EQUAL("ffffffffffffffff", c.Get(6)); - CHECK_EQUAL("gggggggggggggggggggggggggggggggg", c.Get(7)); + CHECK_EQUAL("", c.get(0)); + CHECK_EQUAL("a", c.get(1)); + CHECK_EQUAL("bb", c.get(2)); + CHECK_EQUAL("ccc", c.get(3)); + CHECK_EQUAL("dddd", c.get(4)); + CHECK_EQUAL("eeeeeeee", c.get(5)); + CHECK_EQUAL("ffffffffffffffff", c.get(6)); + CHECK_EQUAL("gggggggggggggggggggggggggggggggg", c.get(7)); CHECK_EQUAL(8, c.size()); } TEST_FIXTURE(db_setup_string, ArrayStringSet1) { - c.Set(0, "ccc"); - c.Set(1, "bb"); - c.Set(2, "a"); - c.Set(3, ""); - - CHECK_EQUAL("ccc", c.Get(0)); - CHECK_EQUAL("bb", c.Get(1)); - CHECK_EQUAL("a", c.Get(2)); - CHECK_EQUAL("", c.Get(3)); - CHECK_EQUAL("dddd", c.Get(4)); - CHECK_EQUAL("eeeeeeee", c.Get(5)); - CHECK_EQUAL("ffffffffffffffff", c.Get(6)); - CHECK_EQUAL("gggggggggggggggggggggggggggggggg", c.Get(7)); + c.set(0, "ccc"); + c.set(1, "bb"); + c.set(2, "a"); + c.set(3, ""); + + CHECK_EQUAL("ccc", c.get(0)); + CHECK_EQUAL("bb", c.get(1)); + CHECK_EQUAL("a", c.get(2)); + CHECK_EQUAL("", c.get(3)); + CHECK_EQUAL("dddd", c.get(4)); + CHECK_EQUAL("eeeeeeee", c.get(5)); + CHECK_EQUAL("ffffffffffffffff", c.get(6)); + CHECK_EQUAL("gggggggggggggggggggggggggggggggg", c.get(7)); CHECK_EQUAL(8, c.size()); } TEST_FIXTURE(db_setup_string, ArrayStringInsert1) { // Insert in middle - c.Insert(4, "xx", 2); - - CHECK_EQUAL("ccc", c.Get(0)); - CHECK_EQUAL("bb", c.Get(1)); - CHECK_EQUAL("a", c.Get(2)); - CHECK_EQUAL("", c.Get(3)); - CHECK_EQUAL("xx", c.Get(4)); - CHECK_EQUAL("dddd", c.Get(5)); - CHECK_EQUAL("eeeeeeee", c.Get(6)); - CHECK_EQUAL("ffffffffffffffff", c.Get(7)); - CHECK_EQUAL("gggggggggggggggggggggggggggggggg", c.Get(8)); + c.insert(4, "xx"); + + CHECK_EQUAL("ccc", c.get(0)); + CHECK_EQUAL("bb", c.get(1)); + CHECK_EQUAL("a", c.get(2)); + CHECK_EQUAL("", c.get(3)); + CHECK_EQUAL("xx", c.get(4)); + CHECK_EQUAL("dddd", c.get(5)); + CHECK_EQUAL("eeeeeeee", c.get(6)); + CHECK_EQUAL("ffffffffffffffff", c.get(7)); + CHECK_EQUAL("gggggggggggggggggggggggggggggggg", c.get(8)); CHECK_EQUAL(9, c.size()); } TEST_FIXTURE(db_setup_string, ArrayStringDelete1) { // Delete from end - c.Delete(8); - - CHECK_EQUAL("ccc", c.Get(0)); - CHECK_EQUAL("bb", c.Get(1)); - CHECK_EQUAL("a", c.Get(2)); - CHECK_EQUAL("", c.Get(3)); - CHECK_EQUAL("xx", c.Get(4)); - CHECK_EQUAL("dddd", c.Get(5)); - CHECK_EQUAL("eeeeeeee", c.Get(6)); - CHECK_EQUAL("ffffffffffffffff", c.Get(7)); + c.erase(8); + + CHECK_EQUAL("ccc", c.get(0)); + CHECK_EQUAL("bb", c.get(1)); + CHECK_EQUAL("a", c.get(2)); + CHECK_EQUAL("", c.get(3)); + CHECK_EQUAL("xx", c.get(4)); + CHECK_EQUAL("dddd", c.get(5)); + CHECK_EQUAL("eeeeeeee", c.get(6)); + CHECK_EQUAL("ffffffffffffffff", c.get(7)); CHECK_EQUAL(8, c.size()); } TEST_FIXTURE(db_setup_string, ArrayStringDelete2) { // Delete from top - c.Delete(0); - - CHECK_EQUAL("bb", c.Get(0)); - CHECK_EQUAL("a", c.Get(1)); - CHECK_EQUAL("", c.Get(2)); - CHECK_EQUAL("xx", c.Get(3)); - CHECK_EQUAL("dddd", c.Get(4)); - CHECK_EQUAL("eeeeeeee", c.Get(5)); - CHECK_EQUAL("ffffffffffffffff", c.Get(6)); + c.erase(0); + + CHECK_EQUAL("bb", c.get(0)); + CHECK_EQUAL("a", c.get(1)); + CHECK_EQUAL("", c.get(2)); + CHECK_EQUAL("xx", c.get(3)); + CHECK_EQUAL("dddd", c.get(4)); + CHECK_EQUAL("eeeeeeee", c.get(5)); + CHECK_EQUAL("ffffffffffffffff", c.get(6)); CHECK_EQUAL(7, c.size()); } TEST_FIXTURE(db_setup_string, ArrayStringDelete3) { // Delete from middle - c.Delete(3); - - CHECK_EQUAL("bb", c.Get(0)); - CHECK_EQUAL("a", c.Get(1)); - CHECK_EQUAL("", c.Get(2)); - CHECK_EQUAL("dddd", c.Get(3)); - CHECK_EQUAL("eeeeeeee", c.Get(4)); - CHECK_EQUAL("ffffffffffffffff", c.Get(5)); + c.erase(3); + + CHECK_EQUAL("bb", c.get(0)); + CHECK_EQUAL("a", c.get(1)); + CHECK_EQUAL("", c.get(2)); + CHECK_EQUAL("dddd", c.get(3)); + CHECK_EQUAL("eeeeeeee", c.get(4)); + CHECK_EQUAL("ffffffffffffffff", c.get(5)); CHECK_EQUAL(6, c.size()); } TEST_FIXTURE(db_setup_string, ArrayStringDeleteAll) { // Delete all items one at a time - c.Delete(0); - c.Delete(0); - c.Delete(0); - c.Delete(0); - c.Delete(0); - c.Delete(0); + c.erase(0); + c.erase(0); + c.erase(0); + c.erase(0); + c.erase(0); + c.erase(0); CHECK(c.is_empty()); CHECK_EQUAL(0, c.size()); @@ -244,27 +244,27 @@ TEST_FIXTURE(db_setup_string, ArrayStringInsert2) c.add("d"); // Insert in top with expansion - c.Insert(0, "xxxxx", 5); + c.insert(0, "xxxxx"); - CHECK_EQUAL("xxxxx", c.Get(0)); - CHECK_EQUAL("a", c.Get(1)); - CHECK_EQUAL("b", c.Get(2)); - CHECK_EQUAL("c", c.Get(3)); - CHECK_EQUAL("d", c.Get(4)); + CHECK_EQUAL("xxxxx", c.get(0)); + CHECK_EQUAL("a", c.get(1)); + CHECK_EQUAL("b", c.get(2)); + CHECK_EQUAL("c", c.get(3)); + CHECK_EQUAL("d", c.get(4)); CHECK_EQUAL(5, c.size()); } TEST_FIXTURE(db_setup_string, ArrayStringInsert3) { // Insert in middle with expansion - c.Insert(3, "xxxxxxxxxx", 10); - - CHECK_EQUAL("xxxxx", c.Get(0)); - CHECK_EQUAL("a", c.Get(1)); - CHECK_EQUAL("b", c.Get(2)); - CHECK_EQUAL("xxxxxxxxxx", c.Get(3)); - CHECK_EQUAL("c", c.Get(4)); - CHECK_EQUAL("d", c.Get(5)); + c.insert(3, "xxxxxxxxxx"); + + CHECK_EQUAL("xxxxx", c.get(0)); + CHECK_EQUAL("a", c.get(1)); + CHECK_EQUAL("b", c.get(2)); + CHECK_EQUAL("xxxxxxxxxx", c.get(3)); + CHECK_EQUAL("c", c.get(4)); + CHECK_EQUAL("d", c.get(5)); CHECK_EQUAL(6, c.size()); } @@ -364,6 +364,31 @@ TEST_FIXTURE(db_setup_string, ArrayStringCount) CHECK_EQUAL(3, count); } +// FIXME: The following unit test has ben temporarily commented +// out. See https://github.com/Tightdb/tightdb/pull/84 +/* +TEST_FIXTURE(db_setup_string, ArrayStringWithZeroBytes) +{ + c.Clear(); + + const char buf_1[] = { 'a', 0, 'b', 0, 'c' }; + const char buf_2[] = { 0, 'a', 0, 'b', 0 }; + const char buf_3[] = { 0, 0, 0, 0, 0 }; + + c.add(StringData(buf_1, sizeof buf_1)); + c.add(StringData(buf_2, sizeof buf_2)); + c.add(StringData(buf_3, sizeof buf_3)); + + CHECK_EQUAL(5, c.get(0).size()); + CHECK_EQUAL(5, c.get(1).size()); + CHECK_EQUAL(5, c.get(2).size()); + + CHECK_EQUAL(StringData(buf_1, sizeof buf_1), c.get(0)); + CHECK_EQUAL(StringData(buf_2, sizeof buf_2), c.get(1)); + CHECK_EQUAL(StringData(buf_3, sizeof buf_3), c.get(2)); +} +*/ + TEST_FIXTURE(db_setup_string, ArrayStringDestroy) { // clean up (ALWAYS PUT THIS LAST) diff --git a/test/testarraystringlong.cpp b/test/testarraystringlong.cpp index 0f5d8149a66..c1561250e69 100644 --- a/test/testarraystringlong.cpp +++ b/test/testarraystringlong.cpp @@ -19,25 +19,25 @@ TEST_FIXTURE(db_setup_string_long, ArrayStringLongMultiEmpty) c.add(""); CHECK_EQUAL(6, c.size()); - CHECK_EQUAL("", c.Get(0)); - CHECK_EQUAL("", c.Get(1)); - CHECK_EQUAL("", c.Get(2)); - CHECK_EQUAL("", c.Get(3)); - CHECK_EQUAL("", c.Get(4)); - CHECK_EQUAL("", c.Get(5)); + CHECK_EQUAL("", c.get(0)); + CHECK_EQUAL("", c.get(1)); + CHECK_EQUAL("", c.get(2)); + CHECK_EQUAL("", c.get(3)); + CHECK_EQUAL("", c.get(4)); + CHECK_EQUAL("", c.get(5)); } TEST_FIXTURE(db_setup_string_long, ArrayStringLongSet) { - c.Set(0, "hey"); + c.set(0, "hey"); CHECK_EQUAL(6, c.size()); - CHECK_EQUAL("hey", c.Get(0)); - CHECK_EQUAL("", c.Get(1)); - CHECK_EQUAL("", c.Get(2)); - CHECK_EQUAL("", c.Get(3)); - CHECK_EQUAL("", c.Get(4)); - CHECK_EQUAL("", c.Get(5)); + CHECK_EQUAL("hey", c.get(0)); + CHECK_EQUAL("", c.get(1)); + CHECK_EQUAL("", c.get(2)); + CHECK_EQUAL("", c.get(3)); + CHECK_EQUAL("", c.get(4)); + CHECK_EQUAL("", c.get(5)); } TEST_FIXTURE(db_setup_string_long, ArrayStringLongAdd) @@ -46,12 +46,12 @@ TEST_FIXTURE(db_setup_string_long, ArrayStringLongAdd) CHECK_EQUAL(0, c.size()); c.add("abc"); - CHECK_EQUAL("abc", c.Get(0)); // single + CHECK_EQUAL("abc", c.get(0)); // single CHECK_EQUAL(1, c.size()); c.add("defg"); //non-empty - CHECK_EQUAL("abc", c.Get(0)); - CHECK_EQUAL("defg", c.Get(1)); + CHECK_EQUAL("abc", c.get(0)); + CHECK_EQUAL("defg", c.get(1)); CHECK_EQUAL(2, c.size()); } @@ -61,52 +61,52 @@ TEST_FIXTURE(db_setup_string_long, ArrayStringLongSet2) c.Clear(); c.add("abc"); - c.Set(0, "de"); // shrink single - CHECK_EQUAL("de", c.Get(0)); + c.set(0, "de"); // shrink single + CHECK_EQUAL("de", c.get(0)); CHECK_EQUAL(1, c.size()); - c.Set(0, "abcd"); // grow single - CHECK_EQUAL("abcd", c.Get(0)); + c.set(0, "abcd"); // grow single + CHECK_EQUAL("abcd", c.get(0)); CHECK_EQUAL(1, c.size()); c.add("efg"); - CHECK_EQUAL("abcd", c.Get(0)); - CHECK_EQUAL("efg", c.Get(1)); + CHECK_EQUAL("abcd", c.get(0)); + CHECK_EQUAL("efg", c.get(1)); CHECK_EQUAL(2, c.size()); - c.Set(1, "hi"); // shrink last - CHECK_EQUAL("abcd", c.Get(0)); - CHECK_EQUAL("hi", c.Get(1)); + c.set(1, "hi"); // shrink last + CHECK_EQUAL("abcd", c.get(0)); + CHECK_EQUAL("hi", c.get(1)); CHECK_EQUAL(2, c.size()); - c.Set(1, "jklmno"); // grow last - CHECK_EQUAL("abcd", c.Get(0)); - CHECK_EQUAL("jklmno", c.Get(1)); + c.set(1, "jklmno"); // grow last + CHECK_EQUAL("abcd", c.get(0)); + CHECK_EQUAL("jklmno", c.get(1)); CHECK_EQUAL(2, c.size()); c.add("pq"); - c.Set(1, "efghijkl"); // grow middle - CHECK_EQUAL("abcd", c.Get(0)); - CHECK_EQUAL("efghijkl", c.Get(1)); - CHECK_EQUAL("pq", c.Get(2)); + c.set(1, "efghijkl"); // grow middle + CHECK_EQUAL("abcd", c.get(0)); + CHECK_EQUAL("efghijkl", c.get(1)); + CHECK_EQUAL("pq", c.get(2)); CHECK_EQUAL(3, c.size()); - c.Set(1, "x"); // shrink middle - CHECK_EQUAL("abcd", c.Get(0)); - CHECK_EQUAL("x", c.Get(1)); - CHECK_EQUAL("pq", c.Get(2)); + c.set(1, "x"); // shrink middle + CHECK_EQUAL("abcd", c.get(0)); + CHECK_EQUAL("x", c.get(1)); + CHECK_EQUAL("pq", c.get(2)); CHECK_EQUAL(3, c.size()); - c.Set(0, "qwertyuio"); // grow first - CHECK_EQUAL("qwertyuio", c.Get(0)); - CHECK_EQUAL("x", c.Get(1)); - CHECK_EQUAL("pq", c.Get(2)); + c.set(0, "qwertyuio"); // grow first + CHECK_EQUAL("qwertyuio", c.get(0)); + CHECK_EQUAL("x", c.get(1)); + CHECK_EQUAL("pq", c.get(2)); CHECK_EQUAL(3, c.size()); - c.Set(0, "mno"); // shrink first - CHECK_EQUAL("mno", c.Get(0)); - CHECK_EQUAL("x", c.Get(1)); - CHECK_EQUAL("pq", c.Get(2)); + c.set(0, "mno"); // shrink first + CHECK_EQUAL("mno", c.get(0)); + CHECK_EQUAL("x", c.get(1)); + CHECK_EQUAL("pq", c.get(2)); CHECK_EQUAL(3, c.size()); } @@ -115,34 +115,34 @@ TEST_FIXTURE(db_setup_string_long, ArrayStringLongInsert) { c.Clear(); - c.Insert(0, "abc"); // single - CHECK_EQUAL(c.Get(0), "abc"); + c.insert(0, "abc"); // single + CHECK_EQUAL(c.get(0), "abc"); CHECK_EQUAL(1, c.size()); - c.Insert(1, "d"); // end - CHECK_EQUAL("abc", c.Get(0)); - CHECK_EQUAL("d", c.Get(1)); + c.insert(1, "d"); // end + CHECK_EQUAL("abc", c.get(0)); + CHECK_EQUAL("d", c.get(1)); CHECK_EQUAL(2, c.size()); - c.Insert(2, "ef"); // end - CHECK_EQUAL("abc", c.Get(0)); - CHECK_EQUAL("d", c.Get(1)); - CHECK_EQUAL("ef", c.Get(2)); + c.insert(2, "ef"); // end + CHECK_EQUAL("abc", c.get(0)); + CHECK_EQUAL("d", c.get(1)); + CHECK_EQUAL("ef", c.get(2)); CHECK_EQUAL(3, c.size()); - c.Insert(1, "ghij"); // middle - CHECK_EQUAL("abc", c.Get(0)); - CHECK_EQUAL("ghij", c.Get(1)); - CHECK_EQUAL("d", c.Get(2)); - CHECK_EQUAL("ef", c.Get(3)); + c.insert(1, "ghij"); // middle + CHECK_EQUAL("abc", c.get(0)); + CHECK_EQUAL("ghij", c.get(1)); + CHECK_EQUAL("d", c.get(2)); + CHECK_EQUAL("ef", c.get(3)); CHECK_EQUAL(4, c.size()); - c.Insert(0, "klmno"); // first - CHECK_EQUAL("klmno", c.Get(0)); - CHECK_EQUAL("abc", c.Get(1)); - CHECK_EQUAL("ghij", c.Get(2)); - CHECK_EQUAL("d", c.Get(3)); - CHECK_EQUAL("ef", c.Get(4)); + c.insert(0, "klmno"); // first + CHECK_EQUAL("klmno", c.get(0)); + CHECK_EQUAL("abc", c.get(1)); + CHECK_EQUAL("ghij", c.get(2)); + CHECK_EQUAL("d", c.get(3)); + CHECK_EQUAL("ef", c.get(4)); CHECK_EQUAL(5, c.size()); } @@ -156,29 +156,29 @@ TEST_FIXTURE(db_setup_string_long, ArrayStringLongDelete) c.add("ghij"); c.add("klmno"); - c.Delete(0); // first - CHECK_EQUAL("bc", c.Get(0)); - CHECK_EQUAL("def", c.Get(1)); - CHECK_EQUAL("ghij", c.Get(2)); - CHECK_EQUAL("klmno", c.Get(3)); + c.erase(0); // first + CHECK_EQUAL("bc", c.get(0)); + CHECK_EQUAL("def", c.get(1)); + CHECK_EQUAL("ghij", c.get(2)); + CHECK_EQUAL("klmno", c.get(3)); CHECK_EQUAL(4, c.size()); - c.Delete(3); // last - CHECK_EQUAL("bc", c.Get(0)); - CHECK_EQUAL("def", c.Get(1)); - CHECK_EQUAL("ghij", c.Get(2)); + c.erase(3); // last + CHECK_EQUAL("bc", c.get(0)); + CHECK_EQUAL("def", c.get(1)); + CHECK_EQUAL("ghij", c.get(2)); CHECK_EQUAL(3, c.size()); - c.Delete(1); // middle - CHECK_EQUAL("bc", c.Get(0)); - CHECK_EQUAL("ghij", c.Get(1)); + c.erase(1); // middle + CHECK_EQUAL("bc", c.get(0)); + CHECK_EQUAL("ghij", c.get(1)); CHECK_EQUAL(2, c.size()); - c.Delete(0); // single - CHECK_EQUAL("ghij", c.Get(0)); + c.erase(0); // single + CHECK_EQUAL("ghij", c.get(0)); CHECK_EQUAL(1, c.size()); - c.Delete(0); // all + c.erase(0); // all CHECK_EQUAL(0, c.size()); CHECK(c.is_empty()); } diff --git a/test/testcolumn.cpp b/test/testcolumn.cpp index 81d32f4018c..b07ef292b45 100644 --- a/test/testcolumn.cpp +++ b/test/testcolumn.cpp @@ -23,99 +23,99 @@ TEST_FIXTURE(db_setup, Column_IsEmpty) TEST_FIXTURE(db_setup, Column_Add0) { c.add(0); - CHECK_EQUAL(c.Get(0), 0); + CHECK_EQUAL(c.get(0), 0); CHECK_EQUAL(c.Size(), (size_t)1); } TEST_FIXTURE(db_setup, Column_Add1) { c.add(1); - CHECK_EQUAL(c.Get(0), 0); - CHECK_EQUAL(c.Get(1), 1); + CHECK_EQUAL(c.get(0), 0); + CHECK_EQUAL(c.get(1), 1); CHECK_EQUAL(c.Size(), 2); } TEST_FIXTURE(db_setup, Column_Add2) { c.add(2); - CHECK_EQUAL(c.Get(0), 0); - CHECK_EQUAL(c.Get(1), 1); - CHECK_EQUAL(c.Get(2), 2); + CHECK_EQUAL(c.get(0), 0); + CHECK_EQUAL(c.get(1), 1); + CHECK_EQUAL(c.get(2), 2); CHECK_EQUAL(c.Size(), 3); } TEST_FIXTURE(db_setup, Column_Add3) { c.add(3); - CHECK_EQUAL(c.Get(0), 0); - CHECK_EQUAL(c.Get(1), 1); - CHECK_EQUAL(c.Get(2), 2); - CHECK_EQUAL(c.Get(3), 3); + CHECK_EQUAL(c.get(0), 0); + CHECK_EQUAL(c.get(1), 1); + CHECK_EQUAL(c.get(2), 2); + CHECK_EQUAL(c.get(3), 3); CHECK_EQUAL(c.Size(), 4); } TEST_FIXTURE(db_setup, Column_Add4) { c.add(4); - CHECK_EQUAL(c.Get(0), 0); - CHECK_EQUAL(c.Get(1), 1); - CHECK_EQUAL(c.Get(2), 2); - CHECK_EQUAL(c.Get(3), 3); - CHECK_EQUAL(c.Get(4), 4); + CHECK_EQUAL(c.get(0), 0); + CHECK_EQUAL(c.get(1), 1); + CHECK_EQUAL(c.get(2), 2); + CHECK_EQUAL(c.get(3), 3); + CHECK_EQUAL(c.get(4), 4); CHECK_EQUAL(c.Size(), 5); } TEST_FIXTURE(db_setup, Column_Add5) { c.add(16); - CHECK_EQUAL(c.Get(0), 0); - CHECK_EQUAL(c.Get(1), 1); - CHECK_EQUAL(c.Get(2), 2); - CHECK_EQUAL(c.Get(3), 3); - CHECK_EQUAL(c.Get(4), 4); - CHECK_EQUAL(c.Get(5), 16); + CHECK_EQUAL(c.get(0), 0); + CHECK_EQUAL(c.get(1), 1); + CHECK_EQUAL(c.get(2), 2); + CHECK_EQUAL(c.get(3), 3); + CHECK_EQUAL(c.get(4), 4); + CHECK_EQUAL(c.get(5), 16); CHECK_EQUAL(c.Size(), 6); } TEST_FIXTURE(db_setup, Column_Add6) { c.add(256); - CHECK_EQUAL(c.Get(0), 0); - CHECK_EQUAL(c.Get(1), 1); - CHECK_EQUAL(c.Get(2), 2); - CHECK_EQUAL(c.Get(3), 3); - CHECK_EQUAL(c.Get(4), 4); - CHECK_EQUAL(c.Get(5), 16); - CHECK_EQUAL(c.Get(6), 256); + CHECK_EQUAL(c.get(0), 0); + CHECK_EQUAL(c.get(1), 1); + CHECK_EQUAL(c.get(2), 2); + CHECK_EQUAL(c.get(3), 3); + CHECK_EQUAL(c.get(4), 4); + CHECK_EQUAL(c.get(5), 16); + CHECK_EQUAL(c.get(6), 256); CHECK_EQUAL(c.Size(), 7); } TEST_FIXTURE(db_setup, Column_Add7) { c.add(65536); - CHECK_EQUAL(c.Get(0), 0); - CHECK_EQUAL(c.Get(1), 1); - CHECK_EQUAL(c.Get(2), 2); - CHECK_EQUAL(c.Get(3), 3); - CHECK_EQUAL(c.Get(4), 4); - CHECK_EQUAL(c.Get(5), 16); - CHECK_EQUAL(c.Get(6), 256); - CHECK_EQUAL(c.Get(7), 65536); + CHECK_EQUAL(c.get(0), 0); + CHECK_EQUAL(c.get(1), 1); + CHECK_EQUAL(c.get(2), 2); + CHECK_EQUAL(c.get(3), 3); + CHECK_EQUAL(c.get(4), 4); + CHECK_EQUAL(c.get(5), 16); + CHECK_EQUAL(c.get(6), 256); + CHECK_EQUAL(c.get(7), 65536); CHECK_EQUAL(c.Size(), 8); } TEST_FIXTURE(db_setup, Column_Add8) { c.add(4294967296LL); - CHECK_EQUAL(c.Get(0), 0); - CHECK_EQUAL(c.Get(1), 1); - CHECK_EQUAL(c.Get(2), 2); - CHECK_EQUAL(c.Get(3), 3); - CHECK_EQUAL(c.Get(4), 4); - CHECK_EQUAL(c.Get(5), 16); - CHECK_EQUAL(c.Get(6), 256); - CHECK_EQUAL(c.Get(7), 65536); - CHECK_EQUAL(c.Get(8), 4294967296LL); + CHECK_EQUAL(c.get(0), 0); + CHECK_EQUAL(c.get(1), 1); + CHECK_EQUAL(c.get(2), 2); + CHECK_EQUAL(c.get(3), 3); + CHECK_EQUAL(c.get(4), 4); + CHECK_EQUAL(c.get(5), 16); + CHECK_EQUAL(c.get(6), 256); + CHECK_EQUAL(c.get(7), 65536); + CHECK_EQUAL(c.get(8), 4294967296LL); CHECK_EQUAL(c.Size(), 9); } @@ -125,7 +125,7 @@ TEST_FIXTURE(db_setup, Column_AddNeg1) c.add(-1); CHECK_EQUAL(c.Size(), 1); - CHECK_EQUAL(c.Get(0), -1); + CHECK_EQUAL(c.get(0), -1); } TEST_FIXTURE(db_setup, Column_AddNeg2) @@ -133,8 +133,8 @@ TEST_FIXTURE(db_setup, Column_AddNeg2) c.add(-256); CHECK_EQUAL(c.Size(), 2); - CHECK_EQUAL(c.Get(0), -1); - CHECK_EQUAL(c.Get(1), -256); + CHECK_EQUAL(c.get(0), -1); + CHECK_EQUAL(c.get(1), -256); } TEST_FIXTURE(db_setup, Column_AddNeg3) @@ -142,9 +142,9 @@ TEST_FIXTURE(db_setup, Column_AddNeg3) c.add(-65536); CHECK_EQUAL(c.Size(), 3); - CHECK_EQUAL(c.Get(0), -1); - CHECK_EQUAL(c.Get(1), -256); - CHECK_EQUAL(c.Get(2), -65536); + CHECK_EQUAL(c.get(0), -1); + CHECK_EQUAL(c.get(1), -256); + CHECK_EQUAL(c.get(2), -65536); } TEST_FIXTURE(db_setup, Column_AddNeg4) @@ -152,24 +152,24 @@ TEST_FIXTURE(db_setup, Column_AddNeg4) c.add(-4294967296LL); CHECK_EQUAL(c.Size(), 4); - CHECK_EQUAL(c.Get(0), -1); - CHECK_EQUAL(c.Get(1), -256); - CHECK_EQUAL(c.Get(2), -65536); - CHECK_EQUAL(c.Get(3), -4294967296LL); + CHECK_EQUAL(c.get(0), -1); + CHECK_EQUAL(c.get(1), -256); + CHECK_EQUAL(c.get(2), -65536); + CHECK_EQUAL(c.get(3), -4294967296LL); } TEST_FIXTURE(db_setup, Column_Set) { - c.Set(0, 3); - c.Set(1, 2); - c.Set(2, 1); - c.Set(3, 0); + c.set(0, 3); + c.set(1, 2); + c.set(2, 1); + c.set(3, 0); CHECK_EQUAL(c.Size(), 4); - CHECK_EQUAL(c.Get(0), 3); - CHECK_EQUAL(c.Get(1), 2); - CHECK_EQUAL(c.Get(2), 1); - CHECK_EQUAL(c.Get(3), 0); + CHECK_EQUAL(c.get(0), 3); + CHECK_EQUAL(c.get(1), 2); + CHECK_EQUAL(c.get(2), 1); + CHECK_EQUAL(c.get(3), 0); } TEST_FIXTURE(db_setup, Column_Insert1) @@ -182,43 +182,43 @@ TEST_FIXTURE(db_setup, Column_Insert1) c.add(3); // Insert in middle - c.Insert(2, 16); + c.insert(2, 16); CHECK_EQUAL(c.Size(), 5); - CHECK_EQUAL(c.Get(0), 0); - CHECK_EQUAL(c.Get(1), 1); - CHECK_EQUAL(c.Get(2), 16); - CHECK_EQUAL(c.Get(3), 2); - CHECK_EQUAL(c.Get(4), 3); + CHECK_EQUAL(c.get(0), 0); + CHECK_EQUAL(c.get(1), 1); + CHECK_EQUAL(c.get(2), 16); + CHECK_EQUAL(c.get(3), 2); + CHECK_EQUAL(c.get(4), 3); } TEST_FIXTURE(db_setup, Column_Insert2) { // Insert at top - c.Insert(0, 256); + c.insert(0, 256); CHECK_EQUAL(c.Size(), 6); - CHECK_EQUAL(c.Get(0), 256); - CHECK_EQUAL(c.Get(1), 0); - CHECK_EQUAL(c.Get(2), 1); - CHECK_EQUAL(c.Get(3), 16); - CHECK_EQUAL(c.Get(4), 2); - CHECK_EQUAL(c.Get(5), 3); + CHECK_EQUAL(c.get(0), 256); + CHECK_EQUAL(c.get(1), 0); + CHECK_EQUAL(c.get(2), 1); + CHECK_EQUAL(c.get(3), 16); + CHECK_EQUAL(c.get(4), 2); + CHECK_EQUAL(c.get(5), 3); } TEST_FIXTURE(db_setup, Column_Insert3) { // Insert at bottom - c.Insert(6, 65536); + c.insert(6, 65536); CHECK_EQUAL(c.Size(), 7); - CHECK_EQUAL(c.Get(0), 256); - CHECK_EQUAL(c.Get(1), 0); - CHECK_EQUAL(c.Get(2), 1); - CHECK_EQUAL(c.Get(3), 16); - CHECK_EQUAL(c.Get(4), 2); - CHECK_EQUAL(c.Get(5), 3); - CHECK_EQUAL(c.Get(6), 65536); + CHECK_EQUAL(c.get(0), 256); + CHECK_EQUAL(c.get(1), 0); + CHECK_EQUAL(c.get(2), 1); + CHECK_EQUAL(c.get(3), 16); + CHECK_EQUAL(c.get(4), 2); + CHECK_EQUAL(c.get(5), 3); + CHECK_EQUAL(c.get(6), 65536); } /* @@ -243,49 +243,49 @@ TEST_FIXTURE(db_setup, Column_Index1) TEST_FIXTURE(db_setup, Column_Delete1) { // Delete from middle - c.Delete(3); + c.erase(3); CHECK_EQUAL(c.Size(), 6); - CHECK_EQUAL(c.Get(0), 256); - CHECK_EQUAL(c.Get(1), 0); - CHECK_EQUAL(c.Get(2), 1); - CHECK_EQUAL(c.Get(3), 2); - CHECK_EQUAL(c.Get(4), 3); - CHECK_EQUAL(c.Get(5), 65536); + CHECK_EQUAL(c.get(0), 256); + CHECK_EQUAL(c.get(1), 0); + CHECK_EQUAL(c.get(2), 1); + CHECK_EQUAL(c.get(3), 2); + CHECK_EQUAL(c.get(4), 3); + CHECK_EQUAL(c.get(5), 65536); } TEST_FIXTURE(db_setup, Column_Delete2) { // Delete from top - c.Delete(0); + c.erase(0); CHECK_EQUAL(c.Size(), 5); - CHECK_EQUAL(c.Get(0), 0); - CHECK_EQUAL(c.Get(1), 1); - CHECK_EQUAL(c.Get(2), 2); - CHECK_EQUAL(c.Get(3), 3); - CHECK_EQUAL(c.Get(4), 65536); + CHECK_EQUAL(c.get(0), 0); + CHECK_EQUAL(c.get(1), 1); + CHECK_EQUAL(c.get(2), 2); + CHECK_EQUAL(c.get(3), 3); + CHECK_EQUAL(c.get(4), 65536); } TEST_FIXTURE(db_setup, Column_Delete3) { // Delete from bottom - c.Delete(4); + c.erase(4); CHECK_EQUAL(c.Size(), 4); - CHECK_EQUAL(c.Get(0), 0); - CHECK_EQUAL(c.Get(1), 1); - CHECK_EQUAL(c.Get(2), 2); - CHECK_EQUAL(c.Get(3), 3); + CHECK_EQUAL(c.get(0), 0); + CHECK_EQUAL(c.get(1), 1); + CHECK_EQUAL(c.get(2), 2); + CHECK_EQUAL(c.get(3), 3); } TEST_FIXTURE(db_setup, Column_DeleteAll) { // Delete all items one at a time - c.Delete(0); - c.Delete(0); - c.Delete(0); - c.Delete(0); + c.erase(0); + c.erase(0); + c.erase(0); + c.erase(0); CHECK(c.is_empty()); CHECK_EQUAL(0, c.Size()); @@ -391,16 +391,16 @@ TEST_FIXTURE(db_setup, Column_FindLeafs) } // Set sentinel values at before and after each break - a.Set(0, 1); - a.Set(TIGHTDB_MAX_LIST_SIZE-1, 2); - a.Set(TIGHTDB_MAX_LIST_SIZE, 3); - a.Set(TIGHTDB_MAX_LIST_SIZE*2-1, 4); - a.Set(TIGHTDB_MAX_LIST_SIZE*2, 5); - a.Set(TIGHTDB_MAX_LIST_SIZE*3-1, 6); - a.Set(TIGHTDB_MAX_LIST_SIZE*3, 7); - a.Set(TIGHTDB_MAX_LIST_SIZE*4-1, 8); - a.Set(TIGHTDB_MAX_LIST_SIZE*4, 9); - a.Set(TIGHTDB_MAX_LIST_SIZE*5-1, 10); + a.set(0, 1); + a.set(TIGHTDB_MAX_LIST_SIZE-1, 2); + a.set(TIGHTDB_MAX_LIST_SIZE, 3); + a.set(TIGHTDB_MAX_LIST_SIZE*2-1, 4); + a.set(TIGHTDB_MAX_LIST_SIZE*2, 5); + a.set(TIGHTDB_MAX_LIST_SIZE*3-1, 6); + a.set(TIGHTDB_MAX_LIST_SIZE*3, 7); + a.set(TIGHTDB_MAX_LIST_SIZE*4-1, 8); + a.set(TIGHTDB_MAX_LIST_SIZE*4, 9); + a.set(TIGHTDB_MAX_LIST_SIZE*5-1, 10); const size_t res1 = a.find_first(1); const size_t res2 = a.find_first(2); @@ -512,7 +512,7 @@ TEST(Column_FindAll_IntMin) size_t i = 0; size_t j = 0; while (i < c.Size()){ - if (c.Get(i) == value) + if (c.get(i) == value) CHECK_EQUAL(int64_t(i), r.Get(j++)); i += 1; } @@ -544,7 +544,7 @@ TEST(Column_FindAll_IntMax) size_t i = 0; size_t j = 0; while (i < c.Size()){ - if (c.Get(i) == value) + if (c.get(i) == value) CHECK_EQUAL(int64_t(i), r.Get(j++)); i += 1; } @@ -614,7 +614,7 @@ TEST(Column_Sum_Average) // Sum of entire range, using default args sum = 0; for (int i = 0; i < 100; i++) { - sum += c.Get(i); + sum += c.get(i); } CHECK_EQUAL(sum, c.sum()); CHECK_EQUAL(sum/100.0, c.average()); @@ -622,7 +622,7 @@ TEST(Column_Sum_Average) // Sum of entire range, given explicit range sum = 0; for (int i = 0; i < 100; i++) { - sum += c.Get(i); + sum += c.get(i); } CHECK_EQUAL(sum, c.sum(0, 100)); CHECK_EQUAL(sum/100.0, c.average(0,100)); @@ -630,7 +630,7 @@ TEST(Column_Sum_Average) // Start to N sum = 0; for (int i = 0; i < 63; i++) { - sum += c.Get(i); + sum += c.get(i); } CHECK_EQUAL(sum, c.sum(0, 63)); CHECK_EQUAL(sum/63.0, c.average(0, 63)); @@ -638,7 +638,7 @@ TEST(Column_Sum_Average) // N to end sum = 0; for (int i = 47; i < 100; i++) { - sum += c.Get(i); + sum += c.get(i); } CHECK_EQUAL(sum, c.sum(47, 100)); CHECK_EQUAL(sum/(100.0-47.0), c.average(47, 100)); @@ -646,7 +646,7 @@ TEST(Column_Sum_Average) // N to M sum = 0; for (int i = 55; i < 79; i++) { - sum += c.Get(i); + sum += c.get(i); } CHECK_EQUAL(sum, c.sum(55, 79)); CHECK_EQUAL(sum/(79.0-55.0), c.average(55, 79)); @@ -676,10 +676,10 @@ TEST(Column_Max2) for (int i = 0; i < 100; i++) { c.add(10); } - c.Set(20, 20); - c.Set(50, 11); // Max must select *first* occurence of largest value - c.Set(51, 11); - c.Set(81, 20); + c.set(20, 20); + c.set(50, 11); // Max must select *first* occurence of largest value + c.set(51, 11); + c.set(81, 20); int64_t t = c.maximum(51, 81); CHECK_EQUAL(11, t); @@ -708,10 +708,10 @@ TEST(Column_Min2) for (int i = 0; i < 100; i++) { c.add(10); } - c.Set(20, 20); - c.Set(50, 9); // Max must select *first* occurence of lowest value - c.Set(51, 9); - c.Set(81, 20); + c.set(20, 20); + c.set(50, 9); // Max must select *first* occurence of lowest value + c.set(51, 9); + c.set(81, 20); int64_t t = c.minimum(51, 81); CHECK_EQUAL(9, t); @@ -730,7 +730,7 @@ TEST(Column_Sort2) c.sort(); for (size_t t = 1; t < 9*TIGHTDB_MAX_LIST_SIZE; t++) { - CHECK(c.Get(t) >= c.Get(t - 1)); + CHECK(c.get(t) >= c.get(t - 1)); } c.Destroy(); @@ -748,9 +748,9 @@ TEST(Column_prepend_many) for (size_t items = 0; items < 3000; ++items) { a.Clear(); for (size_t j = 0; j < items + 1; ++j) { - a.Insert(0, j); + a.insert(0, j); } - a.Insert(items, 444); + a.insert(items, 444); } a.Destroy(); } diff --git a/test/testcolumnbinary.cpp b/test/testcolumnbinary.cpp index 17fefd0bd69..f3441bbce2a 100644 --- a/test/testcolumnbinary.cpp +++ b/test/testcolumnbinary.cpp @@ -11,36 +11,36 @@ ColumnBinary db_setup_column_binary::c; TEST_FIXTURE(db_setup_column_binary, ColumnBinaryMultiEmpty) { - c.add("", 0); - c.add("", 0); - c.add("", 0); - c.add(NULL, 0); - c.add(NULL, 0); - c.add(NULL, 0); + c.add(BinaryData("", 0)); + c.add(BinaryData("", 0)); + c.add(BinaryData("", 0)); + c.add(BinaryData()); + c.add(BinaryData()); + c.add(BinaryData()); CHECK_EQUAL(6, c.Size()); - CHECK_EQUAL(0, c.get_size(0)); - CHECK_EQUAL(0, c.get_size(1)); - CHECK_EQUAL(0, c.get_size(2)); - CHECK_EQUAL(0, c.get_size(3)); - CHECK_EQUAL(0, c.get_size(4)); - CHECK_EQUAL(0, c.get_size(5)); + CHECK_EQUAL(0, c.get(0).size()); + CHECK_EQUAL(0, c.get(1).size()); + CHECK_EQUAL(0, c.get(2).size()); + CHECK_EQUAL(0, c.get(3).size()); + CHECK_EQUAL(0, c.get(4).size()); + CHECK_EQUAL(0, c.get(5).size()); } TEST_FIXTURE(db_setup_column_binary, ColumnBinarySet) { - c.Set(0, "hey", 4); + c.set(0, BinaryData("hey", 4)); CHECK_EQUAL(6, c.Size()); - CHECK_EQUAL("hey", c.get_data(0)); - CHECK_EQUAL(4, c.get_size(0)); - CHECK_EQUAL(0, c.get_size(1)); - CHECK_EQUAL(0, c.get_size(2)); - CHECK_EQUAL(0, c.get_size(3)); - CHECK_EQUAL(0, c.get_size(4)); - CHECK_EQUAL(0, c.get_size(5)); + CHECK_EQUAL("hey", c.get(0).data()); + CHECK_EQUAL(4, c.get(0).size()); + CHECK_EQUAL(0, c.get(1).size()); + CHECK_EQUAL(0, c.get(2).size()); + CHECK_EQUAL(0, c.get(3).size()); + CHECK_EQUAL(0, c.get(4).size()); + CHECK_EQUAL(0, c.get(5).size()); } TEST_FIXTURE(db_setup_column_binary, ColumnBinaryAdd) @@ -48,16 +48,16 @@ TEST_FIXTURE(db_setup_column_binary, ColumnBinaryAdd) c.Clear(); CHECK_EQUAL(0, c.Size()); - c.add("abc", 4); - CHECK_EQUAL("abc", c.get_data(0)); // single - CHECK_EQUAL(4, c.get_size(0)); + c.add(BinaryData("abc", 4)); + CHECK_EQUAL("abc", c.get(0).data()); // single + CHECK_EQUAL(4, c.get(0).size()); CHECK_EQUAL(1, c.Size()); - c.add("defg", 5); //non-empty - CHECK_EQUAL("abc", c.get_data(0)); - CHECK_EQUAL("defg", c.get_data(1)); - CHECK_EQUAL(4, c.get_size(0)); - CHECK_EQUAL(5, c.get_size(1)); + c.add(BinaryData("defg", 5)); //non-empty + CHECK_EQUAL("abc", c.get(0).data()); + CHECK_EQUAL("defg", c.get(1).data()); + CHECK_EQUAL(4, c.get(0).size()); + CHECK_EQUAL(5, c.get(1).size()); CHECK_EQUAL(2, c.Size()); } @@ -66,53 +66,53 @@ TEST_FIXTURE(db_setup_column_binary, ColumnBinarySet2) // {shrink, grow} x {first, middle, last, single} c.Clear(); - c.add("abc", 4); - c.Set(0, "de", 3); // shrink single - CHECK_EQUAL("de", c.get_data(0)); + c.add(BinaryData("abc", 4)); + c.set(0, BinaryData("de", 3)); // shrink single + CHECK_EQUAL("de", c.get(0).data()); CHECK_EQUAL(1, c.Size()); - c.Set(0, "abcd", 5); // grow single - CHECK_EQUAL("abcd", c.get_data(0)); + c.set(0, BinaryData("abcd", 5)); // grow single + CHECK_EQUAL("abcd", c.get(0).data()); CHECK_EQUAL(1, c.Size()); - c.add("efg", 4); - CHECK_EQUAL("abcd", c.get_data(0)); - CHECK_EQUAL("efg", c.get_data(1)); + c.add(BinaryData("efg", 4)); + CHECK_EQUAL("abcd", c.get(0).data()); + CHECK_EQUAL("efg", c.get(1).data()); CHECK_EQUAL(2, c.Size()); - c.Set(1, "hi", 3); // shrink last - CHECK_EQUAL("abcd", c.get_data(0)); - CHECK_EQUAL("hi", c.get_data(1)); + c.set(1, BinaryData("hi", 3)); // shrink last + CHECK_EQUAL("abcd", c.get(0).data()); + CHECK_EQUAL("hi", c.get(1).data()); CHECK_EQUAL(2, c.Size()); - c.Set(1, "jklmno", 7); // grow last - CHECK_EQUAL("abcd", c.get_data(0)); - CHECK_EQUAL("jklmno", c.get_data(1)); + c.set(1, BinaryData("jklmno", 7)); // grow last + CHECK_EQUAL("abcd", c.get(0).data()); + CHECK_EQUAL("jklmno", c.get(1).data()); CHECK_EQUAL(2, c.Size()); - c.add("pq", 3); - c.Set(1, "efghijkl", 9); // grow middle - CHECK_EQUAL("abcd", c.get_data(0)); - CHECK_EQUAL("efghijkl", c.get_data(1)); - CHECK_EQUAL("pq", c.get_data(2)); + c.add(BinaryData("pq", 3)); + c.set(1, BinaryData("efghijkl", 9)); // grow middle + CHECK_EQUAL("abcd", c.get(0).data()); + CHECK_EQUAL("efghijkl", c.get(1).data()); + CHECK_EQUAL("pq", c.get(2).data()); CHECK_EQUAL(3, c.Size()); - c.Set(1, "x", 2); // shrink middle - CHECK_EQUAL("abcd", c.get_data(0)); - CHECK_EQUAL("x", c.get_data(1)); - CHECK_EQUAL("pq", c.get_data(2)); + c.set(1, BinaryData("x", 2)); // shrink middle + CHECK_EQUAL("abcd", c.get(0).data()); + CHECK_EQUAL("x", c.get(1).data()); + CHECK_EQUAL("pq", c.get(2).data()); CHECK_EQUAL(3, c.Size()); - c.Set(0, "qwertyuio", 10); // grow first - CHECK_EQUAL("qwertyuio", c.get_data(0)); - CHECK_EQUAL("x", c.get_data(1)); - CHECK_EQUAL("pq", c.get_data(2)); + c.set(0, BinaryData("qwertyuio", 10)); // grow first + CHECK_EQUAL("qwertyuio", c.get(0).data()); + CHECK_EQUAL("x", c.get(1).data()); + CHECK_EQUAL("pq", c.get(2).data()); CHECK_EQUAL(3, c.Size()); - c.Set(0, "mno", 4); // shrink first - CHECK_EQUAL("mno", c.get_data(0)); - CHECK_EQUAL("x", c.get_data(1)); - CHECK_EQUAL("pq", c.get_data(2)); + c.set(0, BinaryData("mno", 4)); // shrink first + CHECK_EQUAL("mno", c.get(0).data()); + CHECK_EQUAL("x", c.get(1).data()); + CHECK_EQUAL("pq", c.get(2).data()); CHECK_EQUAL(3, c.Size()); } @@ -120,43 +120,43 @@ TEST_FIXTURE(db_setup_column_binary, ColumnBinaryInsert) { c.Clear(); - c.Insert(0, "abc", 4); // single - CHECK_EQUAL("abc", c.get_data(0)); + c.insert(0, BinaryData("abc", 4)); // single + CHECK_EQUAL("abc", c.get(0).data()); CHECK_EQUAL(1, c.Size()); - c.Insert(1, "d", 2); // end - CHECK_EQUAL("abc", c.get_data(0)); - CHECK_EQUAL("d", c.get_data(1)); + c.insert(1, BinaryData("d", 2)); // end + CHECK_EQUAL("abc", c.get(0).data()); + CHECK_EQUAL("d", c.get(1).data()); CHECK_EQUAL(2, c.Size()); - c.Insert(2, "ef", 3); // end - CHECK_EQUAL("abc", c.get_data(0)); - CHECK_EQUAL("d", c.get_data(1)); - CHECK_EQUAL("ef", c.get_data(2)); + c.insert(2, BinaryData("ef", 3)); // end + CHECK_EQUAL("abc", c.get(0).data()); + CHECK_EQUAL("d", c.get(1).data()); + CHECK_EQUAL("ef", c.get(2).data()); CHECK_EQUAL(3, c.Size()); - c.Insert(1, "ghij", 5); // middle - CHECK_EQUAL("abc", c.get_data(0)); - CHECK_EQUAL("ghij", c.get_data(1)); - CHECK_EQUAL("d", c.get_data(2)); - CHECK_EQUAL("ef", c.get_data(3)); + c.insert(1, BinaryData("ghij", 5)); // middle + CHECK_EQUAL("abc", c.get(0).data()); + CHECK_EQUAL("ghij", c.get(1).data()); + CHECK_EQUAL("d", c.get(2).data()); + CHECK_EQUAL("ef", c.get(3).data()); CHECK_EQUAL(4, c.Size()); - c.Insert(0, "klmno", 6); // first - CHECK_EQUAL("klmno", c.get_data(0)); - CHECK_EQUAL("abc", c.get_data(1)); - CHECK_EQUAL("ghij", c.get_data(2)); - CHECK_EQUAL("d", c.get_data(3)); - CHECK_EQUAL("ef", c.get_data(4)); + c.insert(0, BinaryData("klmno", 6)); // first + CHECK_EQUAL("klmno", c.get(0).data()); + CHECK_EQUAL("abc", c.get(1).data()); + CHECK_EQUAL("ghij", c.get(2).data()); + CHECK_EQUAL("d", c.get(3).data()); + CHECK_EQUAL("ef", c.get(4).data()); CHECK_EQUAL(5, c.Size()); - c.Insert(2, "as", 3); // middle again - CHECK_EQUAL("klmno", c.get_data(0)); - CHECK_EQUAL("abc", c.get_data(1)); - CHECK_EQUAL("as", c.get_data(2)); - CHECK_EQUAL("ghij", c.get_data(3)); - CHECK_EQUAL("d", c.get_data(4)); - CHECK_EQUAL("ef", c.get_data(5)); + c.insert(2, BinaryData("as", 3)); // middle again + CHECK_EQUAL("klmno", c.get(0).data()); + CHECK_EQUAL("abc", c.get(1).data()); + CHECK_EQUAL("as", c.get(2).data()); + CHECK_EQUAL("ghij", c.get(3).data()); + CHECK_EQUAL("d", c.get(4).data()); + CHECK_EQUAL("ef", c.get(5).data()); CHECK_EQUAL(6, c.Size()); } @@ -164,35 +164,35 @@ TEST_FIXTURE(db_setup_column_binary, ColumnBinaryDelete) { c.Clear(); - c.add("a", 2); - c.add("bc", 3); - c.add("def", 4); - c.add("ghij", 5); - c.add("klmno", 6); - - c.Delete(0); // first - CHECK_EQUAL("bc", c.get_data(0)); - CHECK_EQUAL("def", c.get_data(1)); - CHECK_EQUAL("ghij", c.get_data(2)); - CHECK_EQUAL("klmno", c.get_data(3)); + c.add(BinaryData("a", 2)); + c.add(BinaryData("bc", 3)); + c.add(BinaryData("def", 4)); + c.add(BinaryData("ghij", 5)); + c.add(BinaryData("klmno", 6)); + + c.erase(0); // first + CHECK_EQUAL("bc", c.get(0).data()); + CHECK_EQUAL("def", c.get(1).data()); + CHECK_EQUAL("ghij", c.get(2).data()); + CHECK_EQUAL("klmno", c.get(3).data()); CHECK_EQUAL(4, c.Size()); - c.Delete(3); // last - CHECK_EQUAL("bc", c.get_data(0)); - CHECK_EQUAL("def", c.get_data(1)); - CHECK_EQUAL("ghij", c.get_data(2)); + c.erase(3); // last + CHECK_EQUAL("bc", c.get(0).data()); + CHECK_EQUAL("def", c.get(1).data()); + CHECK_EQUAL("ghij", c.get(2).data()); CHECK_EQUAL(3, c.Size()); - c.Delete(1); // middle - CHECK_EQUAL("bc", c.get_data(0)); - CHECK_EQUAL("ghij", c.get_data(1)); + c.erase(1); // middle + CHECK_EQUAL("bc", c.get(0).data()); + CHECK_EQUAL("ghij", c.get(1).data()); CHECK_EQUAL(2, c.Size()); - c.Delete(0); // single - CHECK_EQUAL("ghij", c.get_data(0)); + c.erase(0); // single + CHECK_EQUAL("ghij", c.get(0).data()); CHECK_EQUAL(1, c.Size()); - c.Delete(0); // all + c.erase(0); // all CHECK_EQUAL(0, c.Size()); CHECK(c.is_empty()); } diff --git a/test/testcolumnfloat.cpp b/test/testcolumnfloat.cpp index 02a7be57e7b..2437255dc91 100644 --- a/test/testcolumnfloat.cpp +++ b/test/testcolumnfloat.cpp @@ -32,7 +32,7 @@ const size_t doubleValLen = SizeOfArray(doubleVal); void printCol(ColumnFloat& c) { for (size_t i=0; i < c.Size(); ++i) { - std::cerr << " Col[" << i << "] = " << c.Get(i) << " \n"; + std::cerr << " Col[" << i << "] = " << c.get(i) << " \n"; } } @@ -59,7 +59,7 @@ void BasicColumn_AddGet(T val[], size_t valLen) CHECK_EQUAL(i+1, c.Size()); for (size_t j=0; jadd("Test", 1, true, Wed); - CHECK_EQUAL("Test", static_cast(t[0].first)); + CHECK_EQUAL("Test", t[0].first); CHECK_EQUAL(1, t[0].second); CHECK_EQUAL(true, t[0].third); CHECK_EQUAL(Wed, t[0].fourth); @@ -253,7 +253,7 @@ TEST(Group_Serialize_Mem) #endif // TIGHTDB_DEBUG // Serialize to memory (we now own the buffer) - const Group::BufferSpec buffer = toMem.write_to_mem(); + BinaryData buffer = toMem.write_to_mem(); // Load the table Group fromMem(buffer); @@ -278,7 +278,7 @@ TEST(Group_Close) table->add("", 2, true, Wed); // Serialize to memory (we now own the buffer) - const Group::BufferSpec buffer = toMem->write_to_mem(); + BinaryData buffer = toMem->write_to_mem(); Group *fromMem = new Group(buffer); delete toMem; @@ -306,7 +306,7 @@ TEST(Group_Serialize_Optimized) #endif // TIGHTDB_DEBUG // Serialize to memory (we now own the buffer) - const Group::BufferSpec buffer = toMem.write_to_mem(); + BinaryData buffer = toMem.write_to_mem(); // Load the table Group fromMem(buffer); @@ -348,12 +348,12 @@ TEST(Group_Serialize_All) table->insert_bool(1, 0, true); table->insert_date(2, 0, 12345); table->insert_string(3, 0, "test"); - table->insert_binary(4, 0, "binary", 7); + table->insert_binary(4, 0, BinaryData("binary", 7)); table->insert_mixed(5, 0, false); table->insert_done(); // Serialize to memory (we now own the buffer) - const Group::BufferSpec buffer = toMem.write_to_mem(); + BinaryData buffer = toMem.write_to_mem(); // Load the table Group fromMem(buffer); @@ -363,10 +363,10 @@ TEST(Group_Serialize_All) CHECK_EQUAL(1, t->size()); CHECK_EQUAL(12, t->get_int(0, 0)); CHECK_EQUAL(true, t->get_bool(1, 0)); - CHECK_EQUAL((time_t)12345, t->get_date(2, 0)); + CHECK_EQUAL(time_t(12345), t->get_date(2, 0)); CHECK_EQUAL("test", t->get_string(3, 0)); - CHECK_EQUAL(7, t->get_binary(4, 0).len); - CHECK_EQUAL("binary", (const char*)t->get_binary(4, 0).pointer); + CHECK_EQUAL(7, t->get_binary(4, 0).size()); + CHECK_EQUAL("binary", t->get_binary(4, 0).data()); CHECK_EQUAL(type_Bool, t->get_mixed(5, 0).get_type()); CHECK_EQUAL(false, t->get_mixed(5, 0).get_bool()); } @@ -391,7 +391,7 @@ TEST(Group_Persist) table->insert_bool(1, 0, true); table->insert_date(2, 0, 12345); table->insert_string(3, 0, "test"); - table->insert_binary(4, 0, "binary", 7); + table->insert_binary(4, 0, BinaryData("binary", 7)); table->insert_mixed(5, 0, false); table->insert_done(); @@ -406,10 +406,10 @@ TEST(Group_Persist) CHECK_EQUAL(1, table->size()); CHECK_EQUAL(12, table->get_int(0, 0)); CHECK_EQUAL(true, table->get_bool(1, 0)); - CHECK_EQUAL((time_t)12345, table->get_date(2, 0)); + CHECK_EQUAL(time_t(12345), table->get_date(2, 0)); CHECK_EQUAL("test", table->get_string(3, 0)); - CHECK_EQUAL(7, table->get_binary(4, 0).len); - CHECK_EQUAL("binary", (const char*)table->get_binary(4, 0).pointer); + CHECK_EQUAL(7, table->get_binary(4, 0).size()); + CHECK_EQUAL("binary", table->get_binary(4, 0).data()); CHECK_EQUAL(type_Bool, table->get_mixed(5, 0).get_type()); CHECK_EQUAL(false, table->get_mixed(5, 0).get_bool()); @@ -427,10 +427,10 @@ TEST(Group_Persist) CHECK_EQUAL(1, table->size()); CHECK_EQUAL(12, table->get_int(0, 0)); CHECK_EQUAL(true, table->get_bool(1, 0)); - CHECK_EQUAL((time_t)12345, table->get_date(2, 0)); + CHECK_EQUAL(time_t(12345), table->get_date(2, 0)); CHECK_EQUAL("Changed!", table->get_string(3, 0)); - CHECK_EQUAL(7, table->get_binary(4, 0).len); - CHECK_EQUAL("binary", (const char*)table->get_binary(4, 0).pointer); + CHECK_EQUAL(7, table->get_binary(4, 0).size()); + CHECK_EQUAL("binary", table->get_binary(4, 0).data()); CHECK_EQUAL(type_Bool, table->get_mixed(5, 0).get_type()); CHECK_EQUAL(false, table->get_mixed(5, 0).get_bool()); } @@ -880,7 +880,7 @@ TEST(Group_Index_String) CHECK_EQUAL(2, c1); // Serialize to memory (we now own the buffer) - const Group::BufferSpec buffer = toMem.write_to_mem(); + BinaryData buffer = toMem.write_to_mem(); // Load the table Group fromMem(buffer); diff --git a/test/testindexstring.cpp b/test/testindexstring.cpp index 5a5ed7bb354..f13f8b45f55 100644 --- a/test/testindexstring.cpp +++ b/test/testindexstring.cpp @@ -65,13 +65,13 @@ TEST(StringIndex_DeleteAll) // Delete all entries // (reverse order to avoid ref updates) - col.Delete(6); - col.Delete(5); - col.Delete(4); - col.Delete(3); - col.Delete(2); - col.Delete(1); - col.Delete(0); + col.erase(6); + col.erase(5); + col.erase(4); + col.erase(3); + col.erase(2); + col.erase(1); + col.erase(0); #ifdef TIGHTDB_DEBUG CHECK(ndx.is_empty()); #else @@ -89,13 +89,13 @@ TEST(StringIndex_DeleteAll) // Delete all entries // (in order to force constant ref updating) - col.Delete(0); - col.Delete(0); - col.Delete(0); - col.Delete(0); - col.Delete(0); - col.Delete(0); - col.Delete(0); + col.erase(0); + col.erase(0); + col.erase(0); + col.erase(0); + col.erase(0); + col.erase(0); + col.erase(0); #ifdef TIGHTDB_DEBUG CHECK(ndx.is_empty()); #else @@ -120,7 +120,7 @@ TEST(StringIndex_Delete) const StringIndex& ndx = col.CreateIndex(); // Delete first item (in index) - col.Delete(1); + col.erase(1); CHECK_EQUAL(0, col.find_first(s1)); CHECK_EQUAL(1, col.find_first(s3)); @@ -128,7 +128,7 @@ TEST(StringIndex_Delete) CHECK_EQUAL(not_found, ndx.find_first(s2)); // Delete last item (in index) - col.Delete(2); + col.erase(2); CHECK_EQUAL(0, col.find_first(s1)); CHECK_EQUAL(1, col.find_first(s3)); @@ -136,7 +136,7 @@ TEST(StringIndex_Delete) CHECK_EQUAL(not_found, col.find_first(s2)); // Delete middle item (in index) - col.Delete(1); + col.erase(1); CHECK_EQUAL(0, col.find_first(s1)); CHECK_EQUAL(not_found, col.find_first(s3)); @@ -144,8 +144,8 @@ TEST(StringIndex_Delete) CHECK_EQUAL(not_found, col.find_first(s2)); // Delete all items - col.Delete(0); - col.Delete(0); + col.erase(0); + col.erase(0); #ifdef TIGHTDB_DEBUG CHECK(ndx.is_empty()); #endif @@ -168,7 +168,7 @@ TEST(StringIndex_Insert) col.CreateIndex(); // Insert item in top of column - col.Insert(0, s5); + col.insert(0, s5); CHECK_EQUAL(0, col.find_first(s5)); CHECK_EQUAL(1, col.find_first(s1)); @@ -178,7 +178,7 @@ TEST(StringIndex_Insert) //CHECK_EQUAL(5, ndx.find_first(s1)); // duplicate // Append item in end of column - col.Insert(6, s6); + col.insert(6, s6); CHECK_EQUAL(0, col.find_first(s5)); CHECK_EQUAL(1, col.find_first(s1)); @@ -188,7 +188,7 @@ TEST(StringIndex_Insert) CHECK_EQUAL(6, col.find_first(s6)); // Insert item in middle - col.Insert(3, s7); + col.insert(3, s7); CHECK_EQUAL(0, col.find_first(s5)); CHECK_EQUAL(1, col.find_first(s1)); @@ -216,7 +216,7 @@ TEST(StringIndex_Set) col.CreateIndex(); // Set top value - col.Set(0, s5); + col.set(0, s5); CHECK_EQUAL(0, col.find_first(s5)); CHECK_EQUAL(1, col.find_first(s2)); @@ -225,7 +225,7 @@ TEST(StringIndex_Set) CHECK_EQUAL(4, col.find_first(s1)); // Set bottom value - col.Set(4, s6); + col.set(4, s6); CHECK_EQUAL(not_found, col.find_first(s1)); CHECK_EQUAL(0, col.find_first(s5)); @@ -235,7 +235,7 @@ TEST(StringIndex_Set) CHECK_EQUAL(4, col.find_first(s6)); // Set middle value - col.Set(2, s7); + col.set(2, s7); CHECK_EQUAL(not_found, col.find_first(s3)); CHECK_EQUAL(not_found, col.find_first(s1)); diff --git a/test/testshared.cpp b/test/testshared.cpp index c41011c2a33..030c4dbf85f 100644 --- a/test/testshared.cpp +++ b/test/testshared.cpp @@ -109,7 +109,7 @@ TEST(Shared_Initial2) CHECK_EQUAL(1, t1[0].first); CHECK_EQUAL(2, t1[0].second); CHECK_EQUAL(false, t1[0].third); - CHECK_EQUAL("test", (const char*)t1[0].fourth); + CHECK_EQUAL("test", t1[0].fourth); } } @@ -154,7 +154,7 @@ TEST(Shared_Initial2_Mem) CHECK_EQUAL(1, t1[0].first); CHECK_EQUAL(2, t1[0].second); CHECK_EQUAL(false, t1[0].third); - CHECK_EQUAL("test", (const char*)t1[0].fourth); + CHECK_EQUAL("test", t1[0].fourth); } } @@ -192,7 +192,7 @@ TEST(Shared1) CHECK_EQUAL(1, t2[0].first); CHECK_EQUAL(2, t2[0].second); CHECK_EQUAL(false, t2[0].third); - CHECK_EQUAL("test", (const char*)t2[0].fourth); + CHECK_EQUAL("test", t2[0].fourth); // Do a new change while stil having current read transaction open { @@ -208,7 +208,7 @@ TEST(Shared1) CHECK_EQUAL(1, t2[0].first); CHECK_EQUAL(2, t2[0].second); CHECK_EQUAL(false, t2[0].third); - CHECK_EQUAL("test", (const char*)t2[0].fourth); + CHECK_EQUAL("test", t2[0].fourth); // Do one more new change while stil having current read transaction open // so we know that it does not overwrite data held by @@ -225,7 +225,7 @@ TEST(Shared1) CHECK_EQUAL(1, t2[0].first); CHECK_EQUAL(2, t2[0].second); CHECK_EQUAL(false, t2[0].third); - CHECK_EQUAL("test", (const char*)t2[0].fourth); + CHECK_EQUAL("test", t2[0].fourth); } // Start a new read transaction and verify that it can now see the changes @@ -237,15 +237,15 @@ TEST(Shared1) CHECK_EQUAL(1, t3[0].first); CHECK_EQUAL(2, t3[0].second); CHECK_EQUAL(false, t3[0].third); - CHECK_EQUAL("test", (const char*)t3[0].fourth); + CHECK_EQUAL("test", t3[0].fourth); CHECK_EQUAL(2, t3[1].first); CHECK_EQUAL(3, t3[1].second); CHECK_EQUAL(true, t3[1].third); - CHECK_EQUAL("more test", (const char*)t3[1].fourth); + CHECK_EQUAL("more test", t3[1].fourth); CHECK_EQUAL(0, t3[2].first); CHECK_EQUAL(1, t3[2].second); CHECK_EQUAL(false, t3[2].third); - CHECK_EQUAL("even more test", (const char*)t3[2].fourth); + CHECK_EQUAL("even more test", t3[2].fourth); } } @@ -293,7 +293,7 @@ TEST(Shared_rollback) CHECK_EQUAL(1, t[0].first); CHECK_EQUAL(2, t[0].second); CHECK_EQUAL(false, t[0].third); - CHECK_EQUAL("test", (const char*)t[0].fourth); + CHECK_EQUAL("test", t[0].fourth); } // Greate more changes (but rollback) @@ -312,7 +312,7 @@ TEST(Shared_rollback) CHECK_EQUAL(1, t[0].first); CHECK_EQUAL(2, t[0].second); CHECK_EQUAL(false, t[0].third); - CHECK_EQUAL("test", (const char*)t[0].fourth); + CHECK_EQUAL("test", t[0].fourth); } } @@ -762,7 +762,7 @@ TEST(Shared_Notifications) CHECK_EQUAL(1, t1[0].first); CHECK_EQUAL(2, t1[0].second); CHECK_EQUAL(false, t1[0].third); - CHECK_EQUAL("test", (const char*)t1[0].fourth); + CHECK_EQUAL("test", t1[0].fourth); } // No other instance have changed db since last transaction @@ -795,7 +795,7 @@ TEST(Shared_FromSerialized) CHECK_EQUAL(1, t1[0].first); CHECK_EQUAL(2, t1[0].second); CHECK_EQUAL(false, t1[0].third); - CHECK_EQUAL("test", (const char*)t1[0].fourth); + CHECK_EQUAL("test", t1[0].fourth); } } diff --git a/test/testtable.cpp b/test/testtable.cpp index 21ed99f85e4..747b012af12 100644 --- a/test/testtable.cpp +++ b/test/testtable.cpp @@ -180,7 +180,7 @@ TEST(Table4) const TestTableEnum::Cursor r = table.back(); // last item CHECK_EQUAL(Mon, r.first); - CHECK_EQUAL("HelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHello", (const char*)r.second); + CHECK_EQUAL("HelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHello", r.second); // Test string column searching CHECK_EQUAL(size_t(1), table.column().second.find_first("HelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHello")); @@ -315,6 +315,8 @@ TEST(Table_HighLevelCopy) } +namespace { + void setup_multi_table(Table& table, const size_t rows, const size_t sub_rows) { // Create table with all column types @@ -362,14 +364,14 @@ void setup_multi_table(Table& table, const size_t rows, const size_t sub_rows) break; } - table.insert_binary(8, i, "binary", 7); + table.insert_binary(8, i, BinaryData("binary", 7)); switch (i % 8) { case 0: - table.insert_mixed(9, i, (bool)false); + table.insert_mixed(9, i, false); break; case 1: - table.insert_mixed(9, i, (int64_t)(i*i*sign)); + table.insert_mixed(9, i, int64_t(i*i*sign)); break; case 2: table.insert_mixed(9, i, "string"); @@ -378,7 +380,7 @@ void setup_multi_table(Table& table, const size_t rows, const size_t sub_rows) table.insert_mixed(9, i, Date(123456789)); break; case 4: - table.insert_mixed(9, i, Mixed(BinaryData("binary", 7))); + table.insert_mixed(9, i, BinaryData("binary", 7)); break; case 5: { @@ -424,6 +426,8 @@ void setup_multi_table(Table& table, const size_t rows, const size_t sub_rows) table.optimize(); } +} // anonymous namespace + TEST(Table_Delete_All_Types) { @@ -539,7 +543,7 @@ TEST(Table_test_json_simple) table.insert_date(2, i, 0x7fffeeeeL); table.insert_string(3, i, "helloooooo"); const char bin[] = "123456789012345678901234567890nopq"; - table.insert_binary(4, i, bin, sizeof(bin) ); + table.insert_binary(4, i, BinaryData(bin, sizeof bin)); table.insert_done(); } @@ -898,11 +902,11 @@ TEST(TableAutoEnumeration) CHECK_EQUAL(8, table[3+n].first); CHECK_EQUAL(9, table[4+n].first); - CHECK_EQUAL("abd", (const char*)table[0+n].second); - CHECK_EQUAL("eftg", (const char*)table[1+n].second); - CHECK_EQUAL("hijkl", (const char*)table[2+n].second); - CHECK_EQUAL("mnopqr", (const char*)table[3+n].second); - CHECK_EQUAL("stuvxyz", (const char*)table[4+n].second); + CHECK_EQUAL("abd", table[0+n].second); + CHECK_EQUAL("eftg", table[1+n].second); + CHECK_EQUAL("hijkl", table[2+n].second); + CHECK_EQUAL("mnopqr", table[3+n].second); + CHECK_EQUAL("stuvxyz", table[4+n].second); CHECK_EQUAL(true, table[0+n].third); CHECK_EQUAL(true, table[1+n].third); @@ -950,11 +954,11 @@ TEST(TableAutoEnumerationFindFindAll) TestTableAE::View tv = table.column().second.find_all("eftg"); CHECK_EQUAL(5, tv.size()); - CHECK_EQUAL("eftg", static_cast(tv[0].second)); - CHECK_EQUAL("eftg", static_cast(tv[1].second)); - CHECK_EQUAL("eftg", static_cast(tv[2].second)); - CHECK_EQUAL("eftg", static_cast(tv[3].second)); - CHECK_EQUAL("eftg", static_cast(tv[4].second)); + CHECK_EQUAL("eftg", tv[0].second); + CHECK_EQUAL("eftg", tv[1].second); + CHECK_EQUAL("eftg", tv[2].second); + CHECK_EQUAL("eftg", tv[3].second); + CHECK_EQUAL("eftg", tv[4].second); } namespace { @@ -1535,8 +1539,8 @@ TEST(Table_Mixed) CHECK_EQUAL(12, table.get_mixed(1, 1).get_int()); CHECK_EQUAL("test", table.get_mixed(1, 2).get_string()); CHECK_EQUAL(324234, table.get_mixed(1, 3).get_date()); - CHECK_EQUAL("binary", (const char*)table.get_mixed(1, 4).get_binary().pointer); - CHECK_EQUAL(7, table.get_mixed(1, 4).get_binary().len); + CHECK_EQUAL("binary", table.get_mixed(1, 4).get_binary().data()); + CHECK_EQUAL(7, table.get_mixed(1, 4).get_binary().size()); table.insert_int(0, 5, 0); table.insert_mixed(1, 5, Mixed::subtable_tag()); @@ -1557,8 +1561,8 @@ TEST(Table_Mixed) CHECK_EQUAL(12, table.get_mixed(1, 1).get_int()); CHECK_EQUAL("test", table.get_mixed(1, 2).get_string()); CHECK_EQUAL(324234, table.get_mixed(1, 3).get_date()); - CHECK_EQUAL("binary", (const char*)table.get_mixed(1, 4).get_binary().pointer); - CHECK_EQUAL(7, table.get_mixed(1, 4).get_binary().len); + CHECK_EQUAL("binary", table.get_mixed(1, 4).get_binary().data()); + CHECK_EQUAL(7, table.get_mixed(1, 4).get_binary().size()); // Get table from mixed column and add schema and some values TableRef subtable = table.get_subtable(1, 5); @@ -1602,8 +1606,8 @@ TEST(Table_Mixed) CHECK_EQUAL(12, table.get_mixed(1, 1).get_int()); CHECK_EQUAL("test", table.get_mixed(1, 2).get_string()); CHECK_EQUAL(324234, table.get_mixed(1, 3).get_date()); - CHECK_EQUAL("binary", (const char*)table.get_mixed(1, 4).get_binary().pointer); - CHECK_EQUAL(7, table.get_mixed(1, 4).get_binary().len); + CHECK_EQUAL("binary", table.get_mixed(1, 4).get_binary().data()); + CHECK_EQUAL(7, table.get_mixed(1, 4).get_binary().size()); CHECK_EQUAL(float(1.123), table.get_mixed(1, 6).get_float()); CHECK_EQUAL(double(2.234), table.get_mixed(1, 7).get_double()); @@ -1892,8 +1896,8 @@ TEST(Table_DateAndBinary) for (size_t i=0; i