kwave  18.07.70
Kwave::RIFFParser Class Reference

#include <RIFFParser.h>

Inheritance diagram for Kwave::RIFFParser:
Inheritance graph
Collaboration diagram for Kwave::RIFFParser:
Collaboration graph

Public Slots

void cancel ()
 

Signals

void action (const QString &name)
 
void progress (int percent)
 

Public Member Functions

 RIFFParser (QIODevice &device, const QStringList &main_chunks, const QStringList &known_subchunks)
 
virtual ~RIFFParser ()
 
bool parse ()
 
bool parse (Kwave::RIFFChunk *parent, quint32 offset, quint32 length)
 
bool isSane ()
 
void dumpStructure ()
 
Kwave::RIFFChunkfindChunk (const QByteArray &path)
 
unsigned int chunkCount (const QByteArray &path)
 
Kwave::RIFFChunkfindMissingChunk (const QByteArray &name)
 
void repair ()
 

Protected Member Functions

QByteArray read4ByteString (qint64 offset)
 
Kwave::RIFFChunk::ChunkType guessType (const QByteArray &name)
 
bool isValidName (const char *name)
 
bool isKnownName (const QByteArray &name)
 
void detectEndianness ()
 
Kwave::RIFFChunkaddChunk (Kwave::RIFFChunk *parent, const QByteArray &name, const QByteArray &format, quint32 length, quint32 phys_offset, quint32 phys_length, Kwave::RIFFChunk::ChunkType type)
 
bool addGarbageChunk (Kwave::RIFFChunk *parent, quint32 offset, quint32 length)
 
bool addEmptyChunk (Kwave::RIFFChunk *parent, const QByteArray &name, quint32 offset)
 
void listAllChunks (Kwave::RIFFChunk &parent, Kwave::RIFFChunkList &list)
 
Kwave::RIFFChunkchunkAt (quint32 offset)
 
QList< quint32 > scanForName (const QByteArray &name, quint32 offset, quint32 length, int progress_start=0, int progress_count=1)
 

Private Member Functions

void collectGarbage ()
 
bool joinGarbageToEmpty ()
 
void fixGarbageEnds ()
 
void discardGarbage (Kwave::RIFFChunk &chunk)
 

Private Attributes

QIODevice & m_dev
 
Kwave::RIFFChunk m_root
 
QStringList m_main_chunk_names
 
QStringList m_sub_chunk_names
 
Kwave::byte_order_t m_endianness
 
bool m_cancel
 

Detailed Description

Definition at line 38 of file RIFFParser.h.

Constructor & Destructor Documentation

◆ RIFFParser()

Kwave::RIFFParser::RIFFParser ( QIODevice &  device,
const QStringList &  main_chunks,
const QStringList &  known_subchunks 
)

Constructor.

Parameters
deviceQIODevice to parse through.
main_chunkslist of known names of main chunks
known_subchunkslist of known subchunks

Definition at line 58 of file RIFFParser.cpp.

References m_root, Kwave::RIFFChunk::Root, and Kwave::RIFFChunk::setType().

61  :m_dev(device),
62  m_root(Q_NULLPTR, "", "", toUint32(device.size()), 0,
63  toUint32(device.size())),
64  m_main_chunk_names(main_chunks), m_sub_chunk_names(known_subchunks),
66 {
68 }
QStringList m_sub_chunk_names
Definition: RIFFParser.h:265
QStringList m_main_chunk_names
Definition: RIFFParser.h:262
void setType(ChunkType type)
Definition: RIFFChunk.h:88
static quint32 toUint32(quint64 x)
Definition: RIFFParser.cpp:52
Kwave::RIFFChunk m_root
Definition: RIFFParser.h:259
Kwave::byte_order_t m_endianness
Definition: RIFFParser.h:268
QIODevice & m_dev
Definition: RIFFParser.h:256
Here is the call graph for this function:

◆ ~RIFFParser()

Kwave::RIFFParser::~RIFFParser ( )
virtual

Destructor

Definition at line 71 of file RIFFParser.cpp.

72 {
73 }

Member Function Documentation

◆ action

void Kwave::RIFFParser::action ( const QString &  name)
signal

emits the name of the currently performed action

Referenced by detectEndianness(), and findMissingChunk().

Here is the caller graph for this function:

◆ addChunk()

Kwave::RIFFChunk * Kwave::RIFFParser::addChunk ( Kwave::RIFFChunk parent,
const QByteArray &  name,
const QByteArray &  format,
quint32  length,
quint32  phys_offset,
quint32  phys_length,
Kwave::RIFFChunk::ChunkType  type 
)
protected

Creates and adds a new chunk. Will be parented to the first non-garbage chunk.

Parameters
parentpointer to the parent node (or null if root node)
namethe 4-byte name of the chunk
formatthe 4-byte format specifier, only valid for main chunks, contains invalid data in sub-chunks
lengthsize of the chunk's data
phys_offsetstart of the chunk name in the source
phys_lengthlength allocated in the source (file)
typechunk type,
See also
RIFFChunk::ChunkType
Returns
pointer to the new created chunk

Definition at line 235 of file RIFFParser.cpp.

References Kwave::RIFFChunk::Garbage, m_root, Kwave::RIFFChunk::parent(), Kwave::RIFFChunk::physStart(), Kwave::RIFFChunk::setType(), Kwave::RIFFChunk::subChunks(), and Kwave::RIFFChunk::type().

Referenced by addEmptyChunk(), addGarbageChunk(), and parse().

240 {
241  // do not add anything to garbage, use the garbage's parent instead
242  while (parent && (parent->type() == Kwave::RIFFChunk::Garbage)) {
243  parent = parent->parent();
244  }
245 
246  // if no parent found, use root
247  if (!parent) {
248  parent = &m_root;
249  }
250  Q_ASSERT(parent);
251 
252  // create a new chunk object
253  Kwave::RIFFChunk *chunk = new Kwave::RIFFChunk(
254  parent, name, format, length, phys_offset, phys_length);
255  Q_ASSERT(chunk);
256  if (!chunk) return Q_NULLPTR;
257  chunk->setType(type);
258 
259  // sort the chunk into the parent, order by physical start
260  Kwave::RIFFChunk *before = Q_NULLPTR;
261  Kwave::RIFFChunkList &chunks = parent->subChunks();
262  foreach (Kwave::RIFFChunk *c, chunks) {
263  if (!c) continue;
264  quint32 pos = c->physStart();
265  if (pos > phys_offset) {
266  before = c;
267  break;
268  }
269  }
270 
271  int index = (before) ? chunks.indexOf(before) : chunks.size();
272  chunks.insert(index, chunk);
273 
274  return chunk;
275 }
quint32 physStart() const
Definition: RIFFChunk.h:135
Kwave::RIFFChunk * parent() const
Definition: RIFFChunk.h:103
const char name[16]
Definition: memcpy.c:510
ChunkType type() const
Definition: RIFFChunk.h:85
void setType(ChunkType type)
Definition: RIFFChunk.h:88
QList< Kwave::RIFFChunk * > RIFFChunkList
Definition: RIFFChunk.h:30
Kwave::RIFFChunkList & subChunks()
Definition: RIFFChunk.h:151
Kwave::RIFFChunk m_root
Definition: RIFFParser.h:259
Here is the call graph for this function:
Here is the caller graph for this function:

◆ addEmptyChunk()

bool Kwave::RIFFParser::addEmptyChunk ( Kwave::RIFFChunk parent,
const QByteArray &  name,
quint32  offset 
)
protected

Adds a chunk with a valid name and no length information.

Parameters
parentpointer to the parent node
namethe valid name of the chunk
offsetstart of the chunk name in the source
Returns
true if creation succeeded, false if out of memory

Definition at line 293 of file RIFFParser.cpp.

References addChunk(), and Kwave::RIFFChunk::Empty.

Referenced by parse().

296 {
297  // create the new chunk first
298  Kwave::RIFFChunk *chunk = addChunk(parent, name, "----", 0, offset,
300  return (chunk);
301 }
const char name[16]
Definition: memcpy.c:510
Kwave::RIFFChunk * addChunk(Kwave::RIFFChunk *parent, const QByteArray &name, const QByteArray &format, quint32 length, quint32 phys_offset, quint32 phys_length, Kwave::RIFFChunk::ChunkType type)
Definition: RIFFParser.cpp:235
Here is the call graph for this function:
Here is the caller graph for this function:

◆ addGarbageChunk()

bool Kwave::RIFFParser::addGarbageChunk ( Kwave::RIFFChunk parent,
quint32  offset,
quint32  length 
)
protected

Adds a chunk that has no valid name and thus is not recognized. It is assumed that it only contains undecodeable garbage without any valid name, length or other header information.

Parameters
parentpointer to the parent node
offsetstart of the chunk name in the source
lengthlength of the garbage area in bytes
Returns
true if creation succeeded, false if out of memory

Definition at line 278 of file RIFFParser.cpp.

References addChunk(), Kwave::RIFFChunk::Garbage, and name.

Referenced by parse().

281 {
282  qDebug("adding garbage chunk at 0x%08X, length=%u",offset,length);
283 
284  // create the new chunk first
285  QByteArray name(16, 0);
286  qsnprintf(name.data(), name.size(), "[0x%08X]", offset);
287  Kwave::RIFFChunk *chunk = addChunk(parent, name, "", length, offset,
288  length, Kwave::RIFFChunk::Garbage);
289  return (chunk);
290 }
const char name[16]
Definition: memcpy.c:510
Kwave::RIFFChunk * addChunk(Kwave::RIFFChunk *parent, const QByteArray &name, const QByteArray &format, quint32 length, quint32 phys_offset, quint32 phys_length, Kwave::RIFFChunk::ChunkType type)
Definition: RIFFParser.cpp:235
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cancel

void Kwave::RIFFParser::cancel ( )
slot

Cancels the current action.

Definition at line 816 of file RIFFParser.cpp.

References m_cancel.

817 {
818  qDebug("RIFFParser: --- cancel ---");
819  m_cancel = true;
820 }

◆ chunkAt()

Kwave::RIFFChunk * Kwave::RIFFParser::chunkAt ( quint32  offset)
protected

Returns a pointer to a chunk that starts at a given offset or zero if none found.

Parameters
offsetthe start position (physical start)
Returns
pointer to the chunk or zero

Definition at line 534 of file RIFFParser.cpp.

References listAllChunks(), m_root, and Kwave::RIFFChunk::physStart().

Referenced by parse().

535 {
537  listAllChunks(m_root, list);
538  foreach (Kwave::RIFFChunk *chunk, list)
539  if (chunk && chunk->physStart() == offset) return chunk;
540  return Q_NULLPTR;
541 }
void listAllChunks(Kwave::RIFFChunk &parent, Kwave::RIFFChunkList &list)
Definition: RIFFParser.cpp:525
quint32 physStart() const
Definition: RIFFChunk.h:135
QList< Kwave::RIFFChunk * > RIFFChunkList
Definition: RIFFChunk.h:30
Kwave::RIFFChunk m_root
Definition: RIFFParser.h:259
Here is the call graph for this function:
Here is the caller graph for this function:

◆ chunkCount()

unsigned int Kwave::RIFFParser::chunkCount ( const QByteArray &  path)

Returns the number of times a chunk is present

Definition at line 463 of file RIFFParser.cpp.

References listAllChunks(), m_root, Kwave::RIFFChunk::name(), and Kwave::RIFFChunk::path().

Referenced by Kwave::WavDecoder::open().

464 {
465  unsigned int count = 0;
466  Kwave::RIFFChunkList chunks;
467  listAllChunks(m_root, chunks);
468 
469  foreach (Kwave::RIFFChunk *chunk, chunks) {
470  if (!chunk) continue;
471  if (path.contains("/")) {
472  // search for full path
473  if (chunk->path() == path) ++count;
474  } else {
475  // search for name only
476  if (chunk->name() == path) ++count;
477  }
478  }
479 
480  return count;
481 }
void listAllChunks(Kwave::RIFFChunk &parent, Kwave::RIFFChunkList &list)
Definition: RIFFParser.cpp:525
const QByteArray path() const
Definition: RIFFChunk.cpp:88
QList< Kwave::RIFFChunk * > RIFFChunkList
Definition: RIFFChunk.h:30
Kwave::RIFFChunk m_root
Definition: RIFFParser.h:259
const QByteArray & name() const
Definition: RIFFChunk.h:91
Here is the call graph for this function:
Here is the caller graph for this function:

◆ collectGarbage()

void Kwave::RIFFParser::collectGarbage ( )
private

clear all main chunks that contain only garbage and convert them into garbage chunks

Definition at line 632 of file RIFFParser.cpp.

References Kwave::RIFFChunk::Garbage, listAllChunks(), m_cancel, m_root, Kwave::RIFFChunk::physEnd(), Kwave::RIFFChunk::physStart(), Kwave::RIFFChunk::setLength(), Kwave::RIFFChunk::setType(), Kwave::RIFFChunk::subChunks(), and Kwave::RIFFChunk::type().

Referenced by repair().

633 {
634  // clear all main chunks that contain only garbage and convert them
635  // into garbage chunks
636  bool start_over;
637  do {
638  start_over = false;
639  Kwave::RIFFChunkList chunks;
640  listAllChunks(m_root, chunks);
641 
642  foreach (Kwave::RIFFChunk *chunk, chunks) {
643  if (!chunk) continue;
644  if (start_over || m_cancel) break;
645 
646  // skip garbage chunks themselfes
647  if (chunk->type() == Kwave::RIFFChunk::Garbage) continue;
648 
649  Kwave::RIFFChunkList &subchunks = chunk->subChunks();
650  bool contains_only_garbage = true;
651  foreach (Kwave::RIFFChunk *sub, subchunks) {
652  if (m_cancel) break;
653  if (sub && (sub->type() != Kwave::RIFFChunk::Garbage)) {
654  contains_only_garbage = false;
655  break;
656  }
657  }
658 
659  if (subchunks.count() && contains_only_garbage) {
660  quint32 start = chunk->physStart();
661  quint32 end = chunk->physEnd();
662 
663  qDebug("chunk at 0x%08X contains only garbage!", start);
664  // -> convert into a garbage chunk !
666  chunk->setLength(end - start + 4 + 1);
667  while (!subchunks.isEmpty()) {
668  Kwave::RIFFChunk *c = subchunks.takeLast();
669  if (c) delete c;
670  }
671  chunks.clear();
672 
673  // start over the scan...
674  start_over = true;
675  break;
676  }
677  }
678  } while (start_over && !m_cancel);
679 }
void listAllChunks(Kwave::RIFFChunk &parent, Kwave::RIFFChunkList &list)
Definition: RIFFParser.cpp:525
quint32 physEnd() const
Definition: RIFFChunk.cpp:79
quint32 physStart() const
Definition: RIFFChunk.h:135
ChunkType type() const
Definition: RIFFChunk.h:85
void setType(ChunkType type)
Definition: RIFFChunk.h:88
QList< Kwave::RIFFChunk * > RIFFChunkList
Definition: RIFFChunk.h:30
Kwave::RIFFChunkList & subChunks()
Definition: RIFFChunk.h:151
Kwave::RIFFChunk m_root
Definition: RIFFParser.h:259
void setLength(quint32 length)
Definition: RIFFChunk.cpp:142
Here is the call graph for this function:
Here is the caller graph for this function:

◆ detectEndianness()

void Kwave::RIFFParser::detectEndianness ( )
protected

Tries to detect the endianness of the source. If successful, the endianness will be set. If failed, will be set to "Unknown".

Definition at line 107 of file RIFFParser.cpp.

References _, action(), Kwave::BigEndian, Kwave::LittleEndian, m_cancel, m_dev, m_endianness, m_main_chunk_names, m_root, m_sub_chunk_names, name, Kwave::RIFFChunk::physLength(), Kwave::RIFFChunk::physStart(), progress(), read4ByteString(), scanForName(), and Kwave::UnknownEndian.

Referenced by parse().

108 {
109  // first try the easy way, works if file is sane
110  QString sane_name = QLatin1String(read4ByteString(0));
111  if (sane_name == _("RIFF")) {
113  return;
114  }
115  if (sane_name == _("RIFX")) {
117  return;
118  }
119 
120  // ok, our file is damaged at least a bit, try to discover
121  emit action(i18n("Detecting endianness (standard search)..."));
122  emit progress(0);
123 
124  QList<quint32> riff_offsets = scanForName("RIFF",
125  m_root.physStart(), m_root.physLength(), 0, 2);
126  if (m_cancel) return;
127 
128  QList<quint32> rifx_offsets = scanForName("RIFX",
129  m_root.physStart(), m_root.physLength(), 1, 2);
130  if (m_cancel) return;
131 
132  // if RIFF found and RIFX not found -> little endian
133  if (riff_offsets.count() && !rifx_offsets.count()) {
134  qDebug("detected little endian format");
136  emit progress(100);
137  return;
138  }
139 
140  // if RIFX found and RIFF not found -> big endian
141  if (rifx_offsets.count() && !riff_offsets.count()) {
142  qDebug("detected big endian format");
144  emit progress(100);
145  return;
146  }
147 
148  // not detectable -> detect by searching all known chunks and
149  // detect best match
150  emit action(i18n("Detecting endianness (statistic search)..."));
151  qDebug("doing statistic search to determine endianness...");
152  unsigned int le_matches = 0;
153  unsigned int be_matches = 0;
154  QStringList names;
155  names += m_main_chunk_names;
156  names += m_sub_chunk_names;
157 
158  // average length should be approx. half of file size
159  double half = (m_dev.size() >> 1);
160 
161  // loop over all chunk names
162  int count = names.count();
163  int index = 0;
164  foreach (QString chunk_name, names) {
165  // scan all offsets where the name matches
166  QByteArray name = chunk_name.toLatin1();
167  QList<quint32> offsets = scanForName(name,
169  index, count);
170  if (m_cancel) return;
171 
172  // loop over all found offsets
173  foreach (quint32 ofs, offsets) {
174  m_dev.seek(ofs + 4);
175 
176  // read length, assuming little endian
177  quint32 len = 0;
178  m_dev.read(reinterpret_cast<char *>(&len), 4);
179  double dist_le = fabs(half - qFromLittleEndian<quint32>(len));
180  double dist_be = fabs(half - qFromBigEndian<quint32>(len));
181 
182  // evaluate distance to average length
183  if (dist_be > dist_le) ++le_matches;
184  if (dist_le > dist_be) ++be_matches;
185  }
186 
187  emit progress(100 * (++index) / count);
188  }
189  qDebug("big endian matches: %u", be_matches);
190  qDebug("little endian matches: %u", le_matches);
191 
192  if (le_matches > be_matches) {
193  qDebug("assuming little endian");
195  } else if (be_matches > le_matches) {
196  qDebug("assuming big endian");
198  } else {
199  // give up :-(
200  qDebug("unable to determine endianness");
202  }
203 
204  emit progress(100);
205 }
QStringList m_sub_chunk_names
Definition: RIFFParser.h:265
QByteArray read4ByteString(qint64 offset)
Definition: RIFFParser.cpp:208
void action(const QString &name)
quint32 physStart() const
Definition: RIFFChunk.h:135
quint32 physLength() const
Definition: RIFFChunk.h:146
QStringList m_main_chunk_names
Definition: RIFFParser.h:262
const char name[16]
Definition: memcpy.c:510
void progress(int percent)
Kwave::RIFFChunk m_root
Definition: RIFFParser.h:259
#define _(m)
Definition: memcpy.c:66
Kwave::byte_order_t m_endianness
Definition: RIFFParser.h:268
QIODevice & m_dev
Definition: RIFFParser.h:256
QList< quint32 > scanForName(const QByteArray &name, quint32 offset, quint32 length, int progress_start=0, int progress_count=1)
Definition: RIFFParser.cpp:484
Here is the call graph for this function:
Here is the caller graph for this function:

◆ discardGarbage()

void Kwave::RIFFParser::discardGarbage ( Kwave::RIFFChunk chunk)
private

Discards all garbage sub-chunks

Definition at line 796 of file RIFFParser.cpp.

References Kwave::RIFFChunk::Garbage, m_cancel, Kwave::RIFFChunk::subChunks(), and Kwave::RIFFChunk::type().

Referenced by repair().

797 {
798  QMutableListIterator<Kwave::RIFFChunk *> it(chunk.subChunks());
799  while (it.hasNext()) {
800  Kwave::RIFFChunk *ch = it.next();
801  if (m_cancel) break;
802  if (!ch) continue;
803  if (ch->type() == Kwave::RIFFChunk::Garbage) {
804  // garbage found -> deleting it
805  it.remove();
806  delete ch;
807  } else {
808  // recursively delete garbage
809  discardGarbage(*ch);
810  }
811  }
812 
813 }
ChunkType type() const
Definition: RIFFChunk.h:85
Kwave::RIFFChunkList & subChunks()
Definition: RIFFChunk.h:151
void discardGarbage(Kwave::RIFFChunk &chunk)
Definition: RIFFParser.cpp:796
Here is the call graph for this function:
Here is the caller graph for this function:

◆ dumpStructure()

void Kwave::RIFFParser::dumpStructure ( )

Dumps the structure of all chunks, useful for debugging.

Definition at line 431 of file RIFFParser.cpp.

References Kwave::RIFFChunk::dumpStructure(), and m_root.

Referenced by Kwave::WavDecoder::open().

432 {
434 }
void dumpStructure()
Definition: RIFFChunk.cpp:203
Kwave::RIFFChunk m_root
Definition: RIFFParser.h:259
Here is the call graph for this function:
Here is the caller graph for this function:

◆ findChunk()

Kwave::RIFFChunk * Kwave::RIFFParser::findChunk ( const QByteArray &  path)

Tries to find a chunk in the tree of parsed chunks, only accepting a full match.

Parameters
paththe full path of the chunk to be searched
Returns
the found chunk or zero if nothing found

Definition at line 443 of file RIFFParser.cpp.

References listAllChunks(), m_root, Kwave::RIFFChunk::name(), and Kwave::RIFFChunk::path().

Referenced by Kwave::WavDecoder::open().

444 {
445  Kwave::RIFFChunkList chunks;
446  listAllChunks(m_root, chunks);
447 
448  foreach (Kwave::RIFFChunk *chunk, chunks) {
449  if (!chunk) continue;
450  if (path.contains("/")) {
451  // search for full path
452  if (chunk->path() == path) return chunk;
453  } else {
454  // search for name only
455  if (chunk->name() == path) return chunk;
456  }
457  }
458 
459  return Q_NULLPTR;
460 }
void listAllChunks(Kwave::RIFFChunk &parent, Kwave::RIFFChunkList &list)
Definition: RIFFParser.cpp:525
const QByteArray path() const
Definition: RIFFChunk.cpp:88
QList< Kwave::RIFFChunk * > RIFFChunkList
Definition: RIFFChunk.h:30
Kwave::RIFFChunk m_root
Definition: RIFFParser.h:259
const QByteArray & name() const
Definition: RIFFChunk.h:91
Here is the call graph for this function:
Here is the caller graph for this function:

◆ findMissingChunk()

Kwave::RIFFChunk * Kwave::RIFFParser::findMissingChunk ( const QByteArray &  name)

Tries very hard to find a missing chunk by stepping through the whole file or source.

Parameters
namethe 4-byte name of the chunk
Returns
the found chunk or zero if nothing found

Definition at line 544 of file RIFFParser.cpp.

References action(), Kwave::RIFFChunk::Garbage, listAllChunks(), m_cancel, m_root, parse(), Kwave::RIFFChunk::physEnd(), Kwave::RIFFChunk::physLength(), Kwave::RIFFChunk::physStart(), progress(), scanForName(), and Kwave::RIFFChunk::type().

Referenced by Kwave::WavDecoder::open().

545 {
546  emit action(i18n("Searching for missing chunk '%1'...",
547  QLatin1String(name)));
548  emit progress(0);
549 
550  bool found_something = false;
551 
552  // first search in all garbage areas
553  Kwave::RIFFChunkList all_chunks;
554  listAllChunks(m_root, all_chunks);
555 
556  int index = 0;
557  int count = all_chunks.count();
558  foreach (Kwave::RIFFChunk *chunk, all_chunks) {
559  if (m_cancel) break;
560  if (!chunk) continue;
561  if (chunk->type() == Kwave::RIFFChunk::Garbage) {
562  // search for the name
563  qDebug("searching in garbage at 0x%08X", chunk->physStart());
564  QList<quint32> offsets = scanForName(name,
565  chunk->physStart(), chunk->physLength(),
566  index, count);
567  if (offsets.count()) found_something = true;
568 
569  // process the results -> convert them into chunks
570  quint32 end = chunk->physEnd();
571  foreach (quint32 pos, offsets) {
572  if (m_cancel) break;
573  quint32 len = end - pos + 1;
574  qDebug("found at [0x%08X...0x%08X] len=%u", pos, end, len);
575  parse(chunk, pos, len);
576  qDebug("-------------------------------");
577  }
578  }
579  ++index;
580  }
581 
582  // not found in garbage? search over the rest of the file"
583  if (!found_something && !m_cancel) {
584  qDebug("brute-force search from 0x%08X to 0x%08X",
585  0, m_root.physEnd());
586  QList<quint32> offsets = scanForName(name, 0, m_root.physLength());
587 
588  // process the results -> convert them into chunks
589  quint32 end = m_root.physEnd();
590  foreach (quint32 pos, offsets) {
591  if (m_cancel) break;
592  quint32 len = end - pos + 1;
593  qDebug("found at [0x%08X...0x%08X] len=%u", pos, end, len);
594  parse(&m_root, pos, len);
595  qDebug("-------------------------------");
596  }
597  }
598 
599  return Q_NULLPTR;
600 }
void listAllChunks(Kwave::RIFFChunk &parent, Kwave::RIFFChunkList &list)
Definition: RIFFParser.cpp:525
void action(const QString &name)
quint32 physEnd() const
Definition: RIFFChunk.cpp:79
quint32 physStart() const
Definition: RIFFChunk.h:135
quint32 physLength() const
Definition: RIFFChunk.h:146
const char name[16]
Definition: memcpy.c:510
ChunkType type() const
Definition: RIFFChunk.h:85
QList< Kwave::RIFFChunk * > RIFFChunkList
Definition: RIFFChunk.h:30
void progress(int percent)
Kwave::RIFFChunk m_root
Definition: RIFFParser.h:259
QList< quint32 > scanForName(const QByteArray &name, quint32 offset, quint32 length, int progress_start=0, int progress_count=1)
Definition: RIFFParser.cpp:484
Here is the call graph for this function:
Here is the caller graph for this function:

◆ fixGarbageEnds()

void Kwave::RIFFParser::fixGarbageEnds ( )
private

fixes the end of garbage chunks to no longer overlap valid chunks

Definition at line 682 of file RIFFParser.cpp.

References Kwave::RIFFChunk::Garbage, Kwave::RIFFChunk::isChildOf(), listAllChunks(), m_cancel, m_root, Kwave::RIFFChunk::name(), Kwave::RIFFChunk::physEnd(), Kwave::RIFFChunk::physStart(), Kwave::RIFFChunk::setLength(), and Kwave::RIFFChunk::type().

Referenced by repair().

683 {
684  qDebug("fixing ends of garbage chunks...");
685 
686  Kwave::RIFFChunkList chunks;
687  listAllChunks(m_root, chunks);
688  QListIterator<Kwave::RIFFChunk *> it1(chunks);
689  QListIterator<Kwave::RIFFChunk *> it2(chunks);
690 
691  // try all combinations of chunks
692  if (it1.hasNext()) it1.next();
693  while (it1.hasNext() && !m_cancel) {
694  Kwave::RIFFChunk *c1 = it1.next();
695  it2 = it1;
696  if (it2.hasNext()) it2.next();
697  while (it2.hasNext() && !m_cancel) {
698  Kwave::RIFFChunk *c2 = it2.next();
699 
700  // children always overlap their parents
701  if (c2->isChildOf(c1)) continue;
702 
703  // get ranges
704  quint32 s1 = c1->physStart();
705  quint32 e1 = c1->physEnd();
706  quint32 s2 = c2->physStart();
707  quint32 e2 = c2->physEnd();
708 
709  // check for overlaps
710  if ((s2 <= e1) && (e2 >= s1)) {
711  qDebug("overlap detected:");
712  qDebug(" at 0x%08X...0x%08X '%s'",
713  s1, e1, c1->name().data());
714  qDebug(" at 0x%08X...0x%08X '%s'",
715  s2, e2, c2->name().data());
716 
717  if ((c1->type() == Kwave::RIFFChunk::Garbage) && (s1 < s2)) {
718  // shorten garbage
719  e1 = s2 - 1;
720  quint32 len = e1 - s1 + 1;
721  qDebug("shortening garbage to %u bytes", len);
722  c1->setLength(len);
723  }
724  }
725  }
726  }
727 
728 }
void listAllChunks(Kwave::RIFFChunk &parent, Kwave::RIFFChunkList &list)
Definition: RIFFParser.cpp:525
quint32 physEnd() const
Definition: RIFFChunk.cpp:79
quint32 physStart() const
Definition: RIFFChunk.h:135
ChunkType type() const
Definition: RIFFChunk.h:85
QList< Kwave::RIFFChunk * > RIFFChunkList
Definition: RIFFChunk.h:30
bool isChildOf(Kwave::RIFFChunk *chunk)
Definition: RIFFChunk.cpp:149
Kwave::RIFFChunk m_root
Definition: RIFFParser.h:259
const QByteArray & name() const
Definition: RIFFChunk.h:91
void setLength(quint32 length)
Definition: RIFFChunk.cpp:142
Here is the call graph for this function:
Here is the caller graph for this function:

◆ guessType()

Kwave::RIFFChunk::ChunkType Kwave::RIFFParser::guessType ( const QByteArray &  name)
protected

Tries to find the chunk name in the list of known main chunk names and returns RIFFChunk::Main if successful. Otherwise returns RIFFChunk::Sub or RIFFChunk::Garbage if the chunk name is not valid.

Parameters
namethe name of the chunk
Returns
RIFFChunk::Main or RIFFChunk::Sub or RIFFChunk::Garbage

Definition at line 91 of file RIFFParser.cpp.

References Kwave::RIFFChunk::Garbage, isValidName(), m_main_chunk_names, Kwave::RIFFChunk::Main, and Kwave::RIFFChunk::Sub.

Referenced by joinGarbageToEmpty(), and parse().

92 {
94  return (m_main_chunk_names.contains(QLatin1String(name))) ?
96 }
bool isValidName(const char *name)
Definition: RIFFParser.cpp:76
QStringList m_main_chunk_names
Definition: RIFFParser.h:262
const char name[16]
Definition: memcpy.c:510
Here is the call graph for this function:
Here is the caller graph for this function:

◆ isKnownName()

bool Kwave::RIFFParser::isKnownName ( const QByteArray &  name)
protected

Returns true if the given chunk name is known as main or sub chunk

Definition at line 99 of file RIFFParser.cpp.

References m_main_chunk_names, and m_sub_chunk_names.

Referenced by joinGarbageToEmpty().

100 {
101  if (m_main_chunk_names.contains(QLatin1String(name))) return true;
102  if (m_sub_chunk_names.contains(QLatin1String(name))) return true;
103  return false;
104 }
QStringList m_sub_chunk_names
Definition: RIFFParser.h:265
QStringList m_main_chunk_names
Definition: RIFFParser.h:262
const char name[16]
Definition: memcpy.c:510
Here is the caller graph for this function:

◆ isSane()

bool Kwave::RIFFParser::isSane ( )

Returns true if the source contains no structural errors and no garbage or empty chunks.

Definition at line 437 of file RIFFParser.cpp.

References Kwave::RIFFChunk::isSane(), and m_root.

Referenced by Kwave::WavDecoder::open().

438 {
439  return m_root.isSane();
440 }
Kwave::RIFFChunk m_root
Definition: RIFFParser.h:259
bool isSane() const
Definition: RIFFChunk.cpp:49
Here is the call graph for this function:
Here is the caller graph for this function:

◆ isValidName()

bool Kwave::RIFFParser::isValidName ( const char *  name)
protected

Returns true if the given chunk name is valid

Definition at line 76 of file RIFFParser.cpp.

Referenced by guessType(), and parse().

77 {
78  int i;
79  for (i=0; i < 4; ++i) {
80  char c = name[i];
81  if ((c >= 'a') && (c <= 'z')) continue;
82  if ((c >= 'A') && (c <= 'Z')) continue;
83  if ((c >= '0') && (c <= '9')) continue;
84  if ((c == ' ') || (c == '(') || (c == ')'))continue;
85  return false;
86  }
87  return true;
88 }
const char name[16]
Definition: memcpy.c:510
Here is the caller graph for this function:

◆ joinGarbageToEmpty()

bool Kwave::RIFFParser::joinGarbageToEmpty ( )
private

joins garbage to previous empty chunks. If a chunk follows a previously empty chunk with an unknown name it will be joined too.

Returns
true if it needs an additional pass

Definition at line 731 of file RIFFParser.cpp.

References Kwave::RIFFChunk::dataLength(), Kwave::RIFFChunk::dataStart(), Kwave::RIFFChunk::Empty, Kwave::RIFFChunk::Garbage, guessType(), isKnownName(), listAllChunks(), m_cancel, m_root, Kwave::RIFFChunk::Main, Kwave::RIFFChunk::name(), Kwave::RIFFChunk::parent(), parse(), Kwave::RIFFChunk::physLength(), Kwave::RIFFChunk::physStart(), read4ByteString(), Kwave::RIFFChunk::setFormat(), Kwave::RIFFChunk::setLength(), Kwave::RIFFChunk::setType(), Kwave::RIFFChunk::subChunks(), and Kwave::RIFFChunk::type().

Referenced by repair().

732 {
733  qDebug("joining garbage to empty chunks (and to garbage)...");
734 
735  Kwave::RIFFChunkList chunks;
736  listAllChunks(m_root, chunks);
737  QMutableListIterator<Kwave::RIFFChunk *> it1(chunks);
738  QMutableListIterator<Kwave::RIFFChunk *> it2(chunks);
739 
740  // join garbage to empty chunks
741  if (it2.hasNext()) it2.next();
742  while (it2.hasNext() && it1.hasNext() && !m_cancel) {
743  Kwave::RIFFChunk *chunk = it1.next();
744  Kwave::RIFFChunk *next = it2.next();
745  if (!chunk || !next) continue;
746  bool join = false;
747 
748  if ( ((chunk->type() == Kwave::RIFFChunk::Empty) ||
749  (chunk->dataLength() == 0)) &&
750  ((next->type() == Kwave::RIFFChunk::Garbage) ||
751  (!isKnownName(next->name())) ) )
752  {
753  // join garbage and unknown stuff to empty
754  join = true;
755  }
756 
757  if ( (chunk->type() == Kwave::RIFFChunk::Garbage) &&
758  (next->type() == Kwave::RIFFChunk::Garbage) )
759  {
760  // join garbage to garbage
761  join = true;
762  }
763 
764  if (join) {
765  if ((next->type() == Kwave::RIFFChunk::Garbage) ||
766  (!isKnownName(next->name())) )
767  {
768  quint32 len = next->physLength() + 4;
769  qDebug("joining garbage to empty chunk '%s' at 0x%08X, %u bytes",
770  chunk->name().data(), chunk->physStart(), len);
771  chunk->setLength(len);
772  chunk->setType(guessType(chunk->name()));
773 
774  // remove the garbage chunk, it's no longer needed
775  it2.remove();
776  if (next->parent())
777  next->parent()->subChunks().removeAll(next);
778  delete next;
779 
780  if (chunk->type() == Kwave::RIFFChunk::Main) {
781  // was joined to a main chunk -> parse again!
782  chunk->setFormat(read4ByteString(chunk->physStart() + 8));
783  parse(chunk, chunk->dataStart(), chunk->dataLength());
784  }
785 
786  // need_one_more_pass !
787  return true;
788  }
789  }
790  }
791 
792  return false;
793 }
QByteArray read4ByteString(qint64 offset)
Definition: RIFFParser.cpp:208
void listAllChunks(Kwave::RIFFChunk &parent, Kwave::RIFFChunkList &list)
Definition: RIFFParser.cpp:525
quint32 physStart() const
Definition: RIFFChunk.h:135
quint32 physLength() const
Definition: RIFFChunk.h:146
Kwave::RIFFChunk * parent() const
Definition: RIFFChunk.h:103
bool isKnownName(const QByteArray &name)
Definition: RIFFParser.cpp:99
quint32 dataStart() const
Definition: RIFFChunk.cpp:130
ChunkType type() const
Definition: RIFFChunk.h:85
void setType(ChunkType type)
Definition: RIFFChunk.h:88
QList< Kwave::RIFFChunk * > RIFFChunkList
Definition: RIFFChunk.h:30
quint32 dataLength() const
Definition: RIFFChunk.cpp:136
Kwave::RIFFChunkList & subChunks()
Definition: RIFFChunk.h:151
Kwave::RIFFChunk m_root
Definition: RIFFParser.h:259
Kwave::RIFFChunk::ChunkType guessType(const QByteArray &name)
Definition: RIFFParser.cpp:91
const QByteArray & name() const
Definition: RIFFChunk.h:91
void setLength(quint32 length)
Definition: RIFFChunk.cpp:142
void setFormat(const QByteArray &format)
Definition: RIFFChunk.h:100
Here is the call graph for this function:
Here is the caller graph for this function:

◆ listAllChunks()

void Kwave::RIFFParser::listAllChunks ( Kwave::RIFFChunk parent,
Kwave::RIFFChunkList list 
)
protected

Recursively creates a "flat" list of all chunks.

Parameters
parentnode to start with
listreceives references to the chunks

Definition at line 525 of file RIFFParser.cpp.

References Kwave::RIFFChunk::subChunks().

Referenced by chunkAt(), chunkCount(), collectGarbage(), findChunk(), findMissingChunk(), fixGarbageEnds(), and joinGarbageToEmpty().

527 {
528  list.append(&parent);
529  foreach (Kwave::RIFFChunk *chunk, parent.subChunks())
530  if (chunk) listAllChunks(*chunk, list);
531 }
void listAllChunks(Kwave::RIFFChunk &parent, Kwave::RIFFChunkList &list)
Definition: RIFFParser.cpp:525
Kwave::RIFFChunkList & subChunks()
Definition: RIFFChunk.h:151
Here is the call graph for this function:
Here is the caller graph for this function:

◆ parse() [1/2]

bool Kwave::RIFFParser::parse ( )

Parses the whole source.

Returns
true if passed without any error

Definition at line 219 of file RIFFParser.cpp.

References detectEndianness(), m_dev, m_endianness, m_root, toUint32(), and Kwave::UnknownEndian.

Referenced by findMissingChunk(), joinGarbageToEmpty(), Kwave::WavDecoder::open(), and parse().

220 {
221  // first of all we have to find out the endianness of our source
223 
224  // not detectable -> no chance of finding anything useful -> give up!
226  qWarning("unable to detect endianness -> giving up!");
227  return false;
228  }
229 
230  // find all primary chunks
231  return parse(&m_root, 0, toUint32(m_dev.size()));
232 }
static quint32 toUint32(quint64 x)
Definition: RIFFParser.cpp:52
Kwave::RIFFChunk m_root
Definition: RIFFParser.h:259
Kwave::byte_order_t m_endianness
Definition: RIFFParser.h:268
QIODevice & m_dev
Definition: RIFFParser.h:256
Here is the call graph for this function:
Here is the caller graph for this function:

◆ parse() [2/2]

bool Kwave::RIFFParser::parse ( Kwave::RIFFChunk parent,
quint32  offset,
quint32  length 
)

Parses a range of the source and adds all found chunks to a list of chunks. Also parses recursively for sub-chunks and builds a tree.

Parameters
parentpointer to the parent node
offsetstart of the chunk name in the source
lengthsize of the area where to search
Returns
true if passed without any error

Definition at line 304 of file RIFFParser.cpp.

References addChunk(), addEmptyChunk(), addGarbageChunk(), chunkAt(), Kwave::RIFFChunk::dataLength(), Kwave::RIFFChunk::dataStart(), guessType(), isValidName(), m_cancel, m_dev, m_endianness, m_root, Kwave::RIFFChunk::Main, Kwave::RIFFChunk::name(), name, parse(), Kwave::RIFFChunk::path(), Kwave::RIFFChunk::physEnd(), Kwave::RIFFChunk::physLength(), read4ByteString(), Kwave::RIFFChunk::setType(), Kwave::RIFFChunk::Sub, Kwave::RIFFChunk::subChunks(), and SYSTEM_ENDIANNES.

306 {
307  bool error = false;
308  Kwave::RIFFChunkList found_chunks;
309 
310  Q_ASSERT(parent);
311  if (m_dev.isSequential()) return false;
312  if (!parent) return false;
313 
314  // be more robust if the file has not correctly padded
315  if (length & 1) length++;
316 
317  do {
318 // qDebug("RIFFParser::parse(offset=0x%08X, length=0x%08X)",
319 // offset, length);
320 
321  // make sure that we are still in the source (file)
322  if (offset >= m_dev.size()) {
323  error = true;
324  break;
325  }
326 
327  // abort search if we passed the same position twice
328  // (this might happen if an intensive search is performed
329  // and one position can be reached in two or more ways)
330  // only exception: the root chunk, this always overlaps
331  // with the first chunk at start of search!
332  Kwave::RIFFChunk *prev = chunkAt(offset);
333  if (prev && (m_root.subChunks().count())) break;
334 
335  // chunks with less than 4 bytes are not possible
336  if (length < 4) {
337  qWarning("chunk with less than 4 bytes at offset 0x%08X, "\
338  "length=%u bytes!", offset, length);
339  // too short stuff is "garbage"
340  addGarbageChunk(parent, offset, length);
341  error = true;
342  break;
343  }
344 
345  m_dev.seek(offset);
346 
347  // get the chunk name
348  QByteArray name = read4ByteString(m_dev.pos());
349 
350  // check if the name really contains only ASCII characters
351  if (!isValidName(name)) {
352  qWarning("invalid chunk name at offset 0x%08X", offset);
353  // unreadable name -> make it a "garbage" chunk
354  qDebug("addGarbageChunk(offset=0x%08X, length=0x%08X)",
355  offset, length);
356  addGarbageChunk(parent, offset, length);
357  error = true;
358  break;
359  }
360 
361  // get the length stored in the chunk itself
362  quint32 len = 0;
363  if (length >= 8) {
364  // length information present
365  m_dev.read(reinterpret_cast<char *>(&len), 4);
366  if (m_endianness != SYSTEM_ENDIANNES) len = qbswap<quint32>(len);
367  }
368  if (len == 0) {
369  // valid name but no length information -> badly truncated
370  // -> make it a zero-length chunk
371  qDebug("empty chunk '%s' at 0x%08X", name.data(), offset);
372  addEmptyChunk(parent, name, offset);
373 
374  if (length > 8) {
375  // there's some garbage behind
376  offset += 8;
377  length -= 8;
378  }
379  error = true;
380  continue;
381  }
382 
383  // read the format if present
384  QByteArray format = read4ByteString(m_dev.pos());
385 
386  // calculate the physical length of the chunk
387  quint32 phys_len = (length - 8 < len) ? (length - 8) : len;
388  if (phys_len & 1) phys_len++;
389 
390  // now create a new chunk, per default type is "sub-chunk"
391 /* qDebug("new chunk, name='%s', len=0x%08X, ofs=0x%08X, "\
392  "phys_len=0x%08X (next=0x%08X)",
393  name.data(),
394  len,offset,phys_len, offset+phys_len+8); */
395  Kwave::RIFFChunk *chunk = addChunk(parent, name, format, len, offset,
396  phys_len, Kwave::RIFFChunk::Sub);
397  if (!chunk) break;
398  found_chunks.append(chunk);
399 
400  // if not at the end of the file, parse all further chunks
401  length -= chunk->physLength() + 8;
402  offset = chunk->physEnd() + 1;
403 // qDebug(" parse loop end: offset=0x%08X, length=0x%08X",offset,length);
404  } while (length && !m_cancel);
405 
406  // parse for sub-chunks in the chunks we newly found
407  foreach (Kwave::RIFFChunk *chunk, found_chunks) {
408  if (!chunk) continue;
409  if ( (guessType(chunk->name()) == Kwave::RIFFChunk::Main) &&
410  (chunk->dataLength() >= 4) )
411  {
413 
414  QByteArray path = (parent ? parent->path() : QByteArray("")) +
415  '/' + chunk->name();
416 /* qDebug("scanning for chunks in '%s' (format='%s'), "\
417  "offset=0x%08X, length=0x%08X",
418  path.data(), chunk->format().data(),
419  chunk->dataStart(), chunk->dataLength());*/
420  if (!parse(chunk, chunk->dataStart(), chunk->dataLength())) {
421  error = true;
422  }
423 
424  }
425  }
426 
427  return (!error && !m_cancel);
428 }
QByteArray read4ByteString(qint64 offset)
Definition: RIFFParser.cpp:208
bool isValidName(const char *name)
Definition: RIFFParser.cpp:76
#define SYSTEM_ENDIANNES
Definition: RIFFParser.cpp:42
quint32 physEnd() const
Definition: RIFFChunk.cpp:79
quint32 physLength() const
Definition: RIFFChunk.h:146
bool addGarbageChunk(Kwave::RIFFChunk *parent, quint32 offset, quint32 length)
Definition: RIFFParser.cpp:278
const QByteArray path() const
Definition: RIFFChunk.cpp:88
Kwave::RIFFChunk * chunkAt(quint32 offset)
Definition: RIFFParser.cpp:534
quint32 dataStart() const
Definition: RIFFChunk.cpp:130
const char name[16]
Definition: memcpy.c:510
void setType(ChunkType type)
Definition: RIFFChunk.h:88
QList< Kwave::RIFFChunk * > RIFFChunkList
Definition: RIFFChunk.h:30
quint32 dataLength() const
Definition: RIFFChunk.cpp:136
Kwave::RIFFChunkList & subChunks()
Definition: RIFFChunk.h:151
Kwave::RIFFChunk m_root
Definition: RIFFParser.h:259
bool addEmptyChunk(Kwave::RIFFChunk *parent, const QByteArray &name, quint32 offset)
Definition: RIFFParser.cpp:293
Kwave::RIFFChunk::ChunkType guessType(const QByteArray &name)
Definition: RIFFParser.cpp:91
const QByteArray & name() const
Definition: RIFFChunk.h:91
Kwave::RIFFChunk * addChunk(Kwave::RIFFChunk *parent, const QByteArray &name, const QByteArray &format, quint32 length, quint32 phys_offset, quint32 phys_length, Kwave::RIFFChunk::ChunkType type)
Definition: RIFFParser.cpp:235
Kwave::byte_order_t m_endianness
Definition: RIFFParser.h:268
QIODevice & m_dev
Definition: RIFFParser.h:256
Here is the call graph for this function:

◆ progress

void Kwave::RIFFParser::progress ( int  percent)
signal

emits a progress in percent

Referenced by detectEndianness(), findMissingChunk(), and scanForName().

Here is the caller graph for this function:

◆ read4ByteString()

QByteArray Kwave::RIFFParser::read4ByteString ( qint64  offset)
protected

Reads a 4-byte string from the source device at a given offset. The current source position will be set to 4 bytes after the given offset afterwards.

Parameters
offsetposition within the source, no range checks!
Returns
string with 4 bytes

Definition at line 208 of file RIFFParser.cpp.

References m_dev.

Referenced by detectEndianness(), joinGarbageToEmpty(), and parse().

209 {
210  char s[5] = {0, 0, 0, 0, 0};
211 
212  m_dev.seek(offset);
213  m_dev.read(&s[0], 4);
214 
215  return QByteArray(s);
216 }
QIODevice & m_dev
Definition: RIFFParser.h:256
Here is the caller graph for this function:

◆ repair()

void Kwave::RIFFParser::repair ( )

Tries to repair the RIFF file by solving inconsistencies

See also
collectGarbage()
joinGarbageToEmpty()
fixGarbageEnds()
discardGarbage()

Definition at line 603 of file RIFFParser.cpp.

References collectGarbage(), discardGarbage(), fixGarbageEnds(), joinGarbageToEmpty(), m_cancel, and m_root.

Referenced by Kwave::WavDecoder::open().

604 {
605  bool one_more_pass = true;
606 
607  while (one_more_pass && !m_cancel) {
608  // crawl in garbage for all known chunks and sub-chunks
609  // crawlInGarbage();
610 
611  // clear all main chunks that contain only garbage and convert them
612  // into garbage chunks. maybe they were only false hits in a previous
613  // search in garbage
614  collectGarbage();
615 
616  // join garbage to empty chunks
617  if (joinGarbageToEmpty()) continue;
618 
619  // resolve overlaps of garbage with other chunks
620  fixGarbageEnds();
621 
622  // throw away all remaining garbage
623  qDebug("discarding garbage...");
625 
626  // done, no more passes needed
627  one_more_pass = false;
628  }
629 }
bool joinGarbageToEmpty()
Definition: RIFFParser.cpp:731
Kwave::RIFFChunk m_root
Definition: RIFFParser.h:259
void discardGarbage(Kwave::RIFFChunk &chunk)
Definition: RIFFParser.cpp:796
Here is the call graph for this function:
Here is the caller graph for this function:

◆ scanForName()

QList< quint32 > Kwave::RIFFParser::scanForName ( const QByteArray &  name,
quint32  offset,
quint32  length,
int  progress_start = 0,
int  progress_count = 1 
)
protected

Performs a scan for a 4-character chunk name over a range of the source. Also emits progress bar info from [(start/count) ... ((start+1)/count-1)]

Parameters
namethe name of the chunk to be found
offsetposition for start of the scan
lengthnumber of bytes to scan
progress_startstart of the progress [0..progress_count-1]
progress_countnumber of progress sections
Returns
list of positions of where the name exists

Definition at line 484 of file RIFFParser.cpp.

References m_cancel, m_dev, and progress().

Referenced by detectEndianness(), and findMissingChunk().

487 {
488  QList<quint32> matches;
489  if (length < 4) return matches;
490  quint32 end = offset + ((length > 4) ? (length - 4) : 0);
491  char buffer[5];
492  memset(buffer, 0x00, sizeof(buffer));
493 
494  m_dev.seek(offset);
495  m_dev.read(&buffer[0], 4);
496 
497  qDebug("scannig for '%s' at [0x%08X...0x%08X] ...", name.data(),
498  offset, end);
499  quint32 pos;
500  int next = 1;
501  for (pos = offset; (pos <= end) && !m_cancel; ++pos) {
502  if (name == buffer) {
503  // found the name
504  matches.append(pos);
505  }
506  // try the next offset
507  buffer[0] = buffer[1];
508  buffer[1] = buffer[2];
509  buffer[2] = buffer[3];
510  m_dev.getChar(&(buffer[3]));
511 
512  // update progress bar
513  if (!--next && progress_count && (end > offset)) {
514  int percent = (((100*progress_start + (100*(pos-offset)) /
515  (end-offset))) / progress_count);
516  emit progress(percent);
517  next = (end-offset)/100;
518  }
519  }
520 
521  return matches;
522 }
const char name[16]
Definition: memcpy.c:510
void progress(int percent)
QIODevice & m_dev
Definition: RIFFParser.h:256
Here is the caller graph for this function:

Member Data Documentation

◆ m_cancel

bool Kwave::RIFFParser::m_cancel
private

can be set to true in order to cancel a running operation

Definition at line 271 of file RIFFParser.h.

Referenced by cancel(), collectGarbage(), detectEndianness(), discardGarbage(), findMissingChunk(), fixGarbageEnds(), joinGarbageToEmpty(), parse(), repair(), and scanForName().

◆ m_dev

QIODevice& Kwave::RIFFParser::m_dev
private

I/O device with the source of the file

Definition at line 256 of file RIFFParser.h.

Referenced by detectEndianness(), parse(), read4ByteString(), and scanForName().

◆ m_endianness

Kwave::byte_order_t Kwave::RIFFParser::m_endianness
private

endianness of the RIFF file, auto-detected

Definition at line 268 of file RIFFParser.h.

Referenced by detectEndianness(), and parse().

◆ m_main_chunk_names

QStringList Kwave::RIFFParser::m_main_chunk_names
private

list of known names of main chunks

Definition at line 262 of file RIFFParser.h.

Referenced by detectEndianness(), guessType(), and isKnownName().

◆ m_root

◆ m_sub_chunk_names

QStringList Kwave::RIFFParser::m_sub_chunk_names
private

list of known names of sub chunks

Definition at line 265 of file RIFFParser.h.

Referenced by detectEndianness(), and isKnownName().


The documentation for this class was generated from the following files: