bool IniReader::Parse() { FILE* f = OpenGameFile(m_filename, "r"); if(f == NULL) return false; bool res = true; enum ParseState { S_DEFAULT, S_IGNORERESTLINE, S_PROPNAME, S_PROPVALUE, S_SECTION }; ParseState state = S_DEFAULT; std::string propname; std::string section; std::string value; while(!feof(f) && !ferror(f)) { unsigned char c = 0; if(fread(&c, 1, 1, f) == 0) break; if(c == '\r') continue; // ignore this switch(state) { case S_DEFAULT: if(c >= 128) break; // just ignore unicode-stuff when we are in this state (UTF8 bytes at beginning are also handled by this) else if(isspace(c)) break; // ignore spaces and newlines else if(c == '#') { state = S_IGNORERESTLINE; /* this is a comment */ break; } else if(c == '[') { state = S_SECTION; section = ""; break; } else if(c == '=') { warnings << "WARNING: \"=\" is not allowed as the first character in a line of " << m_filename << endl; break; /* ignore */ } else { state = S_PROPNAME; propname = c; break; } case S_SECTION: if(c == ']') { if( ! OnNewSection(section) ) { res = false; goto parseCleanup; } state = S_DEFAULT; NewSection(section); break; } else if(c == '\n') { warnings << "WARNING: section-name \"" << section << "\" of " << m_filename << " is not closed correctly" << endl; state = S_DEFAULT; break; } else if(isspace(c)) { warnings << "WARNING: section-name \"" << section << "\" of " << m_filename << " contains a space" << endl; break; /* ignore */ } else { section += c; break; } case S_PROPNAME: if(c == '\n') { warnings << "WARNING: property \"" << propname << "\" of " << m_filename << " incomplete" << endl; state = S_DEFAULT; break; } else if(isspace(c)) break; // just ignore spaces else if(c == '=') { state = S_PROPVALUE; value = ""; break; } else { propname += c; break; } case S_PROPVALUE: if(c == '\n' || c == '#') { if( ! OnEntry(section, propname, value) ) { res = false; goto parseCleanup; } NewEntryInSection(propname, value); if(c == '#') state = S_IGNORERESTLINE; else state = S_DEFAULT; break; } else if(isspace(c) && value == "") break; // ignore heading spaces else { value += c; break; } case S_IGNORERESTLINE: if(c == '\n') state = S_DEFAULT; break; // ignore everything } } // In case the endline is missing at the end of file, finish the parsing of the last line if (state == S_PROPVALUE) { if( ! OnEntry(section, propname, value) ) { res = false; goto parseCleanup; } NewEntryInSection(propname, value); } // DEBUG: dump the file /*notes << "Dump of " << m_filename << endl; for (SectionMap::iterator it = m_sections.begin(); it != m_sections.end(); ++it) { notes << "[" << it->first << "]" << endl; for (Section::iterator k = it->second.begin(); k != it->second.end(); ++k) notes << k->first << "=" << k->second << endl; notes << endl; } notes << endl;*/ parseCleanup: fclose(f); return res; }
void CSectionDecoder::OnTsPacket(CTsHeader& header, byte* tsPacket) { try { if (header.TransportError) { m_section.Reset(); // Will force us to wait for new PayloadUnitStart return; } if (m_pid >= 0x1fff) return; if (header.Pid != m_pid) return; if (!header.HasPayload) return; int start = header.PayLoadStart; int pointer_field = 0; if (header.PayloadUnitStart) { if (start >= 188) return; pointer_field = start + tsPacket[start] + 1; if (m_section.BufferPos == 0) start += tsPacket[start] + 1; else start++; } int numloops = 0; while (start < 188) { numloops++; if (m_section.BufferPos == 0) { if (!header.PayloadUnitStart) return; if (tsPacket[start] == 0xFF) return; int section_length = SnapshotSectionLength(tsPacket, start); start = StartNewSection(tsPacket, start, section_length); } else { if (m_section.section_length == -1) m_section.CalcSectionLength(tsPacket, start); if (m_section.section_length == 0) { if (m_bLog) XBMC->Log(LOG_DEBUG, "!!! CSectionDecoder::OnTsPacket got a section with section length: 0 on pid: 0x%X tableid: 0x%X bufferpos: %d start: %d - Discarding whole packet.", header.Pid, m_section.Data[0], m_section.BufferPos, start); m_section.Reset(); return; } int len = m_section.section_length - m_section.BufferPos; if (pointer_field != 0 && ((start + len) > pointer_field)) { // We have an incomplete section here len = pointer_field - start; start = AppendSection(tsPacket, start, len); m_section.section_length = m_section.BufferPos - 1; start = pointer_field; } else start = AppendSection(tsPacket, start, len); } if (m_section.SectionComplete() && m_section.section_length > 0) { uint32_t crc = 0; // Only long syntax (section_syntax_indicator == 1) has a CRC // Short syntax may have CRC e.g. TOT, but that is part of the specific section if (m_section.section_syntax_indicator == 1) crc = crc32((char*)m_section.Data, m_section.section_length + 3); if (crc == 0 || (m_bCrcCheck == false)) { OnNewSection(m_section); if (m_pCallback != NULL) m_pCallback->OnNewSection(header.Pid, m_section.table_id, m_section); } else { // If the section is complete and the CRC fails, then this section is crap! m_section.Reset(); return; } m_section.Reset(); } pointer_field = 0; if (numloops > 100) { XBMC->Log(LOG_DEBUG, "!!! CSectionDecoder::OnTsPacket Entered infinite loop. pid: %X start: %d BufferPos: %d SectionLength: %d - Discarding section and moving to next packet", header.Pid, start, m_section.BufferPos, m_section.section_length); m_section.Reset(); return; } } } catch (...) { XBMC->Log(LOG_DEBUG, "exception in CSectionDecoder::OnTsPacket"); } }