stlab.adobe.com Adobe Systems Incorporated

dictionary_arg_stream.hpp

Go to the documentation of this file.
00001 /*************************************************************************
00002 *
00003 * ADOBE CONFIDENTIAL
00004 * ___________________
00005 *
00006 *  Copyright 2008 Adobe Systems Incorporated
00007 *  All Rights Reserved.
00008 *
00009 * NOTICE:  All information contained herein is, and remains
00010 * the property of Adobe Systems Incorporated and its suppliers,
00011 * if any.  The intellectual and technical concepts contained
00012 * herein are proprietary to Adobe Systems Incorporated and its
00013 * suppliers and may be covered by U.S. and Foreign Patents,
00014 * patents in process, and are protected by trade secret or copyright law.
00015 * Dissemination of this information or reproduction of this material
00016 * is strictly forbidden unless prior written permission is obtained
00017 * from Adobe Systems Incorporated.
00018 **************************************************************************/
00019 
00020 #ifndef ADOBE_DICTIONARY_ARG_STREAM_HPP
00021 #define ADOBE_DICTIONARY_ARG_STREAM_HPP
00022 
00023 #include <adobe/arg_stream.hpp>
00024 
00025 #include <adobe/is_range.hpp>
00026 #include <adobe/dictionary.hpp>
00027 
00028 #include <boost/range/begin.hpp>
00029 #include <boost/range/end.hpp>
00030 #include <boost/range/value_type.hpp>
00031 #include <boost/array.hpp>
00032 #include <boost/utility/value_init.hpp>
00033 
00034 #include <new> // std::nothrow_t
00035 
00036 namespace adobe
00037 {
00038 
00039 
00052 template <typename R>
00053 R get_dictionary_entry(adobe::dictionary_t const & dict, adobe::name_t const & key)
00054 {
00055     // throws bad_cast if result is not castable to R
00056     return get_value(dict, key).cast<R>();
00057 }
00058 template <typename R>
00059 bool get_dictionary_entry(adobe::dictionary_t const & dict, adobe::name_t const & key, R & r)
00060 {
00061     // returns false (and leaves r alone) if key not in dictionary
00062     return get_value(dict, key, r);
00063 }
00064 
00065 
00066 template <typename Dictionary, typename InputRange /*to get the keys*/, typename NoThrow = void /* or std::nothrow_t */>
00067 struct dictionary_arg_stream_base
00068 {
00069     typedef Dictionary dictionary_type;
00070     typedef InputRange range_type;
00071     typedef typename boost::range_iterator<InputRange const>::type iterator;
00072 
00073     dictionary_type dict;
00074     range_type range;
00075     iterator curr;
00076 
00077     dictionary_arg_stream_base(dictionary_type & d, range_type const & key_range)
00078         : dict(d), range(key_range), curr(boost::begin(key_range))
00079     {
00080     }
00081 
00082     bool eof() const
00083     {
00084         return curr == boost::end(range);
00085     }
00086 
00087     void throw_if_eof() const
00088     {
00089         if (eof())
00090         {
00091             throw arg_stream::no_more_args();
00092         }
00093     }
00094 
00095     void reset()
00096     {
00097         curr = boost::begin(range);
00098     }
00099 };
00100 
00114 template <typename Dictionary, typename InputRange /*to get the keys*/, typename NoThrow = void /* or std::nothrow_t */>
00115 struct dictionary_arg_stream : dictionary_arg_stream_base<Dictionary, InputRange>
00116 {
00117 // we use this-> because otherwise the compiler doesn't actually know that it is in the base class
00118 // (becaue the base is a template, so if specialized, it might not be there!
00119     typedef dictionary_arg_stream_base<Dictionary, InputRange> _inherited;
00120     using _inherited::dictionary_type;
00121     using _inherited::range_type;
00122     using _inherited::throw_if_eof;
00123     using _inherited::dict;
00124     using _inherited::curr;
00125 
00131     dictionary_arg_stream(Dictionary & d, InputRange const & key_range)
00132         : dictionary_arg_stream_base<Dictionary, InputRange>(d, key_range)
00133     {
00134     }
00135 
00136     template <typename R>
00137     R get_next_arg()
00138     {
00139         throw_if_eof();
00140 
00141         // can throw if the result of get_value is not castable to R
00142         return get_dictionary_entry<R>(dict, *curr++);
00143     }
00144 };
00145 template <typename Dictionary, typename InputRange /*to get the keys*/>
00146 struct dictionary_arg_stream<Dictionary, InputRange, std::nothrow_t>
00147     : dictionary_arg_stream_base<Dictionary, InputRange>
00148 {
00149     dictionary_arg_stream(Dictionary & d, InputRange const & key_range)
00150         : dictionary_arg_stream_base<Dictionary, InputRange>(d, key_range)
00151     {
00152     }
00153 
00154     template <typename R>
00155     R get_next_arg()
00156     {
00157         this->throw_if_eof();
00158 
00159         R r = boost::initialized_value;
00160         get_dictionary_entry(this->dict, *this->curr++, r);
00161         return r;
00162     }
00163 };
00164 
00165 
00166 template <typename Dictionary, typename InputRange /*to get the keys*/>
00167 dictionary_arg_stream<Dictionary, InputRange, void>
00168     make_dictionary_arg_stream(
00169         Dictionary & dict, InputRange const & key_range)
00170 {
00171     return dictionary_arg_stream<Dictionary, InputRange, void>(dict, key_range);
00172 }
00173 
00174 template <typename Dictionary, typename InputRange /*to get the keys*/>
00175 dictionary_arg_stream<Dictionary, InputRange, std::nothrow_t>
00176     make_dictionary_arg_stream(
00177         Dictionary & dict, InputRange const & key_range, std::nothrow_t)
00178 {
00179     return dictionary_arg_stream<Dictionary, InputRange, std::nothrow_t>(dict, key_range);
00180 }
00181 
00182 
00183 namespace dictionary_arg_stream_detail
00184 {
00185     template<size_t>
00186     struct member_test_helper
00187     {
00188     };
00189 
00190     struct function_not_present {};
00191     template <typename R>
00192     function_not_present get_dictionary_entry(...);
00193 
00194     template <typename Dictionary, typename Key>
00195     struct has_get_dictionary_entry_template
00196     {
00197         static Dictionary * dict;
00198         static Key * key;
00199         static adobe::detail::yes_struct SFINAE(int);
00200         static adobe::detail::no_struct SFINAE(function_not_present const &);
00201         static const bool value = sizeof(SFINAE(get_dictionary_entry<int>(*dict, *key))) == sizeof(adobe::detail::yes_struct);
00202     };
00203     template <typename Dictionary, typename Key, typename R>
00204     struct has_get_dictionary_entry_function
00205     {
00206         static Dictionary * dict;
00207         static Key * key;
00208         static R * r;
00209         static adobe::detail::yes_struct SFINAE(int);
00210         static adobe::detail::no_struct SFINAE(function_not_present const &);
00211         static const bool value = sizeof(SFINAE(get_dictionary_entry(*dict, *key, *r))) == sizeof(adobe::detail::yes_struct);
00212     };
00213 
00214     template <typename Dictionary, typename Range>
00215     struct is_range_for_dictionary
00216     {
00217         static const bool value = has_get_dictionary_entry_template<Dictionary, typename boost::range_value<Range>::type>::value;
00218     };
00219 
00220     static const int test = is_range_for_dictionary<adobe::dictionary_t, boost::array<adobe::name_t, 3> >::value;
00221 
00222     ADOBE_HAS_TYPE_IMPL(key_type);
00223 
00224     template <typename Dictionary, typename DefaultKey, bool has_type = ADOBE_HAS_TYPE(Dictionary, key_type)>
00225     struct key_type;
00226 
00227     template <typename Dictionary, typename DefaultKey>
00228     struct key_type<Dictionary, DefaultKey, false>
00229     {
00230         typedef DefaultKey type;
00231     };
00232     template <typename Dictionary, typename DefaultKey>
00233     struct key_type<Dictionary, DefaultKey, true>
00234     {
00235         typedef typename Dictionary::key_type type;
00236     };
00237 
00238 
00239     // for the single arg case (single arg after dict arg)
00240     // is that arg a key to the dictionary representing an arg,
00241     // or is it a range of keys for the dictionary
00242     template <typename NoThrow = std::nothrow_t, bool isRange = true>
00243     struct if_range_base
00244     {
00245         template <typename F, typename Dictionary, typename InputRange>
00246             static typename arg_stream::result_type<F>::type
00247                 call(F f, Dictionary const & dict, InputRange const & range)
00248         {
00249             return arg_stream::call(f, make_dictionary_arg_stream(dict, range, std::nothrow));
00250         }
00251     };
00252     template <>
00253     struct if_range_base<void, true>
00254     {
00255         template <typename F, typename Dictionary, typename InputRange>
00256             static typename arg_stream::result_type<F>::type
00257                 call(F f, Dictionary const & dict, InputRange const & range)
00258         {
00259             return arg_stream::call(f, make_dictionary_arg_stream(dict, range));
00260         }
00261     };
00262 
00263     template <>
00264     struct if_range_base<std::nothrow_t, false>
00265     {
00266         template <typename F, typename Dictionary, typename Key>
00267             static typename arg_stream::result_type<F>::type
00268                 call(F f, Dictionary const & dict, Key const & keyable)
00269         {
00270             typedef typename key_type<Dictionary, Key>::type key_type;
00271             key_type key(keyable);
00272             std::pair<key_type const *, key_type const *> key_range(&key, &key + 1);
00273             return arg_stream::call(f, make_dictionary_arg_stream(dict, key_range, std::nothrow));
00274         }
00275     };
00276     template <>
00277     struct if_range_base<void, false>
00278     {
00279         template <typename F, typename Dictionary, typename Key>
00280             static typename arg_stream::result_type<F>::type
00281                 call(F f, Dictionary const & dict, Key const & keyable)
00282         {
00283             typedef typename key_type<Dictionary, Key>::type key_type;
00284             key_type key(keyable);
00285             std::pair<key_type const *, key_type const *> key_range(&key, &key + 1);
00286             return arg_stream::call(f, make_dictionary_arg_stream(dict, key_range));
00287         }
00288     };
00289 
00290     template <typename NoThrow, typename Dictionary, typename T>
00291     struct if_range_else_key
00292         : if_range_base<NoThrow, is_range_for_dictionary<Dictionary, T>::value>
00293     {
00294     };
00295 }
00296 
00303 template <typename F, typename Dictionary, typename SingleArg>
00304     typename arg_stream::result_type<F>::type
00305         call_with_dictionary(F f, Dictionary const & dict, SingleArg const & key_or_key_range)
00306 {
00307     return dictionary_arg_stream_detail::if_range_else_key<void, Dictionary, SingleArg>::call(f, dict, key_or_key_range);
00308 }
00309 
00310 // nothrow case:
00311 template <typename F, typename Dictionary, typename SingleArg>
00312     typename arg_stream::result_type<F>::type
00313         call_with_dictionary(F f, std::nothrow_t, Dictionary const & dict, SingleArg const & key_or_key_range)
00314 {
00315     return dictionary_arg_stream_detail::if_range_else_key<std::nothrow_t, Dictionary, SingleArg>::call(f, dict, key_or_key_range);
00316 }
00317 
00318 // member function cases
00319 template <class T, typename F, typename Dictionary, typename SingleArg>
00320     typename arg_stream::result_type<F>::type
00321         call_member_with_dictionary(T * that, F f, Dictionary const & dict, SingleArg const & key_or_key_range)
00322 {
00323     return dictionary_arg_stream_detail::if_range_else_key<void, Dictionary, SingleArg>::call(that, f, dict, key_or_key_range);
00324 }
00325 
00326 template <class T, typename F, typename Dictionary, typename SingleArg>
00327     typename arg_stream::result_type<F>::type
00328         call_member_with_dictionary(T* that, F f, std::nothrow_t, Dictionary const & dict, SingleArg const & key_or_key_range)
00329 {
00330     return dictionary_arg_stream_detail::if_range_else_key<std::nothrow_t, Dictionary, SingleArg>::call(that, f, dict, key_or_key_range);
00331 }
00332 
00333 
00335 template <typename F, typename Dictionary, typename T1, typename T2 >
00336     typename arg_stream::result_type<F>::type 
00337         call_with_dictionary(F f, Dictionary const & dict,
00338             T1 const & key1, T2 const & key2)
00339 {
00340     typedef typename dictionary_arg_stream_detail::key_type<Dictionary, T1>::type key_type;
00341     boost::array<key_type, 2> arr = { key_type(key1), key_type(key2) };
00342     return call_with_dictionary(f, dict, arr);
00343 }
00344 
00345 template <typename X, typename F, typename Dictionary, typename T1, typename T2 >
00346     typename arg_stream::result_type<F>::type 
00347         call_member_with_dictionary(X & x, F f, Dictionary const & dict,
00348             T1 const & key1, T2 const & key2)
00349 {
00350     typedef typename dictionary_arg_stream_detail::key_type<Dictionary, T1>::type key_type;
00351     boost::array<key_type, 2> arr = { key_type(key1), key_type(key2) };
00352     return call_member_with_dictionary(x, f, dict, arr);
00353 }
00354 
00355 template <typename F, typename Dictionary, typename T1, typename T2 >
00356     typename arg_stream::result_type<F>::type 
00357         call_with_dictionary(F f, std::nothrow_t, Dictionary const & dict,
00358             T1 const & key1, T2 const & key2)
00359 {
00360     typedef typename dictionary_arg_stream_detail::key_type<Dictionary, T1>::type key_type;
00361     boost::array<key_type, 2> arr = { key_type(key1), key_type(key2) };
00362     return call_with_dictionary(f, std::nothrow, dict, arr);
00363 }
00364 
00365 template <typename X, typename F, typename Dictionary, typename T1, typename T2 >
00366     typename arg_stream::result_type<F>::type 
00367         call_member_with_dictionary(X x, F f, std::nothrow_t, Dictionary const & dict,
00368             T1 const & key1, T2 const & key2)
00369 {
00370     typedef typename dictionary_arg_stream_detail::key_type<Dictionary, T1>::type key_type;
00371     boost::array<key_type, 2> arr = { key_type(key1), key_type(key2) };
00372     return call_member_with_dictionary(x, f, std::nothrow, dict, arr);
00373 }
00374 
00376 template <typename F, typename Dictionary, typename T1, typename T2, typename T3>
00377     typename arg_stream::result_type<F>::type 
00378         call_with_dictionary(F f, Dictionary const & dict,
00379             T1 const & key1, T2 const & key2, T3 const & key3)
00380 {
00381     typedef typename dictionary_arg_stream_detail::key_type<Dictionary, T1>::type key_type;
00382     boost::array<key_type, 3> arr = { key_type(key1), key_type(key2), key_type(key3) };
00383     return call_with_dictionary(f, dict, arr);
00384 }
00385 
00386 template <typename X, typename F, typename Dictionary, typename T1, typename T2, typename T3>
00387     typename arg_stream::result_type<F>::type 
00388         call_member_with_dictionary(X & x, F f, Dictionary const & dict,
00389             T1 const & key1, T2 const & key2, T3 const & key3)
00390 {
00391     typedef typename dictionary_arg_stream_detail::key_type<Dictionary, T1>::type key_type;
00392     boost::array<key_type, 3> arr = { key_type(key1), key_type(key2), key_type(key3) };
00393     return call_member_with_dictionary(x, f, dict, arr);
00394 }
00395 
00396 template <typename F, typename Dictionary, typename T1, typename T2, typename T3>
00397     typename arg_stream::result_type<F>::type 
00398         call_with_dictionary(F f, std::nothrow_t, Dictionary const & dict,
00399             T1 const & key1, T2 const & key2, T3 const & key3)
00400 {
00401     typedef typename dictionary_arg_stream_detail::key_type<Dictionary, T1>::type key_type;
00402     boost::array<key_type, 3> arr = { key_type(key1), key_type(key2), key_type(key3) };
00403     return call_with_dictionary(f, std::nothrow, dict, arr);
00404 }
00405 
00406 template <typename X, typename F, typename Dictionary, typename T1, typename T2, typename T3>
00407     typename arg_stream::result_type<F>::type 
00408         call_member_with_dictionary(X x, F f, std::nothrow_t, Dictionary const & dict,
00409             T1 const & key1, T2 const & key2, T3 const & key3)
00410 {
00411     typedef typename dictionary_arg_stream_detail::key_type<Dictionary, T1>::type key_type;
00412     boost::array<key_type, 3> arr = { key_type(key1), key_type(key2), key_type(key3) };
00413     return call_member_with_dictionary(x, f, std::nothrow, dict, arr);
00414 }
00415 
00417 template <typename F, typename Dictionary, typename T1, typename T2, typename T3, typename T4>
00418     typename arg_stream::result_type<F>::type 
00419         call_with_dictionary(F f, Dictionary const & dict,
00420             T1 const & key1, T2 const & key2, T3 const & key3, T4 const & key4)
00421 {
00422     typedef typename dictionary_arg_stream_detail::key_type<Dictionary, T1>::type key_type;
00423     boost::array<key_type, 4> arr = { key_type(key1), key_type(key2), key_type(key3), key_type(key4) };
00424     return call_with_dictionary(f, dict, arr);
00425 }
00426 
00427 template <typename X, typename F, typename Dictionary, typename T1, typename T2, typename T3, typename T4>
00428     typename arg_stream::result_type<F>::type 
00429         call_member_with_dictionary(X & x, F f, Dictionary const & dict,
00430             T1 const & key1, T2 const & key2, T3 const & key3, T4 const & key4)
00431 {
00432     typedef typename dictionary_arg_stream_detail::key_type<Dictionary, T1>::type key_type;
00433     boost::array<key_type, 4> arr = { key_type(key1), key_type(key2), key_type(key3), key_type(key4) };
00434     return call_member_with_dictionary(x, f, dict, arr);
00435 }
00436 
00437 template <typename F, typename Dictionary, typename T1, typename T2, typename T3, typename T4>
00438     typename arg_stream::result_type<F>::type 
00439         call_with_dictionary(F f, std::nothrow_t, Dictionary const & dict,
00440             T1 const & key1, T2 const & key2, T3 const & key3, T4 const & key4)
00441 {
00442     typedef typename dictionary_arg_stream_detail::key_type<Dictionary, T1>::type key_type;
00443     boost::array<key_type, 4> arr = { key_type(key1), key_type(key2), key_type(key3), key_type(key4) };
00444     return call_with_dictionary(f, std::nothrow, dict, arr);
00445 }
00446 
00447 template <typename X, typename F, typename Dictionary, typename T1, typename T2, typename T3, typename T4>
00448     typename arg_stream::result_type<F>::type 
00449         call_member_with_dictionary(X x, F f, std::nothrow_t, Dictionary const & dict,
00450             T1 const & key1, T2 const & key2, T3 const & key3, T4 const & key4)
00451 {
00452     typedef typename dictionary_arg_stream_detail::key_type<Dictionary, T1>::type key_type;
00453     boost::array<key_type, 4> arr = { key_type(key1), key_type(key2), key_type(key3), key_type(key4) };
00454     return call_member_with_dictionary(x, f, std::nothrow, dict, arr);
00455 }
00456 
00457 
00458 } // namespace adobe
00459 
00460 #endif // include guard
00461 

Copyright © 2006-2007 Adobe Systems Incorporated.

Use of this website signifies your agreement to the Terms of Use and Online Privacy Policy.

Search powered by Google