1/// @ref gtx_io 2/// @file glm/gtx/io.inl 3/// @author Jan P Springer ([email protected]) 4 5#include <iomanip> // std::fixed, std::setfill<>, std::setprecision, std::right, std::setw 6#include <ostream> // std::basic_ostream<> 7#include "../gtc/matrix_access.hpp" // glm::col, glm::row 8#include "../gtx/type_trait.hpp" // glm::type<> 9 10namespace glm{ 11namespace io 12{ 13 template <typename CTy> 14 GLM_FUNC_QUALIFIER format_punct<CTy>::format_punct(size_t a) 15 : std::locale::facet(a) 16 , formatted(true) 17 , precision(3) 18 , width(1 + 4 + 1 + precision) 19 , separator(',') 20 , delim_left('[') 21 , delim_right(']') 22 , space(' ') 23 , newline('\n') 24 , order(column_major) 25 {} 26 27 template <typename CTy> 28 GLM_FUNC_QUALIFIER format_punct<CTy>::format_punct(format_punct const& a) 29 : std::locale::facet(0) 30 , formatted(a.formatted) 31 , precision(a.precision) 32 , width(a.width) 33 , separator(a.separator) 34 , delim_left(a.delim_left) 35 , delim_right(a.delim_right) 36 , space(a.space) 37 , newline(a.newline) 38 , order(a.order) 39 {} 40 41 template <typename CTy> std::locale::id format_punct<CTy>::id; 42 43 template <typename CTy, typename CTr> 44 GLM_FUNC_QUALIFIER basic_state_saver<CTy, CTr>::basic_state_saver(std::basic_ios<CTy, CTr>& a) 45 : state_(a) 46 , flags_(a.flags()) 47 , precision_(a.precision()) 48 , width_(a.width()) 49 , fill_(a.fill()) 50 , locale_(a.getloc()) 51 {} 52 53 template <typename CTy, typename CTr> 54 GLM_FUNC_QUALIFIER basic_state_saver<CTy, CTr>::~basic_state_saver() 55 { 56 state_.imbue(locale_); 57 state_.fill(fill_); 58 state_.width(width_); 59 state_.precision(precision_); 60 state_.flags(flags_); 61 } 62 63 template <typename CTy, typename CTr> 64 GLM_FUNC_QUALIFIER basic_format_saver<CTy, CTr>::basic_format_saver(std::basic_ios<CTy, CTr>& a) 65 : bss_(a) 66 { 67 a.imbue(std::locale(a.getloc(), new format_punct<CTy>(get_facet<format_punct<CTy> >(a)))); 68 } 69 70 template <typename CTy, typename CTr> 71 GLM_FUNC_QUALIFIER 72 basic_format_saver<CTy, CTr>::~basic_format_saver() 73 {} 74 75 GLM_FUNC_QUALIFIER precision::precision(unsigned a) 76 : value(a) 77 {} 78 79 GLM_FUNC_QUALIFIER width::width(unsigned a) 80 : value(a) 81 {} 82 83 template <typename CTy> 84 GLM_FUNC_QUALIFIER delimeter<CTy>::delimeter(CTy a, CTy b, CTy c) 85 : value() 86 { 87 value[0] = a; 88 value[1] = b; 89 value[2] = c; 90 } 91 92 GLM_FUNC_QUALIFIER order::order(order_type a) 93 : value(a) 94 {} 95 96 template <typename FTy, typename CTy, typename CTr> 97 GLM_FUNC_QUALIFIER FTy const& get_facet(std::basic_ios<CTy, CTr>& ios) 98 { 99 if(!std::has_facet<FTy>(ios.getloc())) 100 ios.imbue(std::locale(ios.getloc(), new FTy)); 101 102 return std::use_facet<FTy>(ios.getloc()); 103 } 104 105 template <typename CTy, typename CTr> 106 GLM_FUNC_QUALIFIER std::basic_ios<CTy, CTr>& formatted(std::basic_ios<CTy, CTr>& ios) 107 { 108 const_cast<format_punct<CTy>&>(get_facet<format_punct<CTy> >(ios)).formatted = true; 109 return ios; 110 } 111 112 template <typename CTy, typename CTr> 113 GLM_FUNC_QUALIFIER std::basic_ios<CTy, CTr>& unformatted(std::basic_ios<CTy, CTr>& ios) 114 { 115 const_cast<format_punct<CTy>&>(get_facet<format_punct<CTy> >(ios)).formatted = false; 116 return ios; 117 } 118 119 template <typename CTy, typename CTr> 120 GLM_FUNC_QUALIFIER std::basic_ostream<CTy, CTr>& operator<<(std::basic_ostream<CTy, CTr>& os, precision const& a) 121 { 122 const_cast<format_punct<CTy>&>(get_facet<format_punct<CTy> >(os)).precision = a.value; 123 return os; 124 } 125 126 template <typename CTy, typename CTr> 127 GLM_FUNC_QUALIFIER std::basic_ostream<CTy, CTr>& operator<<(std::basic_ostream<CTy, CTr>& os, width const& a) 128 { 129 const_cast<format_punct<CTy>&>(get_facet<format_punct<CTy> >(os)).width = a.value; 130 return os; 131 } 132 133 template <typename CTy, typename CTr> 134 GLM_FUNC_QUALIFIER std::basic_ostream<CTy, CTr>& operator<<(std::basic_ostream<CTy, CTr>& os, delimeter<CTy> const& a) 135 { 136 format_punct<CTy> & fmt(const_cast<format_punct<CTy>&>(get_facet<format_punct<CTy> >(os))); 137 138 fmt.delim_left = a.value[0]; 139 fmt.delim_right = a.value[1]; 140 fmt.separator = a.value[2]; 141 142 return os; 143 } 144 145 template <typename CTy, typename CTr> 146 GLM_FUNC_QUALIFIER std::basic_ostream<CTy, CTr>& operator<<(std::basic_ostream<CTy, CTr>& os, order const& a) 147 { 148 const_cast<format_punct<CTy>&>(get_facet<format_punct<CTy> >(os)).order = a.value; 149 return os; 150 } 151} // namespace io 152 153namespace detail 154{ 155 template <typename CTy, typename CTr, template <typename, precision> class V, typename T, precision P> 156 GLM_FUNC_QUALIFIER std::basic_ostream<CTy, CTr>& 157 print_vector_on(std::basic_ostream<CTy, CTr>& os, V<T,P> const& a) 158 { 159 typename std::basic_ostream<CTy, CTr>::sentry const cerberus(os); 160 161 if(cerberus) 162 { 163 io::format_punct<CTy> const & fmt(io::get_facet<io::format_punct<CTy> >(os)); 164 165 length_t const& components(type<V, T, P>::components); 166 167 if(fmt.formatted) 168 { 169 io::basic_state_saver<CTy> const bss(os); 170 171 os << std::fixed << std::right << std::setprecision(fmt.precision) << std::setfill(fmt.space) << fmt.delim_left; 172 173 for(length_t i(0); i < components; ++i) 174 { 175 os << std::setw(fmt.width) << a[i]; 176 if(components-1 != i) 177 os << fmt.separator; 178 } 179 180 os << fmt.delim_right; 181 } 182 else 183 { 184 for(length_t i(0); i < components; ++i) 185 { 186 os << a[i]; 187 188 if(components-1 != i) 189 os << fmt.space; 190 } 191 } 192 } 193 194 return os; 195 } 196}//namespace detail 197 198 template <typename CTy, typename CTr, typename T, precision P> 199 GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, tquat<T,P> const& a) 200 { 201 return detail::print_vector_on(os, a); 202 } 203 204 template <typename CTy, typename CTr, typename T, precision P> 205 GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, tvec1<T,P> const& a) 206 { 207 return detail::print_vector_on(os, a); 208 } 209 210 template <typename CTy, typename CTr, typename T, precision P> 211 GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, tvec2<T,P> const& a) 212 { 213 return detail::print_vector_on(os, a); 214 } 215 216 template <typename CTy, typename CTr, typename T, precision P> 217 GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, tvec3<T,P> const& a) 218 { 219 return detail::print_vector_on(os, a); 220 } 221 222 template <typename CTy, typename CTr, typename T, precision P> 223 GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, tvec4<T,P> const& a) 224 { 225 return detail::print_vector_on(os, a); 226 } 227 228namespace detail 229{ 230 template <typename CTy, typename CTr, template <typename, precision> class M, typename T, precision P> 231 GLM_FUNC_QUALIFIER std::basic_ostream<CTy, CTr>& print_matrix_on(std::basic_ostream<CTy, CTr>& os, M<T,P> const& a) 232 { 233 typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os); 234 235 if(cerberus) 236 { 237 io::format_punct<CTy> const & fmt(io::get_facet<io::format_punct<CTy> >(os)); 238 239 length_t const& cols(type<M, T, P>::cols); 240 length_t const& rows(type<M, T, P>::rows); 241 242 if(fmt.formatted) 243 { 244 os << fmt.newline << fmt.delim_left; 245 246 switch(fmt.order) 247 { 248 case io::column_major: 249 { 250 for(length_t i(0); i < rows; ++i) 251 { 252 if (0 != i) 253 os << fmt.space; 254 255 os << row(a, i); 256 257 if(rows-1 != i) 258 os << fmt.newline; 259 } 260 } 261 break; 262 263 case io::row_major: 264 { 265 for(length_t i(0); i < cols; ++i) 266 { 267 if(0 != i) 268 os << fmt.space; 269 270 os << column(a, i); 271 272 if(cols-1 != i) 273 os << fmt.newline; 274 } 275 } 276 break; 277 } 278 279 os << fmt.delim_right; 280 } 281 else 282 { 283 switch (fmt.order) 284 { 285 case io::column_major: 286 { 287 for(length_t i(0); i < cols; ++i) 288 { 289 os << column(a, i); 290 291 if(cols - 1 != i) 292 os << fmt.space; 293 } 294 } 295 break; 296 297 case io::row_major: 298 { 299 for (length_t i(0); i < rows; ++i) 300 { 301 os << row(a, i); 302 303 if (rows-1 != i) 304 os << fmt.space; 305 } 306 } 307 break; 308 } 309 } 310 } 311 312 return os; 313 } 314}//namespace detail 315 316 template <typename CTy, typename CTr, typename T, precision P> 317 GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, tmat2x2<T,P> const& a) 318 { 319 return detail::print_matrix_on(os, a); 320 } 321 322 template <typename CTy, typename CTr, typename T, precision P> 323 GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, tmat2x3<T,P> const& a) 324 { 325 return detail::print_matrix_on(os, a); 326 } 327 328 template <typename CTy, typename CTr, typename T, precision P> 329 GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, tmat2x4<T,P> const& a) 330 { 331 return detail::print_matrix_on(os, a); 332 } 333 334 template <typename CTy, typename CTr, typename T, precision P> 335 GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, tmat3x2<T,P> const& a) 336 { 337 return detail::print_matrix_on(os, a); 338 } 339 340 template <typename CTy, typename CTr, typename T, precision P> 341 GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, tmat3x3<T,P> const& a) 342 { 343 return detail::print_matrix_on(os, a); 344 } 345 346 template <typename CTy, typename CTr, typename T, precision P> 347 GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr> & operator<<(std::basic_ostream<CTy,CTr>& os, tmat3x4<T,P> const& a) 348 { 349 return detail::print_matrix_on(os, a); 350 } 351 352 template <typename CTy, typename CTr, typename T, precision P> 353 GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr> & operator<<(std::basic_ostream<CTy,CTr>& os, tmat4x2<T,P> const& a) 354 { 355 return detail::print_matrix_on(os, a); 356 } 357 358 template <typename CTy, typename CTr, typename T, precision P> 359 GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr> & operator<<(std::basic_ostream<CTy,CTr>& os, tmat4x3<T,P> const& a) 360 { 361 return detail::print_matrix_on(os, a); 362 } 363 364 template <typename CTy, typename CTr, typename T, precision P> 365 GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr> & operator<<(std::basic_ostream<CTy,CTr>& os, tmat4x4<T,P> const& a) 366 { 367 return detail::print_matrix_on(os, a); 368 } 369 370namespace detail 371{ 372 template <typename CTy, typename CTr, template <typename, precision> class M, typename T, precision P> 373 GLM_FUNC_QUALIFIER std::basic_ostream<CTy, CTr>& print_matrix_pair_on(std::basic_ostream<CTy, CTr>& os, std::pair<M<T, P> const, M<T, P> const> const& a) 374 { 375 typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os); 376 377 if(cerberus) 378 { 379 io::format_punct<CTy> const& fmt(io::get_facet<io::format_punct<CTy> >(os)); 380 M<T,P> const& ml(a.first); 381 M<T,P> const& mr(a.second); 382 length_t const& cols(type<M, T, P>::cols); 383 length_t const& rows(type<M, T, P>::rows); 384 385 if(fmt.formatted) 386 { 387 os << fmt.newline << fmt.delim_left; 388 389 switch(fmt.order) 390 { 391 case io::column_major: 392 { 393 for(length_t i(0); i < rows; ++i) 394 { 395 if(0 != i) 396 os << fmt.space; 397 398 os << row(ml, i) << ((rows-1 != i) ? fmt.space : fmt.delim_right) << fmt.space << ((0 != i) ? fmt.space : fmt.delim_left) << row(mr, i); 399 400 if(rows-1 != i) 401 os << fmt.newline; 402 } 403 } 404 break; 405 case io::row_major: 406 { 407 for(length_t i(0); i < cols; ++i) 408 { 409 if(0 != i) 410 os << fmt.space; 411 412 os << column(ml, i) << ((cols-1 != i) ? fmt.space : fmt.delim_right) << fmt.space << ((0 != i) ? fmt.space : fmt.delim_left) << column(mr, i); 413 414 if(cols-1 != i) 415 os << fmt.newline; 416 } 417 } 418 break; 419 } 420 421 os << fmt.delim_right; 422 } 423 else 424 { 425 os << ml << fmt.space << mr; 426 } 427 } 428 429 return os; 430 } 431}//namespace detail 432 433 template <typename CTy, typename CTr, typename T, precision P> 434 GLM_FUNC_QUALIFIER std::basic_ostream<CTy, CTr>& operator<<( 435 std::basic_ostream<CTy, CTr> & os, 436 std::pair<tmat4x4<T, P> const, 437 tmat4x4<T, P> const> const& a) 438 { 439 return detail::print_matrix_pair_on(os, a); 440 } 441}//namespace glm 442