![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Тип AniString
Германн © (2011-05-13 02:30:00)Напомните мне пожалуйста какой смысл имеет (если имеет) для данного типа символ #0. Конкретно, функция Length его учитывает или нет?
Германн (2011-05-16 03:31:00) [1]
> Anatoly Podgoretsky © (15.05.11 07:32) [39]
>
> > Германн (15.05.2011 06:13:38) [38]
>
> Почему не убью, особенно для TCP/IP
>
Потому что лень будет разбираться с кодом. :)
Ведь вывод в визуальный контрол у меня не планируется даже. :)
Германн (2011-05-16 03:26:00) [2]
> бери мой, может подойдет
Странно, что ты в данном модуле не добавил свой привычный блок комментария об авторе кода. Я уже добавил в сей юнит комментарий, что сей юнит создан тобой. Но естественно я не помню, как ты оформляешь сей комментарий.
Германн (2011-05-16 01:04:00) [3]
> Германн © (16.05.11 00:37) [43]
>
>
> > DVM © (15.05.11 23:14) [40]
Хотя. На всякий случай код сохранил. Если задача усложнится, то он может пригодиться.
Германн (2011-05-16 00:37:00) [4]
> DVM © (15.05.11 23:14) [40]
>
>
> > Германн © (13.05.11 16:46) [14]
> >
> > > Для какой такой особой цели
> >
> > Приемный накопительный буфер.
>
> бери мой, может подойдет
>
Спасибо, хорошая штука. Но в моем случае это из пушки по воробьям.
DVM (2011-05-15 23:15:00) [5]
// Извлечение первых ACount символов с их удалением из буфера ------------------
function TBuffer.Extract(ACount: integer): PAnsiChar;
var
OldHead: PAnsiChar;
begin
if ACount > FSize then ACount := FSize;
if ACount < 0 then ACount := 0;
OldHead := FHead;
Inc(FHead, ACount);
Dec(FSize, ACount);
result := OldHead;
end;
//------------------------------------------------------------------------------
procedure TBuffer.Empty;
begin
FSize := 0;
FHead := FStorage;
FTail := FHead;
end;
//------------------------------------------------------------------------------
function TBuffer.Assign(AStorage: PAnsiChar; ASize: integer): integer;
begin
if Assigned(AStorage) and (ASize > 0) then
begin
FreeMem(FStorage, FAllocation);
FSize := ASize;
FAllocation := FSize;
GetMem(FStorage, FAllocation);
FHead := FStorage;
Move(AStorage^, FStorage^, FSize);
FTail := FHead + FSize;
end;
result := FSize;
end;
//------------------------------------------------------------------------------
function TBuffer.Assign(ABuffer: TBuffer): integer;
begin
result := Assign(ABuffer.Storage, ABuffer.Size);
end;
//------------------------------------------------------------------------------
destructor TBuffer.Destroy;
begin
FreeMem(FStorage, FAllocation);
inherited Destroy;
end;
//------------------------------------------------------------------------------
function TBuffer.GetBytes(Index: Integer): PAnsiChar;
begin
result := Head + Index;
end;
//------------------------------------------------------------------------------
procedure TBuffer.Tidy;
begin
if FHead <> FStorage then
begin
if FSize = 0 then
begin
FHead := FStorage;
FTail := FHead;
end
else
begin
Move(FHead^, FStorage, FSize);
FHead := FStorage;
FTail := FHead + FSize;
end;
end;
end;
//------------------------------------------------------------------------------
function TBuffer.IsEmpty: boolean;
begin
result := FSize = 0;
end;
//------------------------------------------------------------------------------
procedure TBuffer.Compact;
var
Temp: PAnsiChar;
begin
if FSize > 0 then
begin
GetMem(Temp, FSize);
Move(FHead^, Temp^, FSize);
FreeMem(FStorage, FAllocation);
FStorage := Temp;
FAllocation := FSize;
end
else
begin
FreeMem(FStorage, FAllocation);
FSize := 0;
FAllocation := MinAllocation;
GetMem(FStorage, FAllocation);
end;
FHead := FStorage;
FTail := FHead + FSize;
FAllocation := FSize;
end;
//------------------------------------------------------------------------------
end.
DVM (2011-05-15 23:15:00) [6]
implementation
//------------------------------------------------------------------------------
constructor TBuffer.Create;
begin
Create(0);
end;
//------------------------------------------------------------------------------
constructor TBuffer.Create(ASize: integer);
begin
if ASize > 0 then
FAllocation := ASize
else
FAllocation := MinAllocation;
FSize := 0;
GetMem(FStorage, FAllocation);
FHead := FStorage;
FTail := FHead;
end;
//------------------------------------------------------------------------------
constructor TBuffer.Create(AStorage: PAnsiChar; ASize: integer);
begin
if (ASize > 0) and Assigned(AStorage) then
begin
FAllocation := ASize;
FSize := ASize;
GetMem(FStorage, FAllocation);
FHead := FStorage;
Move(AStorage^, FStorage^, ASize);
FTail := FHead + FSize;
end
else
Create;
end;
//------------------------------------------------------------------------------
constructor TBuffer.Create(ABuffer: TBuffer);
begin
if (Assigned(ABuffer)) and (ABuffer.Size > 0) then
begin
FAllocation := ABuffer.Size;
FSize := ABuffer.Size;
GetMem(FStorage, FAllocation);
FHead := FStorage;
Move(ABuffer.Storage^, FStorage^, ABuffer.Size);
FTail := FHead + FSize;
end
else
Create;
end;
//------------------------------------------------------------------------------
procedure TBuffer.SetSize(ASize: integer);
begin
if FSize <> ASize then
begin
if FSize < ASize then
Expand(ASize)
else
begin
FSize := ASize;
FTail := FHead + FSize;
end;
end;
end;
// Отсекает первые ACount символов ----------------------------------------------
function TBuffer.Consume(ACount: integer): integer;
begin
if ACount > FSize then ACount := FSize;
if ACount < 0 then ACount := 0;
FHead := FHead + ACount;
FSize := FSize - ACount;
Result := ACount;
end;
// Отсекает последние ACount символов -------------------------------------------
function TBuffer.Shrink(ACount: integer): integer;
begin
if ACount > FSize then ACount := FSize;
if ACount < 0 then ACount := 0;
FSize := FSize - ACount;
if FTail > FHead + FSize then FTail := FHead + FSize;
Result := ACount;
end;
// Расширение буфера -----------------------------------------------------------
function TBuffer.Expand(ACount: integer): integer;
var
Spare, HeadSpace, TailSpace, Width, OldAllocation: integer;
NewStorage: PAnsiChar;
begin
result := FSize;
if ACount <= 0 then exit;
// Свободный (незанятый) объем буфера
Spare := FAllocation - FSize;
// Свободное место в начале буфера
HeadSpace := FHead - FStorage;
// Свободное место в конце буфера
TailSpace := Spare - HeadSpace;
// Размер (ширина) занятой части буфера
Width := Tail - Head;
// Если в буфере есть достаточно свободного места для добавления ACount байт
if Spare >= ACount then
begin
// Если хвост меньше чем надо добавить
if TailSpace < ACount then
begin
// Двигаем полезные данные в начало буфера
Move(FHead^, FStorage^, FSize);
// Начало данных совпадает с началом буфера
FHead := FStorage;
// Хвост данных на расстоянии width от головы
FTail := FHead + Width;
end;
end
else
// Если в буфере недостаточно места для добавления count символов
begin
OldAllocation := FAllocation;
// Общий объем буфера увеличиваем на count
FAllocation := FAllocation + ACount;
// Создаем временный буфер нужного размера
GetMem(NewStorage, FAllocation);
FillChar(NewStorage^, FAllocation, 0);
if FStorage <> nil then
begin
// Копируем в него данные из старого буфера
Move(FHead^, NewStorage^, FSize);
// Старый буфер удаляем
FreeMem(FStorage, OldAllocation);
end;
// Новый буфер заменяет старый
FStorage := NewStorage;
// Данные в начале буфера
FHead := FStorage;
// Хвоcт на расстоянии width от головы буфера
FTail := FHead + Width;
end;
// Устанавливаем новый размер буфера
FSize := FSize + ACount;
// Возвращаем новый размер
result := FSize;
end;
// Добавление данных в конец буфера --------------------------------------------
function TBuffer.Append(AStorage: PAnsiChar; ASize: integer): integer;
begin
if Assigned(AStorage) and (ASize > 0) then
begin
Expand(ASize);
Move(AStorage^, FTail^, ASize);
FTail := FTail + ASize;
end;
result := FSize;
end;
// Добавление данных в конец буфера --------------------------------------------
function TBuffer.Append(ABuffer: TBuffer): integer;
begin
result := Append(ABuffer.Storage, ABuffer.Size);
end;
DVM (2011-05-15 23:14:00) [7]
> Германн © (13.05.11 16:46) [14]
>
> > Для какой такой особой цели
>
> Приемный накопительный буфер.
бери мой, может подойдет
unit uBuffer;
interface
const
MinAllocation = 1024;
type
TBuffer = class(TObject)
private
FStorage: PAnsiChar;
FAllocation: integer;
FHead: PAnsiChar;
FTail: PAnsiChar;
FSize: integer;
function GetBytes(Index: Integer): PAnsiChar;
procedure SetSize(ASize: integer);
public
constructor Create; overload;
constructor Create(ASize: integer); overload;
constructor Create(AStorage: PAnsiChar; ASize: integer); overload;
constructor Create(ABuffer: TBuffer); overload;
destructor Destroy; override;
function Append(ABuffer: TBuffer): integer; overload;
function Append(AStorage: PAnsiChar; ASize: integer): integer; overload;
function Assign(AStorage: PAnsiChar; ASize: integer): integer; overload;
function Assign(ABuffer: TBuffer): integer; overload;
function Consume(ACount: integer): integer;
procedure Empty;
procedure Compact;
function IsEmpty: boolean;
function Expand(ACount: integer): integer;
function Extract(ACount: integer): PAnsiChar;
function Shrink(ACount: integer): integer;
procedure Tidy;
property Head: PAnsiChar read FHead;
property Size: integer read FSize write SetSize;
property Storage: PAnsiChar read FStorage;
property Tail: PAnsiChar read FTail;
property Allocation: integer read FAllocation;
property Bytes[Index: Integer]: PAnsiChar read GetBytes;
end;
Anatoly Podgoretsky (2011-05-15 07:32:00) [8]> Германн (15.05.2011 06:13:38) [38]
Почему не убью, особенно для TCP/IP
Германн (2011-05-15 06:13:00) [9]
> Германн © (14.05.11 02:28) [37]
Значится так.
По протоколу TCP/IP посылаю сам себе и получаю от самого себя некие команды. Команды посылаются в текстовом виде типа "CCCxxx..x#13". Где CCC - трёхбуквенный идентификатор команды, xxx..x - параметры команды произвольной длины, #13 признак конца команды. (Да не убъёт меня АП за отсутствие #10).
Сейчас принял такое решение. Для приемного накопительного буфера использую "настоящий" PAnsiChar. Zero-based array не прошёл по ряду причин. В обработчике события OnDataAvailable (библиотека ICS) ввёл локальную переменную типа AnsiString, в которую "копирую" содержимое данного буфера. Далее работаю в этом обработчике со строкой, применяя функциb Pos и Delete при разборке содержимого/принятого. По завершении обработки сохраняю остаток в буфере типа
MyStr:=PAnsiChar(St);
Превышения размера принятых данных более установленного при создании объекта вроде быть не должно, но это я частично учел. При приёме я проверяю размер уже существующих данных в буфере плюс принятых только что.
Германн (2011-05-14 02:28:00) [10]
> sniknik © (13.05.11 21:59) [27]
>
> > У строк куча готовых функций типа Copy, Pos etc. Простое
> сложение двух строк опять же.
> и что? нет, не пойму, серьезно. понятно когда чего-то нет
> и поэтому использовать не удобно, но когда есть что-то дополнительное,
> пусть не нужное, при прочих равных, ну и что? не используй
> и все.
>
> вот когда говорят - у велосипеда нет колес, одна голая рама,
> поэтому ездить на нем не могу. это понятно. а вот когда
> - у велосипеда куча запасных колес, плюс насосы, и т.д.
> всякие фенечки, гараж, и бесплатная обслуга, поэтому ездить
> на нем не могу.... ????? на тебя же это добро не навьючивают,
> обслуживать тебя самого не заставляют, оно есть и есть,
> чем нужно воспользуешься, что не нужно, пусть в гараже
> лежит. непонятно в общем.
>
> ты бы "на пальцах" как для идиотов пояснил бы.
Сегодня уже не в состоянии.
Anatoly Podgoretsky (2011-05-13 23:48:00) [11]> sniknik (13.05.2011 22:37:33) [33]
Да они просто нагнали страху, мол размер будет неправильный, ну и что?
sniknik (2011-05-13 23:07:00) [12]> чтобы потом не переписывать.
тут тоже без разницы, что массив использовать, что строку. с обоими можно написать так, что придется, или не придется переписывать.
хотя мой опыт подсказывает, чем меньше "закладок на будущее", усилий по "несуществующей еще совместимости", и больше внимание на текущее, тем без проблемней проект... а будущее, для какого то конкретного, может (и в 90% точно) и не наступит.
т.е. подавляющее большинство усилий на то "чтобы завтра было хорошо" тратится впустую. не тратить их вовсе, и когда понадобится просто переписать по новой/изменить было бы проще (но все одно тратят).
Eraser (2011-05-13 22:40:00) [13]> [31] Anatoly Podgoretsky © (13.05.11 22:17)
так в том то и дело, не удивлюсь, что скоро проект придется переделывать на юникод, почему бы не сделать сразу так, чтобы потом не переписывать.
sniknik (2011-05-13 22:37:00) [14]> Они это утверждают в связи с Юникод, но кто же мешает вместо String написать AnsiString
на самом деле, даже если написать WideString ничего не помешает использовать его как буфер под байты... единственное удобство потеряется, т.к. самому придется все высчитывать, а вот проблем от (цитата статьи) "или использует строку как буфер для данных" не вижу, и никогда не испытывал. в отличие от "в которых несколько разработчиков", тут постоянно, но только строки/буферы данных/и т.д. в этом не виноваты...
sniknik (2011-05-13 22:26:00) [15]> Кроме того и SetLength можно делать один раз и никакой разницы с
> array[0.1023] of char
> Кроме удобства
именно, все тоже, только удобнее, память не выделять, и есть дополнительные функции обработки.
единственное условие, не путать char и widechar, но как будто с массивом или pchar по другому, и решается все одним, правильным, объявлением типа, дальше оно тебе само врнинги и ошибки будет показывать...
и если не видно разницы... то выбирают почему то "по грязнее", чтобы еще ручной стирки досталось, вместо - "узнать побольше, и делать поменьше".
не понятно.
Anatoly Podgoretsky (2011-05-13 22:17:00) [16]> Eraser (13.05.2011 22:00:28) [28]
Они это утверждают в связи с Юникод, но кто же мешает вместо String написать
AnsiString
Anatoly Podgoretsky (2011-05-13 22:13:00) [17]> sniknik (13.05.2011 20:19:23) [23]
Так и массив можно объявить с 1
Кроме того и SetLength можно делать один раз и никакой разницы с
array[0.1023] of char
Кроме удобства
Anatoly Podgoretsky (2011-05-13 22:08:00) [18]> Германн (13.05.2011 17:32:17) [17]
vs GetMem и плюс еще FreeMem
Eraser (2011-05-13 22:00:00) [19]> [22] Германн © (13.05.11 20:19)
я всего лишь повторяю то, что рекомендует embarcadero http://edn.embarcadero.com/article/38703. Практика это подтверждает, очень часто рассадник багов именно там, где используют строку, как буфер для любых данных. Особенно в крупных проектах, в которых несколько разработчиков.
sniknik (2011-05-13 21:59:00) [20]> У строк куча готовых функций типа Copy, Pos etc. Простое сложение двух строк опять же.
и что? нет, не пойму, серьезно. понятно когда чего-то нет и поэтому использовать не удобно, но когда есть что-то дополнительное, пусть не нужное, при прочих равных, ну и что? не используй и все.
вот когда говорят - у велосипеда нет колес, одна голая рама, поэтому ездить на нем не могу. это понятно. а вот когда - у велосипеда куча запасных колес, плюс насосы, и т.д. всякие фенечки, гараж, и бесплатная обслуга, поэтому ездить на нем не могу.... ????? на тебя же это добро не навьючивают, обслуживать тебя самого не заставляют, оно есть и есть, чем нужно воспользуешься, что не нужно, пусть в гараже лежит. непонятно в общем.
ты бы "на пальцах" как для идиотов пояснил бы.