powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / NextGen compiler и AnsiString
18 сообщений из 118, страница 5 из 5
NextGen compiler и AnsiString
    #38949015
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev AlexeyAleksandr SharahovТолько достает обходить.
Это и есть реальная проблема?

Реальная проблема - скорость в многопоточных приложениях, в пользовательском интерфейсе или в неумелых руках. И примеров тому море.

Вот из недавнего прошлого. Есть процедура, которая вызывается из UI. Интенсивно использует строки, варианты и прочее колдунство. Работает ~11 сек, что естественно нервирует пользователя. Ценой различных извращений время удалось снизить до 3 сек. Уверен, если бы у разработчиков не было под рукой всего этого супер-арсенала, время работы процедуры было бы в районе 0.3-0.5 сек.

Вот из очень далекого. Программист, который в жизни своей написал всего-то две-три прожки длиной больше 500 строк, ни с того ни с сего принялся писать довольно эффективные программы, в которых и строк было в достатке, и вычислений. А все потому, что в тогдашнем компиляторе всего этого супер-арсенала не было.
...
Рейтинг: 0 / 0
NextGen compiler и AnsiString
    #38949040
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TASM.EXE вам в руки.
...
Рейтинг: 0 / 0
NextGen compiler и AnsiString
    #38949070
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov, что, как-то, быстро ты перешёл от COW на управляемые типы вообще.
...
Рейтинг: 0 / 0
NextGen compiler и AnsiString
    #38949228
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev Alexey, ты хочешь поговорить об этом? только теперь не знаю уже, стоит ли.
...
Рейтинг: 0 / 0
NextGen compiler и AnsiString
    #38949302
Cobalt747
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev AlexeyCobalt747Копировать ему в буфер сразу, и пусть с ним делает всё что захочет.
Наличие COW, как раз, и позволяет избегать ненужных копирований.

BeltarВообще у любого нормального человека при работе с компом вырабатывается правило, прежде чем что-то править, делай копии и сохраняйся, как можно чаще, если не вырабатывается, то таких нельзя к компам на пушечный выстрел подпускать.
...
Рейтинг: 0 / 0
NextGen compiler и AnsiString
    #38949339
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahovтолько теперь не знаю уже, стоит ли.
Не держи в себе.

Cobalt747BeltarВообще у любого нормального человека при работе с компом вырабатывается правило, прежде чем что-то править, делай копии и сохраняйся, как можно чаще, если не вырабатывается, то таких нельзя к компам на пушечный выстрел подпускать.
Ты сейчас о чём, вообще???
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
NextGen compiler и AnsiString
    #39618996
PalychXX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вот и я столкнулся с забавной ситуацией, когда при попытке перенести на Delphi 10.1/10.2 приличный объем кода с VCL (который изначально не предполагалось портировать под другие платформы) на Android радостно все отладил в FM под Виндой, а потом сменил платформу и вылезли грабли отсутствия типа AnsiString для Андроид.
В коде много строк в DOS-кодировке (идет работа с различным железом):
Код: pascal
1.
2.
type
  DosString = type AnsiString(866);


Было очень удобно совмещать такой тип с юникодом (задал кодировку и можно присваивать юникодную строку даже без явного приведения типа если уверен, что кроме латинских символов и кириллицы ничего нет) и копировать данные Move() в буфер для передачи в железо или обратно.
Попробовал хак из первого сообщения темы, только более свежую версию для D10.1 - для Андроида получил ошибку при попытке объявить тип "DosString = type AnsiString(866);" и заметил, что для Андроида при использовании Move начальным элементом анси-строки является нулевой элемент.
Еще вместо AnsiString попробовал RAWByteString и SetCodePage (небольшие задержки не критичны). Но тут если сменил кодировку на CP866, то и добавлять нужно тоже в этой же кодировке или сначала формировать все в Win1251 и только перед передачей в железку менять кодировку. Видимо, по этому пути и придется идти, но все это займет прилично времени на модификацию кода и как бы где-то чего-то не забыть.
Поэтому на всякий случай хочу спросить, может кто уже нашел более изящное решение для такой задачи и ему будет не жалко поделиться своими мыслями.
З.Ы. Попробовал и вот такой "велосипед" , но на 10.1/10.2 он сходу не завелся. Попробовал поправить ошибки насколько я понял смысл действий автора - не сработало даже банальное присваивание значения строке, не говоря уже об автоматической конвертации кодировок.
...
Рейтинг: 0 / 0
NextGen compiler и AnsiString
    #39619001
Фотография krapotkin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вот поэтому всегда говорилось - не используйте хаки типа
PalychXXможно присваивать юникодную строку даже без явного приведения типа если уверен
INDY вообще тотально вместо массива байт строки гоняло
ни к чему хорошему это не приводит
если есть кодировки, то можно пользоваться TStringStream с явным указанием Encoding
там все будет перекодировываться нормально.
...
Рейтинг: 0 / 0
NextGen compiler и AnsiString
    #39619148
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PalychXX,

Придётся писать костыли, никуда не денешься
...
Рейтинг: 0 / 0
NextGen compiler и AnsiString
    #39619235
PalychXX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
krapotkinможно пользоваться TStringStream с явным указанием Encoding
Спасибо, но вот сходу не понял, как там явно указать кодировку (такое свойство есть, но ReadOnly).
...
Рейтинг: 0 / 0
NextGen compiler и AnsiString
    #39619259
PalychXX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А, понял, ее при создании экземпляра можно указать:
Код: pascal
1.
ss := TStringStream.Create('', TEncoding.ANSI.GetEncoding(866));


Еще раз спасибо!
...
Рейтинг: 0 / 0
NextGen compiler и AnsiString
    #39619364
Василий №2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вот когда хотя бы Pos сделают для TBytes, можно будет начать говорить о ненужности однобайтовых строк.
...
Рейтинг: 0 / 0
NextGen compiler и AnsiString
    #39619444
PalychXX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Попробовал вместо велосипеда на скорую руку сделать самокат, чтобы как-то приблизить функционал к AnsiString:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
const
  DefCodePage = 1251;

type
  MyString = packed record
    private
      ss: TStringStream;
      function GetData(a: integer): Char;
      procedure SetData(a: integer; const Value: Char);
    public
      class operator Implicit(a: String): MyString;
      property Data[a: integer]: Char Read GetData Write SetData; Default;
      Constructor Create(const CodePage: Cardinal);
      procedure Free;
  end;

implementation

{ MyString }

constructor MyString.Create(const CodePage: Cardinal);
begin
  ss := TStringStream.Create('', TEncoding.ANSI.GetEncoding(CodePage));
end;

procedure MyString.Free;
begin
  FreeAndNil(Self.ss);
end;

function MyString.GetData(a: integer): Char;
begin
  Result := ss.DataString[a];
end;

class operator MyString.Implicit(a: String): MyString;
var
  r: MyString;
begin
  R.Create(DefCodePage);
  R.ss.Clear;
  R.ss.WriteString(a);
  Result := r;
  //R.Free;
end;

procedure MyString.SetData(a: integer; const Value: Char);
var
  s: string;
begin
  s := ss.DataString;
  s[a] := Value;
  ss.Clear;
  ss.WriteString(s);
end;



Если оставить все как есть и в цикле присвоить сотню раз переменной одну и ту же строку:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
var
  ds: MyString;
  i: Integer;
begin
  ds := MyString.Create(866);
  for i := 1 to 100 do
    ds := 'Проверка связи';
  //ds := ds + ' 123';
  ShowMessage('ds[1] = ' + ds[1]);
end;


то при ReportMemoryLeaksOnShutdown := true; на выходе вижу инфу об утечках памяти:
---------------------------
Unexpected Memory Leak
---------------------------
An unexpected memory leak has occurred. The unexpected small block leaks are:
21 - 28 bytes: TMBCSEncoding x 100
29 - 36 bytes: TStringStream x 100
The sizes of unexpected leaked medium and large blocks are: 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236, 8236
---------------------------
ОК
---------------------------

Если раскомментировать в MyString.Implicit строку "R.Free;", то обращение к ds.ss[1] ожидаемо выдает Access violation.

Столкнулся с проблемой создания автоматического деструктора для записи. На stackoverflow был совет делать так:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
TMyRecord = record
  obj: TMyObject;
  guard: IInterface;
end;

rec.obj := TMyObject.Create;
rec.guard := rec.obj;



Но Дельфа шлет меня лесом - TStringStream это не IInterface.
...
Рейтинг: 0 / 0
NextGen compiler и AnsiString
    #39619509
Василий №2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
У записей деструкторов пока не сделали. Так что придется обернуть объект в интерфейс (потомок interfacedobject, чья единственная функция - в деструкторе делать Free объекту, с которым он связан).
...
Рейтинг: 0 / 0
NextGen compiler и AnsiString
    #39619518
GunSmoker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Достаточно type TInterfacedStringStream = class(TStringStream, IInterface) + скопировать реализацию TInterfacedObject.
...
Рейтинг: 0 / 0
NextGen compiler и AnsiString
    #39619653
PalychXX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо! Но, пожалуйста, изложите последние 2 совета чуть развернутей.
Попробовал второй:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
  TInterfacedStringStream = class(TStringStream, IInterface)
{$IFNDEF AUTOREFCOUNT}
  private const
    objDestroyingFlag = Integer($80000000);
    function GetRefCount: Integer; inline;
{$ENDIF}
  protected
{$IFNDEF AUTOREFCOUNT}
    [Volatile] FRefCount: Integer;
    class procedure __MarkDestroying(const Obj); static; inline;
{$ENDIF}
    function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
    function _AddRef: Integer; stdcall;
    function _Release: Integer; stdcall;
  public
{$IFNDEF AUTOREFCOUNT}
    procedure AfterConstruction; override;
    procedure BeforeDestruction; override;
    class function NewInstance: TObject; override;
    property RefCount: Integer read GetRefCount;
{$ENDIF}
  end;

...

{ TInterfacedStringStream }

{$IFNDEF AUTOREFCOUNT}
function TInterfacedStringStream.GetRefCount: Integer;
begin
  Result := FRefCount and not objDestroyingFlag;
end;

class procedure TInterfacedStringStream.__MarkDestroying(const Obj);
var
  LRef: Integer;
begin
  repeat
    LRef := TInterfacedStringStream(Obj).FRefCount;
  until AtomicCmpExchange(TInterfacedStringStream(Obj).FRefCount, LRef or objDestroyingFlag, LRef) = LRef;
end;

procedure TInterfacedStringStream.AfterConstruction;
begin
// Release the constructor's implicit refcount
  AtomicDecrement(FRefCount);
end;

procedure TInterfacedStringStream.BeforeDestruction;
begin
  if RefCount <> 0 then
    Error(reInvalidPtr);
end;

// Set an implicit refcount so that refcounting during construction won't destroy the object.
class function TInterfacedStringStream.NewInstance: TObject;
begin
  Result := inherited NewInstance;
  TInterfacedStringStream(Result).FRefCount := 1;
end;

{$ENDIF AUTOREFCOUNT}

function TInterfacedStringStream.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
  if GetInterface(IID, Obj) then
    Result := 0
  else
    Result := E_NOINTERFACE;
end;

function TInterfacedStringStream._AddRef: Integer;
begin
{$IFNDEF AUTOREFCOUNT}
  Result := AtomicIncrement(FRefCount);
{$ELSE}
  Result := __ObjAddRef;
{$ENDIF}
end;

function TInterfacedStringStream._Release: Integer;
begin
{$IFNDEF AUTOREFCOUNT}
  Result := AtomicDecrement(FRefCount);
  if Result = 0 then
  begin
    // Mark the refcount field so that any refcounting during destruction doesn't infinitely recurse.
    __MarkDestroying(Self);
    Destroy;
  end;
{$ELSE}
  Result := __ObjRelease;
{$ENDIF}
end;



А запись можно оставить как есть, просто добавить поле guard: IInterface; и в конструкторе сделать Self.guard := TInterfacedStringStream(Self.ss)? Компилируется, но на этйо строчке AV вылетает. ЧЯДНТ?
...
Рейтинг: 0 / 0
NextGen compiler и AnsiString
    #39620020
PalychXX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Эх, просто не сразу догадался поменять тип в записи:
Код: pascal
1.
ss: TInterfacedStringStream {TStringStream};


После этого вроде бы все заработало. Всем большое спасибо!!!
...
Рейтинг: 0 / 0
NextGen compiler и AnsiString
    #39620362
Василий №2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ну... так, конечно, тоже можно, но слишком уж сложно.
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
  // Интерфейс-контейнер для объекта временного запроса. Удаляется при выходе
  // за границы области видимости.

  IAutoFreeQuery = interface
    function GetQuery: TQuery;
  property
    Query: TQuery read GetQuery;
  end;

  TAutoFreeQuery = class(TInterfacedObject, IAutoFreeQuery)
  private
    FQuery: TQuery;
  public
    destructor Destroy; override;
    function GetQuery: TQuery;
  end;

destructor TAutoFreeQuery.Destroy;
begin
  FreeAndNil(FQuery);
  inherited;
end;

function TAutoFreeQuery.GetQuery: TQuery;
begin
  Result := FQuery;
end;

// Создает обернутый в интерфейс (самоудаляемый) запрос для временных манипуляций
function TfrmMain.GetTempQuery: IAutoFreeQuery;
var res: TAutoFreeQuery;
begin
  res := TAutoFreeQuery.Create;
  res.FQuery := TQuery.Create(Self);
  res.FQuery... := ...;
  Result := res;
end;



Можно расширить на любой класс содержимого с помощью дженериков
...
Рейтинг: 0 / 0
18 сообщений из 118, страница 5 из 5
Форумы / Delphi [игнор отключен] [закрыт для гостей] / NextGen compiler и AnsiString
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]