1 #ifndef LIBSPRINGLOBBY_HEADERGUARD_SPRINGUNITSYNCLIB_H 2 #define LIBSPRINGLOBBY_HEADERGUARD_SPRINGUNITSYNCLIB_H 3 4 #include <string> 5 #include <stdexcept> 6 #include <list> 7 8 #include "data.h" 9 #include "signatures.h" 10 #include <lslutils/type_forwards.h> 11 #include <boost/noncopyable.hpp> 12 #include <boost/thread/mutex.hpp> 13 14 namespace boost { 15 namespace extensions { 16 class shared_library; 17 } 18 } 19 20 namespace LSL { 21 22 class UnitsyncImage; 23 struct UnitsyncFunctionLoader; 24 25 static const unsigned int MapInfoMaxStartPositions = 16; 26 27 /** \todo needs to be replaced in favor of the ones in out excpetion header **/ 28 /* FIXME: doesn't catch LSL::unitsync 29 class unitsync_assert : public std::runtime_error 30 { 31 public: 32 unitsync_assert(std::string msg) : std::runtime_error(msg) {} 33 }; 34 */ 35 36 //! Everything spring makes available about a map 37 struct SpringMapInfo 38 { 39 char* description; 40 int tidalStrength; 41 int gravity; 42 float maxMetal; 43 int extractorRadius; 44 int minWind; 45 int maxWind; 46 47 int width; 48 int height; 49 int posCount; 50 StartPos positions[MapInfoMaxStartPositions]; 51 52 char* author; 53 SpringMapInfoSpringMapInfo54 SpringMapInfo() 55 : description(NULL) 56 , tidalStrength(0) 57 , gravity(0) 58 , maxMetal(0.0f) 59 , extractorRadius(0) 60 , minWind(0) 61 , maxWind(0) 62 , width(0) 63 , height(0) 64 , posCount(0) 65 , author(NULL) 66 {} 67 }; 68 69 class SpringBundle 70 { 71 public: SpringBundle()72 SpringBundle(): valid(false){}; 73 bool GetBundleVersion(bool force = false); 74 // try to fill missing information by guessing 75 bool AutoComplete(std::string searchpath=""); 76 bool IsValid(); 77 std::string unitsync; 78 std::string spring; 79 std::string version; 80 std::string path; 81 private: 82 bool AutoFindUnitsync(const std::string& unitsyncpath); 83 std::string GetLibExtension(); 84 bool valid; 85 }; 86 87 88 /** 89 * \brief Primitive class handling the unitsync library. 90 * 91 * This class is - in a limited way - thread safe but may block execution 92 * in case two threads use it at the same time. The thread safety ensures 93 * there can never be multiple threads executing unitsync functions at the 94 * same time. However, many unitsync functions use (hidden) global state, 95 * so often there is a need for running multiple unitsync methods while 96 * holding a single lock continuously. 97 */ 98 class UnitsyncLib : public boost::noncopyable 99 { 100 //! we use this to offload the mind numblingly boring pointer loading 101 friend struct UnitsyncFunctionLoader; 102 103 public: 104 /** 105 * Constructor. 106 */ 107 UnitsyncLib(); 108 109 /** 110 * Destructor, unloads unitsync if loaded. 111 */ 112 ~UnitsyncLib(); 113 114 /** 115 * Loads the unitsync library from path. 116 * @param path path to the unitsync lib. 117 * @see Unload(). 118 * @note Throws runtime_error if load failed. 119 */ 120 void Load( const std::string& path); 121 122 /** 123 * Unload the unitsync library. Does nothing if not loaded. 124 * @see Load(). 125 */ 126 void Unload(); 127 128 /** 129 * Returns true if the library is loaded. 130 */ 131 bool IsLoaded() const; 132 133 /** 134 * Gets last error from unitsync library 135 * @note throws unitsync_assert in case of error 136 * @note this method should only be used after using directly an unitsync call to catch it's errors 137 */ 138 void AssertUnitsyncOk() const; 139 140 /** 141 * Get list of errors from unitsync library in an array 142 */ 143 std::vector<std::string> GetUnitsyncErrors() const; 144 145 bool VersionSupports( LSL::GameFeature feature ) const; 146 147 148 int GetModIndex( const std::string& name ); 149 150 std::string GetSpringVersion(); 151 152 /** 153 * Loads unitsync from any number of paths in succession, 154 * queries the Spring versions supported by these unitsyncs, 155 * and returns those. 156 * 157 * This is done by a single function because this "transaction" 158 * needs to hold the unitsync lock the entire time. 159 */ 160 std::map<std::string, SpringBundle> GetSpringVersionList(const std::list<SpringBundle>& unitsync_paths); 161 162 std::string GetSpringDataDir(); 163 int GetSpringDataDirCount(); 164 std::string GetSpringDataDirByIndex( const int index ); 165 std::string GetConfigFilePath(); 166 167 int GetMapCount(); 168 std::string GetMapChecksum( int index ); 169 std::string GetMapName( int index ); 170 int GetMapArchiveCount( int index ); 171 std::string GetMapArchiveName( int arnr ); 172 173 typedef std::vector< std::string > 174 StringVector; 175 StringVector GetMapDeps( int index ); 176 177 /** 178 * @brief Get information about a map. 179 * @param version will get author if >=1. 180 * @note Throws assert_exception if unsuccessful. 181 */ 182 MapInfo GetMapInfoEx( int index, int version ); 183 184 /** 185 * @brief Get minimap. 186 * @note Throws assert_exception if unsuccessful. 187 */ 188 UnitsyncImage GetMinimap( const std::string& mapFileName ); 189 190 /** 191 * @brief Get metalmap. 192 * @note Throws assert_exception if unsuccessful. 193 */ 194 UnitsyncImage GetMetalmap( const std::string& mapFileName ); 195 196 /** 197 * @brief Get heightmap. 198 * @note Throws assert_exception if unsuccesful. 199 */ 200 UnitsyncImage GetHeightmap( const std::string& mapFileName ); 201 202 std::string GetPrimaryModChecksum( int index ); 203 int GetPrimaryModIndex( const std::string& modName ); 204 std::string GetPrimaryModName( int index ); 205 int GetPrimaryModCount(); 206 std::string GetPrimaryModArchive( int index ); 207 std::string GetPrimaryModShortName( int index ); 208 std::string GetPrimaryModVersion( int index ); 209 std::string GetPrimaryModMutator( int index ); 210 std::string GetPrimaryModGame( int index ); 211 std::string GetPrimaryModShortGame( int index ); 212 std::string GetPrimaryModDescription( int index ); 213 int GetPrimaryModArchiveCount( int index ); 214 std::string GetPrimaryModArchiveList( int arnr ); 215 std::string GetPrimaryModChecksumFromName( const std::string& name ); 216 StringVector GetModDeps( int index ); 217 218 StringVector GetSides( const std::string& modName ); 219 220 /** 221 * Add all achives. 222 * @note Not sure what this does, but adding the mod archive path to this when setting new mod seems to work :) 223 */ 224 void AddAllArchives( const std::string& root ); 225 void AddArchive(const std::string& name); 226 227 void SetCurrentMod( const std::string& modname ); 228 void UnSetCurrentMod( ); 229 230 std::string GetFullUnitName( int index ); 231 std::string GetUnitName( int index ); 232 int GetUnitCount(); 233 int ProcessUnitsNoChecksum(); 234 235 /** 236 * Search for a file pattern. 237 * @param the search patterns 238 * @return wxarraystring of results 239 */ 240 StringVector FindFilesVFS( const std::string& name ); 241 int OpenFileVFS( const std::string& name ); 242 int FileSizeVFS( int handle ); 243 int ReadFileVFS( int handle, void* buffer, int bufferLength ); 244 void CloseFileVFS( int handle ); 245 246 unsigned int GetValidMapCount( const std::string& modname ); 247 std::string GetValidMapName( unsigned int MapIndex ); 248 249 int GetMapOptionCount( const std::string& name ); 250 int GetCustomOptionCount( const std::string& modname, const std::string& filename ); 251 int GetModOptionCount( const std::string& name ); 252 int GetAIOptionCount( const std::string& modname, int index ); 253 std::string GetOptionKey( int optIndex ); 254 std::string GetOptionName( int optIndex ); 255 std::string GetOptionDesc( int optIndex ); 256 std::string GetOptionSection( int optIndex ); 257 std::string GetOptionStyle( int optIndex ); 258 int GetOptionType( int optIndex ); 259 int GetOptionBoolDef( int optIndex ); 260 float GetOptionNumberDef( int optIndex ); 261 float GetOptionNumberMin( int optIndex ); 262 float GetOptionNumberMax( int optIndex ); 263 float GetOptionNumberStep( int optIndex ); 264 std::string GetOptionStringDef( int optIndex ); 265 int GetOptionStringMaxLen( int optIndex ); 266 int GetOptionListCount( int optIndex ); 267 std::string GetOptionListDef( int optIndex ); 268 std::string GetOptionListItemKey( int optIndex, int itemIndex ); 269 std::string GetOptionListItemName( int optIndex, int itemIndex ); 270 std::string GetOptionListItemDesc( int optIndex, int itemIndex ); 271 272 int OpenArchive( const std::string& name ); 273 void CloseArchive( int archive ); 274 int FindFilesArchive( int archive, int cur, std::string& nameBuf ); 275 int OpenArchiveFile( int archive, const std::string& name ); 276 int ReadArchiveFile( int archive, int handle, void* buffer, int numBytes) ; 277 void CloseArchiveFile( int archive, int handle ); 278 int SizeArchiveFile( int archive, int handle ); 279 std::string GetArchivePath( const std::string& name ); 280 281 int GetSpringConfigInt( const std::string& key, int defValue ); 282 std::string GetSpringConfigString( const std::string& key, const std::string& defValue ); 283 float GetSpringConfigFloat( const std::string& key, const float defValue ); 284 void SetSpringConfigString( const std::string& key, const std::string& value ); 285 void SetSpringConfigInt( const std::string& key, int value ); 286 void SetSpringConfigFloat( const std::string& key, const float value ); 287 288 /// AI info 289 int GetSkirmishAICount( const std::string& modname ); 290 /** 291 * Get next search result. 292 * @param the AI index within range of GetSkirmishAIInfoCount 293 * @return an array made of blocks with this layout { key, value, description } 294 */ 295 StringVector GetAIInfo( int index ); 296 297 std::string GetArchiveChecksum( const std::string& VFSPath ); 298 299 /// lua parser 300 301 void CloseParser(); 302 bool OpenParserFile( const std::string& filename, const std::string& filemodes, const std::string& accessModes ); 303 bool OpenParserSource( const std::string& source, const std::string& accessModes ); 304 bool ParserExecute(); 305 std::string ParserErrorLog(); 306 307 void ParserAddTable( int key, bool override ); 308 void ParserAddTable( const std::string& key, bool override ); 309 void ParserEndTable(); 310 void ParserAddTableValue( int key, int val ); 311 void ParserAddTableValue( const std::string& key, int val ); 312 void ParserAddTableValue( int key, bool val ); 313 void ParserAddTableValue( const std::string& key, bool val ); 314 void ParserAddTableValue( int key, const std::string& val ); 315 void ParserAddTableValue( const std::string& key, const std::string& val ); 316 void ParserAddTableValue( int key, float val ); 317 void ParserAddTableValue( const std::string& key, float val ); 318 319 bool ParserGetRootTable(); 320 bool ParserGetRootTableExpression( const std::string& exp ); 321 bool ParserGetSubTableInt( int key ); 322 bool ParserGetSubTableString( const std::string& key ); 323 bool ParserGetSubTableInt( const std::string& exp ); 324 void ParserPopTable(); 325 326 bool ParserKeyExists( int key ); 327 bool ParserKeyExists( const std::string& key ); 328 329 int ParserGetKeyType( int key ); 330 int ParserGetKeyType( const std::string& key ); 331 332 int ParserGetIntKeyListCount(); 333 int ParserGetIntKeyListEntry( int index ); 334 int ParserGetStringKeyListCount(); 335 int ParserGetStringKeyListEntry( int index ); 336 337 int GetKeyValue( int key, int defval ); 338 bool GetKeyValue( int key, bool defval ); 339 std::string GetKeyValue( int key, const std::string& defval ); 340 float GetKeyValue( int key, float defval ); 341 int GetKeyValue( const std::string& key, int defval ); 342 bool GetKeyValue( const std::string& key, bool defval ); 343 std::string GetKeyValue( const std::string& key, const std::string& defval ); 344 float GetKeyValue( const std::string& key, float defval ); 345 346 347 private: 348 UnitsyncLib( const UnitsyncLib& ); 349 //! Keeps track if unitsync is loaded or not. 350 bool m_loaded; 351 352 //! Handle to the unitsync library. 353 void* m_libhandle; 354 355 //! Critical section controlling access to unitsync functions. 356 mutable boost::mutex m_lock; 357 358 //! Path to unitsync. 359 std::string m_path; 360 361 //! the current loaded mod. 362 std::string m_current_mod; 363 364 /** 365 * Loads the unitsync library from path. 366 * @note this function is not threadsafe if called from code not locked. 367 * @see Load() 368 */ 369 void _Load( const std::string& path ); 370 371 /** 372 * Initializes unitsync. 373 */ 374 void _Init(); 375 376 /** 377 * Calls RemoveAllArchives if available, _Init() otherwise. 378 */ 379 void _RemoveAllArchives(); 380 381 /** 382 * Internal Unload() function. 383 * @note this function is not threadsafe if called from code not locked. 384 * @see Unload() 385 */ 386 void _Unload(); 387 388 /** 389 * Returns true if the library is loaded. Internal. 390 */ 391 bool _IsLoaded() const; 392 393 void _ConvertSpringMapInfo( const SpringMapInfo& in, MapInfo& out ); 394 395 void _SetCurrentMod( const std::string& modname ); 396 397 /** 398 * \name function objects 399 * Pointers to the functions in unitsync. 400 */ 401 ///@{ 402 403 InitPtr m_init; 404 UnInitPtr m_uninit; 405 GetNextErrorPtr m_get_next_error; 406 GetWritableDataDirectoryPtr m_get_writeable_data_dir; 407 GetDataDirectoryPtr m_get_data_dir_by_index; 408 GetDataDirectoryCountPtr m_get_data_dir_count; 409 410 GetMapCountPtr m_get_map_count; 411 GetMapChecksumPtr m_get_map_checksum; 412 GetMapNamePtr m_get_map_name; 413 GetMapDescriptionPtr m_get_map_description; 414 GetMapAuthorPtr m_get_map_author; 415 GetMapWidthPtr m_get_map_width; 416 GetMapHeightPtr m_get_map_height; 417 GetMapTidalStrengthPtr m_get_map_tidalStrength; 418 GetMapWindMinPtr m_get_map_windMin; 419 GetMapWindMaxPtr m_get_map_windMax; 420 GetMapGravityPtr m_get_map_gravity; 421 GetMapResourceCountPtr m_get_map_resource_count; 422 GetMapResourceNamePtr m_get_map_resource_name; 423 GetMapResourceMaxPtr m_get_map_resource_max; 424 GetMapResourceExtractorRadiusPtr m_get_map_resource_extractorRadius; 425 GetMapPosCountPtr m_get_map_pos_count; 426 GetMapPosXPtr m_get_map_pos_x; 427 GetMapPosZPtr m_get_map_pos_z; 428 GetMapInfoExPtr m_get_map_info_ex; 429 GetMinimapPtr m_get_minimap; 430 GetInfoMapSizePtr m_get_infomap_size; 431 GetInfoMapPtr m_get_infomap; 432 433 GetPrimaryModChecksumPtr m_get_mod_checksum; 434 GetPrimaryModIndexPtr m_get_mod_index; 435 GetPrimaryModNamePtr m_get_mod_name; 436 GetPrimaryModCountPtr m_get_mod_count; 437 GetPrimaryModArchivePtr m_get_mod_archive; 438 439 GetSideCountPtr m_get_side_count; 440 GetSideNamePtr m_get_side_name; 441 442 AddAllArchivesPtr m_add_all_archives; 443 RemoveAllArchivesPtr m_remove_all_archives; 444 445 GetUnitCountPtr m_get_unit_count; 446 GetUnitNamePtr m_get_unit_name; 447 GetFullUnitNamePtr m_get_unit_full_name; 448 ProcessUnitsNoChecksumPtr m_proc_units_nocheck; 449 450 InitFindVFSPtr m_init_find_vfs; 451 FindFilesVFSPtr m_find_files_vfs; 452 OpenFileVFSPtr m_open_file_vfs; 453 FileSizeVFSPtr m_file_size_vfs; 454 ReadFileVFSPtr m_read_file_vfs; 455 CloseFileVFSPtr m_close_file_vfs; 456 457 GetSpringVersionPtr m_get_spring_version; 458 GetSpringVersionPatchsetPtr m_get_spring_version_patchset; 459 IsSpringReleaseVersionPtr m_is_spring_release_version; 460 461 ProcessUnitsPtr m_process_units; 462 AddArchivePtr m_add_archive; 463 GetArchiveChecksumPtr m_get_archive_checksum; 464 GetArchivePathPtr m_get_archive_path; 465 GetMapArchiveCountPtr m_get_map_archive_count; 466 GetMapArchiveNamePtr m_get_map_archive_name; 467 GetMapChecksumFromNamePtr m_get_map_checksum_from_name; 468 469 GetPrimaryModShortNamePtr m_get_primary_mod_short_name; 470 GetPrimaryModVersionPtr m_get_primary_mod_version; 471 GetPrimaryModMutatorPtr m_get_primary_mod_mutator; 472 GetPrimaryModGamePtr m_get_primary_mod_game; 473 GetPrimaryModShortGamePtr m_get_primary_mod_short_game; 474 GetPrimaryModDescriptionPtr m_get_primary_mod_description; 475 GetPrimaryModArchivePtr m_get_primary_mod_archive; 476 GetPrimaryModArchiveCountPtr m_get_primary_mod_archive_count; 477 GetPrimaryModArchiveListPtr m_get_primary_mod_archive_list; 478 GetPrimaryModChecksumFromNamePtr m_get_primary_mod_checksum_from_name; 479 GetModValidMapCountPtr m_get_mod_valid_map_count; 480 GetModValidMapPtr m_get_valid_map; 481 482 GetMapOptionCountPtr m_get_map_option_count; 483 GetCustomOptionCountPtr m_get_custom_option_count; 484 GetModOptionCountPtr m_get_mod_option_count; 485 GetSkirmishAIOptionCountPtr m_get_skirmish_ai_option_count; 486 GetOptionKeyPtr m_get_option_key; 487 GetOptionNamePtr m_get_option_name; 488 GetOptionDescPtr m_get_option_desc; 489 GetOptionTypePtr m_get_option_type; 490 GetOptionSectionPtr m_get_option_section; 491 GetOptionStylePtr m_get_option_style; 492 GetOptionBoolDefPtr m_get_option_bool_def; 493 GetOptionNumberDefPtr m_get_option_number_def; 494 GetOptionNumberMinPtr m_get_option_number_min; 495 GetOptionNumberMaxPtr m_get_option_number_max; 496 GetOptionNumberStepPtr m_get_option_number_step; 497 GetOptionStringDefPtr m_get_option_string_def; 498 GetOptionStringMaxLenPtr m_get_option_string_max_len; 499 GetOptionListCountPtr m_get_option_list_count; 500 GetOptionListDefPtr m_get_option_list_def; 501 GetOptionListItemKeyPtr m_get_option_list_item_key; 502 GetOptionListItemNamePtr m_get_option_list_item_name; 503 GetOptionListItemDescPtr m_get_option_list_item_desc; 504 505 OpenArchivePtr m_open_archive; 506 CloseArchivePtr m_close_archive; 507 FindFilesArchivePtr m_find_Files_archive; 508 OpenArchiveFilePtr m_open_archive_file; 509 ReadArchiveFilePtr m_read_archive_file; 510 CloseArchiveFilePtr m_close_archive_file; 511 SizeArchiveFilePtr m_size_archive_file; 512 513 SetSpringConfigFilePtr m_set_spring_config_file_path; 514 GetSpringConfigFilePtr m_get_spring_config_file_path; 515 SetSpringConfigFloatPtr m_set_spring_config_float; 516 GetSpringConfigFloatPtr m_get_spring_config_float; 517 GetSpringConfigIntPtr m_get_spring_config_int; 518 GetSpringConfigStringPtr m_get_spring_config_string; 519 SetSpringConfigStringPtr m_set_spring_config_string; 520 SetSpringConfigIntPtr m_set_spring_config_int; 521 522 GetSkirmishAICountPtr m_get_skirmish_ai_count; 523 GetSkirmishAIInfoCountPtr m_get_skirmish_ai_info_count; 524 GetInfoKeyPtr m_get_skirmish_ai_info_key; 525 GetInfoValuePtr m_get_skirmish_ai_info_value; 526 GetInfoDescriptionPtr m_get_skirmish_ai_info_description; 527 528 // lua parser section 529 530 lpClosePtr m_parser_close; 531 lpOpenFilePtr m_parser_open_file; 532 lpOpenSourcePtr m_parser_open_source; 533 lpExecutePtr m_parser_execute; 534 lpErrorLogPtr m_parser_error_log; 535 536 lpAddTableIntPtr m_parser_add_table_int; 537 lpAddTableStrPtr m_parser_add_table_string; 538 lpEndTablePtr m_parser_end_table; 539 lpAddIntKeyIntValPtr m_parser_add_int_key_int_value; 540 lpAddStrKeyIntValPtr m_parser_add_string_key_int_value; 541 lpAddIntKeyBoolValPtr m_parser_add_int_key_bool_value; 542 lpAddStrKeyBoolValPtr m_parser_add_string_key_bool_value; 543 lpAddIntKeyFloatValPtr m_parser_add_int_key_float_value; 544 lpAddStrKeyFloatValPtr m_parser_add_string_key_float_value; 545 lpAddIntKeyStrValPtr m_parser_add_int_key_string_value; 546 lpAddStrKeyStrValPtr m_parser_add_string_key_string_value; 547 548 lpRootTablePtr m_parser_root_table; 549 lpRootTableExprPtr m_parser_root_table_expression; 550 lpSubTableIntPtr m_parser_sub_table_int; 551 lpSubTableStrPtr m_parser_sub_table_string; 552 lpSubTableExprPtr m_parser_sub_table_expression; 553 lpPopTablePtr m_parser_pop_table; 554 555 lpGetKeyExistsIntPtr m_parser_key_int_exists; 556 lpGetKeyExistsStrPtr m_parser_key_string_exists; 557 558 lpGetIntKeyTypePtr m_parser_int_key_get_type; 559 lpGetStrKeyTypePtr m_parser_string_key_get_type; 560 561 lpGetIntKeyListCountPtr m_parser_int_key_get_list_count; 562 lpGetIntKeyListEntryPtr m_parser_int_key_get_list_entry; 563 lpGetStrKeyListCountPtr m_parser_string_key_get_list_count; 564 lpGetStrKeyListEntryPtr m_parser_string_key_get_list_entry; 565 566 lpGetIntKeyIntValPtr m_parser_int_key_get_int_value; 567 lpGetStrKeyIntValPtr m_parser_string_key_get_int_value; 568 lpGetIntKeyBoolValPtr m_parser_int_key_get_bool_value; 569 lpGetStrKeyBoolValPtr m_parser_string_key_get_bool_value; 570 lpGetIntKeyFloatValPtr m_parser_int_key_get_float_value; 571 lpGetStrKeyFloatValPtr m_parser_string_key_get_float_value; 572 lpGetIntKeyStrValPtr m_parser_int_key_get_string_value; 573 lpGetStrKeyStrValPtr m_parser_string_key_get_string_value; 574 575 ///@} 576 }; 577 578 UnitsyncLib& susynclib(); 579 580 } // namespace LSL 581 582 /** 583 * \file c_api.h 584 * \brief bare metal abstraction to unitsync's C-interface 585 * \section LICENSE 586 Copyright 2012 by The libSpringLobby team. All rights reserved. 587 588 Redistribution and use in source and binary forms, with or without modification, are 589 permitted provided that the following conditions are met: 590 591 1. Redistributions of source code must retain the above copyright notice, this list of 592 conditions and the following disclaimer. 593 594 2. Redistributions in binary form must reproduce the above copyright notice, this list 595 of conditions and the following disclaimer in the documentation and/or other materials 596 provided with the distribution. 597 598 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 599 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 600 AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 601 COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 602 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 603 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 604 USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 605 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 606 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 607 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 608 **/ 609 610 #endif //LIBSPRINGLOBBY_HEADERGUARD_SPRINGUNITSYNCLIB_H 611