Skip to content
Snippets Groups Projects
Commit 94ad93ed authored by Shon Ferguson's avatar Shon Ferguson
Browse files

Renamed the following functions:

CheckNifHeader -> GetNifVersion
GetVersion -> ParseVersionString
IsVersionSupported -> IsSupportedVersion
Added new function, FormatVersionString, to format integer version numbers as a #.#.#.# string.
GetNifVersion so it no longer returns VER_UNSUPPORTED.  It now always returns the actual version value, if possible, which can be passed to IsSupportedVersion if desired.
GetNifVersion now supports version numbers lower than 4.
Added versions 4.0.0.0 and 10.1.0.106 to version constants and IsSupportedVersion function.
Updated some documentation.
parent 1bd54ad6
No related branches found
No related tags found
No related merge requests found
...@@ -5,17 +5,19 @@ All rights reserved. Please see niflib.h for licence. */ ...@@ -5,17 +5,19 @@ All rights reserved. Please see niflib.h for licence. */
#define _NIF_VERSIONS_H_ #define _NIF_VERSIONS_H_
//NIF Version Constants //NIF Version Constants
const unsigned int VER_4_0_0_2 = 0x04000002; /*!< Nif Version 4.0.0.2 */ const unsigned VER_4_0_0_0 = 0X04000000; /*!< NIF Version 4.0.0.0 */
const unsigned int VER_4_1_0_12 = 0x0401000C; /*!< Nif Version 4.1.0.12 */ const unsigned VER_4_0_0_2 = 0x04000002; /*!< NIF Version 4.0.0.2 */
const unsigned int VER_4_2_0_2 = 0x04020002; /*!< Nif Version 4.2.0.2 */ const unsigned VER_4_1_0_12 = 0x0401000C; /*!< NIF Version 4.1.0.12 */
const unsigned int VER_4_2_1_0 = 0x04020100; /*!< Nif Version 4.2.1.0 */ const unsigned VER_4_2_0_2 = 0x04020002; /*!< NIF Version 4.2.0.2 */
const unsigned int VER_4_2_2_0 = 0x04020200; /*!< Nif Version 4.2.2.0 */ const unsigned VER_4_2_1_0 = 0x04020100; /*!< NIF Version 4.2.1.0 */
const unsigned int VER_10_0_1_0 = 0x0A000100; /*!< Nif Version 10.0.1.0 */ const unsigned VER_4_2_2_0 = 0x04020200; /*!< NIF Version 4.2.2.0 */
const unsigned int VER_10_1_0_0 = 0x0A010000; /*!< Nif Version 10.1.0.0 */ const unsigned VER_10_0_1_0 = 0x0A000100; /*!< NIF Version 10.0.1.0 */
const unsigned int VER_10_2_0_0 = 0x0A020000; /*!< Nif Version 10.2.0.0 */ const unsigned VER_10_1_0_0 = 0x0A010000; /*!< NIF Version 10.1.0.0 */
const unsigned int VER_20_0_0_4 = 0x14000004; /*!< Nif Version 20.0.0.4 */ const unsigned VER_10_1_0_106 = 0x0A01006A; /*!< NIF Version 10.1.0.106 */
const unsigned int VER_20_0_0_5 = 0x14000005; /*!< Nif Version 20.0.0.4 */ const unsigned VER_10_2_0_0 = 0x0A020000; /*!< NIF Version 10.2.0.0 */
const unsigned int VER_UNSUPPORTED = 0xFFFFFFFF; /*!< Unsupported Nif Version */ const unsigned VER_20_0_0_4 = 0x14000004; /*!< NIF Version 20.0.0.4 */
const unsigned int VER_INVALID = 0xFFFFFFFE; /*!< Not a Nif file */ const unsigned VER_20_0_0_5 = 0x14000005; /*!< NIF Version 20.0.0.4 */
const unsigned VER_UNSUPPORTED = 0xFFFFFFFF; /*!< Unsupported NIF Version */
const unsigned VER_INVALID = 0xFFFFFFFE; /*!< Not a NIF file */
#endif #endif
\ No newline at end of file
...@@ -115,36 +115,33 @@ struct NifInfo { ...@@ -115,36 +115,33 @@ struct NifInfo {
//--Main Functions--// //--Main Functions--//
/*! /*!
* Reads the header of the given file by file name and returns the NIF version. Call this * Reads the header of the given file by file name and returns the NIF version
* function prior to calling ReadNifList or ReadNifTree, if you need to make sure that the NIF file is supported. * if it is a valid NIF file. Call this function prior to calling ReadNifList
* or ReadNifTree, if you want to make sure that its NIF version is supported
* before trying to read it.
* \param file_name The name of the file to load, or the complete path if it is not in the working directory. * \param file_name The name of the file to load, or the complete path if it is not in the working directory.
* \return The NIF version of the file, in hexadecimal format. If the file is not a NIF file, it returns VER_INVALID. If it is a NIF file, but its version is not supported by the library, it returns VER_UNSUPPORTED. * \return The NIF version of the file, in hexadecimal format. If the file is not a NIF file, it returns VER_INVALID.
* *
* <b>Example:</b> * <b>Example:</b>
* \code * \code
* unsigned int ver = CheckNifHeader("test_in.nif"); * unsigned ver = GetNifVersion("test_in.nif");
* if ( ver == VER_UNSUPPORTED ) cout << "unsupported" << endl; * if ( IsSupportedVersion(ver) == false ) {
* else if ( ver == VER_INVALID ) cout << "invalid" << endl; * cout << "Unsupported.\n" << endl;
* else { * } else if ( ver == VER_INVALID ) {
* vector<NiObjectRef> blocks = ReadNifList( "test_in.nif" ); * cout << "Not a NIF file.\n" << endl;
* cout << blocks[0] << endl; * }
* };
*
* \endcode * \endcode
* *
* <b>In Python:</b> * <b>In Python:</b>
* \code * \code
* ver = CheckNifHeader("test_in.nif") * ver = CheckNifHeader("test_in.nif")
* if ( ver == VER_UNSUPPORTED ): * if ( IsSupportedVersion(ver) == false ):
* print "unsupported" * print "Unsupported."
* elif ( ver == VER_INVALID ): * elif ( ver == VER_INVALID ):
* print "invalid" * print "Not a NIF file."
* else:
* blocks = ReadNifList( "test_in.nif" )
* print blocks[0]
* \endcode * \endcode
*/ */
NIFLIB_API unsigned int CheckNifHeader( string const & file_name ); NIFLIB_API unsigned int GetNifVersion( string const & file_name );
/*! /*!
* Reads the given file by file name and returns a vector of block references * Reads the given file by file name and returns a vector of block references
...@@ -296,18 +293,28 @@ NIFLIB_HIDDEN Ref<NiObject> CreateObject( string block_type ); ...@@ -296,18 +293,28 @@ NIFLIB_HIDDEN Ref<NiObject> CreateObject( string block_type );
#endif #endif
/*! /*!
* Returns whether the requested version is supported. * Returns whether the requested version is explicitly supported. This does
* \param version The version of the nif format to test for availablity. * not mean that the file will not open, rather it means that we have not
* encountered files with this version in our tests yet.
* \param version The version of the NIF format to test for the support level of.
* \return Whether the requested version is supported. * \return Whether the requested version is supported.
*/ */
NIFLIB_API bool IsVersionSupported(unsigned int ver); NIFLIB_API bool IsSupportedVersion( unsigned int version );
/*!
* Parses a version string and returns the equivalent version as a byte-packed integer.
* \param version The version number of the NIF format to parse in string format.
* \return The version in integer format or VER_INVALID if the version string is not in the correct format.
*/
NIFLIB_API unsigned ParseVersionString( string version );
/*! /*!
* Parses the version string and returns in the equivalent version as integer * Takes a NIF version in byte-packed integer format and returns a formatted human-
* \param version The version of the nif format to parse. * readable string. For example, 0x04000002 returns the string "4.0.0.2"
* \return The version in integer format. Returns VER_INVALID for invalid version strings. * \param version The NIF version in integer form.
* \return The equivalent string representation of the version number.
*/ */
NIFLIB_API unsigned int GetVersion(string version); NIFLIB_API string FormatVersionString( unsigned version );
//--USER GUIDE DOCUMENTATION--// //--USER GUIDE DOCUMENTATION--//
......
...@@ -113,7 +113,7 @@ NiObjectRef FindRoot( vector<NiObjectRef> const & blocks ) { ...@@ -113,7 +113,7 @@ NiObjectRef FindRoot( vector<NiObjectRef> const & blocks ) {
return StaticCast<NiObject>(root); return StaticCast<NiObject>(root);
} }
unsigned int CheckNifHeader( string const & file_name ) { unsigned int GetNifVersion( string const & file_name ) {
//--Open File--// //--Open File--//
ifstream in( file_name.c_str(), ifstream::binary ); ifstream in( file_name.c_str(), ifstream::binary );
...@@ -123,24 +123,18 @@ unsigned int CheckNifHeader( string const & file_name ) { ...@@ -123,24 +123,18 @@ unsigned int CheckNifHeader( string const & file_name ) {
string headerstr(header_string); string headerstr(header_string);
// make sure this is a NIF file // make sure this is a NIF file
if ( ( headerstr.substr(0, 22) != "NetImmerse File Format" ) unsigned ver_start = 0;
&& ( headerstr.substr(0, 20) != "Gamebryo File Format" ) ) if ( headerstr.substr(0, 22) == "NetImmerse File Format" ) {
ver_start = 32;
} else if ( headerstr.substr(0, 20) == "Gamebryo File Format" ) {
ver_start = 30;
} else {
//Not a NIF file
return VER_INVALID; return VER_INVALID;
}
// supported versions //Parse version string and return result.
if ( headerstr == "NetImmerse File Format, Version 4.0.0.2" ) return VER_4_0_0_2; return ParseVersionString( headerstr.substr( ver_start ) );
if ( headerstr == "NetImmerse File Format, Version 4.1.0.12" ) return VER_4_1_0_12;
if ( headerstr == "NetImmerse File Format, Version 4.2.0.2" ) return VER_4_2_0_2;
if ( headerstr == "NetImmerse File Format, Version 4.2.1.0" ) return VER_4_2_1_0;
if ( headerstr == "NetImmerse File Format, Version 4.2.2.0" ) return VER_4_2_2_0;
if ( headerstr == "NetImmerse File Format, Version 10.0.1.0" ) return VER_10_0_1_0;
if ( headerstr == "Gamebryo File Format, Version 10.1.0.0" ) return VER_10_1_0_0;
if ( headerstr == "Gamebryo File Format, Version 10.2.0.0" ) return VER_10_2_0_0;
if ( headerstr == "Gamebryo File Format, Version 20.0.0.4" ) return VER_20_0_0_4;
if ( headerstr == "Gamebryo File Format, Version 20.0.0.5" ) return VER_20_0_0_5;
// anything else: unsupported
return VER_UNSUPPORTED;
} }
//Reads the given file by file name and returns a vector of block references //Reads the given file by file name and returns a vector of block references
...@@ -1009,9 +1003,10 @@ void MergeNifTrees( const Ref<NiNode> & target, const Ref<NiSequenceStreamHelper ...@@ -1009,9 +1003,10 @@ void MergeNifTrees( const Ref<NiNode> & target, const Ref<NiSequenceStreamHelper
} }
bool IsVersionSupported(unsigned int ver) { bool IsSupportedVersion( unsigned int version ) {
switch (ver) switch (version)
{ {
case VER_4_0_0_0:
case VER_4_0_0_2: case VER_4_0_0_2:
case VER_4_1_0_12: case VER_4_1_0_12:
case VER_4_2_0_2: case VER_4_2_0_2:
...@@ -1019,6 +1014,7 @@ bool IsVersionSupported(unsigned int ver) { ...@@ -1019,6 +1014,7 @@ bool IsVersionSupported(unsigned int ver) {
case VER_4_2_2_0: case VER_4_2_2_0:
case VER_10_0_1_0: case VER_10_0_1_0:
case VER_10_1_0_0: case VER_10_1_0_0:
case VER_10_1_0_106:
case VER_10_2_0_0: case VER_10_2_0_0:
case VER_20_0_0_4: case VER_20_0_0_4:
case VER_20_0_0_5: case VER_20_0_0_5:
...@@ -1027,29 +1023,62 @@ bool IsVersionSupported(unsigned int ver) { ...@@ -1027,29 +1023,62 @@ bool IsVersionSupported(unsigned int ver) {
return false; return false;
} }
unsigned int GetVersion(string version){ unsigned int ParseVersionString(string version) {
unsigned int outver = 0;
string::size_type start = 0; unsigned int outver = 0;
for(int offset = 3; offset >= 0 && start < version.length(); --offset) {
string::size_type end = version.find_first_of(".", start); string::size_type start = 0, len, end;
string::size_type len = (end == string.npos) ? end : end-start; for( int offset = 3; offset >= 0 && start < version.length(); --offset ) {
int num = 0; end = version.find_first_of( ".", start );
stringstream sstr(version.substr(start, len));
sstr >> num; if ( end == string.npos ) {
if (num > 0xFF) { len = end;
outver = VER_INVALID; } else {
break; len = end-start;
} }
outver |= (num << (offset * 8));
if (len == string::npos) int num = 0;
break; stringstream sstr( version.substr(start, len) );
start = start + len + 1; sstr >> num;
} if ( num > 0xFF ) {
if (outver == 0) return VER_INVALID;
outver = VER_INVALID; }
return outver; outver |= ( num << (offset * 8) );
if ( len == string::npos ) {
break;
}
start = start + len + 1;
}
if ( outver == 0 ) {
return VER_INVALID;
} else {
return outver;
}
}
string FormatVersionString(unsigned version) {
//Cast the version to an array of 4 bytes
char * byte_ver = (char*)&version;
//Put the version parts into an integer array, reversing their order
int int_ver[4] = { byte_ver[3], byte_ver[2], byte_ver[1], byte_ver[0] };
//Format the version string and return it
stringstream out;
if ( int_ver[0] >= 4 ) {
//Version 4+ is in x.x.x.x format.
out << int_ver[0] << "." << int_ver[1] << "." << int_ver[2] << "." << int_ver[3];
} else {
//Versions before 4 are in x.x format.
out << int_ver[0] << "." << int_ver[1];
}
return out.str();
} }
Ref<NiObject> CloneNifTree( Ref<NiObject> const & root, unsigned version, unsigned user_version ) { Ref<NiObject> CloneNifTree( Ref<NiObject> const & root, unsigned version, unsigned user_version ) {
//Create a string stream to temporarily hold the state-save of this tree //Create a string stream to temporarily hold the state-save of this tree
stringstream tmp; stringstream tmp;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment