00001
00002
00003 #include "io_manager.H"
00004 #include "std/file.H"
00005
00006
00007
00008
00009
00010
00011
00012
00013 TAGlist * IOManager::_io_tags = NULL;
00014 IOManager * IOManager::_instance = NULL;
00015
00016
00017
00018
00019 CTAGlist &
00020 IOManager::tags() const
00021 {
00022 if (!_io_tags) {
00023 _io_tags = new TAGlist;
00024
00025 *_io_tags += new TAG_meth<IOManager>(
00026 "basename",
00027 &IOManager::put_basename,
00028 &IOManager::get_basename,
00029 1);
00030 }
00031 return *_io_tags;
00032 }
00033
00034
00035
00036
00037 void
00038 IOManager::get_basename (TAGformat &d)
00039 {
00040 assert(state_() == STATE_SCENE_LOAD);
00041
00042 str_ptr str;
00043 *d >> str;
00044
00045 if (str == "NULL_STR")
00046 {
00047 _basename = NULL_STR;
00048 err_mesg(ERR_LEV_SPAM, "IOManager::get_basename() - Loaded NULL string.");
00049 }
00050 else
00051 {
00052 _basename = str;
00053 err_mesg(ERR_LEV_SPAM, "IOManager::get_basename() - Loaded string: '%s'", **str);
00054 }
00055
00056 }
00057
00058
00059
00060
00061 void
00062 IOManager::put_basename (TAGformat &d) const
00063 {
00064 assert(state_() == STATE_SCENE_SAVE);
00065
00066 d.id();
00067 if (_basename == NULL_STR)
00068 {
00069 err_mesg(ERR_LEV_SPAM, "IOManager::put_basename() - Wrote NULL string.");
00070 *d << str_ptr("NULL_STR");
00071 }
00072 else
00073 {
00074 *d << _basename;
00075 err_mesg(ERR_LEV_SPAM, "IOManager::put_basename() - Wrote string: '%s'", **_basename);
00076 }
00077 d.end_id();
00078 }
00079
00080
00081
00082
00083
00084 IOManager::IOManager() :
00085 _basename(NULL_STR),
00086 _cached_cwd_plus_basename(NULL_STR),
00087 _old_cwd(NULL_STR),
00088 _old_basename(NULL_STR)
00089 {
00090 assert(!_instance);
00091
00092 preload_obs();
00093 postload_obs();
00094 presave_obs();
00095 postsave_obs();
00096
00097 _state.add(STATE_IDLE);
00098
00099 err_mesg(ERR_LEV_SPAM, "IOManager::IOManager() - Instantiated.");
00100 }
00101
00102
00103
00104
00105 IOManager::~IOManager()
00106 {
00107
00108
00109 assert(0);
00110
00111
00112
00113
00114
00115 }
00116
00117
00118
00119
00120 void
00121 IOManager::notify_preload(
00122 NetStream &s,
00123 load_status_t &load_status,
00124 bool from_file,
00125 bool full_scene
00126 )
00127 {
00128
00129 bool ret;
00130 str_ptr path,file,ext;
00131 str_ptr cpath,cfile,cext;
00132
00133
00134 if (!from_file)
00135 {
00136 err_mesg(ERR_LEV_INFO, "IOManager::notify_preload() - *WARNING* Loading from non-file source. Aborting...");
00137 return;
00138 }
00139
00140
00141 switch(state_())
00142 {
00143
00144
00145 case STATE_IDLE:
00146 _state.add((full_scene)?(STATE_SCENE_LOAD):(STATE_PARTIAL_LOAD));
00147 err_mesg(ERR_LEV_INFO, "IOManager::notify_preload() - Loading '%s'... [Source: '%s']",
00148 ((full_scene)?("entire scene"):("scene update")), **s.name());
00149 break;
00150
00151
00152
00153 case STATE_SCENE_SAVE:
00154 assert(!full_scene);
00155 _state.add(STATE_PARTIAL_LOAD);
00156 err_mesg(ERR_LEV_INFO,
00157 "IOManager::notify_preload() - Loading 'scene update' for subsequent save... [Source: '%s']",
00158 **s.name());
00159 break;
00160
00161 case STATE_PARTIAL_SAVE:
00162 case STATE_SCENE_LOAD:
00163 case STATE_PARTIAL_LOAD:
00164 default:
00165 assert(0);
00166 break;
00167 }
00168
00169 if (load_status != LOADobs::LOAD_ERROR_NONE)
00170 {
00171 err_mesg(ERR_LEV_INFO,
00172 "IOManager::notify_preload() - *WARNING* Load procedure already in error state. Aborting...");
00173 return;
00174 }
00175
00176 if (state_() == STATE_SCENE_LOAD)
00177 {
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196 _basename = NULL_STR;
00197
00198
00199 _cached_cwd_plus_basename = NULL_STR;
00200
00201
00202 if ((_old_cwd = getcwd_()) == NULL_STR)
00203 {
00204 err_msg(
00205 "IOManager::notify_preload() - *WARNING* Couldn't save current working directory. Aborting...");
00206 load_status = LOADobs::LOAD_ERROR_CWD;
00207 }
00208
00209
00210
00211 else if (!split_filename(s.name(),path,file,ext))
00212 {
00213 err_msg(
00214 "IOManager::notify_preload() - *WARNING* Couldn't derive a path from stream target: '%s'. Aborting...",
00215 **s.name());
00216 load_status = LOADobs::LOAD_ERROR_CWD;
00217 }
00218 else
00219 {
00220
00221 ret = chdir_(path); assert(ret);
00222 err_mesg(ERR_LEV_SPAM,
00223 "IOManager::notify_preload() - Set new current working directory: '%s'.", **path);
00224 }
00225 }
00226 else
00227 {
00228
00229
00230
00231
00232
00233
00234 if (!split_filename(_cached_cwd_plus_basename,cpath,cfile,cext))
00235 {
00236 err_msg(
00237 "IOManager::notify_preload() - *WARNING* Couldn't derive a path from cached path prefix: '%s'. Aborting...",
00238 **_cached_cwd_plus_basename);
00239 load_status = LOADobs::LOAD_ERROR_CWD;
00240 }
00241 else if (!split_filename(s.name(),path,file,ext))
00242 {
00243 err_msg(
00244 "IOManager::notify_preload() - *WARNING* Couldn't derive a path from stream target: '%s'. Aborting...",
00245 **s.name());
00246 load_status = LOADobs::LOAD_ERROR_CWD;
00247 }
00248 else if (path != cpath)
00249 {
00250 err_msg(
00251 "IOManager::notify_preload() - *WARNING* Scene update load path doesn't match cached working directory. Aborting...");
00252 load_status = LOADobs::LOAD_ERROR_CWD;
00253 }
00254 else
00255 {
00256 err_mesg(ERR_LEV_SPAM,
00257 "IOManager::notify_preload() - Maintaining cached working directory: '%s'.", **path);
00258 }
00259 }
00260 }
00261
00262
00263
00264
00265
00266 void
00267 IOManager::notify_postload(
00268 NetStream &s,
00269 load_status_t &load_status,
00270 bool from_file,
00271 bool full_scene
00272 )
00273 {
00274 str_ptr path;
00275
00276
00277 if (!from_file)
00278 {
00279 err_mesg(ERR_LEV_INFO, "IOManager::notify_postload() - *WARNING* Loading from non-file source. Aborting...");
00280 assert(state_() == STATE_IDLE);
00281 return;
00282 }
00283
00284 assert(state_() == ((full_scene)?(STATE_SCENE_LOAD):(STATE_PARTIAL_LOAD)) );
00285
00286
00287 if (load_status == LOADobs::LOAD_ERROR_NONE)
00288 {
00289 if (state_() == STATE_SCENE_LOAD)
00290 {
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300 if ((path = getcwd_()) == NULL_STR)
00301 {
00302 err_msg(
00303 "IOManager::notify_postload() - *WARNING* Couldn't cache current working directory. Aborting...");
00304 load_status = LOADobs::LOAD_ERROR_CWD;
00305 }
00306 else
00307 {
00308 _cached_cwd_plus_basename = path + "/" + _basename + ((_basename!=NULL_STR)?("--"):(NULL_STR));
00309
00310
00311
00312 err_mesg(ERR_LEV_INFO,
00313 "IOManager::notify_postload() - ...completed 'entire scene' load.");
00314 err_mesg(ERR_LEV_INFO,
00315 "IOManager::notify_postload() - Caching this file load/save prefix: '%s'",
00316 **_cached_cwd_plus_basename);
00317 }
00318 }
00319 else
00320 {
00321
00322
00323
00324
00325
00326
00327
00328 err_mesg(ERR_LEV_INFO,
00329 "IOManager::notify_postload() - ...completed 'scene update' load.");
00330
00331 }
00332 }
00333
00334 else
00335 {
00336 if (state_() == STATE_SCENE_LOAD)
00337 {
00338
00339
00340 _basename = NULL_STR;
00341 _cached_cwd_plus_basename = NULL_STR;
00342
00343 err_msg(
00344 "IOManager::notify_postload() - ...failed 'entire scene' load. [Source: '%s']", **s.name());
00345
00346 if (_old_cwd != NULL_STR)
00347 {
00348 if (chdir_(_old_cwd))
00349 {
00350 err_mesg(ERR_LEV_INFO,
00351 "IOManager::notify_postload() - Restored old current working directory: '%s'",
00352 **_old_cwd);
00353 }
00354 else
00355 {
00356 err_msg(
00357 "IOManager::notify_postload() - *Warning* Failed restoring old current working directory: '%s'",
00358 **_old_cwd);
00359
00360 load_status = LOADobs::LOAD_ERROR_CWD;
00361 }
00362 }
00363 else
00364 {
00365 err_msg(
00366 "IOManager::notify_postload() - *Warning* No saved current working directory to restore.");
00367 }
00368 }
00369 else
00370 {
00371
00372
00373
00374
00375
00376 err_msg(
00377 "IOManager::notify_postload() - ...failed 'scene update' load. [Source: '%s']", **s.name());
00378 }
00379 }
00380 _state.pop();
00381 assert(_state.num() > 0);
00382 }
00383
00384
00385
00386
00387 void
00388 IOManager::notify_presave(
00389 NetStream &s,
00390 save_status_t &save_status,
00391 bool to_file,
00392 bool full_scene
00393 )
00394 {
00395 bool ret;
00396 str_ptr path,file,ext;
00397
00398
00399 if (!to_file)
00400 {
00401 err_mesg(ERR_LEV_INFO, "IOManager::notify_presave() - *WARNING* Saving to non-file source. Aborting...");
00402 return;
00403 }
00404
00405 switch(state_())
00406 {
00407
00408
00409 case STATE_IDLE:
00410 assert(full_scene);
00411 _state.add(STATE_SCENE_SAVE);
00412 err_mesg(ERR_LEV_INFO,
00413 "IOManager::notify_presave() - Saving 'entire scene'... [Dest: '%s']",
00414 **s.name());
00415 break;
00416
00417
00418
00419 case STATE_SCENE_SAVE:
00420 assert(!full_scene);
00421 _state.add(STATE_PARTIAL_SAVE);
00422 err_mesg(ERR_LEV_INFO,
00423 "IOManager::notify_presave() - Saving 'scene update'... [Dest: '%s']",
00424 **s.name());
00425 break;
00426
00427 case STATE_PARTIAL_SAVE:
00428 case STATE_SCENE_LOAD:
00429 case STATE_PARTIAL_LOAD:
00430 default:
00431 assert(0);
00432 break;
00433 }
00434
00435
00436 if (save_status != SAVEobs::SAVE_ERROR_NONE)
00437 {
00438 err_mesg(ERR_LEV_INFO,
00439 "IOManager::notify_presave() - *WARNING* Save procedure already in error state. Aborting...");
00440 return;
00441 }
00442
00443 if (state_() == STATE_SCENE_SAVE)
00444 {
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460 _old_basename = _basename;
00461 if ((_old_cwd = getcwd_()) == NULL_STR)
00462 {
00463 err_msg(
00464 "IOManager::notify_presave() - *WARNING* Couldn't save current working directory. Aborting...");
00465 save_status = SAVEobs::SAVE_ERROR_CWD;
00466 }
00467 else
00468 {
00469
00470
00471
00472
00473
00474 if (!split_filename(s.name(),path,file,ext))
00475 {
00476 err_msg(
00477 "IOManager::notify_presave() - *WARNING* Couldn't derive valid path from target: '%s'. Aborting...",
00478 **s.name());
00479 save_status = SAVEobs::SAVE_ERROR_CWD;
00480 }
00481 else
00482 {
00483
00484 _basename = file;
00485 err_mesg(ERR_LEV_INFO,
00486 "IOManager::notify_presave() - Set new current basename file prefix: '%s'.", **file);
00487
00488 ret = chdir_(path); assert(ret);
00489
00490 err_mesg(ERR_LEV_INFO,
00491 "IOManager::notify_presave() - Set new current working directory: '%s'.", **path);
00492 }
00493 }
00494 }
00495 else
00496 {
00497
00498
00499
00500
00501
00502
00503 if (!split_filename(s.name(),path,file,ext))
00504 {
00505 err_msg(
00506 "IOManager::notify_presave() - *WARNING* Couldn't derive valid path from target: '%s'. Aborting...",
00507 **s.name());
00508 save_status = SAVEobs::SAVE_ERROR_CWD;
00509 }
00510 else if (path != getcwd_())
00511 {
00512 err_msg(
00513 "IOManager::notify_presave() - *WARNING* Path for 'scene update' doesn't match current working directory. Aborting...");
00514 save_status = SAVEobs::SAVE_ERROR_CWD;
00515 }
00516 else
00517 {
00518 err_mesg(ERR_LEV_INFO,
00519 "IOManager::notify_presave() - Maintaing working directory: '%s'.", **path);
00520 }
00521
00522 }
00523 }
00524
00525
00526
00527
00528 void
00529 IOManager::notify_postsave(
00530 NetStream &s,
00531 save_status_t &save_status,
00532 bool to_file,
00533 bool full_scene
00534 )
00535 {
00536
00537 str_ptr path;
00538
00539
00540 if (!to_file)
00541 {
00542 err_mesg(ERR_LEV_INFO, "IOManager::notify_postsave() - *WARNING* Saving to non-file source. Aborting...");
00543 assert(state_() == STATE_IDLE);
00544 return;
00545 }
00546
00547 assert(state_() == ((full_scene)?(STATE_SCENE_SAVE):(STATE_PARTIAL_SAVE)));
00548
00549
00550 if (save_status == SAVEobs::SAVE_ERROR_NONE)
00551 {
00552 if (state_() == STATE_SCENE_SAVE)
00553 {
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563 if ((path = getcwd_()) == NULL_STR)
00564 {
00565 err_msg(
00566 "IOManager::notify_postsave() - *WARNING* Couldn't cache current working directory. Aborting...");
00567 save_status = SAVEobs::SAVE_ERROR_CWD;
00568 }
00569 else
00570 {
00571 _cached_cwd_plus_basename = path + "/" + _basename + ((_basename!=NULL_STR)?("--"):(NULL_STR));
00572
00573
00574 err_mesg(ERR_LEV_INFO,
00575 "IOManager::notify_postsave() - ...completed 'entire scene' save.");
00576 err_mesg(ERR_LEV_INFO,
00577 "IOManager::notify_postsave() - Caching this file load/save prefix: '%s'",
00578 **_cached_cwd_plus_basename);
00579 }
00580 }
00581 else
00582 {
00583
00584
00585
00586
00587
00588
00589
00590 err_mesg(ERR_LEV_INFO,
00591 "IOManager::notify_postsave() - ...completed 'scene update' save.");
00592 }
00593 }
00594
00595
00596 if (save_status != SAVEobs::SAVE_ERROR_NONE)
00597 {
00598 if (state_() == STATE_SCENE_SAVE)
00599 {
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609 _basename = _old_basename;
00610
00611 err_msg(
00612 "IOManager::notify_postsave() - ...failed 'entire scene' save. [Dest: '%s']", **s.name());
00613
00614
00615 if (_old_cwd != NULL_STR)
00616 {
00617 if (chdir_(_old_cwd))
00618 {
00619 err_mesg(ERR_LEV_INFO,
00620 "IOManager::notify_postsave() - Restoring old current working directory: '%s'",
00621 **_old_cwd);
00622 }
00623 else
00624 {
00625 err_msg(
00626 "IOManager::notify_postsave() - *Warning* Failed restoring old current working directory: '%s'",
00627 **_old_cwd);
00628
00629 save_status = SAVEobs::SAVE_ERROR_CWD;
00630 }
00631 }
00632 else
00633 {
00634 err_msg(
00635 "IOManager::notify_postsave() - *Warning* No saved current working directory to restore.");
00636 }
00637 }
00638 else
00639 {
00640
00641
00642
00643
00644
00645
00646 err_msg(
00647 "IOManager::notify_postsave() - ...failed 'scene update' save. [Dest: '%s']", **s.name());
00648 }
00649 }
00650 _state.pop();
00651 assert(_state.num() > 0);
00652 }
00653
00654
00655
00656
00657
00658 str_ptr
00659 IOManager::load_prefix_()
00660 {
00661 str_ptr ret;
00662
00663 switch(state_())
00664 {
00665
00666 case STATE_IDLE:
00667 ret = cwd_();
00668 break;
00669
00670 case STATE_SCENE_LOAD:
00671 ret = current_prefix_();
00672 break;
00673
00674 case STATE_PARTIAL_LOAD:
00675 ret = cached_prefix_();
00676 break;
00677
00678 case STATE_SCENE_SAVE:
00679 case STATE_PARTIAL_SAVE:
00680 default:
00681 assert(0);
00682 break;
00683 }
00684 return ret;
00685 }
00686
00687
00688
00689
00690 str_ptr
00691 IOManager::save_prefix_()
00692 {
00693 str_ptr ret;
00694
00695 switch(state_())
00696 {
00697
00698 case STATE_IDLE:
00699 ret = cwd_();
00700 break;
00701
00702 case STATE_SCENE_SAVE:
00703 case STATE_PARTIAL_SAVE:
00704 ret = current_prefix_();
00705 break;
00706
00707 case STATE_SCENE_LOAD:
00708 case STATE_PARTIAL_LOAD:
00709 default:
00710 assert(0);
00711 break;
00712 }
00713 return ret;
00714 }
00715
00716
00717
00718
00719 str_ptr
00720 IOManager::cwd_()
00721 {
00722 str_ptr ret;
00723
00724 ret = getcwd_();
00725 if (ret != NULL_STR) ret = ret + "/";
00726
00727
00728
00729
00730 return ret;
00731 }
00732
00733
00734
00735
00736 str_ptr
00737 IOManager::current_prefix_()
00738 {
00739 str_ptr ret;
00740
00741 ret = cwd_();
00742 if (_basename != NULL_STR) ret = ret + _basename + "--";
00743
00744 return ret;
00745 }
00746
00747
00748
00749
00750 str_ptr
00751 IOManager::cached_prefix_()
00752 {
00753 return _cached_cwd_plus_basename;
00754 }
00755
00756
00757
00758
00759 bool
00760 IOManager::split_filename(
00761 Cstr_ptr &fullpath,
00762 str_ptr &path,
00763 str_ptr &file,
00764 str_ptr &ext)
00765 {
00766 bool result;
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781 str_ptr old_cwd = getcwd_();
00782 if (old_cwd == NULL_STR)
00783 {
00784 err_mesg(ERR_LEV_SPAM,
00785 "IOManager::split_filename() - *WARNING* Couldn't save old current working directory!!");
00786 }
00787
00788
00789 const char *c_fullpath = **fullpath;
00790
00791
00792 char *c_path = new char[strlen(c_fullpath)+2]; assert(c_path);
00793 char *c_file = new char[strlen(c_fullpath)+2]; assert(c_file);
00794 char *c_ext = new char[strlen(c_fullpath)+2]; assert(c_ext);
00795
00796
00797
00798
00799 strcpy(c_path,c_fullpath);
00800
00801
00802 char *c_path_slash = max( strrchr(c_path,'/'), strrchr(c_path,'\\') );
00803
00804
00805 if (!c_path_slash)
00806 {
00807 strcpy(c_path,".");
00808 }
00809
00810 else
00811 {
00812 ++c_path_slash;
00813 *c_path_slash = '\0';
00814 }
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827 const char *c_fullpath_slash = max( strrchr(c_fullpath,'/'), strrchr(c_fullpath,'\\') );
00828
00829
00830 if (c_fullpath_slash)
00831 {
00832 ++c_fullpath_slash;
00833 strcpy(c_file, c_fullpath_slash);
00834 }
00835
00836 else
00837 {
00838 strcpy(c_file, c_fullpath);
00839 }
00840
00841
00842
00843
00844
00845 char *c_file_dot = strrchr(c_file,'.');
00846
00847
00848 if (c_file_dot && (c_file_dot != c_file))
00849 {
00850
00851 strcpy(c_ext, c_file_dot);
00852
00853
00854 *c_file_dot = '\0';
00855 }
00856
00857 else
00858 {
00859 strcpy(c_ext,"");
00860 }
00861
00862
00863
00864
00865
00866 if (chdir_(c_path) && ((path = getcwd_()) != NULL_STR) )
00867 {
00868
00869
00870
00871 file = str_ptr(c_file);
00872 ext = str_ptr(c_ext);
00873
00874 result = true;
00875 }
00876 else
00877 {
00878
00879
00880 result = false;
00881 }
00882
00883 if ((old_cwd == NULL_STR) || !chdir_(old_cwd) )
00884 {
00885 err_mesg(ERR_LEV_SPAM,
00886 "IOManager::split_filename() - *WARNING* Couldn't restore old current working directory!!");
00887 }
00888
00889 delete[] c_path;
00890 delete[] c_file;
00891 delete[] c_ext;
00892
00893 return result;
00894 }