Chris@16: #ifndef GREGORIAN_SERIALIZE_HPP___ Chris@16: #define GREGORIAN_SERIALIZE_HPP___ Chris@16: Chris@16: /* Copyright (c) 2004-2005 CrystalClear Software, Inc. Chris@16: * Use, modification and distribution is subject to the Chris@16: * Boost Software License, Version 1.0. (See accompanying Chris@16: * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) Chris@16: * Author: Jeff Garland, Bart Garst Chris@101: * $Date$ Chris@16: */ Chris@16: Chris@16: #include "boost/date_time/gregorian/gregorian_types.hpp" Chris@16: #include "boost/date_time/gregorian/parsers.hpp" Chris@16: #include "boost/serialization/split_free.hpp" Chris@16: #include "boost/serialization/nvp.hpp" Chris@16: Chris@16: Chris@16: // macros to split serialize functions into save & load functions Chris@16: // An expanded version is below for gregorian::date Chris@16: // NOTE: these macros define template functions in the boost::serialization namespace. Chris@16: // They must be expanded *outside* of any namespace Chris@16: BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::date_duration) Chris@16: BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::date_duration::duration_rep) Chris@16: BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::date_period) Chris@16: BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::greg_year) Chris@16: BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::greg_month) Chris@16: BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::greg_day) Chris@16: BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::greg_weekday) Chris@16: BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::partial_date) Chris@16: BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::nth_kday_of_month) Chris@16: BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::first_kday_of_month) Chris@16: BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::last_kday_of_month) Chris@16: BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::first_kday_before) Chris@16: BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::first_kday_after) Chris@16: Chris@16: namespace boost { Chris@16: namespace serialization { Chris@16: Chris@16: /*! Method that does serialization for gregorian::date -- splits to load/save Chris@16: */ Chris@16: template Chris@16: inline void serialize(Archive & ar, Chris@16: ::boost::gregorian::date & d, Chris@16: const unsigned int file_version) Chris@16: { Chris@16: split_free(ar, d, file_version); Chris@16: } Chris@16: Chris@16: //! Function to save gregorian::date objects using serialization lib Chris@16: /*! Dates are serialized into a string for transport and storage. Chris@16: * While it would be more efficient to store the internal Chris@16: * integer used to manipulate the dates, it is an unstable solution. Chris@16: */ Chris@16: template Chris@16: void save(Archive & ar, Chris@16: const ::boost::gregorian::date & d, Chris@16: unsigned int /* version */) Chris@16: { Chris@16: std::string ds = to_iso_string(d); Chris@16: ar & make_nvp("date", ds); Chris@16: } Chris@16: Chris@16: //! Function to load gregorian::date objects using serialization lib Chris@16: /*! Dates are serialized into a string for transport and storage. Chris@16: * While it would be more efficient to store the internal Chris@16: * integer used to manipulate the dates, it is an unstable solution. Chris@16: */ Chris@16: template Chris@16: void load(Archive & ar, Chris@16: ::boost::gregorian::date & d, Chris@16: unsigned int /*version*/) Chris@16: { Chris@16: std::string ds; Chris@16: ar & make_nvp("date", ds); Chris@16: try{ Chris@16: d = ::boost::gregorian::from_undelimited_string(ds); Chris@16: }catch(bad_lexical_cast&) { Chris@16: gregorian::special_values sv = gregorian::special_value_from_string(ds); Chris@16: if(sv == gregorian::not_special) { Chris@16: throw; // no match found, rethrow original exception Chris@16: } Chris@16: else { Chris@16: d = gregorian::date(sv); Chris@16: } Chris@16: } Chris@16: } Chris@16: Chris@16: Chris@16: //!override needed b/c no default constructor Chris@16: template Chris@16: inline void load_construct_data(Archive & /*ar*/, Chris@16: ::boost::gregorian::date* dp, Chris@16: const unsigned int /*file_version*/) Chris@16: { Chris@16: // retrieve data from archive required to construct new Chris@16: // invoke inplace constructor to initialize instance of date Chris@16: ::new(dp) ::boost::gregorian::date(::boost::gregorian::not_a_date_time); Chris@16: } Chris@16: Chris@16: /**** date_duration ****/ Chris@16: Chris@16: //! Function to save gregorian::date_duration objects using serialization lib Chris@16: template Chris@16: void save(Archive & ar, const gregorian::date_duration & dd, Chris@16: unsigned int /*version*/) Chris@16: { Chris@16: typename gregorian::date_duration::duration_rep dr = dd.get_rep(); Chris@16: ar & make_nvp("date_duration", dr); Chris@16: } Chris@16: //! Function to load gregorian::date_duration objects using serialization lib Chris@16: template Chris@16: void load(Archive & ar, gregorian::date_duration & dd, unsigned int /*version*/) Chris@16: { Chris@16: typename gregorian::date_duration::duration_rep dr(0); Chris@16: ar & make_nvp("date_duration", dr); Chris@16: dd = gregorian::date_duration(dr); Chris@16: } Chris@16: //!override needed b/c no default constructor Chris@16: template Chris@16: inline void load_construct_data(Archive & /*ar*/, gregorian::date_duration* dd, Chris@16: const unsigned int /*file_version*/) Chris@16: { Chris@16: ::new(dd) gregorian::date_duration(gregorian::not_a_date_time); Chris@16: } Chris@16: Chris@16: /**** date_duration::duration_rep (most likely int_adapter) ****/ Chris@16: Chris@16: //! helper unction to save date_duration objects using serialization lib Chris@16: template Chris@16: void save(Archive & ar, const gregorian::date_duration::duration_rep & dr, Chris@16: unsigned int /*version*/) Chris@16: { Chris@16: typename gregorian::date_duration::duration_rep::int_type it = dr.as_number(); Chris@16: ar & make_nvp("date_duration_duration_rep", it); Chris@16: } Chris@16: //! helper function to load date_duration objects using serialization lib Chris@16: template Chris@16: void load(Archive & ar, gregorian::date_duration::duration_rep & dr, unsigned int /*version*/) Chris@16: { Chris@16: typename gregorian::date_duration::duration_rep::int_type it(0); Chris@16: ar & make_nvp("date_duration_duration_rep", it); Chris@16: dr = gregorian::date_duration::duration_rep::int_type(it); Chris@16: } Chris@16: //!override needed b/c no default constructor Chris@16: template Chris@16: inline void load_construct_data(Archive & /*ar*/, gregorian::date_duration::duration_rep* dr, Chris@16: const unsigned int /*file_version*/) Chris@16: { Chris@16: ::new(dr) gregorian::date_duration::duration_rep(0); Chris@16: } Chris@16: Chris@16: /**** date_period ****/ Chris@16: Chris@16: //! Function to save gregorian::date_period objects using serialization lib Chris@16: /*! date_period objects are broken down into 2 parts for serialization: Chris@16: * the begining date object and the end date object Chris@16: */ Chris@16: template Chris@16: void save(Archive & ar, const gregorian::date_period& dp, Chris@16: unsigned int /*version*/) Chris@16: { Chris@16: gregorian::date d1 = dp.begin(); Chris@16: gregorian::date d2 = dp.end(); Chris@16: ar & make_nvp("date_period_begin_date", d1); Chris@16: ar & make_nvp("date_period_end_date", d2); Chris@16: } Chris@16: //! Function to load gregorian::date_period objects using serialization lib Chris@16: /*! date_period objects are broken down into 2 parts for serialization: Chris@16: * the begining date object and the end date object Chris@16: */ Chris@16: template Chris@16: void load(Archive & ar, gregorian::date_period& dp, unsigned int /*version*/) Chris@16: { Chris@16: gregorian::date d1(gregorian::not_a_date_time); Chris@16: gregorian::date d2(gregorian::not_a_date_time); Chris@16: ar & make_nvp("date_period_begin_date", d1); Chris@16: ar & make_nvp("date_period_end_date", d2); Chris@16: dp = gregorian::date_period(d1,d2); Chris@16: } Chris@16: //!override needed b/c no default constructor Chris@16: template Chris@16: inline void load_construct_data(Archive & /*ar*/, gregorian::date_period* dp, Chris@16: const unsigned int /*file_version*/) Chris@16: { Chris@16: gregorian::date d(gregorian::not_a_date_time); Chris@16: gregorian::date_duration dd(1); Chris@16: ::new(dp) gregorian::date_period(d,dd); Chris@16: } Chris@16: Chris@16: /**** greg_year ****/ Chris@16: Chris@16: //! Function to save gregorian::greg_year objects using serialization lib Chris@16: template Chris@16: void save(Archive & ar, const gregorian::greg_year& gy, Chris@16: unsigned int /*version*/) Chris@16: { Chris@16: unsigned short us = gy; Chris@16: ar & make_nvp("greg_year", us); Chris@16: } Chris@16: //! Function to load gregorian::greg_year objects using serialization lib Chris@16: template Chris@16: void load(Archive & ar, gregorian::greg_year& gy, unsigned int /*version*/) Chris@16: { Chris@16: unsigned short us; Chris@16: ar & make_nvp("greg_year", us); Chris@16: gy = gregorian::greg_year(us); Chris@16: } Chris@16: //!override needed b/c no default constructor Chris@16: template Chris@16: inline void load_construct_data(Archive & /*ar*/, gregorian::greg_year* gy, Chris@16: const unsigned int /*file_version*/) Chris@16: { Chris@16: ::new(gy) gregorian::greg_year(1900); Chris@16: } Chris@16: Chris@16: /**** greg_month ****/ Chris@16: Chris@16: //! Function to save gregorian::greg_month objects using serialization lib Chris@16: template Chris@16: void save(Archive & ar, const gregorian::greg_month& gm, Chris@16: unsigned int /*version*/) Chris@16: { Chris@16: unsigned short us = gm.as_number(); Chris@16: ar & make_nvp("greg_month", us); Chris@16: } Chris@16: //! Function to load gregorian::greg_month objects using serialization lib Chris@16: template Chris@16: void load(Archive & ar, gregorian::greg_month& gm, unsigned int /*version*/) Chris@16: { Chris@16: unsigned short us; Chris@16: ar & make_nvp("greg_month", us); Chris@16: gm = gregorian::greg_month(us); Chris@16: } Chris@16: //!override needed b/c no default constructor Chris@16: template Chris@16: inline void load_construct_data(Archive & /*ar*/, gregorian::greg_month* gm, Chris@16: const unsigned int /*file_version*/) Chris@16: { Chris@16: ::new(gm) gregorian::greg_month(1); Chris@16: } Chris@16: Chris@16: /**** greg_day ****/ Chris@16: Chris@16: //! Function to save gregorian::greg_day objects using serialization lib Chris@16: template Chris@16: void save(Archive & ar, const gregorian::greg_day& gd, Chris@16: unsigned int /*version*/) Chris@16: { Chris@16: unsigned short us = gd.as_number(); Chris@16: ar & make_nvp("greg_day", us); Chris@16: } Chris@16: //! Function to load gregorian::greg_day objects using serialization lib Chris@16: template Chris@16: void load(Archive & ar, gregorian::greg_day& gd, unsigned int /*version*/) Chris@16: { Chris@16: unsigned short us; Chris@16: ar & make_nvp("greg_day", us); Chris@16: gd = gregorian::greg_day(us); Chris@16: } Chris@16: //!override needed b/c no default constructor Chris@16: template Chris@16: inline void load_construct_data(Archive & /*ar*/, gregorian::greg_day* gd, Chris@16: const unsigned int /*file_version*/) Chris@16: { Chris@16: ::new(gd) gregorian::greg_day(1); Chris@16: } Chris@16: Chris@16: /**** greg_weekday ****/ Chris@16: Chris@16: //! Function to save gregorian::greg_weekday objects using serialization lib Chris@16: template Chris@16: void save(Archive & ar, const gregorian::greg_weekday& gd, Chris@16: unsigned int /*version*/) Chris@16: { Chris@16: unsigned short us = gd.as_number(); Chris@16: ar & make_nvp("greg_weekday", us); Chris@16: } Chris@16: //! Function to load gregorian::greg_weekday objects using serialization lib Chris@16: template Chris@16: void load(Archive & ar, gregorian::greg_weekday& gd, unsigned int /*version*/) Chris@16: { Chris@16: unsigned short us; Chris@16: ar & make_nvp("greg_weekday", us); Chris@16: gd = gregorian::greg_weekday(us); Chris@16: } Chris@16: //!override needed b/c no default constructor Chris@16: template Chris@16: inline void load_construct_data(Archive & /*ar*/, gregorian::greg_weekday* gd, Chris@16: const unsigned int /*file_version*/) Chris@16: { Chris@16: ::new(gd) gregorian::greg_weekday(1); Chris@16: } Chris@16: Chris@16: /**** date_generators ****/ Chris@16: Chris@16: /**** partial_date ****/ Chris@16: Chris@16: //! Function to save gregorian::partial_date objects using serialization lib Chris@16: /*! partial_date objects are broken down into 2 parts for serialization: Chris@16: * the day (typically greg_day) and month (typically greg_month) objects Chris@16: */ Chris@16: template Chris@16: void save(Archive & ar, const gregorian::partial_date& pd, Chris@16: unsigned int /*version*/) Chris@16: { Chris@16: gregorian::greg_day gd(pd.day()); Chris@16: gregorian::greg_month gm(pd.month().as_number()); Chris@16: ar & make_nvp("partial_date_day", gd); Chris@16: ar & make_nvp("partial_date_month", gm); Chris@16: } Chris@16: //! Function to load gregorian::partial_date objects using serialization lib Chris@16: /*! partial_date objects are broken down into 2 parts for serialization: Chris@16: * the day (greg_day) and month (greg_month) objects Chris@16: */ Chris@16: template Chris@16: void load(Archive & ar, gregorian::partial_date& pd, unsigned int /*version*/) Chris@16: { Chris@16: gregorian::greg_day gd(1); Chris@16: gregorian::greg_month gm(1); Chris@16: ar & make_nvp("partial_date_day", gd); Chris@16: ar & make_nvp("partial_date_month", gm); Chris@16: pd = gregorian::partial_date(gd,gm); Chris@16: } Chris@16: //!override needed b/c no default constructor Chris@16: template Chris@16: inline void load_construct_data(Archive & /*ar*/, gregorian::partial_date* pd, Chris@16: const unsigned int /*file_version*/) Chris@16: { Chris@16: gregorian::greg_month gm(1); Chris@16: gregorian::greg_day gd(1); Chris@16: ::new(pd) gregorian::partial_date(gd,gm); Chris@16: } Chris@16: Chris@16: /**** nth_kday_of_month ****/ Chris@16: Chris@16: //! Function to save nth_day_of_the_week_in_month objects using serialization lib Chris@16: /*! nth_day_of_the_week_in_month objects are broken down into 3 parts for Chris@16: * serialization: the week number, the day of the week, and the month Chris@16: */ Chris@16: template Chris@16: void save(Archive & ar, const gregorian::nth_kday_of_month& nkd, Chris@16: unsigned int /*version*/) Chris@16: { Chris@16: typename gregorian::nth_kday_of_month::week_num wn(nkd.nth_week()); Chris@16: typename gregorian::nth_kday_of_month::day_of_week_type d(nkd.day_of_week().as_number()); Chris@16: typename gregorian::nth_kday_of_month::month_type m(nkd.month().as_number()); Chris@16: ar & make_nvp("nth_kday_of_month_week_num", wn); Chris@16: ar & make_nvp("nth_kday_of_month_day_of_week", d); Chris@16: ar & make_nvp("nth_kday_of_month_month", m); Chris@16: } Chris@16: //! Function to load nth_day_of_the_week_in_month objects using serialization lib Chris@16: /*! nth_day_of_the_week_in_month objects are broken down into 3 parts for Chris@16: * serialization: the week number, the day of the week, and the month Chris@16: */ Chris@16: template Chris@16: void load(Archive & ar, gregorian::nth_kday_of_month& nkd, unsigned int /*version*/) Chris@16: { Chris@16: typename gregorian::nth_kday_of_month::week_num wn(gregorian::nth_kday_of_month::first); Chris@16: typename gregorian::nth_kday_of_month::day_of_week_type d(gregorian::Monday); Chris@16: typename gregorian::nth_kday_of_month::month_type m(gregorian::Jan); Chris@16: ar & make_nvp("nth_kday_of_month_week_num", wn); Chris@16: ar & make_nvp("nth_kday_of_month_day_of_week", d); Chris@16: ar & make_nvp("nth_kday_of_month_month", m); Chris@16: Chris@16: nkd = gregorian::nth_kday_of_month(wn,d,m); Chris@16: } Chris@16: //!override needed b/c no default constructor Chris@16: template Chris@16: inline void load_construct_data(Archive & /*ar*/, Chris@16: gregorian::nth_kday_of_month* nkd, Chris@16: const unsigned int /*file_version*/) Chris@16: { Chris@16: // values used are not significant Chris@16: ::new(nkd) gregorian::nth_kday_of_month(gregorian::nth_kday_of_month::first, Chris@16: gregorian::Monday,gregorian::Jan); Chris@16: } Chris@16: Chris@16: /**** first_kday_of_month ****/ Chris@16: Chris@16: //! Function to save first_day_of_the_week_in_month objects using serialization lib Chris@16: /*! first_day_of_the_week_in_month objects are broken down into 2 parts for Chris@16: * serialization: the day of the week, and the month Chris@16: */ Chris@16: template Chris@16: void save(Archive & ar, const gregorian::first_kday_of_month& fkd, Chris@16: unsigned int /*version*/) Chris@16: { Chris@16: typename gregorian::first_kday_of_month::day_of_week_type d(fkd.day_of_week().as_number()); Chris@16: typename gregorian::first_kday_of_month::month_type m(fkd.month().as_number()); Chris@16: ar & make_nvp("first_kday_of_month_day_of_week", d); Chris@16: ar & make_nvp("first_kday_of_month_month", m); Chris@16: } Chris@16: //! Function to load first_day_of_the_week_in_month objects using serialization lib Chris@16: /*! first_day_of_the_week_in_month objects are broken down into 2 parts for Chris@16: * serialization: the day of the week, and the month Chris@16: */ Chris@16: template Chris@16: void load(Archive & ar, gregorian::first_kday_of_month& fkd, unsigned int /*version*/) Chris@16: { Chris@16: typename gregorian::first_kday_of_month::day_of_week_type d(gregorian::Monday); Chris@16: typename gregorian::first_kday_of_month::month_type m(gregorian::Jan); Chris@16: ar & make_nvp("first_kday_of_month_day_of_week", d); Chris@16: ar & make_nvp("first_kday_of_month_month", m); Chris@16: Chris@16: fkd = gregorian::first_kday_of_month(d,m); Chris@16: } Chris@16: //!override needed b/c no default constructor Chris@16: template Chris@16: inline void load_construct_data(Archive & /*ar*/, Chris@16: gregorian::first_kday_of_month* fkd, Chris@16: const unsigned int /*file_version*/) Chris@16: { Chris@16: // values used are not significant Chris@16: ::new(fkd) gregorian::first_kday_of_month(gregorian::Monday,gregorian::Jan); Chris@16: } Chris@16: Chris@16: /**** last_kday_of_month ****/ Chris@16: Chris@16: //! Function to save last_day_of_the_week_in_month objects using serialization lib Chris@16: /*! last_day_of_the_week_in_month objects are broken down into 2 parts for Chris@16: * serialization: the day of the week, and the month Chris@16: */ Chris@16: template Chris@16: void save(Archive & ar, const gregorian::last_kday_of_month& lkd, Chris@16: unsigned int /*version*/) Chris@16: { Chris@16: typename gregorian::last_kday_of_month::day_of_week_type d(lkd.day_of_week().as_number()); Chris@16: typename gregorian::last_kday_of_month::month_type m(lkd.month().as_number()); Chris@16: ar & make_nvp("last_kday_of_month_day_of_week", d); Chris@16: ar & make_nvp("last_kday_of_month_month", m); Chris@16: } Chris@16: //! Function to load last_day_of_the_week_in_month objects using serialization lib Chris@16: /*! last_day_of_the_week_in_month objects are broken down into 2 parts for Chris@16: * serialization: the day of the week, and the month Chris@16: */ Chris@16: template Chris@16: void load(Archive & ar, gregorian::last_kday_of_month& lkd, unsigned int /*version*/) Chris@16: { Chris@16: typename gregorian::last_kday_of_month::day_of_week_type d(gregorian::Monday); Chris@16: typename gregorian::last_kday_of_month::month_type m(gregorian::Jan); Chris@16: ar & make_nvp("last_kday_of_month_day_of_week", d); Chris@16: ar & make_nvp("last_kday_of_month_month", m); Chris@16: Chris@16: lkd = gregorian::last_kday_of_month(d,m); Chris@16: } Chris@16: //!override needed b/c no default constructor Chris@16: template Chris@16: inline void load_construct_data(Archive & /*ar*/, Chris@16: gregorian::last_kday_of_month* lkd, Chris@16: const unsigned int /*file_version*/) Chris@16: { Chris@16: // values used are not significant Chris@16: ::new(lkd) gregorian::last_kday_of_month(gregorian::Monday,gregorian::Jan); Chris@16: } Chris@16: Chris@16: /**** first_kday_before ****/ Chris@16: Chris@16: //! Function to save first_day_of_the_week_before objects using serialization lib Chris@16: template Chris@16: void save(Archive & ar, const gregorian::first_kday_before& fkdb, Chris@16: unsigned int /*version*/) Chris@16: { Chris@16: typename gregorian::first_kday_before::day_of_week_type d(fkdb.day_of_week().as_number()); Chris@16: ar & make_nvp("first_kday_before_day_of_week", d); Chris@16: } Chris@16: //! Function to load first_day_of_the_week_before objects using serialization lib Chris@16: template Chris@16: void load(Archive & ar, gregorian::first_kday_before& fkdb, unsigned int /*version*/) Chris@16: { Chris@16: typename gregorian::first_kday_before::day_of_week_type d(gregorian::Monday); Chris@16: ar & make_nvp("first_kday_before_day_of_week", d); Chris@16: Chris@16: fkdb = gregorian::first_kday_before(d); Chris@16: } Chris@16: //!override needed b/c no default constructor Chris@16: template Chris@16: inline void load_construct_data(Archive & /*ar*/, Chris@16: gregorian::first_kday_before* fkdb, Chris@16: const unsigned int /*file_version*/) Chris@16: { Chris@16: // values used are not significant Chris@16: ::new(fkdb) gregorian::first_kday_before(gregorian::Monday); Chris@16: } Chris@16: Chris@16: /**** first_kday_after ****/ Chris@16: Chris@16: //! Function to save first_day_of_the_week_after objects using serialization lib Chris@16: template Chris@16: void save(Archive & ar, const gregorian::first_kday_after& fkda, Chris@16: unsigned int /*version*/) Chris@16: { Chris@16: typename gregorian::first_kday_after::day_of_week_type d(fkda.day_of_week().as_number()); Chris@16: ar & make_nvp("first_kday_after_day_of_week", d); Chris@16: } Chris@16: //! Function to load first_day_of_the_week_after objects using serialization lib Chris@16: template Chris@16: void load(Archive & ar, gregorian::first_kday_after& fkda, unsigned int /*version*/) Chris@16: { Chris@16: typename gregorian::first_kday_after::day_of_week_type d(gregorian::Monday); Chris@16: ar & make_nvp("first_kday_after_day_of_week", d); Chris@16: Chris@16: fkda = gregorian::first_kday_after(d); Chris@16: } Chris@16: //!override needed b/c no default constructor Chris@16: template Chris@16: inline void load_construct_data(Archive & /*ar*/, Chris@16: gregorian::first_kday_after* fkda, Chris@16: const unsigned int /*file_version*/) Chris@16: { Chris@16: // values used are not significant Chris@16: ::new(fkda) gregorian::first_kday_after(gregorian::Monday); Chris@16: } Chris@16: Chris@16: } // namespace serialization Chris@16: } // namespace boost Chris@16: Chris@16: #endif