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 |