Pointer - требуется уточнение

Общие вопросы программирования, алгоритмы и т.п.

Модератор: Модераторы

Pointer - требуется уточнение

Сообщение vitaly_l » 31.03.2013 14:15:17

Всем привет и всем хорошего настроения!

дано:
Код: Выделить всё
type
  AAB=array [0..65535] of byte;
  PAAB=^AAB;
const
  HD: array [0..$F] of char = '0123456789ABCDEF';
var
  FData : Pointer;

В память с указателем FData - из TStream, считываются и заменяются разные данные с разным объёмом и содержимым из одного файла;
Задача: нужно их декодировать.

1) Если вывести for i:=0 to DataSize do TMemo.Add(HD[PPD^ shr 4]+HD[PPD^[i] and $F]);, то в TMemo заносится всё содержимое FData и там есть все данные которые нужны. Задача: нужно их декодировать. Но данные не подвержены, какой-то стабильной структуре и в зависимости от содержимого структура FData меняется. По сути там записаны примерно такие данные:
"DAT1" = 12;
"DAT2" = 12.12341234;
"DAT3" = ''привет';
"DAT4" = (1)|(3)|(5);
"DAT5" = DAT8 := любой из "DAT1"..."DAT7";
"DAT6" = (11.1234)|(2.45634)|(5.3576);
"DAT7" = FSubData; // ещё одна FData в которой лежат array of "DAT1", "DAT2", "DAT3", "DAT4", "DAT5" итд

Задача: Нужно вывести: var dat1 := его значение; var dat2 := его значение; var dat3 := его значение; итд
При этом "DAT1"..."DAT7" - не обязательно имеют такой порядок и необязательно могут быть все... (могут быть только "DAT1" и "DAT5")...

2) Если вывести TMemo.Add(PChar(FData)); то выводится первые четыре буквы из FData, на подобии "DAT1", "DAT2" или "DAT3" итп.
:?: Вопрос: Правильно ли я понимаю, что после первых четырёх символов стоит "#0" и поэтому PChar(FData) выводит только первые 4 буквы?

При этом, если сделать if (PChar(FData) = "DAT3") then ShowMessage('DAT3');, то ничего не будет, хотя в TMemo "DAT3" - запишется. :?: Почему так? :?: Или "#0" стоит после ещё каких-то символов, поэтому PChar(FData) не равно "DAT3"?


Вопросы:
:?: Существуют ли, стандартные схемы чтения и декодирования таких данных или это всегда согласовывается в SDK?
:?: Как правильно узнавать объём памяти зарезервированный указателем FData?
:?: Как правильно читать память с указателем FData не с первого символа, а например с 12?
:?: Как правильно узнавать длину кусочка FData от 12 символа и до знака "#0"? (Если я правильно понимаю в FData может быть много "#0" ?)
:?: Можно ли указатель FData разбить на много под-указателей на подобии FDataDAT1^, FDataDAT2^, FDataDAT3^ и т.д. в соответствии с разделением по "#0", если оно существует или в соответствии с делением на: "DAT1", "DAT2" или "DAT3" итп.?
:!: Любая дополнительная информация востребована.

PS: [i]Заранее благодарен за любой информативный ответ.




.
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41

Re: Pointer - требуется уточнение

Сообщение bormant » 31.03.2013 14:45:10

vitaly_l писал(а):если сделать if (PChar(FData) = "DAT3") then ShowMessage('DAT3');, то ничего не будет, хотя в TMemo "DAT3" - запишется. Почему так?
Потому что указатель FData не равен адресу, по которому компилятор поместил временное значение "DAT3".
Аватара пользователя
bormant
постоялец
 
Сообщения: 407
Зарегистрирован: 21.03.2012 11:26:01

Re: Pointer - требуется уточнение

Сообщение vitaly_l » 31.03.2013 15:04:41

bormant писал(а):Потому что указатель FData не равен адресу, по которому компилятор поместил временное значение "DAT3".

В моём примере: "DAT3" - это значение равнозначное string, а не название переменной содержащей адрес.
PChar(FData) возвращает значение, которое можно присвоить string - правильно? PChar(FData) - возвращает "привет"... Я уточняю:
if (PChar(FData) = "привет")?, она говорит нет... Я ей говорю тогда выведи TMemo.Add(PChar(FData)); - она печатает "привет"... Я у неё, у машины,
спрашиваю If ("привет" = "привет")? - разве это не так?

Добавлено спустя 9 минут 14 секунд:
Эти вопросы - все в силе:
:?: Существуют ли, стандартные схемы чтения и декодирования таких данных или это всегда согласовывается в SDK?
:?: Как правильно узнавать объём памяти зарезервированный указателем FData?
:?: Как правильно читать память с указателем FData не с первого символа, а например с 12?
:?: Как правильно узнавать длину кусочка FData от 12 символа и до знака "#0"? (Если я правильно понимаю в FData может быть много "#0" ?)
:?: Можно ли указатель FData разбить на много под-указателей на подобии FDataDAT1^, FDataDAT2^, FDataDAT3^ и т.д. в соответствии с разделением по "#0", если оно существует или в соответствии с делением на: "DAT1", "DAT2" или "DAT3" итп.?
:!: Любая дополнительная информация востребована.

PS: Заранее благодарен за любой информативный ответ.
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41

Re: Pointer - требуется уточнение

Сообщение bormant » 31.03.2013 15:23:49

PChar(FData) возвращает значение, которое можно присвоить string - правильно?
Нет. При присваивании срабатывает автоматическое приведение типов.
Хотя, похоже я поторопился с выводами в части сравнения указателей, fpc вставил код конвертации ASCIIZ строки в ShortString, вызов функции сравнения коротких строк, по крайней мере вот во что компилируется сравнение t := FData = 'DAT3':
Код: Выделить всё
const
  Data: array [0..4] of char = 'DAT3';
  FData: PChar = @Data;
  SData: String = 'DAT3';

var
  t: Boolean;

begin
  t := FData = 'DAT3';
  t := SData = 'DAT3';
end.
Код: Выделить всё
...
; [10] t := FData = 'DAT3';
      mov   ecx,dword ptr [TC_P$PROGRAM_FDATA]
      lea   eax,dword ptr [ebp-256]
      mov   edx,255
      call   fpc_pchar_to_shortstr
      lea   eax,dword ptr [ebp-256]
      mov   edx,offset _$PROGRAM$_Ld1
      call   fpc_shortstr_compare_equal
      test   eax,eax
      sete   byte ptr [U_P$PROGRAM_T]
; [11] t := SData = 'DAT3';
      mov   eax,offset TC_P$PROGRAM_SDATA
      mov   edx,offset _$PROGRAM$_Ld1
      call   fpc_shortstr_compare_equal
      test   eax,eax
      sete   byte ptr [U_P$PROGRAM_T]
; [12] end.
...
_DATA      SEGMENT   PARA PUBLIC USE32 'DATA'
TC_P$PROGRAM_DATA:
   DB   68,65,84,51,0
   ALIGN 4
TC_P$PROGRAM_FDATA:
   DD   TC_P$PROGRAM_DATA
TC_P$PROGRAM_SDATA:
   DB   4, "DAT3"
   ALIGN 4
_$PROGRAM$_Ld1      DB   4,"DAT3",0
_DATA      ENDS
А вот что пошло не так -- надо поразбираться, возможно баг?
Аватара пользователя
bormant
постоялец
 
Сообщения: 407
Зарегистрирован: 21.03.2012 11:26:01

Re: Pointer - требуется уточнение

Сообщение vitaly_l » 31.03.2013 15:42:08

bormant писал(а):А вот что пошло не так -- надо поразбираться, возможно баг?

По моему Lazarus всё правильно сделал, когда запросил вызов функции сравнения коротких строк или по Вашему должно быть иначе?
Тем более что Вы сравниваете PChar с 'DAT3'? который суть есть shortstr... PS: я с очень большим трудом читаю asm... мало практики.

Добрый bormant и все кто это прочитает, Вы всё знаете, вот этот вопрос наиболее важен, т.к. отвечает сразу на все мои вопросы:
:?: Можно ли данные находящиеся по указателю FData (по которому находится массив данных) разбить на много под-указателей на подобии FData1^, FData2^, FData3^ и т.д. в соответствии с разделением по "#0", если оно существует или в соответствии с делением на ключевые слова в массиве данных: "DAT1", "DAT2" или "DAT3" итп.?

:?: В смысле можно ли узнать/создать новые указатели в соответствии с данными, зная ЧАСТИЧНО их содержимое?
:?: Поиск в памяти по ключевым словам и возвращение указателя - это возможно?
:?: Поиск в памяти по #0 и возвращение указателя - это возможно?


.
Последний раз редактировалось vitaly_l 31.03.2013 16:03:43, всего редактировалось 1 раз.
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41

Re: Pointer - требуется уточнение

Сообщение bormant » 31.03.2013 16:01:10

Кстати, оба сравнения из примера выше у меня дают положительный результат.
vitaly_l писал(а):Можно ли данные находящиеся по указателю FData (по которому находится массив данных) разбить на много под-указателей
Можно. Только это не данные разбиваются, а указатель можно установить на произвольно е место в данных.
vitaly_l писал(а):Поиск в памяти по ключевым словам и возвращение указателя - это возможно?
Поиск в памяти по #0 и возвращение указателя - это возможно?
Естественно можно.

ps. А покажите DumpHex( FData^, 8 ), чтобы понять, что у вас пошло не так при сравнении.
Аватара пользователя
bormant
постоялец
 
Сообщения: 407
Зарегистрирован: 21.03.2012 11:26:01

Re: Pointer - требуется уточнение

Сообщение vitaly_l » 31.03.2013 16:09:02

bormant писал(а):Кстати, оба сравнения из примера выше у меня дают положительный результат.

Я подумал... поробую... мне наверно нужно спрашивать if (PChar(FData) = "DAT3"+#0<=== ) then ShowMessage('DAT3');
тогда она вернёт true, как в Вашем примере...
bormant писал(а):vitaly_l писал(а):
Можно ли данные находящиеся по указателю FData (по которому находится массив данных) разбить на много под-указателей
Можно.
vitaly_l писал(а):
Поиск в памяти по ключевым словам и возвращение указателя - это возможно?
Поиск в памяти по #0 и возвращение указателя - это возможно?
Естественно можно.

Ответ был: Можно, Естественно можно? - это ура!... :roll:

:? :?: А как это делается? :cry:


.

Добавлено спустя 2 минуты 32 секунды:
bormant писал(а):ps. А покажите DumpHex( FData^, 8 ), чтобы понять, что у вас пошло не так при сравнении.

Я его хотел привести, но его невозможно сюда скопировать, т.к. он копируется только до первого знака #0(наверное)... а остальные данные отсекаются...
:idea: Пардон неправильно понял вопрос... нужно (FData^, 8 ) - сейчас сделаю...


.

Добавлено спустя 6 минут 25 секунд:
Вот данные DumpHex( FData^, 8 ):
0 => 49 4D 41 50 (IMAP) в скобках ASCI - это вместо DAT3...
4 => 00 2A 80 00 (здесь искомое значение, но я его ещё не умею декодировать) ...


.

Добавлено спустя 14 минут 41 секунду:
Всё, разобрался почему он отказывался возвращать true... у меня DAT3 объявлено как = array[0..3] of AnsiChar;, а когда сделал сравнение сo string = 'DAT3', то она вернула true...

Остался один вопрос:
:?: Как создать новые указатели в соответствии с ключевыми словами, зная ЧАСТИЧНО содержимое куска памяти с указателем FData?
:?: Как делать поиск в памяти по ключевым словам и получать указатель?
:?: Как делать поиск в памяти по #0 и получать значение с указателем?




.
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41

Re: Pointer - требуется уточнение

Сообщение bormant » 31.03.2013 16:35:15

В другой теме я приводил вам простой пример сравнения FourCC, там где давал разбор 'PNTS'. Обратите внимание, вам просто повезло, что после интересующих вас 4-х символов идёт #0, но там может быть всё, что угодно. Поэтому проще как-то так:
Код: Выделить всё
const
  fcIMAP = $50414d49; // 'IMAP' in little-endian
type
  pLongWord = ^LongWord;
...
  if pLongWord(FData)^ = fcIMAP then ...
Аватара пользователя
bormant
постоялец
 
Сообщения: 407
Зарегистрирован: 21.03.2012 11:26:01

Re: Pointer - требуется уточнение

Сообщение vitaly_l » 31.03.2013 16:45:20

bormant писал(а):Обратите внимание, вам просто повезло, что после интересующих вас 4-х символов идёт #0, но там может быть всё, что угодно.

:?: Вы хотите сказать что 00 2A 80 00 - это и есть #0 - правильно?


.

Добавлено спустя 1 час 25 минут 39 секунд:
Нашёл описание Pointer http://www.interface.ru/fset.asp?Url=/borland/progrdelphi_p2_4.htm

там сказано что Pointer в памяти храниться так: |1|6|привет|0|, где:
"|" -разделитель ячеек,
"1" это кол-во указателей на данный массив,
"6" длинна массива,
"привет" - содержимое массива
"0" - окончание массива... совершенно непонятно зачем нужен 0 если всегда указывается длинна массива.

Так вот в моём массиве, там длинна например равно "1111", и разделителей "#0" - там например 25, а не один...

графически, "мой массив" наверно записан примерно вот так:
|1|82|DAT1 привет|0|DAT2 как дела?|0|DAT3 12345|0|DAT4 123.123123|0|DAT5 (1)(3)(5)|0|DAT6 (1.2345)(3.5432)(5.5678)|0|

Как мне такой массив правильно разбить на указатели в памяти?
(совершенно не факт что в памяти массив выгладит так как я его нарисовал...)

:? Как разбить массив указателя: |1|82|DAT1 привет|0|DAT2 как дела?|0|DAT3 12345|0|DAT4 123.123123|0|DAT5 (1)(3)(5)|0|DAT6 (1.2345)(3.5432)(5.5678)|0| и... присвоить в соответствии с кол-вом разделителей #0 или ключевых слов ====> DAT1, DAT2, DAT3, DAT4 итд...
в общем должно получиться примерно вот так:
:?:
DAT1 := образно преобразовать к |1|6|DAT1 привет|0|
DAT2 := образно преобразовать к |1|14|DAT2 как дела?|0|
DAT3 := образно преобразовать к |1|10|DAT3 12345|0|
DAT4 := образно преобразовать к |1|15|DAT4 123.123123|0|
DAT5 := образно преобразовать к |1|11|DAT5 (1)(3)(5)|0|
DAT6 := образно преобразовать к |1|25|DAT6 (1.2345)(3.5432)(5.5678)|0|
:? :| :cry:
:?: Это можно прогнать побайтово и при нахождении например #0 делить на части или указатели можно делить не разбивая на новые переменные?
только там половина кода в обратной кодировке little-endian и буквы почему-то в ней записываются в нормальном порядке а цифры в обратном...
:evil:


.
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41

Re: Pointer - требуется уточнение

Сообщение bormant » 31.03.2013 19:59:02

Pointer (англ. указатель) в памяти хранится как принято хранить адреса на соответствующей архитектуре. В частности, для 32-битных 8086-совместимых процессоров в защищённом режиме это 32-битное (4-байтовое), а для 64-битных x86-64 -- 64-битное (8-байтовое) значение, хранящее адрес из адресного пространства процесса.

То, что было процитировано после ссылки http://www.interface.ru/fset.asp?Url=/b ... i_p2_4.htm -- это всего лишь способ хранения в памяти динамических ({$H+}) AnsiString конкретного семейства реализаций Pascal/Delphi, раздел так и назывался "Представление строк в памяти".

#0 -- это один байт с кодом 0 (такая синтаксическая конструкция), то же самое, что chr(0) или char(0).
Аватара пользователя
bormant
постоялец
 
Сообщения: 407
Зарегистрирован: 21.03.2012 11:26:01

Re: Pointer - требуется уточнение

Сообщение vitaly_l » 31.03.2013 20:30:32

bormant писал(а):способ хранения в памяти динамических ({$H+}) AnsiString конкретного семейства

Это не даёт пояснений: Как это: 'семейство' - разбить на кусочки с соответствующими указателями на адрес в памяти?
:evil: :?: А можно при разбиении на кусочки, массива Data, который вызывается указателем Pointer, использовать вот это => UTF8Pos и UTF8Copy, для разбиения на нужные куски? И... значения, которые в системе little-endian заносить вначале в String, а потом перевернуть и преобразовать к числам?
:? :?: Значения, при такой инициализации - будут правильными или там что-нить поломается?



.
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41

Re: Pointer - требуется уточнение

Сообщение bormant » 31.03.2013 20:42:46

Это продолжение той же самой задачи (про 3D) или что-то новое?
Аватара пользователя
bormant
постоялец
 
Сообщения: 407
Зарегистрирован: 21.03.2012 11:26:01

Re: Pointer - требуется уточнение

Сообщение vitaly_l » 31.03.2013 21:11:09

bormant писал(а):Это продолжение той же самой задачи (про 3D) или что-то новое?

В GLScene, модуль сделан только на половину и его делал программист, у которого знаний больше чем у меня. Я решил изучить его модуль, т.к. я точно такую задачу, решил бы совсем иначе. Более того, его модуль по идее - должен был быть адаптирован GLScene, но выяснилось что, его модуль - вообще никогда не работал (это сказал некий Yar, который гуру в GLScene и может вносить изменения в репозиторий GLScene).

Я всегда работал с файлами на подобии HTML или XML; там немного другой формат(более высокого уровня) и там всё очевидно. Теперь благодаря, в том числе и Вам, я уже понимаю и этот формат, но пока ещё не совсем научился или даже скорее всего - просто не осознаю, что по сути это одно и тоже..., просто по разному называется и есть некие нестандартные символы, которые визуально в блокноте не отображаются. Я спрашиваю чтобы подстраховаться. Поэтому я и уточняю, т.к. например Вы работаете в данном формате.

Да это продолжение задачи про 3D/

.
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41

Re: Pointer - требуется уточнение

Сообщение bormant » 31.03.2013 21:12:17

По вашему примеру, как он изложен в этой теме, в этом сообщении viewtopic.php?f=13&t=9023#p71211:
Код: Выделить всё
uses Strings;
const
  Data: AnsiString =
  'DAT1 привет'#0'DAT2 как дела?'#0'DAT3 12345'#0'DAT4 123.123123'#0'DAT5 (1)(3)(5)'#0'DAT6 (1.2345)(3.5432)(5.5678)';
var
  p: PChar;
  i: Integer;
  dat: array[1..6] of string;
begin
  p := @Data[1];
  for i := 1 to 6 do begin
    dat[i] := p; p := StrEnd(p) + 1;
  end;
  for i := 1 to 6 do
    WriteLn('DAT', i, ' := ', dat[i]);
end.
Прогон:
Код: Выделить всё
DAT1 := DAT1 привет
DAT2 := DAT2 как дела?
DAT3 := DAT3 12345
DAT4 := DAT4 123.123123
DAT5 := DAT5 (1)(3)(5)
DAT6 := DAT6 (1.2345)(3.5432)(5.5678)
Последний раз редактировалось bormant 31.03.2013 21:38:14, всего редактировалось 1 раз.
Аватара пользователя
bormant
постоялец
 
Сообщения: 407
Зарегистрирован: 21.03.2012 11:26:01

Re: Pointer - требуется уточнение

Сообщение vitaly_l » 31.03.2013 21:36:58

bormant писал(а):По вашему примеру, как он изложен в этой теме:

Там всё, немного сложнее, там не такое разделение, как я показал (я ложно думал что оно такое).
Там #0 - не всегда является точным разделителем.

Вопросы:
1) p := @Data[1]; - почему Вы указали [1], а не просто p := @Data;?
2) p := StrEnd(p) + 1; - зачем Вы смещаете ещё на одно значение, там лежит вот это #0 ?
3) Эта система будет работать для кодировки UTF8?



.
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41

След.

Вернуться в Общее

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 13

Рейтинг@Mail.ru