Javaの移植方法について

画像



むかしむかし...どれくらい? 昨日! (C)、つまり数年前、私はJavaから.NETにささやかなライブラリを移植しました。 .NETだけでなく、バ​​ージョン1.1でも。



アプローチは知られています-Sharpenをあなたの歯(または2003年のビジュアルスタジオのコンバーター、何か好きな人)で、ジグソーパズルで取ります。



イテレータ、構造(「 System.Drawing.Sizeはオブジェクトではありません」)、およびスレッドについては説明しません-banality。 しかし、いくつかの驚きについて-ようこそ。







文化文化、あなたを発明したのは誰ですか?



画像

シードについては、最も単純なものから始めましょう。 数字の文字列への変換、またはその逆。



CultureInfo oldCulture = CurrentThread.CurrentCulture; CultureInfo oldCultureUI = CurrentThread.CurrentUICulture; CurrentThread.CurrentCulture = new CultureInfo("en-US"); CurrentThread.CurrentUICulture = CurrentThread.CurrentCulture; try { render_impl(); } finally { CurrentThread.CurrentCulture = oldCulture; CurrentThread.CurrentUICulture = oldCultureUI; }
      
      







まあ、なぜこの松葉杖?



そして、間違って100,500回書くのはなぜですか。 だから、書かないように



 (float) System.Double.Parse(foo_string, NumberStyles.Float, new CultureInfo("en-US"));
      
      



そして

 new Double(foo_number).ToString(new CultureInfo("en-US"));
      
      





著者は怠zyな犬と寄生虫ですか? オトジ。 そして、あなたは何を望んでいました-締め切りは一週間であり、喜びが来ました



 find ~/pd4ml/sources -type f -print | xargs cat | wc -l 420242
      
      







なぜこのハックが必要なのですか? PDFを生成する必要があり、acrobatリーダーは何とか小数部分と整数部分の区切り記号の形式で国のコンマを尊重しません。 はい、そしてHTML / CSSでは、同じローカル特異性が何らかの形で根を下ろしませんでした、hehe。



建築におけるパラノイアの特徴



画像

内部の元のライブラリには 、明白な方法で構築されたneonkが含まれています 。 さまざまなファイルを配布し、プリンターで印刷して画面に表示する必要がある場合、 java.awt.Graphics2Dが継承され、 PDFDeviceRTFDeviceなどの束があります 。明らかに、このメソッドはどこで機能しないのでしょうか。 どこにでも封印されたインド人に親切に感謝します。



System.Drawing.Contextコントラクトをもたらし、 それから既に継承する抽象MegaDeviceを発明する必要がありました。 それに費やした時間は警備員でした。 そして、これは画面とプリンターへの出力を単に捨てなければならなかったという事実にもかかわらずです。



論理的な質問は-なぜJavaからではなくDotnet契約が取られたのですか?



ここでの答えは簡単です-コンバーター自体が巧妙に変更されました



  g.drawString( prefix + index + " ", x, y );
      
      







  g.DrawString( prefix + index + " ", SupportClass.GraphicsManager.manager.GetFont(g), SupportClass.GraphicsManager.manager.GetBrush(g), new PointF(x, y));
      
      





だから私はそれに適応しなければなりませんでした。 ソースコードは根本的に変更されていません-さもなければ、移植されているもの、ソースの不具合、または導入されたバグを理解できません。



状態マシンと署名済み/未署名



画像

次のレーキはCSSパーサーで起こりました。 まったく同じ( com.steadystate。* )移植時には存在しませんでした。 はい、知っています-文法をJavaCCからANTLRに書き換えるのは正しいでしょう。 前のステップで失われた時間と時間を考慮に入れて、3時間に1〜2時間。



しかし、私の怠lazは別のオプションを促しました-自動生成されたフットクロスを変換します。 彼女はわずか300キロバイトです。簡単です。 そして、浸水。



ここにビットがあります-それらは異なります:



 private static long URShift(long number, int bits) { if ( number >= 0) return number >> bits; else return (number >> bits) + (2L << ~bits); }
      
      





など-署名付きの長いものを署名なしの長いものにキャストすることを忘れないでください。同時に、認証されたIDを削除します。



 if (((ulong)active0 & (ulong)(0x8000103000000000L)) != 0L) { jjmatchedKind = 66; return 577; }
      
      





gotobreak labelのメモリを更新します。それ以外の場合、ジェネリックはどこでもそれらをスカルプトします:



 EOFLoop : for (; ; ) { for (; ; ) { ... else if ((jjtoSkip[URShift(jjmatchedKind, 6)] & (1L << (jjmatchedKind & 63))) != 0L) { if (jjnewLexState[jjmatchedKind] != - 1) curLexState = jjnewLexState[jjmatchedKind]; goto EOFLoop; } ... } }
      
      





そして、FillBuf関数を書き換えてから、ストリームを作成します。これらにもわずかな違いがあります。 そこからマシンが悪化し、ファイルの終わりに到達することはありません。 完全に正確であるために、それは終わりに来て、読み続けようとし続けます:



 int i; try { if(inputStream == null) throw new System.IO.IOException("EOF"); i = inputStream.ReadBlock(buffer, maxNextCharInd, available - maxNextCharInd); if (i <= 0 /* was == -1 */) { inputStream.Close(); inputStream = null; throw new IOException(); } else maxNextCharInd += i; return ; } catch (IOException e) { --bufpos; backup(0); if (tokenBegin == - 1) tokenBegin = bufpos; throw e; }
      
      





そのため、テキストエディターでの大量置換により、パーサーの移植の問題が解決されました。 「簡単」で-私はまだ水たまりに座っていました、はい。 私は一日を殺したが、どうやって殺したのか-泥だらけの仕事のために。 がらくたは 132回ごみに置き換えられました[OK]をクリックします



記号と数字、およびそれらの周りの非自明性



画像

次のステップは、Unicodeおよび右から左へのサポートでした。 そして、 java.lang.Characterという形での驚きが私待っていました。 それだけでなく、彼とSystem.Charの間では名前だけで共通しています。 だからまた



 public static int digit(int codePoint, int radix)
      
      





イプシロン周辺では表示されません(だけでなく)。



15分間のグーグル検索では、この方法を何に置き換えることができるかは示唆されず、大きなクラブが使用されました。 つまり、 java.lang。*の一部が、この関数に関連するものに取り入れられています。 つまり、 java.lang.Characterおよび隣接するjava.lang.CharacterData *とすべての内部テーブル。



(皮肉なことに)Javaは不適切なオープンソースだと誰が言ったのでしょうか?



同じシナリオで、 java.math.BigDecimalが移植されました。 これらは小さな違いです-特に攻撃しているコードに多くの場所がある場合、それらは勇気づけられません。 はい、私はすでに言った-私は残念と寄生虫ですか? これもまた同じです。



BigDecimalでは、setScaleマジックとtrue toString()が必要でした:



  BigDecimal d1 = new BigDecimal(currentLineThickness / 2 + x ); BigDecimal d2 = new BigDecimal(currentLineThickness / 2 + y ); d1 = d1.SetScale(4, BigDecimal.ROUND_UP); d2 = d2.SetScale(4, BigDecimal.ROUND_UP); buf.Append(d1.ToString()).Append(" "); buf.Append(d2.ToString()).Append(" m\n");
      
      







ハッシュテーブルとToString



画像

不快な時間をたくさん送った次の瞬間は、コレクションの有名な平凡さです。 しかし、Unknown Author(TM)は巧みに騎士の動きをしました-彼はHTML属性の周りにキャッシュを構築し、キーとしてToString()を使用しました。



(声を出して考えた)私はハッシュマップをハッシュマップに追加したくありませんが、多くの人が気に入っています。 悟りに達していないか、何か他のものですが、私はそれが好きではありません。



明らかに、属性は名前と値のペアのセットです。 つまり-HashMap。 javaはtoString()で何をしますか? コレクションの内容を印刷します。 しかし、ポイント-まあ、あなたは知っています。 インド風のコーディングが検出されましたか?



解決策は明白でシンプルでした。



  public static String ToString(Hashtable map) { String hta_str = "["; IEnumerator ie = map.Keys.GetEnumerator(); while(ie.MoveNext()) { Object o = map[ie.Current]; if(o is Array) { Array al = (Array)o; hta_str += ie.Current + "=["; for(int jjk=0;jjk<al.Length;++jjk) hta_str += al.GetValue(jjk) + ","; hta_str += "]"; } else hta_str += ie.Current + "=" + o + ","; } hta_str += "]"; return hta_str; }
      
      







「迷惑メールのように」コピーすることすらしませんでした-Hashtable @アドレスではなく、テキストへの何らかのマッピングが必要でした。



甘い-フォントを扱う



画像

そして最後に-私は別の真珠を喜ばせたい-フォントを操作します。 ハーフライブラリの場合は、置換、選択、右から左への左から右への切り替え、アラビア語、中国語、Arialから明朝への自動変更など、マジックのみを扱います。



半分のリットルがなければ食べるのが好きです。



ちなみに、Windows OpenType自体は口withを鳴らしますが、。 彼は「cervelat」シルバーライトのバリエーションにいますが、はい、はい。 そしてこれは、古風な1.1については言うまでもなく、4.0にあります! 私は5.0を待っています-多分彼らはそこに追加しますか?



たとえば、指定されたディレクトリからフォントを取得するには、コードを完全に書き直す必要がありました。



 private static void listFonts(DirectoryInfo dd, String mask, Hashtable listOfFontFaces) { FileInfo[] files = dd.GetFiles(mask); FontFamily newFN = null; bool TtC = mask.Equals("*.ttc"); Hashtable foundFonts = new Hashtable(); System.Drawing.Text.PrivateFontCollection tmpPfc = null; for(int jjk=0;jjk<files.Length;++jjk) { tmpPfc = new System.Drawing.Text.PrivateFontCollection(); try { tmpPfc.AddFontFile(files[jjk].FullName); } catch(Exception /* e */) {} for(int jjv=0;jjv<tmpPfc.Families.Length;++jjv) { newFN = tmpPfc.Families[jjv]; FontFamilySpec spec = (FontFamilySpec)foundFonts[newFN.Name]; if(spec == null) { spec = new FontFamilySpec(newFN.Name); foundFonts[spec.Family] = spec; } String fn = files[jjk].Name; if(TtC) fn += "_" + jjv; spec.Files.Add(fn); spec.Files.Sort(); } tmpPfc.Dispose(); } ... }
      
      





コードは明らかに文書化されていませんが、動作します。



そして、もう一つの魔法があります:



 char c = content[ 0 ]; UnicodeCategory prevUB = Char.GetUnicodeCategory(c); int lastCutPosition = 0; for ( int i = 1; i < content.Length; i++ ) { c = content[i]; if ( c == 0xAD || c == ' ') // soft hyphen continue; byte dirct = java.lang.Character.getDirectionality((int)c); if ( dirct == java.lang.Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC || dirct == java.lang.Character.DIRECTIONALITY_RIGHT_TO_LEFT || dirct == java.lang.Character.DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING || dirct == java.lang.Character.DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE ) // sick of fighting with. // the only expected conflict is a combining of chinese and arabic in a single paragraph break; UnicodeCategory ub = Char.GetUnicodeCategory(c); if ( ub != prevUB ) { String pattern = ""; for ( int j = 0; j < content.Length; j++ ) { char ch = content[j]; if ( prevUB == Char.GetUnicodeCategory(c) ) pattern += ch; } ... prevUB = ub; } } ...
      
      





ここでは、一般的に、コンポートが出てきました-DonnetツールとJava6ソースから無頓着に移植されたツールの両方-ペアのクリーチャーごとに。 非常に明白なトリック。



この魚を飼いならすのは簡単ではありませんでした。 私はコック付きの帽子を誓います! (C)



まとめ



画像

悲しいかな-私は割り当てられた週に恥ずかしそうに投資しませんでした、私も週末をつかみました、そしてそれらの数日後。 そして、彼は何回か戻って、明らかでないレーキをキャッチしました。



その後、クライアントは私の実験を著者に送り、すぐに公式バージョンが作成されました。 今後の開発などとは関係ありません。



元のコードを知ることの全体的な印象は非常にポジティブでした。 ユニバーサルWebキット化の時代に、CSS 2.1をサポートするHTML 5要素を使用して独自のHTML 4レンダリングを作成すると、この純粋なJavaはすべて本物の古い学校になります。



移植中に1匹の小さな動物が損傷したわけではありません。



この情報が誰かに役立つことを願っています。



All Articles