紀伊國屋書店新宿本店でC++ポケットリファレンス、改訂新版 C++ポケットリファレンス、改訂第3版 C++ポケットリファレンス、改訂第4版 C++ポケットリファレンスのC++23対応改訂版になる
改訂第5版 C++ポケットリファレンス (Amazon)/
高橋晶、安藤敏彦、一戸優介、楠田真矢、湯朝剛介著/技術評論社/ISBN 978-4-297-14165-3/3,520円
を購入。
2024年4月22日
2024年4月18日
RAD Studio/Delphi/C++Builder 12.1 Athens Patch 1
RAD Studio/Delphi/C++Builder 12.1 AthensのPatch 1がリリースされています。現時点(2024/04/18)ではGetItからのみダウンロード、インストールすることができます。IDEとコンパイラの不具合修正のようです。
RAD Studio 12 Athens Patch 1 のリリース (en)
RAD Studio 12 Athens Patch 1 のリリース (en)
2024年4月10日
2024年4月9日
[書籍]はじめて学ぶ最新サイバーセキュリティ講義
紀伊國屋書店新宿本店で
Cybersecurity Myths and Misconceptions (Amazon US)の翻訳である
はじめて学ぶ最新サイバーセキュリティ講義 (Amazon)/Eugene H. Spafford、Leigh Metcalf、Josiah Dykstra著/金井哲夫訳/徳丸浩監訳/日経BP/ISBN 9784296070695/3,9604,400円
を購入。
はじめて学ぶ最新サイバーセキュリティ講義 (Amazon)/Eugene H. Spafford、Leigh Metcalf、Josiah Dykstra著/金井哲夫訳/徳丸浩監訳/日経BP/ISBN 9784296070695/3,9604,400円
を購入。
2024年4月4日
RAD Studio/Delphi/C++Builder 12 Athens Release 1 (12.1)
RAD Studio/Delphi/C++Builder 12 AthensのRelease 1 (12.1)がリリースされています。インストールには有効なUpdate Subscriptionが必要です。ポータルサイトからダウンロードできます。
RAD Studio, Delphi, C++Builder 12.1 Web Install
RAD Studio, Delphi, C++Builder 12.1 ISO
12 Athens - Release 1 - RAD Studio (en)
New features and customer reported issues fixed in RAD Studio 12.1
List of publicly reported bugs fixed in 12.1 - RAD Studio
RAD Studio 12.1 Athensの提供開始 (en)
What’s New in RAD Studio 12.1 Athens - YouTube
C++Builder 12.1の新しいClangツールチェイン (en)
How to achieve common tasks with the new Clang toolchain in 12.1
Delphi 12.1 Released Today
RAD Studio, Delphi, C++Builder 12.1 Web Install
RAD Studio, Delphi, C++Builder 12.1 ISO
12 Athens - Release 1 - RAD Studio (en)
New features and customer reported issues fixed in RAD Studio 12.1
List of publicly reported bugs fixed in 12.1 - RAD Studio
RAD Studio 12.1 Athensの提供開始 (en)
What’s New in RAD Studio 12.1 Athens - YouTube
C++Builder 12.1の新しいClangツールチェイン (en)
How to achieve common tasks with the new Clang toolchain in 12.1
Delphi 12.1 Released Today
2024年4月1日
2024/04開催のセミナー
- Web Seminar
- 2024/04/23 17:00-17:45(JST) 「RAD Studio 12.1アップデート情報」 - エンバカデロ・デベロッパーTV(2024年4月23日)
- Live Seminar
- Community Event
2024年3月21日
Firebirdロードマップ(2024/03)
Firebird 6の開発が正式に決まったとのことで、ロードマップが更新されています。
Firebird: Roadmap v6
適当な要約
Firebird: Roadmap v6
適当な要約
- Firebird 3.0 - 安定版。最新版は2023年08月の3.0.11で、次回(3.0.12)は2024年第2四半期内を予定。
- Firebird 4.0 - 安定版。最新版は2023年11月の4.0.4で、次回(4.0.5)は2024年第2四半期内を予定。
- Firebird 5.0 - 安定版。最新版は2024年01月の5.0で、次回(5.0.1)は2024年第2四半期内を予定。
- Firebird 6.0 - 2024年03月に開発開始、2025年第1四半期に最初のアルファ版を、ベータ版を2025年第3四半期に、正式版を2026年第1四半期にリリース予定。
- SQL準拠のJSON関数 issue #5431
- テーブルスペースのサポート issue #1055
- 共有メタデータキャッシュ issue #7954
- SQL標準に準拠したROWデータ型 issue #1115, issue #3031
- SQLスキーマのサポート issue #1113
2024年3月13日
2024年3月4日
[書籍]Expert Delphi - Second Edition
Amazon(JP)で注文した
Expert Delphi - Second Edition (Amazon US, Amazon JP)/Marco Cantù、Paweł Głowacki著/Packt Publishing/ISBN 9781805121107/7,596JPY(printed)
が配送されてきました。2024/03/02に注文して2日目の到着でした(日本国内でのプリントオンデマンドでした)。
Expert Delphi - Second Edition (Amazon US, Amazon JP)/Marco Cantù、Paweł Głowacki著/Packt Publishing/ISBN 9781805121107/7,596JPY(printed)
が配送されてきました。2024/03/02に注文して2日目の到着でした(日本国内でのプリントオンデマンドでした)。
2024年3月1日
2024/03開催のセミナー
- Web Seminar
- 2024/03/12 17:00-17:45(JST) 「Delphi 29歳バースディ!私のDelphi推しプレゼン」 - エンバカデロ・デベロッパーTV(2024年3月12日)
- Live Seminar
- Community Event
2024年2月14日
2024年2月7日
RAD Studio/Delphi/C++Builder 12 Athens Patch 1
RAD Studio/Delphi/C++Builder 12 AthensのPatch 1がリリースされています。多数の不具合修正が含まれています。現時点(2024/02/08)では(やっと復旧した)GetItからのみダウンロード、インストールすることができます。2024/02/10現在でGetItまたはポータルサイトからダウンロード、インストールすることができます。またwebインストーラもPatch 1適用済のみものがダウンロードできるようになっています。
RAD Studio 12.0 Patch 1
RAD Studio, Delphi, C++Builder 12.0 Inline with Patch 1 Web Install
なおオリジナルのwebインストーラからインストールした場合はPatch 1がインストールされているかどうかにかかわらず、IDEのツール→機能の管理で言語やターゲットプラットフォームなどを追加することはできず、一旦アンインストール後にPatch 1適用済のwebインストーラからインストールし直す必要があるため注意が必要です。
RAD Studio 12 Athens Patch 1 のリリース (en)
GetIt アップデート: RAD Studio 12 向けのGetItパッケージインストールが利用可能に! (en)
GetItアップデート: RAD Studio 12 GetIt オンラインインストールが利用可能に! (en)
2024/02/10追記: Patch 1がポータルサイトからダウンロードできるようになったこととオリジナルのwebインストーラからインストールした場合の注意事項を追記しました。
RAD Studio 12.0 Patch 1
RAD Studio, Delphi, C++Builder 12.0 Inline with Patch 1 Web Install
なおオリジナルのwebインストーラからインストールした場合はPatch 1がインストールされているかどうかにかかわらず、IDEのツール→機能の管理で言語やターゲットプラットフォームなどを追加することはできず、一旦アンインストール後にPatch 1適用済のwebインストーラからインストールし直す必要があるため注意が必要です。
RAD Studio 12 Athens Patch 1 のリリース (en)
GetIt アップデート: RAD Studio 12 向けのGetItパッケージインストールが利用可能に! (en)
GetItアップデート: RAD Studio 12 GetIt オンラインインストールが利用可能に! (en)
2024/02/10追記: Patch 1がポータルサイトからダウンロードできるようになったこととオリジナルのwebインストーラからインストールした場合の注意事項を追記しました。
2024年2月1日
2024/02開催のセミナー
- Web Seminar
2024/02/20 17:00-17:45(JST) 「Delphi 29歳バースディ!私のDelphi推しプレゼン」 - エンバカデロ・デベロッパーTV(2024年2月)2024/03/12に延期
- Live Seminar
- Community Event
2024年1月12日
Firebird 5.0
Firebird 5.0がリリースされています。ODSバージョンは13.1になっています。
Firebird: Firebird 5.0 is released
Firebird: Firebird 5.0.0
Firebird 5.0 Release Notes (PDF)
Firebird 5.0 Language Reference (PDF)
Detailed New Features of Firebird 5
Firebird: Firebird 5.0 is released
Firebird: Firebird 5.0.0
Firebird 5.0 Release Notes (PDF)
Firebird 5.0 Language Reference (PDF)
Detailed New Features of Firebird 5
- Detailed New Features of Firebird 5. Part 1: Improvements in Optimizer
- Detailed New Features of Firebird 5. Part 2: SQLs
- Detailed New Features of Firebird, Part 3: Using new clause SKIP LOCKED
- Detailed New Features of Firebird 5, Part 4: Parallel Features: backup/restore/sweep, creation of indices
- Detailed New Features Of Firebird 5, Part 5: Better compression, cache of compiled statements, and more
- Parallel Reading Of Data In Firebird
2024年1月10日
2024年1月1日
2024/01開催のセミナー
- Web Seminar
- 2024/01/30 17:00-17:45(JST) 新年事始め!三浦珠美の「挑戦!はじめてのDelphi」 - エンバカデロ・デベロッパーTV(2024年1月)
- Live Seminar
- Community Event
2023年12月27日
文字列の表示幅を取得する
前回はSkia4DelphiのISkUnicodeを使って文字列を書記素クラスタ(grapheme cluster)に分割する方法を扱いましたが、(等幅フォントでの表記を前提として)文字列が何文字分の幅を占めるのか(いわゆる"表示幅")を取得するためには、それぞれの書記素クラスタ(の基底文字)がいわゆる"半角幅"(halfwidth、1/2 Em)なのか"全角幅"(fullwidth、1 Em)なのかを知る必要があります(Emは文字の高さを基準にした単位で、1/2 Emは高さの半分の文字幅、1 Emは高さと同じ文字幅になる、という意味)。これに関するUnicodeの規格がUnicode Standard Annex #11 East Asian Width(UAX #11)になります。
UAX #11では既存の実装に配慮して、文字をその占める幅によって
では実際にどの文字(コードポイント)がどの分類になるのか、ですが、これはUnicodeデータベースの一部としてhttps://www.unicode.org/Public/UCD/latest/ucd/EastAsianWidth.txtにリストされています。基本的にこれを何らかの形で配列化しておいて参照すればいいのですが、Unicode(UCS4)で扱えるコードポイントは最大でU+0000からU+10FFFFの1,114,112個あり、単純にテーブル化すると約1MBになってしまいます。しかしプレーン4~13は未割当で定義も存在しません(この場合はデフォルトで"N"である(
まずはUAX #11で規定されている分類を列挙型として定義し、レコードヘルパでそれぞれに対応する文字幅を返すようにします。
次にEastAsianWidth.txtをテーブル化します。まずそれぞれのプレーンを格納するテーブルのレコード型と、このテーブルへのポインタと代表値をセットにしたレコード型を定義します。
あとはUnicodeのバージョンアップに簡単に追随できるようにするために、EastAsianWidth.txtから上記のテーブル部分を自動生成する処理を別ユニットに作っていきます。
まず読み込んだプレーン毎のデータを格納するレコード型と、関係するメソッド(初期化、値の指定、代表値だけでテーブルを省略可能かどうかの判定)を用意します。このようになっているものを、正規表現で複数指定、単独指定のどちらかのパターンにマッチングさせて、コードポイント(の範囲)と属性を取り込んでテーブルに格納し、最後にテーブルの内容をDelphiのコードの一部として出力しています。
このConvertEastAsianWidthを使ってEastAsianWidth.txtをEastAsianWidth.incとして変換したら、上記のTPlaneの配列部分を
これで前回のサンプルにチェックボックスを1つ追加して、
誰ですか、絵文字が混ざると意味がないじゃないか、とかいう人は!そう、絵文字がZWJ(ゼロ幅接合子)を使ってグリフを増やすようになったあたりから、実際にレンダリングしてみないとどのくらいの表示幅になるのかはわからなくなっているのです。
最終的なプロジェクト全体をGitHubに上げてあります。今後Unicodeのバージョンが上がっても、更新されたEastAsianWidth.txtを取り込むことで最新のものに準拠することができます。
参考: 東アジアの文字幅 - Wikipedia
UAX #11では既存の実装に配慮して、文字をその占める幅によって
- Fullwidth("F"/全角)
- Halfwidth ("H"/半角)
- Wide ("W"/広)
- Narrow ("Na"/狭)
- Ambiguous ("A"/曖昧)
- Neutral ("N"/中立)(Not East Asian)
では実際にどの文字(コードポイント)がどの分類になるのか、ですが、これはUnicodeデータベースの一部としてhttps://www.unicode.org/Public/UCD/latest/ucd/EastAsianWidth.txtにリストされています。基本的にこれを何らかの形で配列化しておいて参照すればいいのですが、Unicode(UCS4)で扱えるコードポイントは最大でU+0000からU+10FFFFの1,114,112個あり、単純にテーブル化すると約1MBになってしまいます。しかしプレーン4~13は未割当で定義も存在しません(この場合はデフォルトで"N"である(
All code points, assigned or unassigned, that are not listed explicitly are given the value "N".)と明記されています)。そこで今回はプレーン毎に分割して、フルマッピングするプレーンと1つの値で代表させるプレーン、という形で領域を節約した実装を考えてみます。
まずはUAX #11で規定されている分類を列挙型として定義し、レコードヘルパでそれぞれに対応する文字幅を返すようにします。
type TEastAsianWidth = (Neutral, // N Fullwidth, // F Halfwidth, // H Wide, // W Narrow, // Na Ambiguous); // A TEastAsianWidthHelper = record helper for TEastAsianWidth private const Width: array [Boolean,TEastAsianWidth] of Integer = ((1, // Neutral 2, // Fullwidth 1, // Halfwidth 2, // Wide 1, // Narrow 1), // Ambiguous (same as Neutral) (1, // Neutral 2, // Fullwidth 1, // Halfwidth 2, // Wide 1, // Narrow 2)); // Ambiguous (same as Fullwidth) private class var FEastAsian: Boolean; public function GetWidth: Integer; overload; inline; class property EastAsian: Boolean read FEastAsian write FEastAsian; end; function TEastAsianWidthHelper.GetWidth: Integer; begin Result := Width[FEastAsian,Self]; end;ここでクラスプロパティTEastAsianWidth.EastAsianは"A"の扱いを決めるもので、Trueなら東アジアの組版(フォントが日本語など)、Falseなら欧文の組版(フォントが欧文)であることを示します。
次にEastAsianWidth.txtをテーブル化します。まずそれぞれのプレーンを格納するテーブルのレコード型と、このテーブルへのポインタと代表値をセットにしたレコード型を定義します。
type TPlaneData = packed record public Data: array [0..65535] of Byte; end; PPlaneData = ^TPlaneData; TPlane = record PlaneDefault: Byte; PlaneData: PPlaneData; end;このTPlaneの配列(0..16)を今回はEastAsianWidth.txtから生成しますが、とりあえず仮に
const Plane0: TPlaneData = (Data: ( $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00, ... $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00)); Plane0Default = $00; Plane1Default = $00; ... Plane16Default = $00; Planes: array [0..16] of TPlane = ((PlaneDefault: Plane0Default; PlaneData: @Plane0), (PlaneDefault: Plane1Default; PlaneData: nil), ... (PlaneDefault: Plane16Default; PlaneData: nil));こんな定数定義があるものとします。これを使用する形でレコードヘルパTEastAsianWidthHelperにクラスメソッドGetEastAsianWidthを追加します。
uses System.SysUtils, System.RTLConsts; type TEastAsianWidthHelper = record helper for TEastAsianWidth public ... class function GetEastAsianWidth(C: UCS4Char): TEastAsianWidth; static; end; class function TEastAsianWidthHelper.GetEastAsianWidth(C: UCS4Char): TEastAsianWidth; var PlaneNum: Integer; Plane: TPlane; B: Byte; begin PlaneNum := (C shr 16) and $FFFF; if (PlaneNum < Low(Planes)) and (PlaneNum > High(Planes)) then begin raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange); end; Plane := Planes[PlaneNum]; if Plane.PlaneData <> nil then begin B := Plane.PlaneData^.Data[C and $FFFF]; end else begin B := Plane.PlaneDefault; end; Result := TEastAsianWidth(B); end;クラスメソッドGetEastAsianWidthでは、プレーン毎のテーブルがあればそこから、テーブルがなければ代表値を取得し、列挙型TEastAsianWidthとして返します。
あとはUnicodeのバージョンアップに簡単に追随できるようにするために、EastAsianWidth.txtから上記のテーブル部分を自動生成する処理を別ユニットに作っていきます。
まず読み込んだプレーン毎のデータを格納するレコード型と、関係するメソッド(初期化、値の指定、代表値だけでテーブルを省略可能かどうかの判定)を用意します。
type TPlaneData = record Table: array [$0000..$FFFF] of Byte; procedure Init; procedure Fill(StartIndex: UInt16; EndIndex: UInt16; Data: Byte); function IsAllSame: Boolean; end; procedure TPlaneData.Init; var I: Integer; begin for I := Low(Table) to High(Table) do begin Table[I] := 0; // 'Neutral' end; end; procedure TPlaneData.Fill(StartIndex: UInt16; EndIndex: UInt16; Data: Byte); var I: Integer; begin for I := StartIndex to EndIndex do begin Table[I] := Data; end; end; function TPlaneData.IsAllSame: Boolean; var I: Integer; B: Byte; begin B := Table[Low(Table)]; for I := Low(Table) + 1 to High(Table) do begin if Table[I] <> B then begin Result := False; Exit; end; end; Result := True; end;これを使ってUCS4のコード範囲全体を扱うレコード型を用意します。
type TEastAsianWidthProperties = record Planes: array [0..16] of TPlaneData; procedure Init; end; PEastAsianWidthProperties = ^TEastAsianWidthProperties; procedure TEastAsianWidthProperties.Init; var I: Integer; begin for I := Low(Planes) to High(Planes) do begin Planes[I].Init; end; end;あとはEastAsianWidth.txtを解析して値を格納し、テーブル化するメソッドを用意します。
uses System.Classes, System.SysUtils, System.RegularExpressions, System.SysConst; function SymbolToEastAsianWidth(const S: String): Byte; const EastAsianWidthSymbols: array [0..5] of String = ('N', 'F', 'H', 'W', 'Na', 'A'); begin for Result := Low(EastAsianWidthSymbols) to High(EastAsianWidthSymbols) do begin if EastAsianWidthSymbols[Result] = S then begin Exit; end; end; raise EConvertError.CreateRes(@SRangeError); end; procedure ConvertEastAsianWidth(Input, Output: TStrings); var PEAWP: PEastAsianWidthProperties; RegEx1: TRegEx; RegEx2: TRegEx; Match: TMatch; I: Integer; S: String; Position: Integer; StartCodePoint: String; EndCodePoint: String; Name: String; Plane: UInt16; CPLow: UInt16; CPLow2: UInt16; PlaneDefault: Byte; begin New(PEAWP); try PEAWP^.Init; RegEx1 := TRegEx.Create('([0-9A-Fa-f]{4,6})[.][.]([0-9A-Fa-f]{4,6})\s*[;]\s*(.{1,2})\s*'); RegEx2 := TRegEx.Create('([0-9A-Fa-f]{4,6})\s*[;]\s*(.{1,2})\s*'); for I := 0 to Input.Count - 1 do begin S := Input.Strings[I]; Position := Pos('#',S); if Position > 0 then begin Delete(S,Position,Length(S)); end; S := Trim(S); if S = '' then begin Continue; end; Match := RegEx1.Match(S); if Match.Success = True then begin StartCodePoint := Match.Groups[1].Value; EndCodePoint := Match.Groups[2].Value; Name := Match.Groups[3].Value; end else begin Match := RegEx2.Match(S); if Match.Success = True then begin StartCodePoint := Match.Groups[1].Value; EndCodePoint := StartCodePoint; Name := Match.Groups[2].Value; end; end; if Match.Success = True then begin Plane := (StrToInt64('$' + StartCodePoint) shr 16) and $FFFF; if Plane <= 16 then begin CPLow := (StrToInt64('$' + StartCodePoint)) and $FFFF; CPLow2 := (StrToInt64('$' + EndCodePoint)) and $FFFF; PEAWP^.Planes[Plane].Fill(CPLow,CPLow2,Ord(SymbolToEastAsianWidth(Name))); end; end; end; for Plane := Low(PEAWP^.Planes) to High(PEAWP^.Planes) do begin Output.Add(Format(' { Plane%d }',[Plane])); if PEAWP^.Planes[Plane].IsAllSame = False then begin Output.Add(Format(' Plane%d: TPlaneData = (Data: (',[Plane])); S := ''; for I := Low(PEAWP^.Planes[Plane].Table) to High(PEAWP^.Planes[Plane].Table) do begin if (I mod 16) = 0 then begin S := ' '; end; S := S + Format('$%.02X,',[PEAWP^.Planes[Plane].Table[I]]); if (I mod 16) = 15 then begin if I = High(PEAWP^.Planes[Plane].Table) then begin Delete(S,Length(S),1); S := S + '));'; end else begin S := S + ' '; end; S := S + Format(' // U+%.4X',[(Plane shl 16) or (I and $FFF0)]); Output.Add(S); S := ''; end; end; PlaneDefault := 0; end else begin PlaneDefault := PEAWP^.Planes[Plane].Table[0]; end; Output.Add(Format(' Plane%dDefault = $%.2X;',[Plane,PlaneDefault])); Output.Add(''); end; Output.Add(' { Plane data table }'); Output.Add(' Planes: array [0..16] of TPlane ='); for Plane := Low(PEAWP^.Planes) to High(PEAWP^.Planes) do begin if PEAWP^.Planes[Plane].IsAllSame = True then begin S := Format(' (PlaneDefault: Plane%dDefault; PlaneData: nil),',[Plane]); end else begin S := Format(' (PlaneDefault: Plane%dDefault; PlaneData: @Plane%d),',[Plane,Plane]); end; if Plane = Low(PEAWP^.Planes) then begin S[5] := '('; end else if Plane = High(PEAWP^.Planes) then begin Delete(S,Length(S),1); S := S + ');'; end; Output.Add(S); end; finally Dispose(PEAWP); end; end;レコード型TEastAsianWidthPropertiesはサイズが大きく、デフォルトの設定ではスタックオーバフローするため、New/Disposeでヒープ上に確保するようにしています。読み込んだEastAsianWidth.txtの各行が
0000..001F ; N # Cc [32] <control-0000>..
0020 ; Na # Zs SPACE
このConvertEastAsianWidthを使ってEastAsianWidth.txtをEastAsianWidth.incとして変換したら、上記のTPlaneの配列部分を
const {$I 'EastAsianWidth.inc'}と置き換えれば完成です。
これで前回のサンプルにチェックボックスを1つ追加して、
procedure TForm1.Button2Click(Sender: TObject); var SkUnicode: ISkUnicode; L: Integer; TotalL: Integer; W: Integer; TotalW: Integer; begin TEastAsianWidth.EastAsian := CheckBox1.Checked; SkLabel1.Words.Items[0].Caption := Edit1.Text; Memo1.Lines.Clear; SkLabel2.Words.Clear; TotalL := 0; TotalW := 0; SkUnicode := TSkUnicode.Create; for var S in SkUnicode.GetBreaks(Edit1.Text,TSkBreakType.Graphemes) do begin L := Length(S); W := TEastAsianWidth.GetEastAsianWidth(Char.ConvertToUtf32(S,0)).GetWidth; Memo1.Lines.Add(S + Format(' (L=%d,W=%d)',[L,W])); SkLabel2.Words.Add(S + sLineBreak); TotalL := TotalL + L; TotalW := TotalW + W; end; Memo1.Lines.Add(Format('Total: L=%d, W=%d',[L,W])); end;こんな感じで全体の文字数を得ることができるようになります。チェックボックスのチェック状態で"á̂̃̄"のWが変化するのがわかりますね。
誰ですか、絵文字が混ざると意味がないじゃないか、とかいう人は!そう、絵文字がZWJ(ゼロ幅接合子)を使ってグリフを増やすようになったあたりから、実際にレンダリングしてみないとどのくらいの表示幅になるのかはわからなくなっているのです。
最終的なプロジェクト全体をGitHubに上げてあります。今後Unicodeのバージョンが上がっても、更新されたEastAsianWidth.txtを取り込むことで最新のものに準拠することができます。
参考: 東アジアの文字幅 - Wikipedia
2023年12月25日
文字列を書記素クラスタで分割する
このアーティクルはDelphi Advent Calendar 2023の25日目の記事です(12日ぶり11回目)。
Unicodeの世界では、1つの"文字"(書記素、grapheme)が1つのコードポイント(code point)で表されるとは限りません。サロゲートペアとか結合文字とか絵文字とか、文字列に入っているものがどれくらいの"文字数"になっているのかを知るのは意外に難しい話です。
現在一般的と考えられる方法として、
ところがDelphi 12で標準サポートされたSkia4Delphiでは簡単に文字列を書記素クラスタで分割できるようになりました(ICUを取り込んでいるようです)。試しに正規表現(PCRE)による分割と比較してみましょう。
なおDelphi 11 Alexandriaおよびそれ以前のバージョンではSkia4Delphiをインストールする必要があります(現時点(2023/12)の最新は6.0.0)。
新規プロジェクトを作成し、フォーム(フォントサイズを大きめにしておくと結果が見やすくなります)にTEditを1つ、TButtonを2つ、結果表示のためのTMemoを1つ配置します。またプロジェクトツールウィンドウでプロジェクトを右クリック→Skiaを有効化を選択して、実行ファイルと同じ場所にsk4d.dllが配置されるようにします。
usesにSystem.Skiaを追加し、フォームのOnShowイベントで
(Windows上の表示とは若干異なります)
正規表現による分割では絵文字のZWJ(ゼロ幅接合子)による結合はうまく処理できないようです。これはPCRE 8.45がだいぶ古いバージョンで、最新のUnicodeに対応できていないことが原因と考えられます。
次にSkia4Delphiです。
一方でSkia4Delphiによる分割は正しく処理できていますね。ちなみにWindowsでは国旗の絵文字は絵文字としてではなくRegional indicator symbol2文字での表現になるようです(サンプル最後の"🇯🇵"が"JP"となる)。
書記素クラスタによる分割は文字列のレンダリングに必須なためSkia(Skia4Delphi)に実装されていると考えられますが、プログラムで書記素クラスタによる分割が必要になるのは(帳票などで)文字列がどのくらいの幅を占めるかを知りたいときではないでしょうか。そのためには書記素クラスタによる分割だけでなく、Unicode Standard Annex #11 East Asian Widthも必要になります。これはDelphi標準のSystem.CharacterユニットにもSkia4Delphiにも実装されておらず、EastAsianWidth.txtを取り込んで自前で実装する必要があります。これについては後日別のアーティクルで扱うことにします。
Skia4Delphを使って見やすくしたバージョンをGistに上げてあります。
Unicodeの世界では、1つの"文字"(書記素、grapheme)が1つのコードポイント(code point)で表されるとは限りません。サロゲートペアとか結合文字とか絵文字とか、文字列に入っているものがどれくらいの"文字数"になっているのかを知るのは意外に難しい話です。
現在一般的と考えられる方法として、
- ICU( International Components for Unicode、https://icu.unicode.org/)を使う
- 正規表現で"\X"でマッチする
- Unicodeの規格(Unicode Standard Annex #29)を元に自前で実装するr
ところがDelphi 12で標準サポートされたSkia4Delphiでは簡単に文字列を書記素クラスタで分割できるようになりました(ICUを取り込んでいるようです)。試しに正規表現(PCRE)による分割と比較してみましょう。
なおDelphi 11 Alexandriaおよびそれ以前のバージョンではSkia4Delphiをインストールする必要があります(現時点(2023/12)の最新は6.0.0)。
新規プロジェクトを作成し、フォーム(フォントサイズを大きめにしておくと結果が見やすくなります)にTEditを1つ、TButtonを2つ、結果表示のためのTMemoを1つ配置します。またプロジェクトツールウィンドウでプロジェクトを右クリック→Skiaを有効化を選択して、実行ファイルと同じ場所にsk4d.dllが配置されるようにします。
usesにSystem.Skiaを追加し、フォームのOnShowイベントで
procedure TForm1.FormShow(Sender: TObject); begin Edit1.Text := #$20BB7 + '野屋のコピペ' + #$00E5 + #$00E1 + #$0302 + #$0303 + #$0304 + #$1F62D + #$1F937 + #$1F3FD + #$200D + #$2640 + #$FE0F + #$1F468 + #$200D + #$1F469 + #$200D + #$1F467 + #$200D + #$1F466 + #$1F469 + #$1F3FD + #$200D + #$1F4BB + #$1F1EF + #$1F1F5; end;とEdit1.Textにサンプル文字列を設定し、Button1のOnClickイベントで
procedure TForm1.Button1Click(Sender: TObject); begin for var Match in TRegEx.Matches(Edit1.Text,'\X') do begin Memo1.Lines.Add(Match.Value); end; end;Button2のOnClickイベントで
procedure TForm1.Button2Click(Sender: TObject); var SkUnicode: ISkUnicode; begin SkUnicode := TSkUnicode.Create; for var S in SkUnicode.GetBreaks(Edit1.Text,TSkBreakType.Graphemes) do begin Memo1.Lines.Add(S); end; end;とします。では実行してみましょう。まず正規表現です。
𠮷
野
屋
の
コ
ピ
ペ
å
á̂̃̄
😭
🤷
🏽
♀️
👨
👩
👧
👦
👩
🏽
💻
🇯🇵
正規表現による分割では絵文字のZWJ(ゼロ幅接合子)による結合はうまく処理できないようです。これはPCRE 8.45がだいぶ古いバージョンで、最新のUnicodeに対応できていないことが原因と考えられます。
次にSkia4Delphiです。
𠮷
野
屋
の
コ
ピ
ペ
å
á̂̃̄
😭
🤷🏽♀️
👨👩👧👦
👩🏽💻
🇯🇵
書記素クラスタによる分割は文字列のレンダリングに必須なためSkia(Skia4Delphi)に実装されていると考えられますが、プログラムで書記素クラスタによる分割が必要になるのは(帳票などで)文字列がどのくらいの幅を占めるかを知りたいときではないでしょうか。そのためには書記素クラスタによる分割だけでなく、Unicode Standard Annex #11 East Asian Widthも必要になります。これはDelphi標準のSystem.CharacterユニットにもSkia4Delphiにも実装されておらず、EastAsianWidth.txtを取り込んで自前で実装する必要があります。これについては後日別のアーティクルで扱うことにします。
Skia4Delphを使って見やすくしたバージョンをGistに上げてあります。
2023年12月13日
TSqidsEncodingで文字列を難読化する
このアーティクルはDelphi Advent Calendar 2023の12日目の記事です(2日ぶり10回目)。
前回はDelphi 12 Athensで導入されたTSqidsEncodingを普通に使ってみましたが、TSqidsEncodingにはTArray<Integer>を扱うoverloadがあり、今回はそれを使って文字列を難読化してみます。
とはいっても、単にDelphiの文字列(UTF-16)の1文字を単純にUInt16(=Word)として扱うだけです。
前回はDelphi 12 Athensで導入されたTSqidsEncodingを普通に使ってみましたが、TSqidsEncodingにはTArray<Integer>を扱うoverloadがあり、今回はそれを使って文字列を難読化してみます。
とはいっても、単にDelphiの文字列(UTF-16)の1文字を単純にUInt16(=Word)として扱うだけです。
uses ..., System.NetEncoding.Sqids; type TSqidsEncodingHelper = class helper for TSqidsEncoding public function EncodeFromString(const AStr: String): String; function DecodeToString(const AHash: String): String; end; function TSqidsEncodingHelper.EncodeFromString(const AStr: String): String; var Values: TArray文字列の難読化としてXORやROT13などがよく使われますが、このほうがまだましな気がしますね。; I: Integer; begin SetLength(Values,Length(AStr)); for I := 0 to Length(AStr) - 1 do begin Values[I] := UInt16(AStr[I + 1]); end; Result := Encode(Values); end; function TSqidsEncodingHelper.DecodeToString(const AHash: String): String; var Values: TArray ; I: Integer; begin Values := Decode(AHash); SetLength(Result,Length(Values)); for I := 0 to Length(Result) - 1 do begin Result[I + 1] := Char(Values[I]); end; end;
2023年12月10日
TSqidsEncodingで数値と短縮IDを相互変換する
このアーティクルはDelphi Advent Calendar 2023の10日目の記事です(1年ぶり9回目)。
Delphi 12 Athensで数値と短縮IDを相互変換するSqidsを実装したTSqidsEncodingが追加されました。
Sqidsはあくまで難読化であって暗号化ではないので、内容を隠すことはできませんが、ID番号などをそのまま見せるよりはまし、というような場合に有効です。Sqidsの公式サイトでは、適しているケースとして
使用方法は簡単で、エンコードするには
またデコードはTArray<Integer>を返すもの(Decode)、Integerを返すもの(DecodeSingle/TryDecodeSingle)、Stringを返すもの(DecodeToStr)が用意されています。
さらにコンストラクタにエンコード用の文字列を渡すことで生成される文字列をカスタマイズすることもできます。
2023/12/22追記: 公式のblogにもSqidsの使いかたの記事が出ました。
Sqids: RAD Serverとの統合およびスタンドアロンライブラリ (en)
Delphi 12 Athensで数値と短縮IDを相互変換するSqidsを実装したTSqidsEncodingが追加されました。
Sqidsはあくまで難読化であって暗号化ではないので、内容を隠すことはできませんが、ID番号などをそのまま見せるよりはまし、というような場合に有効です。Sqidsの公式サイトでは、適しているケースとして
- 短縮リンク
- URLで安全に使用できる
- イベントID
- 衝突しないエンコード/デコード
- ワンタイムパスワード
- 短く問題のあるワードを含まない
- 機密データ
- 暗号化されるわけではない
- ユーザID
- デコードすることでユーザ数が漏洩する
使用方法は簡単で、エンコードするには
uses ..., System.NetEncoding.Sqids; var Sqids: TSqidsEncoding; begin Sqids := TSqidsEncoding.Create; try Edit2.Text := Sqids.Encode(Edit1.Text); finally Sqids.Free; end; end;デコードするには
var Sqids: TSqidsEncoding; begin Sqids := TSqidsEncoding.Create; try Edit3.Text := Sqids.DecodeToStr(Edit2.Text); finally Sqids.Free; end; end;とするだけです。Sqidsのソースは数値ですが、エンコードではInreger、TArray<Integer>、Stringを受け取るoverloadが用意されています(Stringは単独またはカンマ区切りの数値表現)。
またデコードはTArray<Integer>を返すもの(Decode)、Integerを返すもの(DecodeSingle/TryDecodeSingle)、Stringを返すもの(DecodeToStr)が用意されています。
さらにコンストラクタにエンコード用の文字列を渡すことで生成される文字列をカスタマイズすることもできます。
2023/12/22追記: 公式のblogにもSqidsの使いかたの記事が出ました。
Sqids: RAD Serverとの統合およびスタンドアロンライブラリ (en)
2023年12月1日
2023/12開催のセミナー
- Web Seminar
- 2023/12/19 17:00-17:45(JST) RAD Studio 12を掘り下げる - エンバカデロ・デベロッパーTV(2023年12月)
- Live Seminar
- Community Event
2023年11月15日
2023年11月9日
Firebirdロードマップ(2023/11)
Firebird 4.0.4がリリースされましたが、Firebirdのロードマップも更新されています。
Firebird: Roadmap
適当な要約
Firebird: Roadmap
適当な要約
- Firebird 2.0 - 2012年に開発終了。最新版は2012年04月の2.0.7。
- Firebird 2.1 - 2014年に開発終了。最新版は2014年12月の2.1.7。
- Firebird 2.5 - 2019年に開発終了。最新版は2019年06月の2.5.9。
- Firebird 3.0 - 安定版。最新版は2023年08月の3.0.11で、半年ごとの更新、次回(3.0.12)は2024年第2四半期内を予定。
- Firebird 4.0 - 安定版。最新版は2023年11月の4.0.4で、四半期ごとの更新、次回(4.0.5)は2024年第2四半期内を予定。
- Firebird 5.0 - 2021年05月に開発開始、2023年03月に最初のベータ版(5.0.0 Beta 1)をリリース。
2023年11月8日
RAD Studio/Delphi/C++Builder 12 Athensリリース
RAD Studio/Delphi/C++Builder 12 Athensがリリースされています。
RAD Studio 12 Athens ヘルプ (en)
リリース ノート (en)
インストール ノート (en)
新機能 (en)
New features and customer reported issues fixed in RAD Studio 12.0
Platform Status
ポータルサイトからダウンロード可能です
RAD Studio, Delphi, C++Builder 12.0 Web Install
RAD Studio, Delphi, C++Builder 12.0 Inline with Patch 1 Web Install
RAD Studio, Delphi, C++Builder 12.0 ISO
BDE for RAD Studio 12.0
Embarcadero General Packages Download for RAD Studio 12.0
『RAD Studio 12 Athens』の提供開始 (en)
Delphi/C++Builderライブラリに関する今後の展望 (en)
Android API 33サポートはRAD Studio 12ベータ(Yukon)で実施 (en)
Delphi言語: 文字列リテラルのモダナイゼーション (en)
Clang v15 compiler support coming to C++Builder 12
RAD Studio 12ベータ情報: マルチデバイスに対応したアイコンジェネレータ (en)
RAD Studio 12ベータ情報: 弱いエイリアスの導入による「NativeInt」の対応 (en)
RAD Studio 12のWin64 Clangツールチェーン (en)
[Yukon Beta Blog] C++ and Visual Assist in RAD Studio 12.0
Delphi 12における3 x 12 VCLの機能強化 (en)
Delphi 12における3 x 12 FireMonkeyとAndroidの機能強化 (en)
Delphi 12における3 x 12 データ、インターネット、RTLの機能強化 (en)
Delphi 12における 3 x 12 IDE、インストーラー、Delphi 言語の機能強化 (en)
Delphi 12向けに更新されたZXingデモアプリ(Android 13と iOS 17で動作済み)を公開 (en)
ウェビナーへ寄せられたRAD Studio 12 に関するQ&A (en)
Sqids: RAD Serverとの統合およびスタンドアロンライブラリ (en)
RAD Studio 12向けに新しいプレミアムスタイルを提供 (en)
Delphi / C++Builder 12のSkiaサポートで表現力豊かなUIを構築
GitHub - Embarcadero/RADStudio12Demos: Delphi and C++Builder Demos for Embarcadero RAD Studio version 12
2024/02/10追記: インストーラがPatch 1を含むものに差し替えられています。またBDEおよびEmbarcaderoが提供する主要なパッケージのローカルGetItパッケージもポータルサイトからダウンロードできるようになっています。
RAD Studio 12 Athens ヘルプ (en)
リリース ノート (en)
インストール ノート (en)
新機能 (en)
New features and customer reported issues fixed in RAD Studio 12.0
Platform Status
ポータルサイトからダウンロード可能です
RAD Studio, Delphi, C++Builder 12.0 Inline with Patch 1 Web Install
RAD Studio, Delphi, C++Builder 12.0 ISO
BDE for RAD Studio 12.0
Embarcadero General Packages Download for RAD Studio 12.0
『RAD Studio 12 Athens』の提供開始 (en)
Delphi/C++Builderライブラリに関する今後の展望 (en)
Android API 33サポートはRAD Studio 12ベータ(Yukon)で実施 (en)
Delphi言語: 文字列リテラルのモダナイゼーション (en)
Clang v15 compiler support coming to C++Builder 12
RAD Studio 12ベータ情報: マルチデバイスに対応したアイコンジェネレータ (en)
RAD Studio 12ベータ情報: 弱いエイリアスの導入による「NativeInt」の対応 (en)
RAD Studio 12のWin64 Clangツールチェーン (en)
[Yukon Beta Blog] C++ and Visual Assist in RAD Studio 12.0
Delphi 12における3 x 12 VCLの機能強化 (en)
Delphi 12における3 x 12 FireMonkeyとAndroidの機能強化 (en)
Delphi 12における3 x 12 データ、インターネット、RTLの機能強化 (en)
Delphi 12における 3 x 12 IDE、インストーラー、Delphi 言語の機能強化 (en)
Delphi 12向けに更新されたZXingデモアプリ(Android 13と iOS 17で動作済み)を公開 (en)
ウェビナーへ寄せられたRAD Studio 12 に関するQ&A (en)
Sqids: RAD Serverとの統合およびスタンドアロンライブラリ (en)
RAD Studio 12向けに新しいプレミアムスタイルを提供 (en)
Delphi / C++Builder 12のSkiaサポートで表現力豊かなUIを構築
GitHub - Embarcadero/RADStudio12Demos: Delphi and C++Builder Demos for Embarcadero RAD Studio version 12
2024/02/10追記: インストーラがPatch 1を含むものに差し替えられています。またBDEおよびEmbarcaderoが提供する主要なパッケージのローカルGetItパッケージもポータルサイトからダウンロードできるようになっています。
2023年11月1日
2023/11開催のセミナー
- Web Seminar
- 2023/11/13 16:00-17:00(JST) RAD Studio 12特集 - エンバカデロ・デベロッパーTV(2023年11月)
- Live Seminar
- Community Event
2023年10月19日
[書籍]C++ソフトウェア設計
紀伊國屋書店新宿本店でC++ Software Design (Amazon US)の翻訳である
C++ソフトウェア設計 (Amazon)/Klaus Iglberger著/千住治郎訳/オライリー・ジャパン/ISBN 978-4-8144-0045-4/4,400円
を購入。
C++ソフトウェア設計 (Amazon)/Klaus Iglberger著/千住治郎訳/オライリー・ジャパン/ISBN 978-4-8144-0045-4/4,400円
を購入。
2023年10月17日
InterBase 2020 Update 5
InterBase 2020 Update 5がリリースされています。バージョンは14.5.0.864となっています。
Release Notes for InterBase 2020U5 - InterBase
What's New in InterBase 2020 Update 5 - InterBase
Resolved Defects - InterBase
Embarcadero InterBase 2020 Update 5 のリリース (en)
Release Notes for InterBase 2020U5 - InterBase
What's New in InterBase 2020 Update 5 - InterBase
Resolved Defects - InterBase
Embarcadero InterBase 2020 Update 5 のリリース (en)
2023年10月11日
2023年10月2日
2023年10月1日
2023/10開催のセミナー
- Web Seminar
- 2023/10/31 17:00-17:45(JST) Web API再入門!RAD Serverを使おう - エンバカデロ・デベロッパーTV(2023年10月)
- Replay (1/1)
- 2023/10/31 17:00-17:45(JST) Web API再入門!RAD Serverを使おう - エンバカデロ・デベロッパーTV(2023年10月)
- Live Seminar
- Community Event
登録:
投稿 (Atom)