222 lines
5.7 KiB
C++

/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** 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, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: BitFlagsIO.h /////////////////////////////////////////////////////////////////////////////
// Author: Steven Johnson, March 2002
// Desc:
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __BitFlagsIO_H_
#define __BitFlagsIO_H_
#include "Common/BitFlags.h"
#include "Common/INI.h"
#include "Common/Xfer.h"
//-------------------------------------------------------------------------------------------------
/*
template <size_t NUMBITS>
void BitFlags<NUMBITS>::buildDescription( AsciiString* str ) const
{
if ( str == NULL )
return;//sanity
for( Int i = 0; i < size(); ++i )
{
const char* bitName = getBitNameIfSet(i);
if (bitName != NULL)
{
str->concat( bitName );
str->concat( ",\n");
}
}
}
*/
//-------------------------------------------------------------------------------------------------
template <size_t NUMBITS>
void BitFlags<NUMBITS>::parse(INI* ini, AsciiString* str)
{
// m_bits.reset();
if (str)
str->clear();
Bool foundNormal = false;
Bool foundAddOrSub = false;
// loop through all tokens
for (const char *token = ini->getNextTokenOrNull(); token != NULL; token = ini->getNextTokenOrNull())
{
if (str)
{
if (str->isNotEmpty())
str->concat(" ");
str->concat(token);
}
if (stricmp(token, "NONE") == 0)
{
if (foundNormal || foundAddOrSub)
{
DEBUG_CRASH(("you may not mix normal and +- ops in bitstring lists"));
throw INI_INVALID_NAME_LIST;
}
clear();
break;
}
if (token[0] == '+')
{
if (foundNormal)
{
DEBUG_CRASH(("you may not mix normal and +- ops in bitstring lists"));
throw INI_INVALID_NAME_LIST;
}
Int bitIndex = INI::scanIndexList(token+1, s_bitNameList); // this throws if the token is not found
set(bitIndex, 1);
foundAddOrSub = true;
}
else if (token[0] == '-')
{
if (foundNormal)
{
DEBUG_CRASH(("you may not mix normal and +- ops in bitstring lists"));
throw INI_INVALID_NAME_LIST;
}
Int bitIndex = INI::scanIndexList(token+1, s_bitNameList); // this throws if the token is not found
set(bitIndex, 0);
foundAddOrSub = true;
}
else
{
if (foundAddOrSub)
{
DEBUG_CRASH(("you may not mix normal and +- ops in bitstring lists"));
throw INI_INVALID_NAME_LIST;
}
if (!foundNormal)
clear();
Int bitIndex = INI::scanIndexList(token, s_bitNameList); // this throws if the token is not found
set(bitIndex, 1);
foundNormal = true;
}
}
}
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
template <size_t NUMBITS>
/*static*/ void BitFlags<NUMBITS>::parseFromINI(INI* ini, void* /*instance*/, void *store, const void* /*userData*/)
{
((BitFlags*)store)->parse(ini, NULL);
}
//-------------------------------------------------------------------------------------------------
/** Xfer method
* Version Info:
* 1: Initial version */
//-------------------------------------------------------------------------------------------------
template <size_t NUMBITS>
void BitFlags<NUMBITS>::xfer(Xfer* xfer)
{
// this deserves a version number
XferVersion currentVersion = 1;
XferVersion version = currentVersion;
xfer->xferVersion( &version, currentVersion );
if( xfer->getXferMode() == XFER_SAVE )
{
// save how many entries are to follow
Int c = count();
xfer->xferInt( &c );
// save each of the string data
for( Int i = 0; i < size(); ++i )
{
const char* bitName = getBitNameIfSet(i);
// ignore if this kindof is not set in our mask data
if (bitName == NULL)
continue;
// this bit is set, write the string value
AsciiString bitNameA = bitName;
xfer->xferAsciiString( &bitNameA );
} // end for i
} // end if, save
else if( xfer->getXferMode() == XFER_LOAD )
{
// clear the kind of mask data
clear();
// read how many entries follow
Int c;
xfer->xferInt( &c );
// read each of the string entries
AsciiString string;
for( Int i = 0; i < c; ++i )
{
// read ascii string
xfer->xferAsciiString( &string );
// set in our mask type data
Bool valid = setBitByName( string.str() );
if (!valid)
{
DEBUG_CRASH(("invalid bit name %s",string.str()));
throw XFER_READ_ERROR;
}
} // end for, i
} // end else if, load
else if( xfer->getXferMode() == XFER_CRC )
{
// just call the xfer implementation on the data values
xfer->xferUser( this, sizeof( this ) );
} // end else if, crc
else
{
DEBUG_CRASH(( "BitFlagsXfer - Unknown xfer mode '%d'\n", xfer->getXferMode() ));
throw XFER_MODE_UNKNOWN;
} // end else
} // end xfer
#endif