123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673 |
- ////////////////////////////////////////////////////////////////////////////////
- //
- // Copyright 2016 RWS Inc, All Rights Reserved
- //
- // This program is free software; you can redistribute it and/or modify
- // it under the terms of version 2 of the GNU General Public License as published by
- // the Free Software Foundation
- //
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License along
- // with this program; if not, write to the Free Software Foundation, Inc.,
- // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- //
- //////////////////////////////////////////////////////////////////////////////
- //
- // File.CPP
- //
- // History:
- // 07/29/95 JMI Started.
- //
- // 08/14/95 JMI Changed name from CFile to CNFile.
- //
- // 08/17/95 JMI Added memory file ability.
- //
- // 08/28/95 JMI Added use of m_sMemError to allow Error() function to
- // flag errors.
- //
- // 09/19/95 JMI Altered ASSERT in Close to work with memory files.
- //
- // 09/22/95 JMI Added Open and Close hooks.
- //
- // 10/04/95 JMI Added automagic reopen ability.
- //
- // 10/14/96 MJR Removed <SMRTHEAP.HPP> since it will be taken care of
- // by system.h, which is included via blue.h
- //
- // 10/15/96 JMI Added Read/Write((float*)...) and Read/Write((double*)...).
- //
- // 10/18/96 MJR Fixed memory leaks on Write() functions.
- //
- // 10/21/96 JMI Changed Write() functions to utilize a shared static buf-
- // fer and write in sizeof(ms_u8SwapBuf) byte chunks. Also,
- // fixed possible problem introduced by the #if 1 blocks
- // added to Write(U32/U16) that would have caused twice the
- // info to have been written.
- //
- // 10/21/96 JMI Added ability to read & write in new "ASCII mode".
- //
- // 10/23/96 JMI Open() for memory was initializing m_sFlags to 0 instead
- // of NFILE_BINARY.
- //
- // 10/23/96 JMI Byte swapping was always doing at least a buffers worth
- // and was overrunning the swap buffer. The fix to this
- // was merely implementing the slight performance improvement
- // that was listed in comment before each swap algorithm.
- //
- // 10/25/96 JMI Now reads and writes PIXEL24 which is a 24 bit type
- // defined in <Sys>System.h. It can vary in order on big
- // and little endian systems, but it may, in some cases,
- // not vary. I'm just not sure. For now, this module
- // byte swaps if the file's endianness varies from the
- // systems, but this may not always be the case for 24 bit
- // pixel data.
- //
- // 10/28/96 JMI Disabled warning on constant conditional expression so
- // this file would compile nicely on warning level 4.
- //
- // 10/30/96 JMI Changed:
- // Old label: New label:
- // ========= =========
- // CNFile RFile
- // *_CNFILE_* *_RFILE_*
- // CList RList
- // ENDIAN_BIG RFile::BigEndian
- // ENDIAN_LITTLE RFile::LittleEndian
- // NFILE_BINARY RFile::Binary
- // NFILE_ASCII RFile::Ascii
- // PIXEL24 RPixel24
- // CNFILEOPENHOOK RFile::OpenHook
- // CNFILECLOSEHOOK RFile::CloseHook
- //
- // 12/11/96 JMI Now calls ms_criticall with the number of bytes that are
- // about to be read or written when reading/writing a disk
- // file.
- //
- // 01/22/97 JMI New Open() call allows one to make a file that grows
- // when Write()s exceed its size.
- //
- // 01/28/97 JMI Added yet another Open() overload that allows one to open
- // an existing FILE* stream with an RFile.
- // And yet another Open() which opens from another RFile
- // that is already attached to disk or memory. This is use-
- // ful for descended classes such as RIff (so they can sub-
- // class an existing RFile).
- //
- // 05/30/97 JMI Added FILE_VERBOSE. Which, when defined,
- // causes the resmgr to output TRACEs when a file
- // is not found. Although we all love this feature
- // for debugging purposes, it gets bad when we're
- // loading a file only if it exists.
- //
- // 07/17/97 MJR Added code to set default buffer size for RFile's to
- // 16k, but commented it out pending further testing to
- // determine whether it's a good idea.
- //
- // 08/23/97 JMI Now will call the criticallback for disk files every
- // MAX_CALLBACK_GRANULARITY_BYTES bytes at a maximum to
- // ensure a certain amount of callback granularity.
- //
- // 08/23/97 JMI Fixed bug with not incrementing dest pointers in Read()
- // and Write().
- //
- //////////////////////////////////////////////////////////////////////////////
- //
- // This module handles file stuff, providing services such as Open, Close,
- // Read, and Write. It also can transparently convert data as read in based
- // on the endian nature of the current platform and the endian macro supplied
- // by the app to the Open() or SetEndian() (BigEndian or LittleEndian).
- //
- // There are two modes in which this module can operate (Binary or
- // Ascii (Ascii does not work for memory files)). In order to
- // hide ASCII operation, the ASCII versions of these functions return values
- // that would, hopefully, be acceptable to a binary reader/writer using
- // CNFile. The big suck is that you cannot make a placeholder for places you
- // want to seek back to with intent of updating a field since the field's size,
- // in ASCII mode, is dependent on the value.
- //
- //////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////
- // Headers.
- //////////////////////////////////////////////////////////////////////////////
- #include <stdlib.h>
- #include <memory.h>
- #include <string.h>
- #include <limits.h>
- #include <float.h> // For float and double limits.
- #if PLATFORM_UNIX
- #include <unistd.h>
- #include <dirent.h>
- #include <sys/param.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <ctype.h>
- #endif
- #ifdef WIN32
- #define WIN32_LEAN_AND_MEAN 1
- #include <windows.h>
- #include <io.h>
- #include <direct.h>
- #include <malloc.h>
- #define PATH_MAX MAX_PATH
- #ifndef F_OK
- #define F_OK 00
- #endif
- #ifndef R_OK
- #define R_OK 04
- #endif
- typedef HRESULT (WINAPI *fnSHGetFolderPathW)(HWND hwnd, int nFolder, HANDLE hToken, DWORD dwFlags, LPWSTR pszPath);
- #endif
- #include "Blue.h"
- #ifdef PATHS_IN_INCLUDES
- #include "ORANGE/File/file.h"
- #else
- #include "file.h"
- #endif // PATHS_IN_INCLUDES
- //////////////////////////////////////////////////////////////////////////////
- // Module specific macros.
- //////////////////////////////////////////////////////////////////////////////
- #ifdef SYS_ENDIAN_BIG
- #ifdef SYS_ENDIAN_LITTLE
- #error SYS_ENDIAN_LITTLE & SYS_ENDIAN_BIG cannot both be defined!
- #else
- #define ENDIAN_CONSISTENT (m_endian != LittleEndian)
- #endif // SYS_ENDIAN_LITTLE
- #else
- #ifdef SYS_ENDIAN_LITTLE
- #define ENDIAN_CONSISTENT (m_endian != BigEndian)
- #else
- #error SYS_ENDIAN_LITTLE or SYS_ENDIAN_BIG must be defined!
- #endif // SYS_ENDIAN_LITTLE
- #endif // SYS_ENDIAN_BIG
- // Defines what is whitespace to this module.
- #define WHITE_SPACE "\t \n"
- // Granularity of callbacks in bytes.
- #define MAX_CALLBACK_GRANULARITY_BYTES 1024
- //////////////////////////////////////////////////////////////////////////////
- // Module specific pragmas.
- //////////////////////////////////////////////////////////////////////////////
- #if defined(WIN32)
- #pragma warning (disable: 4127) // conditional expression is constant.
- #endif
- //////////////////////////////////////////////////////////////////////////////
- // Module specific typedefs.
- //////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////
- // Module specific (static) variables.
- //////////////////////////////////////////////////////////////////////////////
- // Called on every read and write with
- // the amount that is about to be
- // processed.
- RFile::CritiCall RFile::ms_criticall = NULL;
- // For hooking Open(char*, ...) calls.
- RFile::OpenHook RFile::ms_hOpen = NULL;
- long RFile::ms_lOpenUser = 0L;
- RFile::CloseHook RFile::ms_hClose = NULL;
- long RFile::ms_lCloseUser = 0L;
- // Used to byte swap by Write().
- U8 RFile::ms_au8SwapBuf[RFILE_SWAP_SIZE];
- // String description of endian (index by Endian enum).
- static char* ms_apszEndian[] =
- {
- "BigEndian",
- "NeutralEndian",
- "LittleEndian",
- };
- #ifdef ALLOW_RFILE_REOPEN
- RList <RFile> RFile::ms_listOpen; // List of open RFiles connected to
- // disk.
- #endif // ALLOW_RFILE_REOPEN
- //////////////////////////////////////////////////////////////////////////////
- // Construction/Destruction.
- //////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////
- //
- // Default constructor.
- //
- //////////////////////////////////////////////////////////////////////////////
- RFile::RFile(void)
- {
- m_fs = NULL;
- m_endian = BigEndian;
- m_flags = NoFlags;
- m_pucFile = NULL;
- m_sOwnMem = FALSE;
- m_pucCur = NULL;
- m_lSize = 0L;
- m_lGrowSize = 0L;
- m_sMemError = 0;
- m_sOpenSem = 0;
- m_sCloseSem = 0;
- m_lUser = 0;
- m_pfileSynch = NULL;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Destructor.
- //
- //////////////////////////////////////////////////////////////////////////////
- RFile::~RFile(void)
- {
- if (m_fs != NULL || m_pucFile != NULL)
- {
- Close();
- TRACE("~RFile(): Closed the file that you forgot to, hoser!\n");
- }
- }
- //////////////////////////////////////////////////////////////////////////////
- // Methods.
- //////////////////////////////////////////////////////////////////////////////
- #if PLATFORM_UNIX
- // this is from PhysicsFS originally ( http://icculus.org/physfs/ )
- // (also zlib-licensed.)
- static int locateOneElement(char *buf)
- {
- char *ptr = NULL;
- DIR *dirp = NULL;
- struct dirent *dent = NULL;
- if (access(buf, F_OK) == 0)
- return 1; /* quick rejection: exists in current case. */
- ptr = strrchr(buf, '/'); /* find entry at end of path. */
- if (ptr == NULL)
- {
- dirp = opendir(".");
- ptr = buf;
- }
- else
- {
- *ptr = '\0';
- dirp = opendir(buf);
- *ptr = '/';
- ptr++; /* point past dirsep to entry itself. */
- }
- while ((dent = readdir(dirp)) != NULL)
- {
- if (strcasecmp(dent->d_name, ptr) == 0)
- {
- strcpy(ptr, dent->d_name); /* found a match. Overwrite with this case. */
- closedir(dirp);
- return 1;
- }
- }
- /* no match at all... */
- closedir(dirp);
- return 0;
- }
- #endif
- static void locateCorrectCase(char *buf)
- {
- #if PLATFORM_UNIX
- char *ptr = buf;
- char *prevptr = buf;
- while (ptr = strchr(ptr + 1, '/'))
- {
- *ptr = '\0'; /* block this path section off */
- if (!locateOneElement(buf))
- {
- *ptr = '/'; /* restore path separator */
- return; /* missing element in path. */
- }
- *ptr = '/'; /* restore path separator */
- }
- /* check final element... */
- locateOneElement(buf);
- #endif
- }
- extern const char *FindCorrectFile(const char *_pszName, const char *pszMode)
- {
- char *pszName = (char *) alloca(strlen(_pszName) + 1);
- strcpy(pszName, _pszName);
- static bool initialized = false;
- static bool nohomedir = false;
- static char prefpath[PATH_MAX];
- if (!initialized)
- {
- TRACE("FindCorrectFile initializing...\n");
- if (rspCommandLine("nohomedir"))
- {
- TRACE("--nohomedir is on the command line.\n");
- nohomedir = true;
- }
- else
- {
- #ifdef WIN32
- /*
- * Vista and later has a new API for this, but SHGetFolderPath works there,
- * and apparently just wraps the new API. This is the new way to do it:
- *
- * SHGetKnownFolderPath(FOLDERID_RoamingAppData, KF_FLAG_CREATE,
- * NULL, &wszPath);
- */
- strcpy(prefpath, ".\\"); // a default for failure case.
- HMODULE lib = LoadLibraryA("Shell32.dll");
- if (lib != NULL)
- {
- fnSHGetFolderPathW pSHGetFolderPathW = (fnSHGetFolderPathW) GetProcAddress(lib, "SHGetFolderPathW");
- if (pSHGetFolderPathW != NULL)
- {
- WCHAR path[MAX_PATH];
- if (SUCCEEDED(pSHGetFolderPathW(NULL, 0x001a/*CSIDL_APPDATA*/ | 0x8000/*CSIDL_FLAG_CREATE*/, NULL, 0, path)))
- {
- // !!! FIXME: screwed if there's a unicode path for now.
- snprintf(prefpath, sizeof (prefpath), "%S\\RunningWithScissors", (const wchar_t *) path);
- mkdir(prefpath);
- snprintf(prefpath, sizeof (prefpath), "%S\\RunningWithScissors\\Postal Plus", (const wchar_t *) path);
- mkdir(prefpath);
- snprintf(prefpath, sizeof (prefpath), "%S\\RunningWithScissors\\Postal Plus\\", (const wchar_t *) path);
- }
- }
- FreeLibrary(lib);
- }
- #elif defined(PLATFORM_MACOSX)
- const char *homedir = getenv("HOME");
- if ( (!homedir) || ((strlen(homedir) + 32) >= sizeof (prefpath)) )
- homedir = "./"; // oh well.
- strcpy(prefpath, homedir);
- if (prefpath[strlen(prefpath)-1] != '/') strcat(prefpath, "/");
- strcat(prefpath, "Library/Application Support/Postal Plus/");
- #else
- const char *homedir = getenv("HOME");
- const char *xdghomedir = getenv("XDG_DATA_HOME");
- const char *append = "";
- if (xdghomedir == NULL)
- {
- if (homedir == NULL)
- xdghomedir = "."; // oh well.
- else
- {
- xdghomedir = homedir;
- append = "/.local/share";
- }
- }
- snprintf(prefpath, sizeof (prefpath), "%s%s/PostalPlus/", xdghomedir, append);
- if (homedir != NULL)
- {
- char oldpath[PATH_MAX];
- snprintf(oldpath, sizeof (oldpath), "%s/.postal1", homedir);
- if (access(oldpath, F_OK) == 0)
- {
- TRACE("using oldschool prefpath at \"%s\"\n", oldpath);
- snprintf(prefpath, sizeof (prefpath), "%s/", oldpath);
- }
- }
- // try to make sure the dirs exist...
- for (char *i = prefpath; *i; i++)
- {
- if (*i == '/')
- {
- *i = '\0';
- mkdir(prefpath, 0700);
- *i = '/';
- }
- }
- mkdir(prefpath, 0700);
- #endif
- TRACE("prefpath is \"%s\"\n", prefpath);
- }
- initialized = true;
- }
- static char finalname[PATH_MAX];
- static bool bail_early = true;
- if (nohomedir)
- strcpy(finalname, pszName);
- else if ((strlen(pszName) + strlen(prefpath)) > sizeof (finalname))
- strcpy(finalname, pszName); // oh well.
- else
- {
- bail_early = false;
- sprintf(finalname, "%s%s", prefpath, pszName);
- }
- locateCorrectCase(finalname);
- if (bail_early) // don't choose between prefpath and basedir?
- return(finalname);
- // writing? Always use prefpath.
- if (strcspn(pszMode, "aAwW+") < strlen(pszMode))
- {
- // build directories...
- for (char *ptr = finalname; *ptr; ptr++)
- {
- if (((*ptr == '/') || (*ptr == '\\')) && (ptr != finalname))
- {
- *ptr = '\0';
- if (access(finalname, F_OK) == -1)
- {
- TRACE("Making directory \"%s\"\n", finalname);
- #ifdef WIN32
- mkdir(finalname);
- #else
- mkdir(finalname, S_IRWXU);
- #endif
- }
- *ptr = '/';
- }
- }
- // read AND write. :/ Copy the file if it's not there.
- if ((strchr(pszMode, '+')) && (access(finalname, F_OK) == -1))
- {
- FILE *in = fopen(pszName, "rb");
- FILE *out = fopen(finalname, "wb");
- if (in && out)
- {
- int ch = 0;
- while (1) // !!! FIXME: this is really lame.
- {
- ch = fgetc(in);
- if (ch == EOF) break;
- fputc(ch, out);
- }
- }
- if (in) fclose(in);
- if (out) fclose(out);
- }
- return finalname;
- }
- else // reading.
- {
- if (access(finalname, R_OK) == -1) // favor prefpath?
- {
- strcpy(finalname, pszName); // nope, use original name.
- locateCorrectCase(finalname);
- }
- }
- return finalname;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Open file pszFileName with fopen flags pszFlags and endian format endian
- // { BigEndian, LittleEndian }.
- // Returns 0 on success.
- //
- //////////////////////////////////////////////////////////////////////////////
- short RFile::Open( // Returns 0 on success.
- const char* pszFileName, // Filename to open.
- const char* pszFlags, // fopen flags to use for opening.
- Endian endian, // { BigEndian | LittleEndian | NeutralEndian }.
- Flags flags) // See comments in Typedefs & Enums section in .h.
- {
- short sRes = 0; // Assume success.
- // If not already open . . .
- if (m_fs == NULL && m_pucFile == NULL)
- {
- short sOpen = TRUE;
- // Store flags for this file.
- // Make sure Ascii and Binary are not both specified.
- ASSERT( (flags & (Ascii | Binary)) != (Ascii | Binary) );
- // Make sure either Ascii or Binary is specified.
- ASSERT( (flags & (Ascii | Binary)) != 0);
- m_flags = flags;
-
- // If hook defined . . .
- if (ms_hOpen != NULL)
- {
- // If not re-entered . . .
- if (m_sOpenSem == 0)
- {
- m_sOpenSem++;
-
- sOpen = (*ms_hOpen)(this, pszFileName, pszFlags, endian, ms_lOpenUser);
-
- m_sOpenSem--;
- }
- }
- // If no hook or hook told use to continue as normal . . .
- if (sOpen == TRUE)
- {
- // Set endian type.
- SetEndian(endian);
- // Attempt to open file.
- m_fs = fopen(FindCorrectFile(pszFileName, pszFlags), pszFlags);
- // If successful . . .
- if (m_fs != NULL)
- {
- // Attempt to set a better buffer size
- int setres = 0;
- #if 0
- size_t bufsize = BUFSIZ;
- if (bufsize < 16384)
- bufsize = (16384 / BUFSIZ) * BUFSIZ;
- setres = setvbuf(m_fs, NULL, _IOFBF, bufsize);
- #endif
- if (setres == 0)
- {
- // Success.
- #ifdef ALLOW_RFILE_REOPEN
- // Store file flags.
- ASSERT(strlen(pszFlags) < sizeof(m_szFlags));
- strcpy(m_szFlags, pszFlags);
-
- // Store file name.
- ASSERT(strlen(pszFileName) < sizeof(m_szFileName));
- strcpy(m_szFileName, pszFileName);
- // Update access.
- m_lLastAccess = Blu_GetTime();
- // Connected.
- m_sDisconnected = FALSE;
- // Add to open list.
- if (ms_listOpen.Add(this) == 0)
- {
- }
- else
- {
- TRACE("Open(\"%s\", \"%s\", %s): Unable to add to open list.\n",
- pszFileName, pszFlags,
- ms_apszEndian[endian]);
- sRes = -3;
- }
- #endif // ALLOW_RFILE_REOPEN
- }
- else
- {
- TRACE("Open(\"%s\", \"%s\", %s): Error returned by setvbuf()!\n",
- pszFileName, pszFlags,
- ms_apszEndian[endian]);
- sRes = -5; // Is there any REAL sense to these error numbers???
- }
- // If an error occurrs after fopen . . .
- if (sRes != 0)
- {
- fclose(m_fs);
- m_fs = NULL;
- }
- }
- else
- {
- #ifdef FILE_VERBOSE
- TRACE("Open(\"%s\", \"%s\", %s): Unable to open file.\n",
- pszFileName, pszFlags,
- ms_apszEndian[endian]);
- #endif // FILE_VERBOSE
- sRes = -1;
- }
- }
- }
- else
- {
- TRACE("Open(\"%s\", \"%s\", %s): File already open.\n",
- pszFileName, pszFlags,
- ms_apszEndian[endian]);
- sRes = -2;
- }
- return sRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Open memory pFile of size lSize and endian format endian
- // { BigEndian, LittleEndian }.
- // Returns 0 on success.
- //
- //////////////////////////////////////////////////////////////////////////////
- short RFile::Open( // Returns 0 on success.
- void* pFile, // Pointer to memory to open.
- long lSize, // Size of *pFile in bytes.
- Endian endian) // { BigEndian | LittleEndian | NeutralEndian }.
- {
- short sRes = 0; // Assume success.
- // If not already open . . .
- if (m_fs == NULL && m_pucFile == NULL)
- {
- // Store flags for this file.
- m_flags = Binary;
-
- // Set endian type.
- SetEndian(endian);
- // Open memory.
- m_pucFile = m_pucCur = (UCHAR*)pFile;
- // Do not own buffer.
- m_sOwnMem = FALSE;
- // Set size of file.
- m_lSize = lSize;
- // Clear error flag.
- m_sMemError = 0;
- }
- else
- {
- TRACE("Open(%08lX, %ld, %s): File already open.\n",
- pFile, lSize,
- ms_apszEndian[endian]);
- sRes = -2;
- }
- return sRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Open memory pFile of size lSize and endian format endian.
- // RFile may size and or relocate the memory in order to expand the memory file.
- // Deallocates on Close().
- // { RFile::Big, RFile::Little }.
- // Returns 0 on success.
- //
- //////////////////////////////////////////////////////////////////////////////
- short RFile::Open( // Returns 0 on success.
- long lSize, // Size in bytes to begin with.
- long lGrowSize, // Min amount in bytes to grow memory file when written passed end.
- // Note: The larger of lGrowSize and the amount overwritten will
- // be allocated in the case of an overrun.
- Endian endian) // { BigEndian | LittleEndian | NeutralEndian }.
- {
- short sRes = 0; // Assume success.
- // If not already open . . .
- if (m_fs == NULL && m_pucFile == NULL)
- {
- // Store flags for this file.
- m_flags = Binary;
-
- // Set endian type.
- SetEndian(endian);
- // Open memory.
- m_pucFile = m_pucCur = (UCHAR*)malloc(lSize);
- if (m_pucFile != NULL)
- {
- // Do own buffer.
- m_sOwnMem = TRUE;
- // Set size of file.
- m_lSize = lSize;
- // Set minimum grow size for overwrites.
- m_lGrowSize = lGrowSize;
- // Clear error flag.
- m_sMemError = 0;
- }
- else
- {
- TRACE("Open(%ld, %ld, %s): File too large for free memory.\n",
- lSize, lGrowSize,
- ms_apszEndian[endian]);
- sRes = -3;
- }
- }
- else
- {
- TRACE("Open(%ld, %ld, %s): File already open.\n",
- lSize, lGrowSize,
- ms_apszEndian[endian]);
- sRes = -2;
- }
- return sRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Open an existing FILE* stream.
- // Once a FILE* is opened, you can use this class's Close() instead of fclose(),
- // if that is more convenient.
- //
- //////////////////////////////////////////////////////////////////////////////
- short RFile::Open( // Returns 0 on success.
- FILE* fs, // FILE* stream to open.
- Endian endian, // { RFile::BigEndian | RFile::LittleEndian | RFile::NeutralEndian }.
- Flags flags /*= // See comments in Typedefs & Enums section
- Binary*/) // above.
- {
- short sRes = 0; // Assume success.
- if (fs != NULL)
- {
- // Store flags for this file.
- // Make sure Ascii and Binary are not both specified.
- ASSERT( (flags & (Ascii | Binary)) != (Ascii | Binary) );
- // Make sure either Ascii or Binary is specified.
- ASSERT( (flags & (Ascii | Binary)) != 0);
- m_flags = flags;
-
- // Set endian.
- SetEndian(endian);
- // Store FILE* stream.
- m_fs = fs;
- }
- else
- {
- TRACE("Open(0x%08lX, %s): Invalid FILE*.\n",
- fs,
- ms_apszEndian[endian]);
- sRes = -1;
- }
- return sRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Open an existing RFile.
- // "Ack!" you say ... and I agree.
- // This basically begins what I like to think of as a synchronization between two RFiles.
- // This RFile snags the current state (basically copies the members) from the specified
- // RFile. Then, one can use the new RFile to access the file/memory/whatever that the
- // original RFile is attached to. When Close() is called, the synchronization is finsished
- // by updating the original RFile with the state from this.
- // Danger: Do not access the original RFile between Open(RFile*)/Close() pairs!
- //
- //////////////////////////////////////////////////////////////////////////////
- short RFile::Open( // Returns 0 on success.
- RFile* pfile) // RFile to open.
- {
- short sRes = 0;
- // Synchronize.
- m_fs = pfile->m_fs;
- m_pucFile = pfile->m_pucFile;
- m_sOwnMem = pfile->m_sOwnMem;
- m_pucCur = pfile->m_pucCur;
- m_lSize = pfile->m_lSize;
- m_lGrowSize = pfile->m_lGrowSize;
-
- m_sMemError = pfile->m_sMemError;
- m_endian = pfile->m_endian;
- m_flags = pfile->m_flags;
- // Remember who to Unsynch with.
- m_pfileSynch = pfile;
- return sRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Change the endian format used to read/write the file.
- // Returns nothing.
- //
- //////////////////////////////////////////////////////////////////////////////
- void RFile::SetEndian(Endian endian)
- {
- ASSERT(endian == BigEndian || endian == NeutralEndian || endian == LittleEndian);
- m_endian = endian;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Close a file successfully opened with Open().
- // Returns 0 on success.
- //
- //////////////////////////////////////////////////////////////////////////////
- short RFile::Close(void)
- {
- short sRes = 0; // Assume success.
- ASSERT(m_fs != NULL || m_pucFile != NULL);
- // If we are synchronizing with another RFile . . .
- if (m_pfileSynch != NULL)
- {
- // De/Un/Resynch.
- m_pfileSynch->m_fs = m_fs;
- m_pfileSynch->m_pucFile = m_pucFile;
- m_pfileSynch->m_sOwnMem = m_sOwnMem;
- m_pfileSynch->m_pucCur = m_pucCur;
- m_pfileSynch->m_lSize = m_lSize;
- m_pfileSynch->m_lGrowSize = m_lGrowSize;
-
- m_pfileSynch->m_sMemError = m_sMemError;
- m_pfileSynch->m_endian = m_endian;
- m_pfileSynch->m_flags = m_flags;
- // Clear ("Close").
- m_fs = NULL;
- m_pucFile = NULL;
- m_sOwnMem = FALSE;
- m_pucCur = NULL;
- m_sMemError = FALSE;
- m_pfileSynch = NULL;
- }
- else
- {
- short sClose = TRUE;
-
- // If hook defined . . .
- if (ms_hClose != NULL)
- {
- // If not re-entered . . .
- if (m_sCloseSem == 0)
- {
- m_sCloseSem++;
-
- sClose = (*ms_hClose)(this, ms_lCloseUser);
-
- m_sCloseSem--;
- }
- }
- // If no hook or hook told us to perform business as usual . . .
- if (sClose == TRUE)
- {
- if (IsFile() == TRUE)
- {
- KEEPCONNECTEDANDUPDATELASTACCESS;
- if (fclose(m_fs) == 0)
- {
- // Success.
- m_fs = NULL;
-
- #ifdef ALLOW_RFILE_REOPEN
- // Remove from open list.
- if (ms_listOpen.Remove(this) == 0)
- {
- }
- else
- {
- TRACE("Close(): Unable to remove this from open list.\n");
- sRes = -3;
- }
- #endif // ALLLOW_RFILE_REOPEN
- }
- else
- {
- TRACE("Close(): Unable to close file.\n");
- sRes = -2;
- }
- }
- else
- {
- if (IsMemory() == TRUE)
- {
- // If we own the buffer . . .
- if (m_sOwnMem != FALSE)
- {
- // Make sure we still have a buffer (a resize could have failed).
- if (m_pucFile != NULL)
- {
- // Be gone.
- free(m_pucFile);
- }
- }
- m_pucFile = NULL;
- m_sOwnMem = FALSE;
- m_pucCur = NULL;
- m_lSize = 0L;
- m_lGrowSize = 0L;
- m_sMemError = 0;
- }
- else
- {
- TRACE("Close(): Unable to close unopened file.\n");
- sRes = -1;
- }
- }
- }
- }
- return sRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Reads sNum bytes from currently open file.
- // Returns number of bytes successfully read.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Read(void* pData, long lNum)
- {
- long lRes = 0; // Assume success.
- if (IsFile() == TRUE)
- {
- long lToRead;
- long lDidRead = 1;
- long lMaxRead = ms_criticall ? MAX_CALLBACK_GRANULARITY_BYTES : lNum;
- do
- {
- lToRead = MIN(lMaxRead, lNum);
- // If there is a CritiCall . . .
- if (ms_criticall != NULL)
- {
- // Call it.
- (*ms_criticall)(lToRead);
- }
- KEEPCONNECTEDANDUPDATELASTACCESS;
- lDidRead = fread(pData, 1, lToRead, m_fs);
- if (lDidRead > 0)
- {
- lRes += lDidRead;
- lNum -= lDidRead;
- pData = (U8*)pData + lDidRead;
- }
- } while (lNum > 0 && lDidRead > 0);
- }
- else
- {
- if (IsMemory() == TRUE)
- {
- if (m_pucCur + lNum <= m_pucFile + m_lSize)
- {
- lRes = lNum;
- }
- else
- {
- lRes = (m_pucFile + m_lSize) - m_pucCur;
- // TRACE("Read(): Attempt to read passed end of memory file.\n");
- m_sMemError = 1;
- }
-
- // "Read" data.
- memcpy(pData, m_pucCur, lRes);
- // Move file ptr.
- m_pucCur += lRes;
- }
- else
- {
- TRACE("Read(): File not open.\n");
- lRes = -1L;
- }
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Attempts to read lNum TYPE numbers from pfsIn or pu8In.
- //
- //////////////////////////////////////////////////////////////////////////////
- template <
- class TYPE> // Type for storing and overflow checking.
- inline // Speed.
- long ReadASCII( // Returns number of complete TYPE items successfully read
- // and stored.
- TYPE* ptData, // Out: Pointer to array of TYPE items for read data.
- long lNum, // In: Number of TYPE items to read.
- FILE* pfsIn, // In: File stream to use for input.
- double dMax) // In: Maximum value for this type.
- {
- long lRes = 0; // Assume success.
- // Temp var to read into.
- double dTemp;
- while (lNum--)
- {
- if (fscanf(pfsIn, " %le", &dTemp) == 1)
- {
- // Successfully read an item.
-
- // Check size . . .
- if (ABS(dTemp) < dMax)
- {
- // Within range. Store.
- *ptData++ = (TYPE)dTemp;
- // Increment number stored.
- lRes++;
- }
- else
- {
- TRACE("ReadASCII(): Read %le which does not fit into item of size %u bits.\n",
- dTemp, sizeof(TYPE) * 8);
- break;
- }
- }
- else
- {
- TRACE("ReadASCII(): Failed to read numeric of size %u bits.\n",
- sizeof(TYPE) * 8);
- break;
- }
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Reads lNum U8 values from currently open file.
- // Returns number of U8 values successfully written.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Read(U8* pu8Data, long lNum /*= 1L*/)
- {
- long lRes = 0L; // Assume success.
- if ((m_flags & Ascii) != 0)
- {
- // Read ASCII data.
- lRes = ReadASCII(pu8Data, lNum, m_fs, (double)UCHAR_MAX);
- }
- else
- {
- // Read Binary data.
- lRes = Read8(pu8Data, lNum);
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Reads lNum S8 values from currently open file.
- // Returns number of S8 values successfully written.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Read(S8* ps8Data, long lNum /*= 1L*/)
- {
- long lRes = 0L; // Assume success.
- if ((m_flags & Ascii) != 0)
- {
- // Read ASCII data.
- lRes = ReadASCII(ps8Data, lNum, m_fs, (double)CHAR_MAX);
- }
- else
- {
- // Read Binary data.
- lRes = Read8((U8*)ps8Data, lNum);
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Reads sNum U16 values from currently open file.
- // Returns number of U16 values successfully read.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Read(U16* pu16Data, long lNum /*= 1L*/)
- {
- long lRes = 0L; // Assume success.
- if ((m_flags & Ascii) != 0)
- {
- // Read ASCII data.
- lRes = ReadASCII(pu16Data, lNum, m_fs, (double)USHRT_MAX);
- }
- else
- {
- // Read Binary data.
- lRes = Read16(pu16Data, lNum);
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Reads lNum S16 values from currently open file.
- // Returns number of S16 values successfully read.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Read(S16* ps16Data, long lNum /*= 1L*/)
- {
- long lRes = 0L; // Assume success.
- if ((m_flags & Ascii) != 0)
- {
- // Read ASCII data.
- lRes = ReadASCII(ps16Data, lNum, m_fs, (double)SHRT_MAX);
- }
- else
- {
- // Read Binary data.
- lRes = Read16((U16*)ps16Data, lNum);
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Reads lNum RPixel24 values from currently open file.
- // Returns number of RPixel24 values successfully read.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Read(RPixel24* ppix24, long lNum /*= 1L*/)
- {
- long lRes = 0L; // Assume success.
- if ((m_flags & Ascii) != 0)
- {
- ASSERT(0 && "**Cannot read 24 bit types in ASCII**");
- // Read ASCII data.
- // lRes = ReadASCII(ppix24, lNum, m_fs, (double)(1 << 24));
- }
- else
- {
- // Read Binary data.
- lRes = Read24(ppix24, lNum);
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Reads sNum U32 values from currently open file.
- // Returns number of U32 values successfully read.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Read(U32* pu32Data, long lNum /*= 1L*/)
- {
- long lRes = 0L; // Assume success.
- if ((m_flags & Ascii) != 0)
- {
- // Read ASCII data.
- lRes = ReadASCII(pu32Data, lNum, m_fs, (double)ULONG_MAX);
- }
- else
- {
- // Read Binary data.
- lRes = Read32(pu32Data, lNum);
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Reads lNum S32 values from currently open file.
- // Returns number of S32 values successfully read.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Read(S32* ps32Data, long lNum /*= 1L*/)
- {
- long lRes = 0L; // Assume success.
- if ((m_flags & Ascii) != 0)
- {
- // Read ASCII data.
- lRes = ReadASCII(ps32Data, lNum, m_fs, (double)LONG_MAX);
- }
- else
- {
- // Read Binary data.
- lRes = Read32((U32*)ps32Data, lNum);
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Reads lNum U64 values from currently open file.
- // Returns number of U64 values successfully read.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Read(U64* pu64Data, long lNum /*= 1L*/)
- {
- long lRes = 0L; // Assume success.
- if ((m_flags & Ascii) != 0)
- {
- ASSERT(0 && "**Cannot read 64 bit types other than double in ASCII**");
- }
- else
- {
- // Read Binary data.
- lRes = Read64(pu64Data, lNum);
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Reads lNum S64 values from currently open file.
- // Returns number of S64 values successfully read.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Read(S64* ps64Data, long lNum /*= 1L*/)
- {
- long lRes = 0L; // Assume success.
- if ((m_flags & Ascii) != 0)
- {
- ASSERT(0 && "**Cannot read 64 bit types other than double in ASCII**");
- }
- else
- {
- // Read Binary data.
- lRes = Read64((U64*)ps64Data, lNum);
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Reads lNum float values from currently open file.
- // Returns number of float values successfully read.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Read(float* pfData, long lNum /*= 1L*/)
- {
- long lRes = 0L; // Assume success.
- if ((m_flags & Ascii) != 0)
- {
- // Read ASCII data.
- lRes = ReadASCII(pfData, lNum, m_fs, (double)FLT_MAX);
- }
- else
- {
- // Read Binary data.
- lRes = Read32((U32*)pfData, lNum);
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Reads lNum double values from currently open file.
- // Returns number of double values successfully read.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Read(double* pdData, long lNum /*= 1L*/)
- {
- long lRes = 0L; // Assume success.
- if ((m_flags & Ascii) != 0)
- {
- // Read ASCII data.
- lRes = ReadASCII(pdData, lNum, m_fs, DBL_MAX);
- }
- else
- {
- // Read Binary data.
- lRes = Read64((U64*)pdData, lNum);
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- // NOTE that this function has very different functionality in each of the
- // two Open() modes (Ascii & Binary).
- //////////////////////////////////////////////////////////////////////////////
- //
- // ASCII MODE:
- // Reads a quotes or white-space delimited string. Quotes preceded by back-
- // slash are ignored and are stored as just quotes (without the backslash).
- // Strings are either whitespace or quotes delimited (e.g., a string beginning
- // with quotes can only be ended by quotes, and a string beginning without
- // quotes can only be ended by whitespace).
- // Returns number of characters successfully stored (which may be less than
- // the amount read), NOT including the NULL terminator (like strlen()).
- //
- // BINARY MODE:
- // Reads a NULL terminated string.
- // Returns number of characters successfully read,
- // including the NULL terminator (UNlike strlen()).
- //
- //
- // pszString must point to a memory block sufficiently large
- // enough to hold the string.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Read(char* pszString)
- {
- long lRes = 0; // Assume nothing.
- if (m_flags & Binary)
- {
- do
- {
- // Read one character.
- if (Read(pszString, 1) == 1)
- {
- }
- else
- {
- TRACE("Read(): Failed to read to NULL terminator of string.\n");
- *pszString = '\0';
- }
- lRes++;
-
- // Do this until we hit the NULL or an error occurs.
- } while (*pszString++ != '\0');
- }
- else
- {
- // Skip whitespace.
- do
- {
- if (Read(pszString, 1) == 1)
- {
- }
- else
- {
- break;
- }
- } while (strchr(WHITE_SPACE, *pszString++) == NULL);
- // Note whether started by qutoes.
- short sInQuotes = FALSE;
- if (*pszString == '"')
- {
- sInQuotes = TRUE;
- }
- // Store string.
- short sLastCharWasBackSlash = FALSE;
- while (*pszString != '\0')
- {
- if (Read(pszString, 1) == 1)
- {
- // Increment count.
- lRes++;
- // If previous was backslash . . .
- if (sLastCharWasBackSlash != FALSE)
- {
- // If current is quotes . . .
- if (*pszString == '"')
- {
- // Overwrite backslash.
- *pszString-- = '"';
- // Deduct from count.
- lRes--;
- }
- }
- switch (*pszString++)
- {
- case '\\':
- sLastCharWasBackSlash = TRUE;
- break;
- case '"':
- // If this is quotes delimited . . .
- if (sInQuotes != FALSE && sLastCharWasBackSlash == FALSE)
- {
- // Done.
- *pszString = '\0';
- }
- // Intentional fall through to default case.
- default:
- // Clear last was backslash flag.
- sLastCharWasBackSlash = FALSE;
- // If this is whitespace delimited . . .
- if (sInQuotes == FALSE)
- {
- // If this is whitespace . . .
- if (strchr(WHITE_SPACE, *pszString) != NULL)
- {
- // Done.
- *pszString = '\0';
- }
- }
- break;
- }
- }
- else
- {
- // Done.
- *pszString = '\0';
- }
- }
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Writes lNum bytes from currently open file.
- // Returns number of bytes successfully written.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Write(const void* pData, long lNum)
- {
- long lRes = 0; // Assume success.
- if (IsFile() == TRUE)
- {
- long lToWrite;
- long lDidWrite = 1;
- long lMaxWrite = ms_criticall ? MAX_CALLBACK_GRANULARITY_BYTES : lNum;
- do
- {
- lToWrite = MIN(lMaxWrite, lNum);
- // If there is a CritiCall . . .
- if (ms_criticall != NULL)
- {
- // Call it.
- (*ms_criticall)(lNum);
- }
- KEEPCONNECTEDANDUPDATELASTACCESS;
- lDidWrite = fwrite(pData, 1, lToWrite, m_fs);
- if (lDidWrite > 0)
- {
- lRes += lDidWrite;
- lNum -= lDidWrite;
- pData = (U8*)pData + lDidWrite;
- }
- } while (lDidWrite > 0 && lNum > 0);
- }
- else
- {
- if (IsMemory() == TRUE)
- {
- // If still within buffer . . .
- if (m_pucCur + lNum <= m_pucFile + m_lSize)
- {
- lRes = lNum;
- }
- else
- {
- // If we don't own the bufer . . .
- if (m_sOwnMem == FALSE)
- {
- // Unlike normal files, our file can't get bigger.
- // Our space is limited by the original value of m_lSize.
- lRes = (m_pucFile + m_lSize) - m_pucCur;
- TRACE("Write(): Attempt to write passed end of memory file.\n");
- m_sMemError = 1;
- }
- else
- {
- // Attempt to enlarge the buffer by the max of m_lGrowSize or the
- // overrun amount.
- long lCurPos = m_pucCur - m_pucFile;
- long lDistanceToEOF = m_lSize - lCurPos;
- long lNewSize = m_lSize + MAX(m_lGrowSize, (lNum - lDistanceToEOF) );
- // Enlarge . . .
- UCHAR* pucNewFile = (UCHAR*)realloc(m_pucFile, lNewSize);
- // If successful . . .
- if (pucNewFile != NULL)
- {
- // Set new buffer pointer.
- m_pucFile = pucNewFile;
- // Set current position.
- m_pucCur = pucNewFile + lCurPos;
- // Set new buffer size.
- m_lSize = lNewSize;
- // Write amount requested.
- lRes = lNum;
- }
- else
- {
- // Only write what we can. Keep same buffer.
- lRes = lDistanceToEOF;
- }
- }
- }
-
- // "Write" data.
- memcpy(m_pucCur, pData, lRes);
- // Move file ptr.
- m_pucCur += lRes;
- }
- else
- {
- TRACE("Write(): File not open.\n");
- lRes = -1L;
- }
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Attempts to write lNum TYPE numbers from pfsIn or pu8In.
- //
- //////////////////////////////////////////////////////////////////////////////
- template <
- class TYPE> // Type for storing and overflow checking.
- inline // Speed.
- long WriteASCII( // Returns number of complete TYPE items successfully
- // written.
- TYPE* ptData, // In: Pointer to array of TYPE items for write data.
- long lNum, // In: Number of TYPE items to read.
- FILE* pfsOut, // In: File stream to use for output.
- char* pszFrmt) // In: Output printf style format specifier.
- {
- long lRes = 0; // Assume success.
- while (lNum--)
- {
- if (fprintf(pfsOut, pszFrmt, *ptData++) > 0)
- {
- // Successfully wrote an item.
-
- // Increment number written.
- lRes++;
- }
- else
- {
- TRACE("WriteASCII(): Failed to write numeric of size %u bits.\n",
- sizeof(TYPE) * 8);
- break;
- }
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Writes lNum U8 values to currently open file.
- // Returns number of U8 values successfully written.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Write(const U8* pu8Data, long lNum /*= 1L*/)
- {
- long lRes = 0L; // Assume success.
- if ((m_flags & Ascii) != 0)
- {
- // Write ASCII data.
- lRes = WriteASCII(pu8Data, lNum, m_fs, "%u ");
- }
- else
- {
- // Write Binary data.
- lRes = Write8(pu8Data, lNum);
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Writes lNum S8 values to currently open file.
- // Returns number of S8 values successfully written.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Write(const S8* ps8Data, long lNum /*= 1L*/)
- {
- long lRes = 0L; // Assume success.
- if ((m_flags & Ascii) != 0)
- {
- // Write ASCII data.
- lRes = WriteASCII(ps8Data, lNum, m_fs, "%d ");
- }
- else
- {
- // Write Binary data.
- lRes = Write8((U8*)ps8Data, lNum);
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Writes sNum U16 values from currently open file.
- // Returns number of U16 values successfully written.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Write(const U16* pu16Data, long lNum /*= 1L*/)
- {
- long lRes = 0L; // Assume success.
- if ((m_flags & Ascii) != 0)
- {
- // Write ASCII data.
- lRes = WriteASCII(pu16Data, lNum, m_fs, "%u ");
- }
- else
- {
- // Write Binary data.
- lRes = Write16(pu16Data, lNum);
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Writes lNum S16 values to currently open file.
- // Returns number of S16 values successfully written.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Write(const S16* ps16Data, long lNum /*= 1L*/)
- {
- long lRes = 0L; // Assume success.
- if ((m_flags & Ascii) != 0)
- {
- // Write ASCII data.
- lRes = WriteASCII(ps16Data, lNum, m_fs, "%d ");
- }
- else
- {
- // Write Binary data.
- lRes = Write16((U16*)ps16Data, lNum);
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Writes lNum RPixel24 values to currently open file.
- // Returns number of RPixel24 values successfully written.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Write(const RPixel24* ppix24, long lNum /*= 1L*/)
- {
- long lRes = 0; // Assume success.
- if ((m_flags & Ascii) != 0)
- {
- ASSERT(0 && "**Cannot write 24 bit types in ASCII**");
- // Write ASCII data.
- // lRes = WriteASCII(ppix24, lNum, m_fs, "%06lX ");
- }
- else
- {
- // Write Binary data.
- lRes = Write24(ppix24, lNum);
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Writes sNum U32 values from currently open file.
- // Returns number of U32 values successfully written.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Write(const U32* pu32Data, long lNum /*= 1L*/)
- {
- long lRes = 0; // Assume success.
- if ((m_flags & Ascii) != 0)
- {
- // Write ASCII data.
- lRes = WriteASCII(pu32Data, lNum, m_fs, "%lu ");
- }
- else
- {
- // Write Binary data.
- lRes = Write32(pu32Data, lNum);
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Writes lNum S32 values to currently open file.
- // Returns number of S32 values successfully written.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Write(const S32* ps32Data, long lNum /*= 1L*/)
- {
- long lRes = 0; // Assume success.
- if ((m_flags & Ascii) != 0)
- {
- // Write ASCII data.
- lRes = WriteASCII(ps32Data, lNum, m_fs, "%ld ");
- }
- else
- {
- // Write Binary data.
- lRes = Write32((U32*)ps32Data, lNum);
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Writes lNum float values to the currently open file.
- // Returns number of float values successfully written.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Write(const float* pfData, long lNum /*= 1L*/)
- {
- long lRes = 0; // Assume success.
- if ((m_flags & Ascii) != 0)
- {
- // Write ASCII data.
- lRes = WriteASCII(pfData, lNum, m_fs, "%e ");
- }
- else
- {
- // Write Binary data.
- lRes = Write32((U32*)pfData, lNum);
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Writes lNum double values to the currently open file.
- // Returns number of double values successfully written.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Write(const double* pdData, long lNum /*= 1L*/)
- {
- long lRes = 0; // Assume success.
- if ((m_flags & Ascii) != 0)
- {
- // Write ASCII data.
- lRes = WriteASCII(pdData, lNum, m_fs, "%le ");
- }
- else
- {
- // Write Binary data.
- lRes = Write64((U64*)pdData, lNum);
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Writes lNum U64 values to currently open file.
- // Returns number of U64 values successfully written.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Write(const U64* pu64Data, long lNum /*= 1L*/)
- {
- long lRes = 0; // Assume success.
- if ((m_flags & Ascii) != 0)
- {
- ASSERT(0 && "**Cannot write 64 bit types other than double in ASCII**");
- }
- else
- {
- // Write Binary data.
- lRes = Write64(pu64Data, lNum);
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Writes lNum S64 values to currently open file.
- // Returns number of S64 values successfully written.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Write(const S64* ps64Data, long lNum /*= 1L*/)
- {
- long lRes = 0; // Assume success.
- if ((m_flags & Ascii) != 0)
- {
- ASSERT(0 && "**Cannot write 64 bit types other than double in ASCII**");
- }
- else
- {
- // Write Binary data.
- lRes = Write64((U64*)ps64Data, lNum);
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- // NOTE that this function has very different functionality in each of the
- // two Open() modes (Ascii & Binary).
- //////////////////////////////////////////////////////////////////////////////
- //
- // ASCII MODE:
- // Writes a NULL terminated string. The string is surrounded by quotes in
- // the file. Quotes in your string will be converted to \".
- // Returns number of characters from your string successfully written (which
- // is less than the total amount written) (this value should be the same
- // as that returned from strlen() on success).
- //
- // BINARY MODE:
- // Writes a NULL terminated string.
- // Returns number of characters successfully written,
- // including the NULL terminator (UNlike strlen()).
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Write(const char* pszString)
- {
- long lRes = 0; // Assume nothing.
-
- if (m_flags & Binary)
- {
- lRes = Write(pszString, strlen(pszString) + 1);
- }
- else
- {
- // Write leading quotes.
- if (Write("\"", 1) == 1)
- {
- while (*pszString != '\0')
- {
- switch (*pszString)
- {
- case '"':
- if (Write("\\", 1) == 1)
- {
- }
- break;
- }
- if (Write(pszString, 1) == 1)
- {
- lRes++;
- }
- else
- {
- break;
- }
- }
-
- // Write trailing quotes.
- Write("\"", 1);
- }
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Seeks within the file based on the supplied position argument
- // { SEEK_SET, SEEK_CUR, SEEK_END }.
- // Returns 0 on success.
- //
- //////////////////////////////////////////////////////////////////////////////
- short RFile::Seek(long lPos, long lOrigin)
- {
- short sRes = 0; // Assume success.
- if (IsFile() == TRUE)
- {
- KEEPCONNECTEDANDUPDATELASTACCESS;
- sRes = fseek(m_fs, lPos, lOrigin);
- }
- else
- {
- if (IsMemory() == TRUE)
- {
- switch (lOrigin)
- {
- case SEEK_SET:
- // If w/i range . . .
- if (lPos <= m_lSize && lPos >= 0)
- {
- m_pucCur = m_pucFile + lPos;
- }
- else
- {
- m_sMemError = 1;
- TRACE("Seek(): Attempt to seek passed end or before beginning of mem file.\n");
- sRes = -3;
- }
- break;
- case SEEK_CUR:
- // If w/i range . . .
- if (m_pucCur + lPos <= m_pucFile + m_lSize && m_pucCur + lPos >= m_pucFile)
- {
- m_pucCur += lPos;
- }
- else
- {
- m_sMemError = 1;
- TRACE("Seek(): Attempt to seek passed end or before beginning of mem file.\n");
- sRes = -3;
- }
- break;
- case SEEK_END:
- if (lPos <= 0 && -lPos <= m_lSize)
- {
- m_pucCur = m_pucFile + m_lSize + lPos;
- }
- else
- {
- m_sMemError = 1;
- TRACE("Seek(): Attempt to seek passed end or before beginning of mem file.\n");
- sRes = -3;
- }
- break;
- default:
- TRACE("Seek(): Invalid origin flag provided.\n");
- sRes = -2;
- break;
- }
- }
- else
- {
- TRACE("Seek(): File not open.\n");
- sRes = -1;
- }
- }
- return sRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Returns the current file position or -1 on error.
- // Returns 0 on success.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Tell(void)
- {
- long lRes = -1L; // Assume error.
- if (IsFile() == TRUE)
- {
- KEEPCONNECTEDANDUPDATELASTACCESS;
- lRes = ftell(m_fs);
- }
- else
- {
- if (IsMemory() == TRUE)
- {
- lRes = m_pucCur - m_pucFile;
- }
- else
- {
- TRACE("Tell(): File not open.\n");
- }
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Returns the size of the file on success. Negative on error.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::GetSize(void)
- {
- long lRes;
- // Remember the current position.
- long lPos = Tell();
- if (lPos >= 0L)
- {
- // Attempt to seek to the end . . .
- if (Seek(0L, SEEK_END) == 0)
- {
- // Current pos is size of file.
- lRes = Tell();
-
- // Seek back.
- if (Seek(lPos, SEEK_SET) == 0)
- {
- // Success.
- }
- else
- {
- TRACE("GetSize(): Unable to seek back to start point.\n");
- lRes = -3;
- }
- }
- else
- {
- TRACE("GetSize(): Unable to seek to end of file.\n");
- lRes = -2;
- }
- }
- else
- {
- TRACE("GetSize(): Unable to tell position of file.\n");
- lRes = -1;
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- // Internal Methods.
- //////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////
- //
- // Reads in 8 bit data, swapped if necessary (BWAH HA).
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Read8( // Returns number of 8 bit items read.
- U8* pu8, // In: 8 bit data to read (swapping, if necessary).
- long lNum) // In: Number of 8 bit items to read.
- {
- long lRes = 0;
- // Read data.
- lRes = Read((void*)pu8, lNum);
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Reads in 16 bit data, swapped if necessary.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Read16( // Returns number of 16 bit items read.
- U16* pu16, // In: 16 bit data to read (swapping, if necessary).
- long lNum) // In: Number of 16 bit items to read.
- {
- long lRes = 0;
- // Read data.
- lRes = Read((void*)pu16, lNum * sizeof(U16)) / sizeof(U16);
- // If m_endian is consistent with this platform . . .
- if (ENDIAN_CONSISTENT)
- {
- // Done.
- }
- else
- {
- // Convert.
- U8 u8_0;
- U8* pu8 = (U8*)pu16;
- for (long l = 0L; l < lRes; l++, pu8 += sizeof(U16))
- {
- // Store end.
- u8_0 = *(pu8 + 1);
- // Put beginning in end.
- *(pu8 + 1) = *(pu8 + 0);
- // Put end in beginning.
- *(pu8 + 0) = u8_0;
- }
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Reads in 24 bit data, swapped if necessary.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Read24( // Returns number of 24 bit items read.
- RPixel24* ppix24, // In: 24 bit data to read (swapping, if necessary).
- long lNum) // In: Number of 24 bit items to read.
- {
- long lRes = 0;
- // Read data.
- lRes = Read((void*)ppix24, lNum * sizeof(RPixel24)) / sizeof(RPixel24);
- // If m_endian is consistent with this platform . . .
- if (ENDIAN_CONSISTENT)
- {
- // Done.
- }
- else
- {
- // Convert.
- U8 u8_0;
- U8* pu8 = (U8*)ppix24;
- for (long l = 0L; l < lRes; l++, pu8 += sizeof(RPixel24))
- {
- // Store end.
- u8_0 = *(pu8 + 2);
- // Put beginning in end.
- *(pu8 + 2) = *(pu8 + 0);
- // Put end in beginning.
- *(pu8 + 0) = u8_0;
- // Middle does not need to be swapped in odd sized types.
- }
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Reads in 32 bit data, swapped if necessary.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Read32( // Returns number of 32 bit items read.
- U32* pu32, // In: 32 bit data to read (swapping, if necessary).
- long lNum) // In: Number of 32 bit items to read.
- {
- long lRes = 0;
- // Read data.
- lRes = Read((void*)pu32, lNum * sizeof(U32)) / sizeof(U32);
- // If m_endian is consistent with this platform . . .
- if (ENDIAN_CONSISTENT)
- {
- // Done.
- }
- else
- {
- // Convert.
- U8 u8_0;
- U8 u8_1;
- U8* pu8 = (U8*)pu32;
- for (long l = 0L; l < lRes; l++, pu8 += sizeof(U32))
- {
- // Store end.
- u8_0 = *(pu8 + 3);
- // Store second to end.
- u8_1 = *(pu8 + 2);
- // Put beginning into end.
- *(pu8 + 3) = *(pu8 + 0);
- // Put second to beginning into second to end.
- *(pu8 + 2) = *(pu8 + 1);
-
- // Put end in beginning.
- *(pu8 + 0) = u8_0;
- // Put second to end into second to beginning.
- *(pu8 + 1) = u8_1;
- }
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Reads in 64 bit data, swapped if necessary.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Read64( // Returns number of 64 bit items read.
- U64* pu64, // In: 64 bit data to read (swapping, if necessary).
- long lNum) // In: Number of 64 bit items to read.
- {
- long lRes = 0;
- // Read data.
- lRes = Read((void*)pu64, lNum * sizeof(U64)) / sizeof(U64);
- // If m_endian is consistent with this platform . . .
- if (ENDIAN_CONSISTENT)
- {
- // Done.
- }
- else
- {
- // Convert.
- U8 u8Tmp;
- U8* pu8 = (U8*)pu64;
- for (long l = 0L; l < lRes; l++, pu8 += sizeof(U64))
- {
- u8Tmp = *(pu8 + 0);
- *(pu8 + 0) = *(pu8 + 7);
- *(pu8 + 7) = u8Tmp;
- u8Tmp = *(pu8 + 1);
- *(pu8 + 1) = *(pu8 + 6);
- *(pu8 + 6) = u8Tmp;
- u8Tmp = *(pu8 + 2);
- *(pu8 + 2) = *(pu8 + 5);
- *(pu8 + 5) = u8Tmp;
- u8Tmp = *(pu8 + 3);
- *(pu8 + 3) = *(pu8 + 4);
- *(pu8 + 4) = u8Tmp;
- }
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Writes out 8 bit data, swapped if necessary (BWAH HA).
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Write8( // Returns number of 8 bit items written.
- const U8* pu8, // In: 8 bit data to write (swapping, if necessary).
- long lNum) // In: Number of 8 bit items to write.
- {
- long lRes = 0;
- lRes = Write((void*)pu8, lNum);
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Writes out 16 bit data, swapped if necessary.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Write16( // Returns number of 16 bit items written.
- const U16* pu16, // In: 16 bit data to write (swapping, if necessary).
- long lNum) // In: Number of 16 bit items to write.
- {
- long lRes = 0;
- // If m_endian is consistent with this platform . . .
- if (ENDIAN_CONSISTENT)
- {
- // Write data.
- lRes = Write((void*)pu16, lNum * sizeof(U16)) / sizeof(U16);
- }
- else
- {
- // Convert.
- // Note that this could be sped up a bit more by using a variable to store
- // the current lSrc position before entering the inner loop and then subtract
- // that from lSrc after exiting the inner loop to determine the amount of
- // items to write.
- // No template is used b/c it would be necessary to loop on sizeof(U32)
- // which would negate much of the effort of this algorithm.
- U8* pu8Src = (U8*)pu16; // Source data.
- U8* pu8Dst; // Temp destination to be written after
- // swapped to.
- long lSrc; // Number of source items swapped/written.
- long lDst; // Number of items swapped on current
- // iteration.
- long lWritten = 0; // Number of items written on current
- // iteration.
- for (lSrc = 0L; lSrc < lNum && lWritten >= 0L; lRes += lWritten / sizeof(U16))
- {
- pu8Dst = ms_au8SwapBuf;
- for (
- lDst = 0L;
- lSrc < lNum && lDst < sizeof(ms_au8SwapBuf);
- lDst += sizeof(U16), lSrc++, pu8Src += sizeof(U16), pu8Dst += sizeof(U16) )
- {
- *(pu8Dst + 1) = *(pu8Src + 0);
- *(pu8Dst + 0) = *(pu8Src + 1);
- }
-
- // Write data subportion.
- lWritten = Write((void*)ms_au8SwapBuf, lDst);
- }
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Writes out 24 bit data, swapped if necessary.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Write24( // Returns number of 24 bit items written.
- const RPixel24* ppix24, // In: 24 bit data to write (swapping, if necessary).
- long lNum) // In: Number of 24 bit items to write.
- {
- long lRes = 0;
- // If m_endian is consistent with this platform . . .
- if (ENDIAN_CONSISTENT)
- {
- // Write data.
- lRes = Write((void*)ppix24, lNum * sizeof(RPixel24)) / sizeof(RPixel24);
- }
- else
- {
- // Convert.
- // Note that this could be sped up a bit more by using a variable to store
- // the current lSrc position before entering the inner loop and then subtract
- // that from lSrc after exiting the inner loop to determine the amount of
- // items to write.
- // No template is used b/c it would be necessary to loop on sizeof(U32)
- // which would negate much of the effort of this algorithm.
- U8* pu8Src = (U8*)ppix24; // Source data.
- U8* pu8Dst; // Temp destination to be written after
- // swapped to.
- long lSrc; // Number of source items swapped/written.
- long lDst; // Number of items swapped on current
- // iteration.
- long lWritten = 0; // Number of items written on current
- // iteration.
- for (lSrc = 0L; lSrc < lNum && lWritten >= 0L; lRes += lWritten / sizeof(RPixel24))
- {
- pu8Dst = ms_au8SwapBuf;
- for (
- lDst = 0L;
- lSrc < lNum && lDst < sizeof(ms_au8SwapBuf);
- lDst += sizeof(RPixel24), lSrc++, pu8Src += sizeof(RPixel24), pu8Dst += sizeof(RPixel24) )
- {
- *(pu8Dst + 2) = *(pu8Src + 0);
- *(pu8Dst + 1) = *(pu8Src + 1);
- *(pu8Dst + 0) = *(pu8Src + 2);
- }
-
- // Write data subportion.
- lWritten = Write((void*)ms_au8SwapBuf, lDst);
- }
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Writes out 32 bit data, swapped if necessary.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Write32( // Returns number of 32 bit items written.
- const U32* pu32, // In: 32 bit data to write (swapping, if necessary).
- long lNum) // In: Number of 32 bit items to write.
- {
- long lRes = 0;
- // If m_endian is consistent with this platform . . .
- if (ENDIAN_CONSISTENT)
- {
- // Write data.
- lRes = Write((void*)pu32, lNum * sizeof(U32)) / sizeof(U32);
- }
- else
- {
- // Convert.
- // Note that this could be sped up a bit more by using a variable to store
- // the current lSrc position before entering the inner loop and then subtract
- // that from lSrc after exiting the inner loop to determine the amount of
- // items to write.
- // No template is used b/c it would be necessary to loop on sizeof(U32)
- // which would negate much of the effort of this algorithm.
- U8* pu8Src = (U8*)pu32; // Source data.
- U8* pu8Dst; // Temp destination to be written after
- // swapped to.
- long lSrc; // Number of source items swapped/written.
- long lDst; // Number of items swapped on current
- // iteration.
- long lWritten = 0; // Number of items written on current
- // iteration.
- for (lSrc = 0L; lSrc < lNum && lWritten >= 0L; lRes += lWritten / sizeof(U32))
- {
- pu8Dst = ms_au8SwapBuf;
- for (
- lDst = 0L;
- lSrc < lNum && lDst < sizeof(ms_au8SwapBuf);
- lDst += sizeof(U32), lSrc++, pu8Src += sizeof(U32), pu8Dst += sizeof(U32) )
- {
- *(pu8Dst + 3) = *(pu8Src + 0);
- *(pu8Dst + 2) = *(pu8Src + 1);
- *(pu8Dst + 1) = *(pu8Src + 2);
- *(pu8Dst + 0) = *(pu8Src + 3);
- }
-
- // Write data subportion.
- lWritten = Write((void*)ms_au8SwapBuf, lDst);
- }
- }
- return lRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Writes out 64 bit data, swapped if necessary.
- //
- //////////////////////////////////////////////////////////////////////////////
- long RFile::Write64( // Returns number of 64 bit items written.
- const U64* pu64, // In: 64 bit data to write (swapping, if necessary).
- long lNum) // In: Number of 64 bit items to write.
- {
- long lRes = 0;
- // If m_endian is consistent with this platform . . .
- if (ENDIAN_CONSISTENT)
- {
- // Done.
- lRes = Write((void*)pu64, lNum * sizeof(U64)) / sizeof(U64);
- }
- else
- {
- // Note that this could be sped up a bit more by using a variable to store
- // the current lSrc position before entering the inner loop and then subtract
- // that from lSrc after exiting the inner loop to determine the amount of
- // items to write.
- // No template is used b/c it would be necessary to loop on sizeof(U32)
- // which would negate much of the effort of this algorithm.
- U8* pu8Src = (U8*)pu64; // Source data.
- U8* pu8Dst; // Temp destination to be written after
- // swapped to.
- long lSrc; // Number of source items swapped/written.
- long lDst; // Number of items swapped on current
- // iteration.
- long lWritten = 0; // Number of items written on current
- // iteration.
- for (lSrc = 0L; lSrc < lNum && lWritten >= 0L; lRes += lWritten / sizeof(U64))
- {
- pu8Dst = ms_au8SwapBuf;
- for (
- lDst = 0L;
- lSrc < lNum && lDst < sizeof(ms_au8SwapBuf);
- lDst += sizeof(U64), lSrc++, pu8Src += sizeof(U64), pu8Dst += sizeof(U64) )
- {
- *(pu8Dst + 0) = *(pu8Src + 7);
- *(pu8Dst + 1) = *(pu8Src + 6);
- *(pu8Dst + 2) = *(pu8Src + 5);
- *(pu8Dst + 3) = *(pu8Src + 4);
- *(pu8Dst + 4) = *(pu8Src + 3);
- *(pu8Dst + 5) = *(pu8Src + 2);
- *(pu8Dst + 6) = *(pu8Src + 1);
- *(pu8Dst + 7) = *(pu8Src + 0);
- }
-
- // Write data subportion.
- lWritten = Write((void*)ms_au8SwapBuf, lDst);
- }
- }
- return lRes;
- }
- #ifdef ALLOW_RFILE_REOPEN
- //////////////////////////////////////////////////////////////////////////////
- //
- // Disconnects a disk file from the disk temporarily so that another
- // can use the FILE* that is made available. Returns 0 on success.
- //
- //////////////////////////////////////////////////////////////////////////////
- short RFile::Disconnect(void)
- {
- short sRes = 0; // Assume success.
-
- // Must be disk file and must be connected.
- ASSERT(IsFile() == TRUE);
- ASSERT(m_sDisconnected == FALSE);
- // Close this file. BUT DON'T CLEAR m_fs!!!! Needed for calls to IsFile(),
- // etc.
- if (fclose(m_fs) == 0)
- {
- // Successfully disconnected.
- }
- else
- {
- TRACE("Disconnect(): Unable to close file for disconnection from "
- "disk.\n");
- sRes = -2;
- }
- return sRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Reconnects a disk file that has been previously disconnected.
- // Does nothing if connected (i.e., if m_sDisconnected == FALSE).
- // Returns 0 on success.
- //
- //////////////////////////////////////////////////////////////////////////////
- short RFile::Reconnect(void)
- {
- short sRes = 0; // Assume success.
- // Must be disk file.
- ASSERT(IsFile() == TRUE);
-
- // If disconnected . . .
- if (m_sDisconnected == TRUE)
- {
- // Re open.
- m_fs = fopen(m_szFileName, m_szFlags);
- if (m_fs != NULL)
- {
- // Reconnected. Add to open list.
- if (ms_listOpen.Add(this) == 0)
- {
- // Success.
- }
- else
- {
- TRACE("Reconnect(): Unable to add file to open files list!\n");
- sRes = -2;
- }
- }
- else
- {
- TRACE("Reconnect(): UNABLE TO RECONNECT FILE! A FILE MAY HAVE BEEN "
- "LOCKED BY ANOTHER USER/APP DURING DURATION OF DISCONNECT!\n");
- sRes = -1;
- }
- }
- return sRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Disconnect the RFile attached to disk file that was accessed
- // longest ago.
- // Returns 0 on success.
- // (static)
- //
- //////////////////////////////////////////////////////////////////////////////
- short RFile::MakeStreamAvailable(void)
- {
- short sRes = 0; // Assume success.
- // Find the open RFile attached to disk that was accessed longest ago.
- // All RFiles in the ms_listOpen list are attached to disk files.
- RFile* pfileOld = ms_listOpen.GetHead();
- RFile* pfile = ms_listOpen.GetNext();
- while (pfile != NULL)
- {
- // If current was accessed longer ago than pfileOld . . .
- if (pfile->m_lLastAccess < pfileOld->m_lLastAccess)
- {
- pfileOld = pfile;
- }
- pfile = ms_listOpen.GetNext();
- }
- // If we got one . . .
- if (pfileOld != NULL)
- {
- // Attempt to temporarily disconnect . . .
- if (pfileOld->Disconnect() == 0)
- {
- // Remove RFile from list.
- if (ms_listOpen.Remove(pfileOld) == 0)
- {
- }
- else
- {
- TRACE("MakeStreamAvailable(): Unable to remove RFile from list! "
- "This could cause major problems!\n");
- // No error return value since we actually made on available.
- }
- }
- else
- {
- TRACE("MakeStreamAvailable(): Unable to disconnect RFile.\n");
- sRes = -2;
- }
- }
- else
- {
- TRACE("MakeStreamAvailable(): No open RFiles attached to disk.\n");
- sRes = -1;
- }
- return sRes;
- }
- #endif // ALLOW_RFILE_REOPEN
- //////////////////////////////////////////////////////////////////////////////
- // Querries.
- //////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////
- // EOF
- //////////////////////////////////////////////////////////////////////////////
|