CLabel.C
//-----------------------------------------------------------------------------
// $Header: /tmp_mnt/asis/offline/ceres/cool/project/RCS/CLabel.C,v 2.1 1996/10/04 08:42:57 voigt Exp $
//
// COOL Program Library
// Copyright (C) CERES collaboration, 1996
//
// Implementation of class CLabel.
//
//-----------------------------------------------------------------------------
#include "CLabel.h"
#include <string.h>
#include <iomanip.h>
#include "CDataStream.h"
CLabel::CLabel()
{
id = 0;
length = 0;
size = 0;
data = 0;
swapped = False;
asciiReverted = False;
name = "";
}
CLabel::CLabel(const CLabel& label)
{
id = label.id;
length = label.length;
size = label.size;
name = label.name;
swapped = label.swapped;
asciiReverted = label.asciiReverted;
if (label.size > 0) {
data = new CWord[label.size];
memcpy(data, label.data, label.size*sizeof(CWord));
}
else
data = 0;
}
CLabel& CLabel::operator= (const CLabel& label)
{
if (this == &label) // same class object
return *this;
else {
if (size > 0) delete [] data; // free old store
id = label.id;
length = label.length;
size = label.size;
name = label.name;
swapped = label.swapped;
asciiReverted = label.asciiReverted;
if (label.size > 0) {
data = new CWord[label.size];
memcpy(data, label.data, label.size*sizeof(CWord));
}
else
data = 0;
return *this;
}
}
int CLabel::operator== (const CLabel& label) const
{
return (label.id == id);
}
CLabel::~CLabel()
{
delete [] data;
}
void CLabel::swap()
{
for (int i=0; i<size; i++)
data[i] = (data[i] << 16 | data[i] >> 16);
swapped = swapped ? False : True;
}
void CLabel::list(ostream& ost)
{
ost << setw(10) << dec << name << setw(10) << id
<< setw(10) << length << setw(10) << size << endl;
}
void CLabel::dump(ostream& ost, int nWordsToDump)
{
//
// Header line
//
ost << "label: " << name << " (" << dec << id << "), ";
ost << (swapped ? "swapped" : "not swapped") << endl;
ost << "total length: " << dec << length << " words";
ost << ", data size: " << dec << size << " words" << endl;
//
// Hex dump
//
unsigned long *ldata = (unsigned long *) &data[0];
int nWords;
nWords = (nWordsToDump == -1 ? size : nWordsToDump);
for (int i=0; i<nWords; i++) {
if (i%8 == 0)
ost << hex << setw(8) << setfill('0') << i*2 << ":\t";
ost << ' ' << hex << setw(8) << setfill('0') << ldata[i];
if (i%8 == 7 || i == nWords-1)
ost << dec << endl;
}
}
void CLabel::revertAsciiData()
{
#ifdef ARCH_IS_LITTLE_ENDIAN
// On architectures using the little-endian byte-ordering,
// the interpretation of characters needs special treatment.
// To be interpreted correctly, all character's need to be
// re-ordered in their original sequence. Hence:
int index=0;
unsigned long *pbuf = data;
for (index=0; index<size; index++) {
reverse4Bytes((char *) pbuf);
pbuf++;
}
// now we ARE back to Big-Endian format of the buffer ...
asciiReverted = asciiReverted ? False : True; // flag it...
#endif
}
void CLabel::read(Cifstream& ist)
{
//
// Init data member
//
id = 0;
delete [] data;
data = 0;
length = 0;
size = 0;
name = "";
if (ist.eof() || ist.bad()) return; // nothing to read
//
// Read label header
//
CWord magic;
ist.read((char*) &length, sizeof(CWord));
ist.read((char*) &magic, sizeof(CWord));
//
// Check for magic word and read label identifiers.
// If the magic word isn't at the expected position
// an iterative search is started until it is found
// or an EoF or corrupted istream state is detected.
//
if (magic != MagicWord) {
while (ist.good() && !ist.eof() && magic != MagicWord) {
length = (int) magic;
ist.read((char*) &magic, sizeof(CWord));
}
if (ist.bad() || ist.eof()) {
length = 0;
return;
}
}
char text[sizeof(CWord)];
ist.read((char*) &id, sizeof(CWord));
ist.read(text, sizeof(CWord));
#ifdef ARCH_IS_LITTLE_ENDIAN
reverse4Bytes(text); // character strings need to be re-ordered...
#endif
name = CString(text,sizeof(CWord));
//
// Store label data in newly allocated memory
//
if (length-4 > 0) {
data = new CWord[length-4];
if (data == 0) {
cerr << "CLabel::read():\n";
cerr << "\tERROR\n";
cerr << "\tFailed allocating " << length-4 << " long words to hold data.\n";
return;
}
ist.read((char*) &data[0], (length-4)*sizeof(CWord));
size = ist.gcount()/sizeof(CWord);
if (size != length-4) {
cerr << "CLabel::read():\n";
cerr << "\tERROR\n";
cerr << "\tExtracted less data words than noted in label header.\n";
cerr << "\t" << length-4 << " words expected, ";
cerr << size << " words read.\n";
}
}
//
// Check status of input stream
//
if (ist.bad()) {
cerr << "CLabel::read():\n";
cerr << "\tERROR\n";
cerr << "\tFailed reading complete label from input stream.\n";
cerr << "\tist.bad()=" << dec << ist.bad();
cerr << ", ist.rdstate()=" << dec << ist.rdstate() << endl;
}
}
void CLabel::write(Cofstream& ost)
{
if (!ost || ost.bad()) return; // no valid ostream
//
// Write label header
//
CWord realLength = size+4;
ost.write((char*) &realLength, sizeof(CWord));
#ifdef ARCH_IS_LITTLE_ENDIAN
char *pname = new char[sizeof(CWord)];
// here we need to copy in order to ensure integrity
// since the buffer IS modified after all
strncpy(pname, (const char*) &MagicWord, sizeof(CWord));
ost.write(pname, sizeof(CWord));
#else
ost.write((char*) &MagicWord, sizeof(CWord));
#endif
ost.write((char*) &id, sizeof(CWord));
#ifdef ARCH_IS_LITTLE_ENDIAN
// here we need to copy in order to ensure integrity
// since the buffer IS modified after all
strncpy(pname, name.data(), sizeof(CWord));
ost.write(pname, sizeof(CWord));
delete [] pname;
#else
ost.write((char*) name.data(), sizeof(CWord));
#endif
//
// Check if data are swapped or reverted
// If swapped/reverted undo this before writing, but redo afterwards.
//
CBoolean wasSwapped = swapped;
if (swapped) this->swap();
CBoolean wasReverted = asciiReverted;
if (asciiReverted) this->revertAsciiData();
//
// Write data
//
ost.write((char*) data, size*sizeof(CWord));
if (wasSwapped) this->swap(); // back to previous state
if (wasReverted) this->revertAsciiData(); // back to previous state
}