OberonCore
https://forum.oberoncore.ru/

Как оформлять копание в битах?
https://forum.oberoncore.ru/viewtopic.php?f=2&t=112
Страница 1 из 1

Автор:  Trurl [ Вторник, 07 Февраль, 2006 11:45 ]
Заголовок сообщения:  Как оформлять копание в битах?

Предположим, нам надо передававать данные в определенном двочном формате.
Какой вариант вам больше нравится?

1
Код:
IMPORT S:=SYSTEM, ..
TYPE
  Req = RECORD
    opcode : BYTE;
    mode    : BYTE;
    length  : SHORTINT;
    window  : INTEGER;
  END;
  AReq = ARRAY SIZE(Req) OF BYTE;

VAR rq:Req;
  ...
  rq.opcode := opcode;
  rq.mode  := mode;
  rq.length := length;
  rq.window := window;

  stream.WriteBytes(S.VAL(AReq, rq), 0,SIZE(Req),res);


2
Код:
CONST szReq =8;
VAR rq: ARRAY szReq OF BYTE;
    opcode : BYTE;
    mode    : BYTE;
    length  : SHORTINT;
    window  : INTEGER;

  ix:=0;
  S.PUT(S.ADR(rq[0]),opcode);
  S.PUT(S.ADR(rq[1]),mode);
  S.PUT(S.ADR(rq[2]),length);
  S.PUT(S.ADR(rq[4]),window);
  stream.WriteBytes(rq, 0,szReq,res);


3
Код:
CONST szReq =8;

  PROCEDURE WInt8(VAR b:ARRAY OF BYTE; VAR i: INTEGER; x: INTEGER);
  BEGIN
    b[i]:= SHORT(SHORT(x)); INC(i)
  END WInt8;
  ...

  VAR rq: ARRAY szReq OF BYTE;
    ix: INTEGER;

  ix:=0;
  WInt8(rq,ix,opcode);
  WInt8(rq,ix,mode);
  WInt16(rq,ix,length);
  WInt32(rq,ix,window);
  stream.WriteBytes(rq, 0,szReq,res);

Автор:  sacred [ Вторник, 07 Февраль, 2006 12:39 ]
Заголовок сообщения:  Re: Как оформлять копание в битах?

Trurl писал(а):
Предположим, нам надо передававать данные в определенном двочном формате.
Какой вариант вам больше нравится?


3- й вариант совсем не нравится. Вот это место: INC(i) внутри процедуры. Нафиг нам побочные эффекты?

Ну вообще 1-й вариант выглядит красивее всех. 2-й хуже из-за обилия дополнительных переменных. Но, хотя с другой стороны, это всё абстрактно, может в реальной задаче все эти переменные уже есть и тогда нет смысла их запихивать в запись.

Автор:  Сергей Губанов [ Вторник, 07 Февраль, 2006 14:11 ]
Заголовок сообщения:  Re: Как оформлять копание в битах?

Я за третий вариант. Только, чуток, подкрутил бы:
Код:
TYPE
  Writer* = RECORD
    offset*: INTEGER
  END;

  PROCEDURE (VAR this: Writer) WriteByte* (VAR dst: ARRAY OF BYTE; value: BYTE), NEW;
  BEGIN dst[this.offset] := value; INC(this.offset)
  END WriteByte;


wr.offset := 12;
wr.WriteByte(buffer, value1);
wr.WriteShort(buffer, value2);
wr.WriteInt(buffer, value3);

Модуль с таким Writer (и соответствующим Reader) можно потом повторно использовать для различных целей...

Автор:  Илья Ермаков [ Вторник, 07 Февраль, 2006 16:50 ]
Заголовок сообщения: 

По мне - первый либо третий.

Первый - проще и наглядней всех остальных.
У второго никаких преимуществ нет, при этом плодятся низкоуровневые VAL, в смещении каждого из которых можно ошибиться (опечататься) - предположим такую возможность :-)

Третий интересен попыткой обобщения.

Однако ни в одном, кроме первого, описание структуры данных явно не фигурирует, что не есть хорошо...

Автор:  Илья Ермаков [ Вторник, 07 Февраль, 2006 16:51 ]
Заголовок сообщения: 

А вообще говоря, обобщать нужно на уровне Writer, чтобы он принимал ANYREC, как это сделано в SqlDB.Exec и Table.

Автор:  Сергей Губанов [ Вторник, 07 Февраль, 2006 17:44 ]
Заголовок сообщения: 

Илья Ермаков писал(а):
Writer, чтобы он принимал ANYREC


О! Вот так бы лучше всего!!!

Автор:  Trurl [ Вторник, 07 Февраль, 2006 18:03 ]
Заголовок сообщения: 

Илья Ермаков писал(а):
Первый - проще и наглядней всех остальных.

С первым вот какие проблемы.
Разных форматов - порядка 100.
Некоторые имеют поле переменной длины – наглядность теряется.
Надо тщательно следить за выравниванием.

Цитата:
А вообще говоря, обобщать нужно на уровне Writer, чтобы он принимал ANYREC, как это сделано в SqlDB.Exec и Table.

Ну, что-то в этом роде есть
Код:
 PROCEDURE WRec(VAR b:ARRAY OF BYTE; VAR ix: INTEGER; IN r:ANYREC);
 VAR size: INTEGER;
 BEGIN
   S.GET(S.TYP(r),size);
   S.MOVE(S.ADR(r), S.ADR(b[ix]), size);
   INC(ix,size);
 END WRec;
 

Автор:  Trurl [ Вторник, 07 Февраль, 2006 18:06 ]
Заголовок сообщения:  Re: Как оформлять копание в битах?

Сергей Губанов писал(а):
Я за третий вариант. Только, чуток, подкрутил бы:
Код:
TYPE
  Writer* = RECORD
    offset*: INTEGER
  END;

  PROCEDURE (VAR this: Writer) WriteByte* (VAR dst: ARRAY OF BYTE; value: BYTE), NEW;
  BEGIN dst[this.offset] := value; INC(this.offset)
  END WriteByte;



Это было бы хорошо, если бы Writer хранил ссылку на массив. А так - бессмысленно.

Автор:  Сергей Губанов [ Среда, 08 Февраль, 2006 12:01 ]
Заголовок сообщения:  Re: Как оформлять копание в битах?

Trurl писал(а):
бессмысленно.


Код:
TYPE
  Packet* = RECORD
    length-: INTEGER;
    pos-: INTEGER;
    buff-: ARRAY 32768 OF BYTE (* столько хватит? *)
  END;

  PROCEDURE (VAR this: Packet) Clear*, NEW;
    VAR i: INTEGER;
  BEGIN this.length := 0; this.pos := 0;
    FOR i := 0 TO LEN(this.buff)-1 DO this.buff[i] := 0 END
  END Clear;

  PROCEDURE (VAR this: Packet) WriteByte* (value: BYTE), NEW;
  BEGIN ASSERT(this.pos < LEN(this.buff));
    this.buff[this.pos] := value; INC(this.pos);
    IF this.length < this.pos THEN this.length := this.pos END
  END WriteByte;

  PROCEDURE (VAR this: Packet) SetPos* (pos: INTEGER), NEW;
  ...

Автор:  Иван Горячев [ Четверг, 09 Февраль, 2006 02:27 ]
Заголовок сообщения:  Re: Как оформлять копание в битах?

Ну тогда уж:
Код:
TYPE
  Packet* = RECORD
    pos- : INTEGER; (* оно же length, обойдёмся без Seek() *)
    data- : POINTER TO ARRAY OF BYTE;
  END;

PROCEDURE (VAR p : Packet) Init* (length : INTEGER), NEW;
PROCEDURE (VAR p : Packet) WriteByte* (x : BYTE), NEW;
...
PROCEDURE SendPacket* (stream : Stream; p : Packet);
...

Страница 1 из 1 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/