KOffice – TDE office suite
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

805 regels
18 KiB

  1. /* This file is part of the KDE project
  2. Copyright (C) 2002, Dirk Schönberger <dirk.schoenberger@sz-online.de>
  3. This library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Library General Public
  5. License as published by the Free Software Foundation; either
  6. version 2 of the License, or (at your option) any later version.
  7. This library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Library General Public License for more details.
  11. You should have received a copy of the GNU Library General Public License
  12. along with this library; see the file COPYING.LIB. If not, write to
  13. the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  14. * Boston, MA 02110-1301, USA.
  15. */
  16. #include "aielement.h"
  17. #include <tqglobal.h>
  18. AIElement::Private::Private()
  19. {
  20. typ = AIElement::Invalid;
  21. }
  22. AIElement::Private::Private( Private* d )
  23. {
  24. switch( d->typ )
  25. {
  26. case AIElement::Invalid:
  27. break;
  28. case AIElement::String:
  29. case AIElement::Reference:
  30. case AIElement::Operator:
  31. value.ptr = new TQString( *((TQString*)d->value.ptr) );
  32. break;
  33. case AIElement::CString:
  34. // TQCString is explicit shared
  35. value.ptr = new TQCString( *((TQCString*)d->value.ptr) );
  36. break;
  37. /* case AIElement::List:
  38. value.ptr = new TQValueList<AIElement>( *((TQValueList<AIElement>*)d->value.ptr) );
  39. break; */
  40. case AIElement::ElementArray:
  41. value.ptr = new TQValueVector<AIElement>( *((TQValueVector<AIElement>*)d->value.ptr) );
  42. break;
  43. case AIElement::Block:
  44. value.ptr = new TQValueVector<AIElement>( *((TQValueVector<AIElement>*)d->value.ptr) );
  45. break;
  46. case AIElement::ByteArray:
  47. value.ptr = new TQByteArray( *((TQByteArray*)d->value.ptr) );
  48. break;
  49. case AIElement::Int:
  50. value.i = d->value.i;
  51. break;
  52. case AIElement::UInt:
  53. value.u = d->value.u;
  54. break;
  55. case AIElement::Double:
  56. value.d = d->value.d;
  57. break;
  58. case AIElement::Byte:
  59. value.b = d->value.b;
  60. break;
  61. default:
  62. Q_ASSERT( 0 );
  63. }
  64. typ = d->typ;
  65. }
  66. AIElement::Private::~Private()
  67. {
  68. clear();
  69. }
  70. void AIElement::Private::clear()
  71. {
  72. switch( typ )
  73. {
  74. case AIElement::String:
  75. case AIElement::Operator:
  76. case AIElement::Reference:
  77. delete (TQString*)value.ptr;
  78. break;
  79. case AIElement::CString:
  80. delete (TQCString*)value.ptr;
  81. break;
  82. /* case AIElement::List:
  83. delete (TQValueList<AIElement>*)value.ptr;
  84. break; */
  85. case AIElement::ElementArray:
  86. delete (TQValueVector<AIElement>*)value.ptr;
  87. break;
  88. case AIElement::Block:
  89. delete (TQValueVector<AIElement>*)value.ptr;
  90. break;
  91. case AIElement::ByteArray:
  92. delete (TQByteArray*)value.ptr;
  93. break;
  94. case AIElement::Invalid:
  95. case AIElement::Int:
  96. case AIElement::UInt:
  97. case AIElement::Double:
  98. case AIElement::Byte:
  99. break;
  100. }
  101. typ = AIElement::Invalid;
  102. }
  103. /*!
  104. Constructs an invalid aielement.
  105. */
  106. AIElement::AIElement()
  107. {
  108. d = new Private;
  109. }
  110. /*!
  111. Destroys the AIElement and the contained object.
  112. Note that subclasses that reimplement clear() should reimplement
  113. the destructor to call clear(). This destructor calls clear(), but
  114. because it is the destructor, AIElement::clear() is called rather than
  115. a subclass's clear().
  116. */
  117. AIElement::~AIElement()
  118. {
  119. if ( d->deref() )
  120. delete d;
  121. }
  122. /*!
  123. Constructs a copy of the aielement, \a p, passed as the argument to this
  124. constructor. Usually this is a deep copy, but a shallow copy is made
  125. if the stored data type is explicitly shared, as e.g. TQImage is.
  126. */
  127. AIElement::AIElement( const AIElement& p )
  128. {
  129. d = new Private;
  130. *this = p;
  131. }
  132. /*!
  133. Constructs a new aielement with a string value, \a val.
  134. */
  135. AIElement::AIElement( const TQString& val, Type type )
  136. {
  137. d = new Private;
  138. d->typ = type;
  139. d->value.ptr = new TQString( val );
  140. }
  141. /*!
  142. Constructs a new aielement with a C-string value, \a val.
  143. If you want to modify the TQCString after you've passed it to this
  144. constructor, we recommend passing a deep copy (see
  145. TQCString::copy()).
  146. */
  147. AIElement::AIElement( const TQCString& val )
  148. {
  149. d = new Private;
  150. d->typ = CString;
  151. d->value.ptr = new TQCString( val );
  152. }
  153. /*!
  154. Constructs a new aielement with a C-string value of \a val if \a val
  155. is non-null. The aielement creates a deep copy of \a val.
  156. If \a val is null, the resulting aielement has type Invalid.
  157. */
  158. AIElement::AIElement( const char* val )
  159. {
  160. d = new Private;
  161. if ( val == 0 )
  162. return;
  163. d->typ = CString;
  164. d->value.ptr = new TQCString( val );
  165. }
  166. /*!
  167. Constructs a new aielement with an integer value, \a val.
  168. */
  169. AIElement::AIElement( int val )
  170. {
  171. d = new Private;
  172. d->typ = Int;
  173. d->value.i = val;
  174. }
  175. /*!
  176. Constructs a new aielement with an unsigned integer value, \a val.
  177. */
  178. AIElement::AIElement( uint val )
  179. {
  180. d = new Private;
  181. d->typ = UInt;
  182. d->value.u = val;
  183. }
  184. /*!
  185. Constructs a new aielement with an byte value, \a val.
  186. */
  187. AIElement::AIElement( uchar val )
  188. {
  189. d = new Private;
  190. d->typ = Byte;
  191. d->value.b = val;
  192. }
  193. /*!
  194. Constructs a new aielement with a floating point value, \a val.
  195. */
  196. AIElement::AIElement( double val )
  197. {
  198. d = new Private;
  199. d->typ = Double;
  200. d->value.d = val;
  201. }
  202. /*!
  203. Constructs a new aielement with a list value, \a val.
  204. */
  205. /* AIElement::AIElement( const TQValueList<AIElement>& val )
  206. {
  207. d = new Private;
  208. d->typ = List;
  209. d->value.ptr = new TQValueList<AIElement>( val );
  210. } */
  211. AIElement::AIElement( const TQValueVector<AIElement>& val, Type type )
  212. {
  213. d = new Private;
  214. d->typ = type;
  215. d->value.ptr = new TQValueVector<AIElement>( val );
  216. }
  217. AIElement::AIElement( const TQByteArray& val )
  218. {
  219. d = new Private;
  220. d->typ = ByteArray;
  221. d->value.ptr = new TQByteArray( val );
  222. }
  223. /*!
  224. Assigns the value of the aielement \a aielement to this aielement.
  225. This is a deep copy of the aielement, but note that if the aielement
  226. holds an explicitly shared type such as TQImage, a shallow copy
  227. is performed.
  228. */
  229. AIElement& AIElement::operator= ( const AIElement& aielement )
  230. {
  231. AIElement& other = (AIElement&)aielement;
  232. other.d->ref();
  233. if ( d->deref() )
  234. delete d;
  235. d = other.d;
  236. return *this;
  237. }
  238. /*!
  239. \internal
  240. */
  241. void AIElement::detach()
  242. {
  243. if ( d->count == 1 )
  244. return;
  245. d->deref();
  246. d = new Private( d );
  247. }
  248. /*!
  249. Returns the name of the type stored in the aielement.
  250. The returned strings describe the C++ datatype used to store the
  251. data: for example, "TQFont", TQSTRING_OBJECT_NAME_STRING, or "TQValueList<AIElement>".
  252. An Invalid aielement returns 0.
  253. */
  254. const char* AIElement::typeName() const
  255. {
  256. return typeToName( d->typ );
  257. }
  258. /*! Convert this aielement to type Invalid and free up any resources
  259. used.
  260. */
  261. void AIElement::clear()
  262. {
  263. if ( d->count > 1 )
  264. {
  265. d->deref();
  266. d = new Private;
  267. return;
  268. }
  269. d->clear();
  270. }
  271. static const int ntypes = 11;
  272. static const char* const type_map[ntypes] =
  273. {
  274. 0,
  275. // "TQValueList<AIElement>",
  276. TQSTRING_OBJECT_NAME_STRING,
  277. "int",
  278. "uint",
  279. "double",
  280. "TQCString",
  281. "Operator",
  282. "Reference",
  283. "TQValueVector<AIElement>",
  284. TQBYTEARRAY_OBJECT_NAME_STRING,
  285. "uchar",
  286. };
  287. /*!
  288. Converts the enum representation of the storage type, \a typ, to its
  289. string representation.
  290. */
  291. const char* AIElement::typeToName( Type typ )
  292. {
  293. if ( typ >= ntypes )
  294. return 0;
  295. return type_map[typ];
  296. }
  297. /*!
  298. Converts the string representation of the storage type gven in \a
  299. name, to its enum representation.
  300. If the string representation cannot be converted to any enum
  301. representation, the aielement is set to \c Invalid.
  302. */
  303. AIElement::Type AIElement::nameToType( const char* name )
  304. {
  305. for ( int i = 0; i < ntypes; i++ ) {
  306. if ( !qstrcmp( type_map[i], name ) )
  307. return (Type) i;
  308. }
  309. return Invalid;
  310. }
  311. /*!
  312. Returns the aielement as a TQString if the aielement has type()
  313. String, CString, ByteArray, Int, Uint, Double,
  314. or TQString() otherwise.
  315. \sa asString()
  316. */
  317. const TQString AIElement::toString() const
  318. {
  319. if ( d->typ == CString )
  320. return TQString::fromLatin1( toCString() );
  321. if ( d->typ == Int )
  322. return TQString::number( toInt() );
  323. if ( d->typ == UInt )
  324. return TQString::number( toUInt() );
  325. if ( d->typ == Double )
  326. return TQString::number( toDouble() );
  327. if ( d->typ == Byte )
  328. return TQString::number( toByte() );
  329. if ( d->typ != String )
  330. return TQString();
  331. return *((TQString*)d->value.ptr);
  332. }
  333. const TQString AIElement::toReference() const
  334. {
  335. if ( d->typ != Reference )
  336. return TQString();
  337. return *((TQString*)d->value.ptr);
  338. }
  339. const TQString AIElement::toOperator() const
  340. {
  341. if ( d->typ != Operator )
  342. return TQString();
  343. return *((TQString*)d->value.ptr);
  344. }
  345. /*!
  346. Returns the aielement as a TQCString if the aielement has type()
  347. CString or String, or a 0 otherwise.
  348. \sa asCString()
  349. */
  350. const TQCString AIElement::toCString() const
  351. {
  352. if ( d->typ == CString )
  353. return *((TQCString*)d->value.ptr);
  354. if ( d->typ == String )
  355. return ((TQString*)d->value.ptr)->latin1();
  356. if ( d->typ == Operator )
  357. return ((TQString*)d->value.ptr)->latin1();
  358. if ( d->typ == Reference )
  359. return ((TQString*)d->value.ptr)->latin1();
  360. return 0;
  361. }
  362. /*!
  363. Returns the aielement as an int if the aielement has type()
  364. String, CString, Int, UInt, Double, Byte, or 0 otherwise.
  365. If \a ok is non-null, \a *ok is set to TRUE if the value could be
  366. converted to an int and FALSE otherwise.
  367. \sa asInt() canCast()
  368. */
  369. int AIElement::toInt( bool * ok ) const
  370. {
  371. if( d->typ == String )
  372. return ((TQString*)d->value.ptr)->toInt( ok );
  373. if ( d->typ == CString )
  374. return ((TQCString*)d->value.ptr)->toInt( ok );
  375. if ( ok )
  376. *ok = canCast( UInt );
  377. if( d->typ == Int )
  378. return d->value.i;
  379. if( d->typ == UInt )
  380. return (int)d->value.u;
  381. if( d->typ == Byte )
  382. return (int)d->value.b;
  383. if ( d->typ == Double )
  384. return (int)d->value.d;
  385. return 0;
  386. }
  387. uchar AIElement::toByte( bool * ok ) const
  388. {
  389. if( d->typ == String )
  390. return ((TQString*)d->value.ptr)->toShort( ok );
  391. if ( d->typ == CString )
  392. return ((TQCString*)d->value.ptr)->toShort( ok );
  393. if ( ok )
  394. *ok = canCast( UInt );
  395. if( d->typ == Byte )
  396. return d->value.b;
  397. if( d->typ == Int )
  398. return (uchar)d->value.i;
  399. if( d->typ == UInt )
  400. return (uchar)d->value.u;
  401. if ( d->typ == Double )
  402. return (uchar)d->value.d;
  403. return 0;
  404. }
  405. /*!
  406. Returns the aielement as an unsigned int if the aielement has type()
  407. String, CString, UInt, Int, Double, Byte, or 0 otherwise.
  408. If \a ok is non-null, \a *ok is set to TRUE if the value could be
  409. converted to a uint and FALSE otherwise.
  410. \sa asUInt()
  411. */
  412. uint AIElement::toUInt( bool * ok ) const
  413. {
  414. if( d->typ == String )
  415. return ((TQString*)d->value.ptr)->toUInt( ok );
  416. if ( d->typ == CString )
  417. return ((TQCString*)d->value.ptr)->toUInt( ok );
  418. if ( ok )
  419. *ok = canCast( UInt );
  420. if( d->typ == Int )
  421. return d->value.i;
  422. if( d->typ == UInt )
  423. return (int)d->value.u;
  424. if( d->typ == Byte )
  425. return (int)d->value.b;
  426. if ( d->typ == Double )
  427. return (int)d->value.d;
  428. return 0;
  429. }
  430. /*!
  431. Returns the aielement as a double if the aielement has type()
  432. String, CString, Double, Int, UInt, Byte, or 0.0 otherwise.
  433. If \a ok is non-null, \a *ok is set to TRUE if the value could be
  434. converted to a double and FALSE otherwise.
  435. \sa asDouble()
  436. */
  437. double AIElement::toDouble( bool * ok ) const
  438. {
  439. if( d->typ == String )
  440. return ((TQString*)d->value.ptr)->toDouble( ok );
  441. if ( d->typ == CString )
  442. return ((TQCString*)d->value.ptr)->toDouble( ok );
  443. if ( ok )
  444. *ok = canCast( Double );
  445. if ( d->typ == Double )
  446. return d->value.d;
  447. if ( d->typ == Int )
  448. return (double)d->value.i;
  449. if ( d->typ == UInt )
  450. return (double)d->value.u;
  451. if ( d->typ == Byte )
  452. return (double)d->value.b;
  453. return 0.0;
  454. }
  455. /*!
  456. Returns the aielement as a TQValueList<AIElement> if the aielement has type()
  457. List or StringList, or an empty list otherwise.
  458. Note that if you want to iterate over the list, you should
  459. iterate over a copy, e.g.
  460. \code
  461. TQValueList<AIElement> list = myAIElement.toList();
  462. TQValueList<AIElement>::Iterator it = list.begin();
  463. while( it != list.end() ) {
  464. myProcessing( *it );
  465. ++it;
  466. }
  467. \endcode
  468. \sa asList()
  469. */
  470. /* const TQValueList<AIElement> AIElement::toList() const
  471. {
  472. if ( d->typ == List )
  473. return *((TQValueList<AIElement>*)d->value.ptr);
  474. return TQValueList<AIElement>();
  475. } */
  476. const TQValueVector<AIElement> AIElement::toElementArray() const
  477. {
  478. if ( d->typ == ElementArray )
  479. return *((TQValueVector<AIElement>*)d->value.ptr);
  480. return TQValueVector<AIElement>();
  481. }
  482. const TQValueVector<AIElement> AIElement::toBlock() const
  483. {
  484. if ( d->typ == Block )
  485. return *((TQValueVector<AIElement>*)d->value.ptr);
  486. return TQValueVector<AIElement>();
  487. }
  488. const TQByteArray AIElement::toByteArray() const
  489. {
  490. if ( d->typ == ByteArray )
  491. return *((TQByteArray*)d->value.ptr);
  492. return TQByteArray();
  493. }
  494. #define TQ_VARIANT_AS( f ) TQ##f& AIElement::as##f() { \
  495. if ( d->typ != f ) *this = AIElement( to##f() ); else detach(); return *((TQ##f*)d->value.ptr);}
  496. TQ_VARIANT_AS(String)
  497. TQ_VARIANT_AS(CString)
  498. /*!
  499. Returns the aielement's value as int reference.
  500. */
  501. int& AIElement::asInt()
  502. {
  503. detach();
  504. if ( d->typ != Int ) {
  505. int i = toInt();
  506. d->clear();
  507. d->value.i = i;
  508. d->typ = Int;
  509. }
  510. return d->value.i;
  511. }
  512. /*!
  513. Returns the aielement's value as unsigned int reference.
  514. */
  515. uint& AIElement::asUInt()
  516. {
  517. detach();
  518. if ( d->typ != UInt ) {
  519. uint u = toUInt();
  520. d->clear();
  521. d->value.u = u;
  522. d->typ = UInt;
  523. }
  524. return d->value.u;
  525. }
  526. /*!
  527. Returns the aielement's value as double reference.
  528. */
  529. double& AIElement::asDouble()
  530. {
  531. if ( d->typ != Double ) {
  532. double dbl = toDouble();
  533. d->clear();
  534. d->value.d = dbl;
  535. d->typ = Double;
  536. }
  537. return d->value.d;
  538. }
  539. /*!
  540. Returns the aielement's value as byte reference.
  541. */
  542. uchar& AIElement::asByte()
  543. {
  544. detach();
  545. if ( d->typ != Byte ) {
  546. uchar b = toByte();
  547. d->clear();
  548. d->value.b = b;
  549. d->typ = Byte;
  550. }
  551. return d->value.b;
  552. }
  553. /*!
  554. Returns the aielement's value as aielement list reference.
  555. Note that if you want to iterate over the list, you should
  556. iterate over a copy, e.g.
  557. \code
  558. TQValueList<AIElement> list = myAIElement.asList();
  559. TQValueList<AIElement>::Iterator it = list.begin();
  560. while( it != list.end() ) {
  561. myProcessing( *it );
  562. ++it;
  563. }
  564. \endcode
  565. */
  566. /* TQValueList<AIElement>& AIElement::asList()
  567. {
  568. if ( d->typ != List )
  569. *this = AIElement( toList() );
  570. return *((TQValueList<AIElement>*)d->value.ptr);
  571. } */
  572. TQValueVector<AIElement>& AIElement::asElementArray()
  573. {
  574. if ( d->typ != ElementArray )
  575. *this = AIElement( toElementArray() );
  576. return *((TQValueVector<AIElement>*)d->value.ptr);
  577. }
  578. TQValueVector<AIElement>& AIElement::asBlock()
  579. {
  580. if ( d->typ != Block )
  581. *this = AIElement( toBlock() );
  582. return *((TQValueVector<AIElement>*)d->value.ptr);
  583. }
  584. TQByteArray& AIElement::asByteArray()
  585. {
  586. if ( d->typ != ByteArray )
  587. *this = AIElement( toByteArray() );
  588. return *((TQByteArray*)d->value.ptr);
  589. }
  590. /*!
  591. Returns TRUE if the aielement's type can be cast to the requested
  592. type, \p t. Such casting is done automatically when calling the
  593. toInt(), ... or asInt(), ... methods.
  594. The following casts are done automatically:
  595. <ul>
  596. <li> CString => String
  597. <li> Double => String, Int, UInt
  598. <li> Int => String, Double, UInt
  599. <li> String => CString, Int, Uint, Double
  600. <li> UInt => String, Double, Int
  601. </ul>
  602. */
  603. bool AIElement::canCast( Type t ) const
  604. {
  605. if ( d->typ == t )
  606. return TRUE;
  607. if ( t == Int && ( d->typ == String || d->typ == Double || d->typ == UInt || d->typ == Byte) )
  608. return TRUE;
  609. if ( t == UInt && ( d->typ == String || d->typ == Double || d->typ == Int || d->typ == Byte) )
  610. return TRUE;
  611. if ( t == Double && ( d->typ == String || d->typ == Int || d->typ == UInt || d->typ == Byte) )
  612. return TRUE;
  613. if ( t == CString && d->typ == String )
  614. return TRUE;
  615. if ( t == String && ( d->typ == CString || d->typ == Int || d->typ == UInt || d->typ == Double || d->typ == Byte) )
  616. return TRUE;
  617. return FALSE;
  618. }
  619. /*!
  620. \brief Casts the aielement to the requested type.
  621. If the cast cannot be
  622. done, the aielement is set to the default value of the requested type
  623. (e.g. an empty string if the requested type \p t is
  624. AIElement::String, an empty point array if the requested type \p t is
  625. AIElement::PointArray, etc).
  626. \returns TRUE if the current type of the
  627. aielement was successfully casted; otherwise returns FALSE.
  628. \see canCast()
  629. */
  630. bool AIElement::cast( Type t )
  631. {
  632. switch ( t ) {
  633. /* case AIElement::List:
  634. asList();
  635. break; */
  636. case AIElement::ElementArray:
  637. asElementArray();
  638. break;
  639. case AIElement::Block:
  640. asBlock();
  641. break;
  642. case AIElement::String:
  643. asString();
  644. break;
  645. case AIElement::Int:
  646. asInt();
  647. break;
  648. case AIElement::UInt:
  649. asUInt();
  650. break;
  651. case AIElement::Double:
  652. asDouble();
  653. break;
  654. case AIElement::CString:
  655. asCString();
  656. break;
  657. case AIElement::Byte:
  658. asByte();
  659. break;
  660. case AIElement::ByteArray:
  661. asByteArray();
  662. break;
  663. default:
  664. case AIElement::Invalid:
  665. (*this) = AIElement();
  666. }
  667. return canCast( t );
  668. }
  669. /*! Compares this AIElement with \a v and returns TRUE if they are
  670. equal; otherwise returns FALSE.
  671. */
  672. bool AIElement::operator==( const AIElement &v ) const
  673. {
  674. if ( !v.canCast( type() ) )
  675. return FALSE;
  676. switch( d->typ ) {
  677. /* case List:
  678. return v.toList() == toList(); */
  679. case ElementArray:
  680. return v.toElementArray() == toElementArray();
  681. case Block:
  682. return v.toBlock() == toBlock();
  683. case ByteArray:
  684. return v.toByteArray() == toByteArray();
  685. case String:
  686. return v.toString() == toString();
  687. case Operator:
  688. return v.toOperator() == toOperator();
  689. case Reference:
  690. return v.toReference() == toReference();
  691. case CString:
  692. return v.toCString() == toCString();
  693. case Int:
  694. return v.toInt() == toInt();
  695. case UInt:
  696. return v.toUInt() == toUInt();
  697. case Byte:
  698. return v.toByte() == toByte();
  699. case Invalid:
  700. break;
  701. }
  702. return FALSE;
  703. }
  704. /*! Compares this AIElement with \a v and returns TRUE if they are
  705. not equal; otherwise returns FALSE.
  706. */
  707. bool AIElement::operator!=( const AIElement &v ) const
  708. {
  709. return !( v == *this );
  710. }