using System;
using System.Collections.Generic;
using System.IO;
using static BurnOutSharp.Builder.Extensions;
namespace BurnOutSharp.Wrappers
{
public abstract class WrapperBase
{
#region Instance Variables
///
/// Source of the original data
///
protected DataSource _dataSource = DataSource.UNKNOWN;
///
/// Source byte array data
///
/// This is only populated if is
protected byte[] _byteArrayData = null;
///
/// Source byte array data offset
///
/// This is only populated if is
protected int _byteArrayOffset = -1;
///
/// Source Stream data
///
/// This is only populated if is
protected Stream _streamData = null;
#endregion
#region Data
///
/// Validate the backing data source
///
/// True if the data source is valid, false otherwise
protected bool DataSourceIsValid()
{
switch (_dataSource)
{
// Byte array data requires both a valid array and offset
case DataSource.ByteArray:
return _byteArrayData != null && _byteArrayOffset >= 0;
// Stream data requires both a valid stream
case DataSource.Stream:
return _streamData != null && _streamData.CanRead && _streamData.CanSeek;
// Everything else is invalid
case DataSource.UNKNOWN:
default:
return false;
}
}
///
/// Check if a data segment is valid in the data source
///
/// Position in the source
/// Length of the data to check
/// True if the positional data is valid, false otherwise
protected bool SegmentValid(int position, int length)
{
// Validate the data souece
if (!DataSourceIsValid())
return false;
switch (_dataSource)
{
case DataSource.ByteArray:
return _byteArrayOffset + position + length <= _byteArrayData.Length;
case DataSource.Stream:
return position + length <= _streamData.Length;
// Everything else is invalid
case DataSource.UNKNOWN:
default:
return false;
}
}
///
/// Read data from the source
///
/// Position in the source to read from
/// Length of the requested data
/// Byte array containing the requested data, null on error
protected byte[] ReadFromDataSource(int position, int length)
{
// Validate the data source
if (!DataSourceIsValid())
return null;
// Validate the requested segment
if (!SegmentValid(position, length))
return null;
// Read and return the data
byte[] sectionData = null;
switch (_dataSource)
{
case DataSource.ByteArray:
sectionData = new byte[length];
Array.Copy(_byteArrayData, _byteArrayOffset + position, sectionData, 0, length);
break;
case DataSource.Stream:
long currentLocation = _streamData.Position;
_streamData.Seek(position, SeekOrigin.Begin);
sectionData = _streamData.ReadBytes(length);
_streamData.Seek(currentLocation, SeekOrigin.Begin);
break;
}
return sectionData;
}
///
/// Read string data from the source
///
/// Position in the source to read from
/// Length of the requested data
/// String list containing the requested data, null on error
protected List ReadStringsFromDataSource(int position, int length)
{
// Read the data as a byte array first
byte[] sourceData = ReadFromDataSource(position, length);
if (sourceData == null)
return null;
// TODO: Complete implementation of string finding
return null;
}
///
/// Get the ending offset of the source
///
/// Value greater than 0 for a valid end of file, -1 on error
protected int GetEndOfFile()
{
// Validate the data souece
if (!DataSourceIsValid())
return -1;
// Return the effective endpoint
switch (_dataSource)
{
case DataSource.ByteArray:
return _byteArrayData.Length - _byteArrayOffset;
case DataSource.Stream:
return (int)_streamData.Length;
case DataSource.UNKNOWN:
default:
return -1;
}
}
#endregion
#region Printing
///
/// Pretty print the Executable information
///
public abstract void Print();
#endregion
}
}