public static MobipocketRecord FromBinary(byte[] data, bool isTextRecord, TrailingEntryParser parser) { if (data == null) { throw new ArgumentNullException("data"); } if (isTextRecord && parser == null) { throw new ArgumentException("parser cannot be null if isTextRecord is true"); } var record = new MobipocketRecord { Data = data, IsTextRecord = isTextRecord }; if (isTextRecord) { try { record.TrailingEntries = parser.Parse(data); } catch (Exception e) { throw new Exception("cannot parse trailing entries for record", e); } } return(record); }
/// <summary> /// Parses all text record /// </summary> private IEnumerable <MobipocketRecord> ParseTextMobipocketRecords() { int bytesUsed = 0; var parser = new TrailingEntryParser(Header.TrailingEntries); int previousOverlapSize = 0; //skip first record as header, and process all text records for (int recordIndex = 0; recordIndex < Header.TextRecordCount; recordIndex++) { //get current record var record = _pdb.Records[recordIndex + 1]; //read record var mobiRecord = MobipocketRecord.FromBinary(record.Data, true, parser); //uncompress text mobiRecord.Text = GetRecordText(mobiRecord, previousOverlapSize, ref bytesUsed); //yield record yield return(mobiRecord); //save trailing entries previousOverlapSize = mobiRecord.TrailingEntries.IsMultibyteCharacterOverlapping ? mobiRecord.TrailingEntries.MultibyteCharacterOverlap.Length : 0; } if (bytesUsed != Header.TotalTextLength) { throw new Exception("text length doesn't match used characters"); } }
//--------------------------------------------- // // Private methods // //--------------------------------------------- #region Private methods private IEnumerable <MobipocketRecord> ParseMobipocketRecords() { foreach (var record in ParseTextMobipocketRecords()) { AddResource(MobipocketResourceTypes.Text, record.Text); yield return(record); } for (int index = (int)Header.FirstNonTextRecord; index < _pdb.Records.Count; index++) { var data = _pdb.Records[index].Data; var record = MobipocketRecord.FromBinary(data); yield return(record); if (record.IsFLISRecord) { AddResource(MobipocketResourceTypes.FLIS, data); } else if (record.IsFCISRecord) { AddResource(MobipocketResourceTypes.FCIS, data); } else if (record.IsEOFRecord) { AddResource(MobipocketResourceTypes.EOF, data); } else { try { using (var stream = new MemoryStream(record.Data)) using (var image = Image.FromStream(stream)) { var format = image.RawFormat; if (format.Equals(ImageFormat.Jpeg) || format.Equals(ImageFormat.Gif) || format.Equals(ImageFormat.Bmp)) { AddResource(MobipocketResourceTypes.Image, data); } else { throw new NotSupportedException("image not supported"); } } } catch { AddResource(MobipocketResourceTypes.Binary, data); } } } }
/// <summary> /// Gets string value associated with palm database record using given compression schemes. /// </summary> /// <param name="record"></param> /// <returns></returns> private string GetRecordText(MobipocketRecord record, int previousOverlapSize, ref int bytesUsed) { if (record == null) { throw new ArgumentException("record"); } //resulting data byte[] resultData; //decompress the text switch (Compression) { case MobipocketCompression.NoCompression: { var segment = record.GetDataWithoutTrailingEntries(); resultData = new byte[segment.Count]; Array.Copy(segment.Array, segment.Offset, resultData, 0, segment.Count); break; } case MobipocketCompression.LZ77: resultData = GetLZ77DecodedText(record.GetDataWithoutTrailingEntries()); break; case MobipocketCompression.Huffdic: throw new NotSupportedException("huffdic compression not supported yet"); default: throw new NotSupportedException(); } //adjust bytes used bytesUsed += resultData.Length; //add Multibyte character overlap entry to text if (record.TrailingEntries.IsMultibyteCharacterOverlapping) { //may be not the most proficient method resultData = resultData.Concat(record.TrailingEntries.MultibyteCharacterOverlap).ToArray(); } return(GetSystemEncoding().GetString(resultData, previousOverlapSize, resultData.Length - previousOverlapSize)); }
public static MobipocketRecord FromBinary(byte[] data, bool isTextRecord, TrailingEntryParser parser) { if (data == null) throw new ArgumentNullException("data"); if (isTextRecord && parser == null) throw new ArgumentException("parser cannot be null if isTextRecord is true"); var record = new MobipocketRecord { Data = data, IsTextRecord = isTextRecord }; if (isTextRecord) { try { record.TrailingEntries = parser.Parse(data); } catch (Exception e) { throw new Exception("cannot parse trailing entries for record", e); } } return record; }