Темиргалеев Е. Э. Использование SET вместо ARRAY n OF BOOLEAN в CpcBeautifierOptions
CpcBeautifierOptions — модуль компонента CpcBeautifier, в котором (на момент написания этой заметки) для хранения набора переключателей в настройках используется булевый массив.
VAR param*: RECORD ... switch*: ARRAY 18 OF BOOLEAN END;
Нет никаких причин избегать1) использования типа SET2), эквивалентного3) ARRAY MAX(SET)+1 OF BOOLEAN4).
switch*: SET
В данном случае такая замена прежде всего приводит к приличному сокращению исходного текста, содержащего param.switch, что делает его более обозримым и ясным. Также несколько сокращается объём кода и данных.
Задание настроек по-умолчанию в процедуре ResetBeautifier:
param.switch[0] := FALSE; param.switch[1] := FALSE; param.switch[2] := FALSE; param.switch[3] := TRUE; param.switch[4] := FALSE; param.switch[5] := FALSE; param.switch[6] := FALSE; param.switch[7] := TRUE; param.switch[8] := TRUE; param.switch[9] := TRUE; param.switch[10] := TRUE; param.switch[11] := TRUE; param.switch[12] := TRUE; param.switch[13] := TRUE; param.switch[14] := TRUE; param.switch[15] := TRUE; param.switch[16] := FALSE; param.switch[17] := FALSE
param.switch := {3, 7..15}
Чтение/запись param.switch в процедурах DoLoadOptions и SaveOptions:
FOR i := 0 TO LEN(param.switch) - 1 DO rd.ReadBool(param.switch[i]) END и FOR i := 0 TO LEN(param.switch) - 1 DO wr.WriteBool(param.switch[i]) END
rd.ReadSet(param.switch) и wr.WriteSet(param.switch)
В процедурах-охраны вида
PROCEDURE XxxGuard* (VAR par: Dialog.Par); BEGIN par.disabled := ~param.switch[x] END XxxGuard;
будет замена
par.disabled := ~(x IN param.switch)
Замечание (не относится к использованию SET): соответствующие охраны SpacesProTabGuard, ProcedureColorGuard и CommentColorGuard могут быть заменены одной процедурой5):
PROCEDURE XxxGuard* (x: INTEGER; VAR par: Dialog.Par); BEGIN par.disabled := ~(x IN param.switch) (* ~param.switch[x] *) END XxxGuard;
07.06.2012
Исходник CpcBeautifierOptions
http://www.zinnamturm.eu/downloadsAC.htm#CpcBeautifier (Release 15-Mar-2012)
MODULE CpcBeautifierOptions; (* 2004-05-21 *) IMPORT Dialog, Files, Ports, StdLog, Stores; CONST optPath = "Cpc/Rsrc/"; optName = "Beautifier.opt"; (* -- switch: -- [0] = Clear Folds [9] = Space Operators -- [1] = Clear Rulers [10] = Space Parmeter Lists -- [2] = Clear Styles [11] = Bold Breaking Keywords -- -- [3] = Indent Check [12] = Bold Exported Names -- [4] = Change Spaces To Tab [13] = Color Procedure Names -- [5] = Remove Trailing Spaces [14] = Color Comments -- -- [6] = Remove Semicolons [15] = Sort Import List -- [7] = Remove Double Spaces [16] = Change Type -- [8] = Remove Single Spaces [17] = Fold Procedure *) VAR param*: RECORD spacesProTab*: INTEGER; procedureColor*: INTEGER; commentColor*: INTEGER; switch*: ARRAY 18 OF BOOLEAN; END; PROCEDURE SpacesProTabGuard* (VAR par: Dialog.Par); BEGIN par.disabled := ~param.switch[4]; END SpacesProTabGuard; PROCEDURE SpacesProTabNotifier* (op, from, to: INTEGER); BEGIN IF op = Dialog.changed THEN IF param.spacesProTab < 1 THEN param.spacesProTab := 1 END; IF param.spacesProTab > 9 THEN param.spacesProTab := 9 END; Dialog.Update(param); END; END SpacesProTabNotifier; PROCEDURE ProcedureColorGuard* (VAR par: Dialog.Par); BEGIN par.disabled := ~param.switch[13]; END ProcedureColorGuard; PROCEDURE CommentColorGuard* (VAR par: Dialog.Par); BEGIN par.disabled := ~param.switch[14]; END CommentColorGuard; PROCEDURE DoLoadOptions (): BOOLEAN; VAR i: INTEGER; rd: Stores.Reader; loc: Files.Locator; file: Files.File; BEGIN loc := Files.dir.This(optPath); IF loc # NIL THEN file := Files.dir.Old(loc, optName, FALSE); IF file # NIL THEN rd.ConnectTo(file); rd.ReadInt(param.spacesProTab); rd.ReadInt(param.procedureColor); rd.ReadInt(param.commentColor); FOR i := 0 TO LEN(param.switch) - 1 DO rd.ReadBool(param.switch[i]); END; file.Close; Dialog.Update(param); RETURN TRUE; END END; RETURN FALSE; END DoLoadOptions; PROCEDURE LoadOptions*; BEGIN IF ~DoLoadOptions() THEN StdLog.String("Error loading CpcBeautifier options"); StdLog.Ln; END; END LoadOptions; PROCEDURE SaveOptions*; VAR res, i: INTEGER; wr: Stores.Writer; loc: Files.Locator; file: Files.File; BEGIN loc := Files.dir.This(optPath); IF loc # NIL THEN file := Files.dir.New(loc, Files.dontAsk); IF file # NIL THEN wr.ConnectTo(file); wr.WriteInt(param.spacesProTab); wr.WriteInt(param.procedureColor); wr.WriteInt(param.commentColor); FOR i := 0 TO LEN(param.switch) - 1 DO wr.WriteBool(param.switch[i]); END; file.Register(optName, "", Files.dontAsk, res); IF res = 0 THEN RETURN END; END END; StdLog.String("Error saving CpcBeautifier options"); StdLog.Ln; END SaveOptions; PROCEDURE RGB (red, green, blue: INTEGER): INTEGER; BEGIN RETURN(blue * 256 + green) * 256 + red END RGB; PROCEDURE ResetBeautifier*; BEGIN param.spacesProTab := 3; param.procedureColor := RGB(172, 0, 0); (* red *) param.commentColor := RGB(0, 128, 64); (* green *) param.switch[0] := FALSE; param.switch[1] := FALSE; param.switch[2] := FALSE; param.switch[3] := TRUE; param.switch[4] := FALSE; param.switch[5] := FALSE; param.switch[6] := FALSE; param.switch[7] := TRUE; param.switch[8] := TRUE; param.switch[9] := TRUE; param.switch[10] := TRUE; param.switch[11] := TRUE; param.switch[12] := TRUE; param.switch[13] := TRUE; param.switch[14] := TRUE; param.switch[15] := TRUE; param.switch[16] := FALSE; param.switch[17] := FALSE; Dialog.Update(param); END ResetBeautifier; BEGIN IF ~DoLoadOptions() THEN ResetBeautifier; END; END CpcBeautifierOptions.