圧縮RTF その2
圧縮RTFの続きです。先回の記事はこちら。
先回説明した伸張アルゴリズムをObjectiv-Cでコーディング作ってみました。c++の書き方で書いているので,拡張子をmmにする必要があります。
/** * Compressed-RTFを伸張する */ - (NSString*) decompressRTF: (NSData*) data { @try { DICTIONARY dic = { "{\\rtf1\\ansi\\mac\\deff0\\deftab720{\\fonttbl;}{\\f0\\fnil \\froman \\fswiss \\fmodern \\fscript \\fdecor MS Sans SerifSymbolArialTimes New RomanCourier{\\colortbl\\red0\\green0\\blue0\r\n\\par \\pard\\plain\\f0\\fs20\\b\\i\\u\\tab\\tx", 207, 0, NO }; NSMutableString* expandedString = [[NSMutableString alloc] init]; NSInteger compSize = 0; // 圧縮データ量 [data getBytes:&compSize range: NSMakeRange(0, 4)]; NSInteger rawSize = 0; // 元データ量 [data getBytes:&rawSize range: NSMakeRange(4, 4)]; NSInteger pos = 16; // 最初の16バイトはヘッダなので,初期値として16を設定 while (pos < [data length]) { int control = 0; [data getBytes:&control range:NSMakeRange(pos++, 1)]; // 1バイト読み込んで,次の位置へ control = control & 0xff; //NSLog(@"control : %x", control); // dataからrunLength分を切り出す for (NSInteger i = 0; i < 8; i++) { // controlビット分だけループする unsigned char word[] = {0,0}; if ((control & 0x01) != 0) { // 最下位ビットが1 [data getBytes:&word range:NSMakeRange(pos, 2)]; pos += 2; NSInteger offset = (word[0] & 0xff) * 16 + (word[1] & 0xff) / 16; // ビックエンディアンで上位の12ビットがディクショナリのオフセット NSInteger length = (word[1] & 0x0f) + 2; // ビックエンディアンで下位4ビットが長さ?2。?2されているので実際の長さは+2する必要あり //NSLog(@"length %d offset %d <-> writePos %d", length, offset, dic.writePos); // offset が dictionaryへの書き込み位置と等しい場合は終了 if (offset == dic.writePos) { pos = [data length]; break; } // dictionaryから指定した範囲の文字列を取ってくる。 while (length > 0) { NSString* work = nil; if (offset + length <= dic.writePos || dic.round) { // 取り出す範囲がdictionaryの範囲内 work = [self readFromDictionay: &dic offset: offset length: length]; length = 0; } else { // 取り出す範囲がdictionaryに存在するデータの範囲を越えている場合 NSInteger workLength = dic.writePos - offset; work = [self readFromDictionay: &dic offset: offset length: workLength]; offset += workLength; length -= workLength; } // dictionary配列に文字列を追加する [self appendToDictionary: &dic string: work]; [expandedString appendString: work]; work = nil; } } else { // 最下位ビットが0 [data getBytes:&word range:NSMakeRange(pos++, 1)]; // 文字リテラル NSString* work = [NSString stringWithFormat:@"%c", word[0]]; // dictionaryに追加 [self appendToDictionary: &dic string: work]; [expandedString appendString: work]; } control /= 2 ; } if ([expandedString length] >= rawSize) { break; } } //NSLog(@"%@", expandedString); return expandedString; } @catch (NSException *exception) { return nil; } } /* * Dictionaryに指定した文字列を書き込む。 * Dictionaryは4096バイトのCircular bufferなので,そのことを考慮して書き込む必要がある。 */ - (void) appendToDictionary: (DICTIONARY*) dic string: (NSString*) str { const char* cp = [str UTF8String]; int length = [str lengthOfBytesUsingEncoding: NSUTF8StringEncoding]; for (int i = 0; i < length; i++) { dic->dictionary[dic->writePos] = cp[i]; dic->writePos++; if (dic->round == NO && dic->writePos > 0xfff) { dic->round = YES; } dic->writePos = (dic->writePos & 0xfff); } } /* * Dictionaryから指定した文字列を取り出す。 * Dictionaryは4096バイトのCircular bufferなので,そのことを考慮して取り出す必要がある。 */ -(NSString*) readFromDictionay:(DICTIONARY*) dic offset:(NSInteger) offset length:(NSInteger) length { char* subArray = new char[length + 1]; memset(subArray, 0, length + 1); for (NSInteger i = 0; i < length; i++) { subArray[i] = dic->dictionary[(offset + i) & 0xfff]; } NSString* work = [NSString stringWithCString: subArray encoding:NSUTF8StringEncoding]; delete[] subArray; return work; }
NSDataオブジェクトに圧縮されたデータを格納して decompressRTF に渡してやれば,伸張できます。 バグなどお気づきの方は,コメントでお知らせいただけると助かります。
よろしくお願いいたします。
| 固定リンク
この記事へのコメントは終了しました。
コメント
スーパーコピー時計(N級品)激安通販専門店
世界一流のスーパーコピーブランド時計の卸売と小売を行っております。
業界でも高い知名度と好評度を持っております。
弊社は進んでいる生産設備成熟な技術と研究部門を持っており、コピー時計のパーツは直接にメーカーから買い、それを組み合わせます。
主な取り扱いブランド:ロレックス時計コピー,パネライ時計コピー,ウブロ時計コピー,ブライトリング時計コピー,IWC時計コピー,
フランクミュラー時計コピー,カルティエ時計コピー,ベル&ロス時計コピー,オメガ時計コピー,ショパール時計コピー,コルム時計コピー,
パテックフィリップ時計コピー,ヴァシュロンコンスタンタン時計コピー,オーデマピゲ時計コピー,ブルカリ時計コピー品を扱っております。
他にも各種ブランドのスーパーコピー品多数、取り扱っております。
以上 宜しくお願い致します。(^0^)
広大な客を歓迎して買います!── (*^-^*)
■ホームページ上でのご注文は24時間受け付けております
投稿: ロレックススーパーコピー | 2020年4月 6日 23:16