dfm

package module
v1.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 9, 2022 License: MIT Imports: 10 Imported by: 1

README

Package dfm is a library, written in Go, to parse, pretty-print and/or generate Delphi's DFM files.

See the Godoc documentation for details of the API.

You can parse a DFM file with either of these functions:

dfm.ParseString(code string)
dfm.ParseBytes(code []byte)
dfm.ParseFile(path string)
dfm.ParseReader(r io.Reader)

which all return a pointer to a dfm.Object.

You can manipulate Objects in memory, either Objects that were parsed from an existing DFM file or you can create a new Object from scratch. These can be written back to file to be used in Delphi.

To generate code from an Object you can call one of these functions:

dfm.Object.Print() []byte
dfm.Object.String() string
dfm.Object.WriteTo(w io.Writer) error

The generated code is formatted exactly like RAD Studio XE4 formats it. It will almost always match the file byte for byte. The only known difference is that floating point numbers might appear slightly different, even though their values will be the same. In the 600 test files there were two where trailing zeros were clamped, this might have been done by hand though. This library was tweaked to match all of the available test DFM files exactly, except for these minor floating point formatting quirks. If you encounter any significant differences, please provide the sample DFM in a Github issue. The output DFMs will be encoded in ASCII, except if any of the identifiers use non-ASCII characters, in that case the code is encoded as UTF-8 and starts with the UTF-8 byte order mark. This matches RAD Studio behavior.

This library was tested against 600 DFM files from both the RAD Studio sources and production code from the company I work at. All files are parsed correctly and printed back to produce the exact same file as was input, except from two minor issues (see above). If you encounter any problems, please write a Github issue.

Documentation

Overview

Package dfm implements a Delphi DFM (.dfm) file parser, generator and printer.

Use any of these functions to parse a DFM file:

ParseString(code string)
ParseBytes(code []byte)
ParseFile(path string)
ParseReader(r io.Reader)

They all return a dfm.Object and error.

A DFM file contains one root Object which contains other objects and properties, forming a tree structure. Properties can be of types (see file dfm.go):

Int
Float
Bool
String
Identifier
Bytes
Set
Tuple
Items

You can maipulate the in-memory tree by replacing its nodes.

To write an Object to a file, use any of these functions:

Object.Print() []byte
Object.String() string
Object.WriteTo(w io.Writer) error

These will create an ASCII or UTF-8 encoded (depending on whether the DFM contains unicode characters in its identifiers) code file, readable by Delphi.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Bool

type Bool bool

Bool is either True or False.

type Bytes

type Bytes []byte

Bytes is a list of hexadecimal binary data in braces, e.g.:

{ FFAC2938AA991234A }

type Float

type Float float64

Float is a floating point number, e.g. 1.23 or 4.5E-6. Float values of NaN and +-Infinity will be printed as 0 since DFMs do not allow them.

type Identifier

type Identifier string

Identifier is a constant like clYellow, poMainFormCenter or FormResize.

type Int

type Int int

Int is a base 10 integer literal.

type Items

type Items [][]Property

Items is a list of property lists (2D list of properies), e.g.:

<
  item
    prop1 = 1
    prop2 = 2
  end
  item
    prop1 = 1
    prop2 = 2
  end>

type Object

type Object struct {
	// Name might be empty. In that case this is an anonymous object like
	//
	//     object TMenuItem
	//       Caption = '...'
	Name string
	Type string
	// Kind determines whether the keyword for the object is "object",
	// "inherited" or "inline".
	Kind ObjectKind
	// If HasIndex is true then the object has Index defined, if not there is no
	// index. Example:
	//
	//     object M: TMenuItem [0]
	//       ...
	//
	// would have HasIndex=true and Index=0.
	HasIndex   bool
	Index      int
	Properties []Property
}

Object can be a TPanel, TLabel, TForm, a sub-class of these or any other graphical element that can be defined in Delphi. It contains a list of properties, which can include child objects as well.

func ParseBytes

func ParseBytes(code []byte) (*Object, error)

ParseBytes expects the code to start with an object. The first object in the given code is parsed, if there are more, they are ignored. A DFM file typically has one top-level object defined in it. It might contain child objects however. The code is expected to be UTF-8 encoded. It may start with a UTF-8 byte oder mark (0xEF,0xBB,0xBF).

func ParseFile

func ParseFile(path string) (*Object, error)

ParseFile parses one object read from the given file. See ParseBytes.

func ParseReader

func ParseReader(r io.Reader) (*Object, error)

ParseReader parses one object read from the given io.Reader. See ParseBytes.

func ParseString

func ParseString(code string) (*Object, error)

ParseString parses one object read from the given file. See ParseBytes. The code must not start with a UTF-8 byte oder mark.

func (Object) Print

func (o Object) Print() []byte

Print returns the text representation of the Object as DFM code as bytes. Float values NaN and +-Infinity are printed as 0 since they are invalid in DFM files. If the Object contains unicode characters the return value will be encoded as UTF-8 and start with the UTF-8 byte order mark.

func (Object) String

func (o Object) String() string

String returns the text representation of the Object as DFM code. Float values NaN and +-Infinity are printed as 0 since they are invalid in DFM files. The string never contains a UTF-8 byte order mark. For that use Object.Print.

func (*Object) WriteTo

func (o *Object) WriteTo(w io.Writer) error

Write prints the text representation of the Object as DFM code to the given io.Writer. Float values NaN and +-Infinity are printed as 0 since they are invalid in DFM files. If the Object contains unicode characters the text will be encoded as UTF-8 and start with the UTF-8 byte order mark.

type ObjectKind

type ObjectKind int

ObjectKind represents the keyword used to define an object in the DFM.

const (
	// Plain objects have the keyword "object".
	Plain ObjectKind = 0
	// Inherited objects have the keyword "inherited".
	Inherited ObjectKind = 1
	// Inline objects have the keyword "inline".
	Inline ObjectKind = 2
)

func (ObjectKind) String

func (k ObjectKind) String() string

String returns the lower-case keyword for the object kind.

type Property

type Property struct {
	Name  string
	Value PropertyValue
}

Property is what is contained in an Object. Possible types are Int, Float, Bool, String, Identifier, Set, Tuple, Bytes, Items and Object. Except for Object, these will appear in the DFM file as:

<name> = <value>

where Name can contain dots, e.g. Font.Height. In case the Value is an Object, the Name is the same as the Object.Name.

type PropertyValue

type PropertyValue interface {
	// contains filtered or unexported methods
}

PropertyValue tags types that can be used for a Property.Value.

type Set

type Set []PropertyValue

Set is a set of flags in brackets like

[akLeft, akTop, akRight]

type String

type String string

String is a UTF-8 string without enclosing quotes and with quoted quotes unquoted. In Delphi we write

'a ''quoted'' string like this'#13#10

for which the value of the Go string will be:

"a 'quoted' string like this\r\n"

type Tuple

type Tuple []PropertyValue

Tuple is a tuple of values in parentheses, e.g.:

(123 456 789)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL