Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #ifndef _UCBHELPER_RESULTSET_HXX
21 : #define _UCBHELPER_RESULTSET_HXX
22 :
23 : #include <com/sun/star/lang/XTypeProvider.hpp>
24 : #include <com/sun/star/lang/XServiceInfo.hpp>
25 : #include <com/sun/star/lang/XComponent.hpp>
26 : #include <com/sun/star/ucb/ResultSetException.hpp>
27 : #include <com/sun/star/ucb/XCommandEnvironment.hpp>
28 : #include <com/sun/star/ucb/XContentAccess.hpp>
29 : #include <com/sun/star/sdbc/XResultSet.hpp>
30 : #include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
31 : #include <com/sun/star/sdbc/XRow.hpp>
32 : #include <com/sun/star/sdbc/XCloseable.hpp>
33 : #include <com/sun/star/beans/XPropertySet.hpp>
34 :
35 : #include "rtl/ref.hxx"
36 : #include "salhelper/simplereferenceobject.hxx"
37 : #include <cppuhelper/weak.hxx>
38 : #include <ucbhelper/macros.hxx>
39 : #include "ucbhelper/ucbhelperdllapi.h"
40 :
41 : namespace ucbhelper {
42 :
43 : //=========================================================================
44 :
45 : #define RESULTSET_SERVICE_NAME "com.sun.star.ucb.ContentResultSet"
46 :
47 : //=========================================================================
48 :
49 : class ResultSetDataSupplier;
50 : struct ResultSet_Impl;
51 :
52 : /**
53 : * This is an implementation of the service com.sun.star.ucb.ContentResultSet.
54 : * It can be used to implement the method XDynamicResultSet::getStaticResultSet,
55 : * which needs to be implemented for instance to implement the command "open"
56 : * at folder objects. This class uses a user supplied ResultSetDataSupplier
57 : * object to request data on demand.
58 : *
59 : * @see ResultSetDataSupplier
60 : */
61 : class UCBHELPER_DLLPUBLIC ResultSet :
62 : public cppu::OWeakObject,
63 : public com::sun::star::lang::XTypeProvider,
64 : public com::sun::star::lang::XServiceInfo,
65 : public com::sun::star::lang::XComponent,
66 : public com::sun::star::ucb::XContentAccess,
67 : public com::sun::star::sdbc::XResultSet,
68 : public com::sun::star::sdbc::XResultSetMetaDataSupplier,
69 : public com::sun::star::sdbc::XRow,
70 : public com::sun::star::sdbc::XCloseable,
71 : public com::sun::star::beans::XPropertySet
72 : {
73 : ResultSet_Impl* m_pImpl;
74 :
75 : public:
76 : /**
77 : * Construction.
78 : *
79 : * @param rxSMgr is a Service Manager.
80 : * @param rProperties is a sequence of properties for that the resultset
81 : * shall be able to obtain the values.
82 : * @param rDataSupplier is a supplier for the resultset data.
83 : */
84 : ResultSet(
85 : const com::sun::star::uno::Reference<
86 : com::sun::star::uno::XComponentContext >& rxContext,
87 : const com::sun::star::uno::Sequence<
88 : com::sun::star::beans::Property >& rProperties,
89 : const rtl::Reference< ResultSetDataSupplier >& rDataSupplier );
90 : /**
91 : * Construction.
92 : *
93 : * @param rxSMgr is a Service Manager.
94 : * @param rProperties is a sequence of properties for that the resultset
95 : * shall be able to obtain the values.
96 : * @param rDataSupplier is a supplier for the resultset data.
97 : * @param rxEnv is the environment for interactions, progress propagation,
98 : * ...
99 : */
100 : ResultSet(
101 : const com::sun::star::uno::Reference<
102 : com::sun::star::uno::XComponentContext >& rxContext,
103 : const com::sun::star::uno::Sequence<
104 : com::sun::star::beans::Property >& rProperties,
105 : const rtl::Reference< ResultSetDataSupplier >& rDataSupplier,
106 : const com::sun::star::uno::Reference<
107 : com::sun::star::ucb::XCommandEnvironment >& rxEnv );
108 : virtual ~ResultSet();
109 :
110 : // XInterface
111 : XINTERFACE_DECL()
112 :
113 : // XTypeProvider
114 : XTYPEPROVIDER_DECL()
115 :
116 : // XServiceInfo
117 : XSERVICEINFO_NOFACTORY_DECL()
118 :
119 : // XComponent
120 : virtual void SAL_CALL
121 : dispose()
122 : throw( com::sun::star::uno::RuntimeException );
123 : virtual void SAL_CALL
124 : addEventListener( const com::sun::star::uno::Reference<
125 : com::sun::star::lang::XEventListener >& Listener )
126 : throw( com::sun::star::uno::RuntimeException );
127 : virtual void SAL_CALL
128 : removeEventListener( const com::sun::star::uno::Reference<
129 : com::sun::star::lang::XEventListener >& Listener )
130 : throw( com::sun::star::uno::RuntimeException );
131 :
132 : // XContentAccess
133 : virtual OUString SAL_CALL
134 : queryContentIdentifierString()
135 : throw( com::sun::star::uno::RuntimeException );
136 : virtual com::sun::star::uno::Reference<
137 : com::sun::star::ucb::XContentIdentifier > SAL_CALL
138 : queryContentIdentifier()
139 : throw( com::sun::star::uno::RuntimeException );
140 : virtual com::sun::star::uno::Reference<
141 : com::sun::star::ucb::XContent > SAL_CALL
142 : queryContent()
143 : throw( com::sun::star::uno::RuntimeException );
144 :
145 : // XResultSetMetaDataSupplier
146 : virtual com::sun::star::uno::Reference<
147 : com::sun::star::sdbc::XResultSetMetaData > SAL_CALL
148 : getMetaData()
149 : throw( com::sun::star::sdbc::SQLException,
150 : com::sun::star::uno::RuntimeException );
151 :
152 : // XResultSet
153 : virtual sal_Bool SAL_CALL
154 : next()
155 : throw( com::sun::star::sdbc::SQLException,
156 : com::sun::star::uno::RuntimeException );
157 : virtual sal_Bool SAL_CALL
158 : isBeforeFirst()
159 : throw( com::sun::star::sdbc::SQLException,
160 : com::sun::star::uno::RuntimeException );
161 : virtual sal_Bool SAL_CALL
162 : isAfterLast()
163 : throw( com::sun::star::sdbc::SQLException,
164 : com::sun::star::uno::RuntimeException );
165 : virtual sal_Bool SAL_CALL
166 : isFirst()
167 : throw( com::sun::star::sdbc::SQLException,
168 : com::sun::star::uno::RuntimeException );
169 : virtual sal_Bool SAL_CALL
170 : isLast()
171 : throw( com::sun::star::sdbc::SQLException,
172 : com::sun::star::uno::RuntimeException );
173 : virtual void SAL_CALL
174 : beforeFirst()
175 : throw( com::sun::star::sdbc::SQLException,
176 : com::sun::star::uno::RuntimeException );
177 : virtual void SAL_CALL
178 : afterLast()
179 : throw( com::sun::star::sdbc::SQLException,
180 : com::sun::star::uno::RuntimeException );
181 : virtual sal_Bool SAL_CALL
182 : first()
183 : throw( com::sun::star::sdbc::SQLException,
184 : com::sun::star::uno::RuntimeException );
185 : virtual sal_Bool SAL_CALL
186 : last()
187 : throw( com::sun::star::sdbc::SQLException,
188 : com::sun::star::uno::RuntimeException );
189 : virtual sal_Int32 SAL_CALL
190 : getRow()
191 : throw( com::sun::star::sdbc::SQLException,
192 : com::sun::star::uno::RuntimeException );
193 : virtual sal_Bool SAL_CALL
194 : absolute( sal_Int32 row )
195 : throw( com::sun::star::sdbc::SQLException,
196 : com::sun::star::uno::RuntimeException );
197 : virtual sal_Bool SAL_CALL
198 : relative( sal_Int32 rows )
199 : throw( com::sun::star::sdbc::SQLException,
200 : com::sun::star::uno::RuntimeException );
201 : virtual sal_Bool SAL_CALL
202 : previous()
203 : throw( com::sun::star::sdbc::SQLException,
204 : com::sun::star::uno::RuntimeException );
205 : virtual void SAL_CALL
206 : refreshRow()
207 : throw( com::sun::star::sdbc::SQLException,
208 : com::sun::star::uno::RuntimeException );
209 : virtual sal_Bool SAL_CALL
210 : rowUpdated()
211 : throw( com::sun::star::sdbc::SQLException,
212 : com::sun::star::uno::RuntimeException );
213 : virtual sal_Bool SAL_CALL
214 : rowInserted()
215 : throw( com::sun::star::sdbc::SQLException,
216 : com::sun::star::uno::RuntimeException );
217 : virtual sal_Bool SAL_CALL
218 : rowDeleted()
219 : throw( com::sun::star::sdbc::SQLException,
220 : com::sun::star::uno::RuntimeException );
221 : virtual com::sun::star::uno::Reference<
222 : com::sun::star::uno::XInterface > SAL_CALL
223 : getStatement()
224 : throw( com::sun::star::sdbc::SQLException,
225 : com::sun::star::uno::RuntimeException );
226 :
227 : // XRow
228 : virtual sal_Bool SAL_CALL
229 : wasNull()
230 : throw( com::sun::star::sdbc::SQLException,
231 : com::sun::star::uno::RuntimeException );
232 : virtual OUString SAL_CALL
233 : getString( sal_Int32 columnIndex )
234 : throw( com::sun::star::sdbc::SQLException,
235 : com::sun::star::uno::RuntimeException );
236 : virtual sal_Bool SAL_CALL
237 : getBoolean( sal_Int32 columnIndex )
238 : throw( com::sun::star::sdbc::SQLException,
239 : com::sun::star::uno::RuntimeException );
240 : virtual sal_Int8 SAL_CALL
241 : getByte( sal_Int32 columnIndex )
242 : throw( com::sun::star::sdbc::SQLException,
243 : com::sun::star::uno::RuntimeException );
244 : virtual sal_Int16 SAL_CALL
245 : getShort( sal_Int32 columnIndex )
246 : throw( com::sun::star::sdbc::SQLException,
247 : com::sun::star::uno::RuntimeException );
248 : virtual sal_Int32 SAL_CALL
249 : getInt( sal_Int32 columnIndex )
250 : throw( com::sun::star::sdbc::SQLException,
251 : com::sun::star::uno::RuntimeException );
252 : virtual sal_Int64 SAL_CALL
253 : getLong( sal_Int32 columnIndex )
254 : throw( com::sun::star::sdbc::SQLException,
255 : com::sun::star::uno::RuntimeException );
256 : virtual float SAL_CALL
257 : getFloat( sal_Int32 columnIndex )
258 : throw( com::sun::star::sdbc::SQLException,
259 : com::sun::star::uno::RuntimeException );
260 : virtual double SAL_CALL
261 : getDouble( sal_Int32 columnIndex )
262 : throw( com::sun::star::sdbc::SQLException,
263 : com::sun::star::uno::RuntimeException );
264 : virtual com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL
265 : getBytes( sal_Int32 columnIndex )
266 : throw( com::sun::star::sdbc::SQLException,
267 : com::sun::star::uno::RuntimeException );
268 : virtual com::sun::star::util::Date SAL_CALL
269 : getDate( sal_Int32 columnIndex )
270 : throw( com::sun::star::sdbc::SQLException,
271 : com::sun::star::uno::RuntimeException );
272 : virtual com::sun::star::util::Time SAL_CALL
273 : getTime( sal_Int32 columnIndex )
274 : throw( com::sun::star::sdbc::SQLException,
275 : com::sun::star::uno::RuntimeException );
276 : virtual com::sun::star::util::DateTime SAL_CALL
277 : getTimestamp( sal_Int32 columnIndex )
278 : throw( com::sun::star::sdbc::SQLException,
279 : com::sun::star::uno::RuntimeException );
280 : virtual com::sun::star::uno::Reference<
281 : com::sun::star::io::XInputStream > SAL_CALL
282 : getBinaryStream( sal_Int32 columnIndex )
283 : throw( com::sun::star::sdbc::SQLException,
284 : com::sun::star::uno::RuntimeException );
285 : virtual com::sun::star::uno::Reference<
286 : com::sun::star::io::XInputStream > SAL_CALL
287 : getCharacterStream( sal_Int32 columnIndex )
288 : throw( com::sun::star::sdbc::SQLException,
289 : com::sun::star::uno::RuntimeException );
290 : virtual com::sun::star::uno::Any SAL_CALL
291 : getObject( sal_Int32 columnIndex,
292 : const com::sun::star::uno::Reference<
293 : com::sun::star::container::XNameAccess >& typeMap )
294 : throw( com::sun::star::sdbc::SQLException,
295 : com::sun::star::uno::RuntimeException );
296 : virtual com::sun::star::uno::Reference<
297 : com::sun::star::sdbc::XRef > SAL_CALL
298 : getRef( sal_Int32 columnIndex )
299 : throw( com::sun::star::sdbc::SQLException,
300 : com::sun::star::uno::RuntimeException );
301 : virtual com::sun::star::uno::Reference<
302 : com::sun::star::sdbc::XBlob > SAL_CALL
303 : getBlob( sal_Int32 columnIndex )
304 : throw( com::sun::star::sdbc::SQLException,
305 : com::sun::star::uno::RuntimeException );
306 : virtual com::sun::star::uno::Reference<
307 : com::sun::star::sdbc::XClob > SAL_CALL
308 : getClob( sal_Int32 columnIndex )
309 : throw( com::sun::star::sdbc::SQLException,
310 : com::sun::star::uno::RuntimeException );
311 : virtual com::sun::star::uno::Reference<
312 : com::sun::star::sdbc::XArray > SAL_CALL
313 : getArray( sal_Int32 columnIndex )
314 : throw( com::sun::star::sdbc::SQLException,
315 : com::sun::star::uno::RuntimeException );
316 :
317 : // XCloseable
318 : virtual void SAL_CALL
319 : close()
320 : throw( com::sun::star::sdbc::SQLException,
321 : com::sun::star::uno::RuntimeException );
322 :
323 : // XPropertySet
324 : virtual com::sun::star::uno::Reference<
325 : com::sun::star::beans::XPropertySetInfo > SAL_CALL
326 : getPropertySetInfo()
327 : throw( com::sun::star::uno::RuntimeException );
328 : virtual void SAL_CALL
329 : setPropertyValue( const OUString& aPropertyName,
330 : const com::sun::star::uno::Any& aValue )
331 : throw( com::sun::star::beans::UnknownPropertyException,
332 : com::sun::star::beans::PropertyVetoException,
333 : com::sun::star::lang::IllegalArgumentException,
334 : com::sun::star::lang::WrappedTargetException,
335 : com::sun::star::uno::RuntimeException );
336 : virtual com::sun::star::uno::Any SAL_CALL
337 : getPropertyValue( const OUString& PropertyName )
338 : throw( com::sun::star::beans::UnknownPropertyException,
339 : com::sun::star::lang::WrappedTargetException,
340 : com::sun::star::uno::RuntimeException );
341 : virtual void SAL_CALL
342 : addPropertyChangeListener( const OUString& aPropertyName,
343 : const com::sun::star::uno::Reference<
344 : com::sun::star::beans::XPropertyChangeListener >& xListener )
345 : throw( com::sun::star::beans::UnknownPropertyException,
346 : com::sun::star::lang::WrappedTargetException,
347 : com::sun::star::uno::RuntimeException );
348 : virtual void SAL_CALL
349 : removePropertyChangeListener( const OUString& aPropertyName,
350 : const com::sun::star::uno::Reference<
351 : com::sun::star::beans::XPropertyChangeListener >& aListener )
352 : throw( com::sun::star::beans::UnknownPropertyException,
353 : com::sun::star::lang::WrappedTargetException,
354 : com::sun::star::uno::RuntimeException );
355 : virtual void SAL_CALL
356 : addVetoableChangeListener( const OUString& PropertyName,
357 : const com::sun::star::uno::Reference<
358 : com::sun::star::beans::XVetoableChangeListener >& aListener )
359 : throw( com::sun::star::beans::UnknownPropertyException,
360 : com::sun::star::lang::WrappedTargetException,
361 : com::sun::star::uno::RuntimeException );
362 : virtual void SAL_CALL
363 : removeVetoableChangeListener( const OUString& PropertyName,
364 : const com::sun::star::uno::Reference<
365 : com::sun::star::beans::XVetoableChangeListener >& aListener )
366 : throw( com::sun::star::beans::UnknownPropertyException,
367 : com::sun::star::lang::WrappedTargetException,
368 : com::sun::star::uno::RuntimeException );
369 :
370 : /////////////////////////////////////////////////////////////////////
371 : // Non-interface methods.
372 : /////////////////////////////////////////////////////////////////////
373 :
374 : /**
375 : * This method propagates property value changes to all registered
376 : * listeners.
377 : *
378 : * @param rEvt is a property change event.
379 : */
380 : void propertyChanged(
381 : const com::sun::star::beans::PropertyChangeEvent& rEvt );
382 :
383 : /**
384 : * This method should be called by the data supplier for the result set
385 : * to indicate that there were new data obtained from the data source.
386 : *
387 : * @param nOld is the old count of rows; must be non-negative.
388 : * @param nnew is the new count of rows; must be non-negative.
389 : */
390 : void rowCountChanged( sal_uInt32 nOld, sal_uInt32 nNew );
391 :
392 : /**
393 : * This method should be called by the data supplier for the result set
394 : * to indicate that there were all rows obtained from the data source.
395 : */
396 : void rowCountFinal();
397 :
398 : /**
399 : * This method returns a sequence containing all properties ( not the
400 : * values! ) of the result set.
401 : *
402 : * @return a sequence of properties.
403 : */
404 : const com::sun::star::uno::Sequence< com::sun::star::beans::Property >&
405 : getProperties();
406 :
407 : /**
408 : * This method returns the environment to use for interactions, progress
409 : * propagation, ... It can by empty.
410 : *
411 : * @return an environment or an empty reference.
412 : */
413 : const com::sun::star::uno::Reference<
414 : com::sun::star::ucb::XCommandEnvironment >&
415 : getEnvironment();
416 : };
417 :
418 : //=========================================================================
419 :
420 : /**
421 : * This is the base class for an object that supplies data to a result set
422 : *
423 : * @see ResultSet
424 : */
425 28 : class ResultSetDataSupplier : public salhelper::SimpleReferenceObject
426 : {
427 : friend class ResultSet;
428 :
429 : // No ref, otherwise we get a cyclic reference between supplier and set!
430 : // Will be set from ResultSet ctor.
431 : ResultSet* m_pResultSet;
432 :
433 : public:
434 28 : ResultSetDataSupplier() : m_pResultSet( 0 ) {}
435 :
436 : /**
437 : * This method returns the resultset this supplier belongs to.
438 : *
439 : * @return the resultset for that the supplier supplies data.
440 : */
441 88 : rtl::Reference< ResultSet > getResultSet() const { return m_pResultSet; }
442 :
443 : /**
444 : * This method returns the identifier string of the content at the
445 : * specified index.
446 : *
447 : * @param nIndex is the zero-based index within the logical data array
448 : * of the supplier; must be non-negative.
449 : * @return the content's identifier string.
450 : */
451 : virtual OUString queryContentIdentifierString( sal_uInt32 nIndex ) = 0;
452 :
453 : /**
454 : * This method returns the identifier of the content at the specified index.
455 : *
456 : * @param nIndex is the zero-based index within the logical data array
457 : * of the supplier; must be non-negative.
458 : * @return the content's identifier.
459 : */
460 : virtual com::sun::star::uno::Reference<
461 : com::sun::star::ucb::XContentIdentifier >
462 : queryContentIdentifier( sal_uInt32 nIndex ) = 0;
463 :
464 : /**
465 : * This method returns the content at the specified index.
466 : *
467 : * @param nIndex is the zero-based index within the logical data array
468 : * of the supplier; must be non-negative.
469 : * @return the content.
470 : */
471 : virtual com::sun::star::uno::Reference< com::sun::star::ucb::XContent >
472 : queryContent( sal_uInt32 nIndex ) = 0;
473 :
474 : /**
475 : * This method returns whether there is a content at the specified index.
476 : *
477 : * @param nIndex is the zero-based index within the logical data array
478 : * of the supplier; must be non-negative.
479 : * @return true, if there is a content at the given index.
480 : */
481 : virtual sal_Bool getResult( sal_uInt32 nIndex ) = 0;
482 :
483 : /**
484 : * This method returns the total count of objects in the logical data array
485 : * of the supplier. The implementation of this method may be very
486 : * "expensive", because it can be necessary to obtain all data in order
487 : * to determine the count. Therefor the ResultSet implementation calls
488 : * it very seldom.
489 : *
490 : * @return the total count of objects; will always be non-negative.
491 : */
492 : virtual sal_uInt32 totalCount() = 0;
493 :
494 : /**
495 : * This method returns the count of objects obtained so far. There is no
496 : * for the implemetation to obtain all objects at once. It can obtain
497 : * all data on demand.
498 : *
499 : * The implementation should call m_pResultSet->rowCountChanged(...)
500 : * everytime it has inserted a new entry in its logical result array.
501 : *
502 : * @return the count of objects obtained so far; will always be
503 : * non-negative.
504 : */
505 : virtual sal_uInt32 currentCount() = 0;
506 :
507 : /**
508 : * This method returns whether the value returned by currentCount() is
509 : * "final". This is the case, if that there was all data obtained by the
510 : * supplier and the current count won't increase any more.
511 : *
512 : * The implementation should call m_pResultSet->rowCountFinal(...) if
513 : * it has inserted all entries in its logical result array.
514 : *
515 : * @return true, if the value returned by currentCount() won't change
516 : anymore.
517 : */
518 : virtual sal_Bool isCountFinal() = 0;
519 :
520 : /**
521 : * This method returns an object for accessing the property values at
522 : * the specified index. The implementation may use the helper class
523 : * ucb::PropertyValueSet to provide the return value.
524 : *
525 : * @param nIndex is the zero-based index within the logical data array
526 : * of the supplier.
527 : * @return the object for accessing the property values.
528 : */
529 : virtual com::sun::star::uno::Reference< com::sun::star::sdbc::XRow >
530 : queryPropertyValues( sal_uInt32 nIndex ) = 0;
531 :
532 : /**
533 : * This method is called to instruct the supplier to release the (possibly
534 : * presnt) property values at the given index.
535 : *
536 : * @param nIndex is the zero-based index within the logical data array
537 : * of the supplier.
538 : */
539 : virtual void releasePropertyValues( sal_uInt32 nIndex ) = 0;
540 :
541 : /**
542 : * This method will be called by the resultset implementation in order
543 : * to instruct the data supplier to release all resources it has
544 : * allocated so far. In case the supplier is collecting data
545 : * asynchronously, that process must be stopped.
546 : */
547 : virtual void close() = 0;
548 :
549 : /**
550 : * This method will be called by the resultset implementation in order
551 : * check, whether an error has occurred while collecting data. The
552 : * implementation of this method must throw an exception in that case.
553 : *
554 : * Note: An exception thrown to indicate an error must always be thrown
555 : * by the thread that created the data supplier. If the supplier collects
556 : * data asynchronously ( i.e. in a separate thread ) and an error
557 : * occures, throwing of the appropriate exception must be deferred
558 : * until validate() is called by the ResultSet implementation from
559 : * inside the main thread.
560 : * In case data are obtained synchronously, the ResultSetException can
561 : * be thrown directly.
562 : *
563 : * @exception ResultSetException thrown, if an error has occurred
564 : */
565 : virtual void validate()
566 : throw( com::sun::star::ucb::ResultSetException ) = 0;
567 : };
568 :
569 : }
570 :
571 : #endif /* !_UCBHELPER_RESULTSET_HXX */
572 :
573 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|