Сомневаюсь в выборе алгоритма хранения строк. Можно сделать как в LinePad'e, то есть выделяется один буффер с указателями на описания строк. А сами эти описатели вместе с строками хранить в куче. Однако так будет довольно трудно хранить большие объемы информации. Какие есть альтернативы?
А зачем кроме строк, и указателей, ещё и описатели? Для лишнего тормоза? Чтобы выбрать оптимальное, нужно определиться с тем, как будет осуществляться доступ к строкам, как они будут добавляться, удаляться и т.п.
А почему нельзя на манер борланда, хранить длину в первом дворде перед строкой. Так же кстати, и формат bstr работает: StrAddr - адрес начала строки dword ptr[StrAddr-4] - длина строки. И адресуешь либо StrAddr, если нужна строка, либо StrAddr-4, если нужна длина.
Ну я примерно так и делаю. TLine = packed record LineLen: DWORD; MemSize: DWORD; Str: array [0..0] of char; end; Но это мелочи, всё таки можно как то поэффективнее(чтобы побыстрее работало) хранить строки. У меня был вариант хранить не отдельно строки, а завести один буфер, и в массиве хранить номера первых символов строк.
Есть разные модели хранения строк. На мой взгляд лучше всего хранить вектор адресов, где каждый адрес указывает на описатель такого типа: Код (Text): typedef struct { header, containing line information: (room, length, collapsed, bookmarked, etc.) CHAR Text [2]; } LINEDEF; Размер аллокации = длина текста (выровненная на 16) + sizeof (LINEDEF); Если сделать собственный аллокатор, чтобы уменьшить избытки от Win32 HeapAlloc() - может получиться оптимально даже для больших файлов.
Такой вариант: выделять сразу относительно большой (на n строк) объём памяти, когда отпадает необходимость в строке, не освобождать память, занимаемую ею, а помечать как свободный этот участок. Полное удаление всего массива - в конце работы программы одним вызовом VirtualFree. Сделать массив таких описателей: Код (Text): s STRUCT maxLen DWORD len DWORD sPtr DWORD empty DWORD s ENDS При "удалении" строки, просто заносить в empty -1, как индикатор. При добавлении просматривать массив описателей на предмет if ( empty && maxLen >= newStrLen). Если найден соответствующий - записать в него данные новой строки, а саму строку записать поверх старой. Если нет удовлетворяющего условию - выделять новый кусок. maxLen будет равно len при первом заполнении памяти строками, при остальных - больше. Думаю, на отказе от постоянного выделения и освобождения будет сэкономлено достаточно много времени.
А встроенный Memory Manager так не делает (встроенный в Delphi)? Насколько я помню, он также помечает блок освобожденным. AsmGuru62 я пока так и делаю.
Как делает делфийский - не знаю, но на мой взгляд это много правильнее постоянных выделений/освобождений. Каждый вызов Virtual/HeapAlloc - это тысячи и десятки тысяч тактов. Поэтому логично свести количество вызовов к паре-тройке, чем вызывать для каждой строки.
очевидно, что проще, но, видимо, cresta хотел выровнять структуру (4x4) или для чего-то знать значение sPtr при empty -1 (вот только зачем?)