update credits
[LibreOffice.git] / include / o3tl / lazy_update.hxx
blobb05bda37ba40142bd6841398c3249c20570634d3
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #ifndef INCLUDED_O3TL_LAZY_UPDATE_HXX
21 #define INCLUDED_O3TL_LAZY_UPDATE_HXX
23 #include <sal/types.h>
24 #include <boost/function.hpp>
26 namespace o3tl
28 /** Update output object lazily
30 This template collects data in input type, and updates the
31 output type with the given update functor, but only if the
32 output is requested. UsefĂșl if updating is expensive, or input
33 changes frequently, but output is only comparatively seldom
34 used.
36 @example
37 <pre>
38 LazyUpdate<InType,OutType,LAZYUPDATE_DIRECT_TAG> myValue;
39 *myValue = newInput;
40 myValue->updateInput( this, that, those );
42 output( *myValue );
43 </pre>
45 <pre>
46 output( myValue.getOutValue() );
47 </pre>
48 if the compiler does not recognize the const context.
50 template< typename InputType, typename OutputType, typename Tag > class LazyUpdate;
52 /// LazyUpdate specialization takes boost::function argument
53 struct LAZYUPDATE_FUNCTOR_TAG {};
54 /// LazyUpdate specialization takes OutputType (*FunctionType)( InputType const& ) argument
55 struct LAZYUPDATE_FUNCTION_TAG {};
56 /// LazyUpdate specialization can directly convert, OutputType ctor must take InputType argument
57 struct LAZYUPDATE_DIRECT_TAG {};
59 // -----------------------------------------------------------------------------------------------------
61 namespace detail
63 /// @internal
64 template< typename InputType, typename OutputType, typename Functor > class LazyUpdateImpl : private Functor
66 public:
67 typedef OutputType output_type;
68 typedef InputType input_type;
70 LazyUpdateImpl() :
71 m_aInput()
74 template< typename ParamType > explicit LazyUpdateImpl( ParamType const& rParm ) :
75 Functor(rParm),
76 m_aInput()
79 enum UnaryConstructorTag{ UNARY_CONSTRUCTOR_TAG };
80 LazyUpdateImpl( const input_type& rInput, UnaryConstructorTag ) :
81 m_aInput(rInput)
84 template< typename ParamType > LazyUpdateImpl( ParamType const& rParm,
85 const input_type& rInput ) :
86 Functor(rParm),
87 m_aInput(rInput)
90 // default copy ctor/assignment operator are ok
91 // LazyUpdate( const LazyUpdate& );
92 // LazyUpdate& operator=( const LazyUpdate& );
94 void setInValue( input_type const& rIn ) { Functor::m_bCacheDirty = true; m_aInput = rIn; }
95 input_type const& getInValue() const { return m_aInput; }
96 output_type const& getOutValue() const { return this->implUpdateValue(m_aInput); }
98 input_type& operator*() { Functor::m_bCacheDirty = true; return m_aInput; }
99 input_type* operator->() { Functor::m_bCacheDirty = true; return &m_aInput; }
101 output_type const& operator*() const { return this->implUpdateValue(m_aInput); }
102 output_type const* operator->() const { return &(this->implUpdateValue(m_aInput)); }
104 private:
105 input_type m_aInput;
108 template< typename InputType, typename OutputType > struct DefaultFunctor
110 protected:
111 typedef OutputType output_type;
112 typedef InputType input_type;
114 DefaultFunctor() :
115 m_aOutput(),
116 m_bCacheDirty(true)
119 OutputType const& implUpdateValue( input_type const& rIn ) const
121 if( m_bCacheDirty )
123 m_aOutput = output_type( rIn );
124 m_bCacheDirty = false;
127 return m_aOutput;
130 mutable output_type m_aOutput;
131 mutable bool m_bCacheDirty; // when true, m_aOutput needs update
134 template< typename InputType, typename OutputType, typename FunctionType > struct FunctionPointer
136 protected:
137 typedef OutputType output_type;
138 typedef InputType input_type;
139 typedef FunctionType function_type;
141 FunctionPointer() :
142 m_pFunc(),
143 m_aOutput(),
144 m_bCacheDirty(true)
148 explicit FunctionPointer( function_type const& pFunc ) :
149 m_pFunc(pFunc),
150 m_aOutput(),
151 m_bCacheDirty(true)
155 output_type const& implUpdateValue( input_type const& rIn ) const
157 if( m_bCacheDirty )
159 m_aOutput = m_pFunc( rIn );
160 m_bCacheDirty = false;
163 return m_aOutput;
166 function_type m_pFunc;
167 mutable output_type m_aOutput;
168 mutable bool m_bCacheDirty; // when true, m_aOutput needs update
172 // -----------------------------------------------------------------------------------------------------
174 // partial specializations for the three LAZYUPDATE_* tags
176 template< typename InputType, typename OutputType > class LazyUpdate<InputType,
177 OutputType,
178 LAZYUPDATE_DIRECT_TAG> :
179 public detail::LazyUpdateImpl<InputType,
180 OutputType,
181 detail::DefaultFunctor<InputType, OutputType> >
183 public:
184 LazyUpdate() {}
185 explicit LazyUpdate( InputType const& rIn ) :
186 detail::LazyUpdateImpl<InputType,
187 OutputType,
188 detail::DefaultFunctor<InputType, OutputType> >(
189 rIn,
190 detail::LazyUpdateImpl<
191 InputType,
192 OutputType,
193 detail::DefaultFunctor<InputType, OutputType> >::UNARY_CONSTRUCTOR_TAG )
197 // -----------------------------------------------------------------------------------------------------
199 template< typename InputType, typename OutputType > class LazyUpdate<InputType,
200 OutputType,
201 LAZYUPDATE_FUNCTION_TAG> :
202 public detail::LazyUpdateImpl<InputType,
203 OutputType,
204 detail::FunctionPointer<
205 InputType,
206 OutputType,
207 OutputType (*)( InputType const& ) > >
209 public:
210 explicit LazyUpdate( OutputType (*pFunc)( InputType const& ) ) :
211 detail::LazyUpdateImpl<InputType,
212 OutputType,
213 detail::FunctionPointer<
214 InputType,
215 OutputType,
216 OutputType (*)( InputType const& )> >(pFunc)
218 LazyUpdate( OutputType (*pFunc)( InputType const& ),
219 InputType const& rIn ) :
220 detail::LazyUpdateImpl<InputType,
221 OutputType,
222 detail::FunctionPointer<
223 InputType,
224 OutputType,
225 OutputType (*)( InputType const& )> >(pFunc,rIn)
229 // -----------------------------------------------------------------------------------------------------
231 template< typename InputType, typename OutputType > class LazyUpdate<InputType,
232 OutputType,
233 LAZYUPDATE_FUNCTOR_TAG> :
234 public detail::LazyUpdateImpl<InputType,
235 OutputType,
236 detail::FunctionPointer<
237 InputType,
238 OutputType,
239 boost::function1<OutputType,InputType> > >
241 public:
242 explicit LazyUpdate( boost::function1<OutputType,InputType> const& rFunc ) :
243 detail::LazyUpdateImpl<InputType,
244 OutputType,
245 detail::FunctionPointer<
246 InputType,
247 OutputType,
248 boost::function1<OutputType,InputType> > >(rFunc)
250 LazyUpdate( boost::function1<OutputType,InputType> const& rFunc,
251 InputType const& rIn ) :
252 detail::LazyUpdateImpl<InputType,
253 OutputType,
254 detail::FunctionPointer<
255 InputType,
256 OutputType,
257 boost::function1<OutputType,InputType> > >(rFunc,rIn)
263 #endif /* INCLUDED_O3TL_LAZY_UPDATE_HXX */
265 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */