Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2014.09.21;
Скачать: [xml.tar.bz2];

Вниз

_DynArrayAddRef/_NewUnicodeString/_NewAnsiString/_NewWideString   Найти похожие ветки 

 
Мистер Хэ   (2014-02-10 17:29) [0]

Нужно узнать объявления и особенности работы на низком уровне с динамическими массивами и строками в Delphi и FPC. Под руками только компиляторы Delphi 6 и XE5 - просьба скопировать данные типы и функции из модуля System своей версии Delphi/FPC если они отличаются!
(комментарии для компактности удалил)

Delphi6:
procedure _DynArrayAddRef;
asm
       TEST    EAX,EAX
       JE      @@exit
  LOCK INC     dword ptr [EAX-8]
@@exit:
end;

function _NewAnsiString(length: Longint): Pointer;
var
 P: PStrRec;
begin
 Result := nil;
 if length <= 0 then Exit;
 GetMem(P, length + sizeof(StrRec) + 1 + ((length + 1) and 1));
 Result := Pointer(Integer(P) + sizeof(StrRec));
 P.length := length;
 P.refcnt := 1;
 PWideChar(Result)[length div 2] := #0;  // length guaranteed >= 2
end;

function _NewWideString(CharLength: Longint): Pointer;
{$IFDEF LINUX}
begin
 Result := _NewAnsiString(CharLength*2);
end;
{$ENDIF}
{$IFDEF MSWINDOWS}
asm
       TEST    EAX,EAX
       JE      @@1
       PUSH    EAX
       PUSH    0
       CALL    SysAllocStringLen
       TEST    EAX,EAX
       JE      WStrError
@@1:
end;
{$ENDIF}


Delphi XE5:
 PStrRec = ^StrRec;
 StrRec = packed record
 {$IF defined(CPUX64)}
   _Padding: LongInt; // Make 16 byte align for payload..
 {$ENDIF}
   codePage: Word;
   elemSize: Word;
   refCnt: Longint;
   length: Longint;
 end;

 PDynArrayRec = ^TDynArrayRec;
 TDynArrayRec = packed record
 {$IFDEF CPUX64}
   _Padding: LongInt; // Make 16 byte align for payload..
 {$ENDIF}
   RefCnt: LongInt;
   Length: NativeInt;
 end;

procedure _DynArrayAddRef(P: Pointer);
begin
 if P <> nil then
   AtomicIncrement(PDynArrayRec(PByte(P) - SizeOf(TDynArrayRec))^.RefCnt);
end;

function _NewUnicodeString(CharLength: LongInt): Pointer;
var
 P: PStrRec;
begin
 Result := nil;
 if CharLength > 0 then
 begin
   // Allocate a memory with record and extra wide-null terminator.
   if CharLength >= (MaxInt - SizeOf(StrRec)) div SizeOf(WideChar) then _IntOver;
   GetMem(P, SizeOf(StrRec) + (CharLength + 1) * SizeOf(WideChar));
   Result := Pointer(PByte(P) + SizeOf(StrRec));
   P.length := CharLength;
   P.refCnt := 1;
   P.elemSize := SizeOf(WideChar);
   P.codePage := Word(DefaultUnicodeCodePage);
   PWideChar(Result)[CharLength] := #0;
 end;
end;

function _NewAnsiString(CharLength: LongInt; CodePage: Word): Pointer;
var
 P: PStrRec;
begin
 Result := nil;
 if CharLength > 0 then
 begin
   // Alloc an extra null for strings with even length.  This has no actual
   // cost since the allocator will round up the request to an even size
   // anyway. All _WideStr allocations have even length, and need a double
   // null terminator.
   if CharLength >= MaxInt - SizeOf(StrRec) then _IntOver;
   GetMem(P, CharLength + SizeOf(StrRec) + 1 + ((CharLength + 1) and 1));
   Result := Pointer(PByte(P) + SizeOf(StrRec));
   P.length := CharLength;
   P.refcnt := 1;
   if CodePage = 0 then
     CodePage := Word(DefaultSystemCodePage);
   P.codePage := CodePage;
   P.elemSize := 1;
   PWideChar(Result)[CharLength div 2] := #0;  // length guaranteed >= 2
 end;
end;

function _NewWideString(CharLength: LongInt): Pointer;
{$IFDEF POSIX}
{$IFDEF PUREPASCAL}
begin
  Result := _NewUnicodeString(CharLength);
end;
{$ELSE}
asm
       JMP     _NewUnicodeString
end;
{$ENDIF !PUREPASCAL}
{$ENDIF POSIX}
{$IFDEF MSWINDOWS}
{$IFDEF PUREPASCAL}
begin
 Result := nil;
 if CharLength <> 0 then
 begin
   Result := SysAllocStringLen(nil, CharLength);
   if Result = nil then
     WStrError;
 end;
end;


 
Мистер Хэ   (2014-02-10 17:31) [1]

да, для Delphi 6:

 PStrRec = ^StrRec;
 StrRec = packed record
   refCnt: Longint;
   length: Longint;
 end;


 
Rouse_ ©   (2014-02-11 10:40) [2]

2007

type
 PStrRec = ^StrRec;
 StrRec = packed record
   refCnt: Longint;
   length: Longint;
 end;

TDynArrayRec - отсутствует

_DynArrayAddRef - как в 6

_NewUnicodeString - отсутствует

function _NewAnsiString(length: Longint): Pointer;
{$IFDEF PUREPASCAL}
var
 P: PStrRec;
begin
 Result := nil;
 if length <= 0 then Exit;
 // Alloc an extra null for strings with even length.  This has no actual cost
 // since the allocator will round up the request to an even size anyway.
 // All widestring allocations have even length, and need a double null terminator.
 GetMem(P, length + sizeof(StrRec) + 1 + ((length + 1) and 1));
 Result := Pointer(Integer(P) + sizeof(StrRec));
 P.length := length;
 P.refcnt := 1;
 PWideChar(Result)[length div 2] := #0;  // length guaranteed >= 2
end;
{$ELSE}
asm
 { ->    EAX     length                  }
 { <-    EAX pointer to new string       }

         TEST    EAX,EAX
         JLE     @@lengthLEZero
         PUSH    EAX
         ADD     EAX,rOff+2                       // one or two nulls (Ansi/Wide)
         AND     EAX, not 1                   // round up to even length
         PUSH    EAX
         CALL    _GetMem
         POP     EDX                              // actual allocated length (>= 2)
         MOV     word ptr [EAX+EDX-2],0           // double null terminator
         ADD     EAX,rOff
         POP     EDX                              // requested string length
         MOV     [EAX-skew].StrRec.length,EDX
         MOV     [EAX-skew].StrRec.refCnt,1
         RET
         
@@lengthLEZero:
         XOR     EAX,EAX
end;
{$ENDIF}

function _NewWideString(CharLength: Longint): Pointer;
{$IFDEF LINUX}
begin
 Result := _NewAnsiString(CharLength*2);
end;
{$ENDIF}
{$IFDEF MSWINDOWS}
asm
       TEST    EAX,EAX
       JE      @@1
       PUSH    EAX
       PUSH    0
       CALL    SysAllocStringLen
       TEST    EAX,EAX
       JE      WStrError
@@1:
end;
{$ENDIF}


 
Мистер Хэ   (2014-02-11 10:43) [3]

> Rouse_ ©   (11.02.14 10:40) [2]

Ага, спасибо!
Получается всё как в Delphi6.

Теперь хочется посмотреть изменения для Delphi 2009 и FPC
Ребят, не поленитесь посмотреть, у кого есть, пожалуйста


 
NoUser ©   (2014-02-11 17:48) [4]

FPC 2.6.2
Type
  pdynarray = ^tdynarray;
  tdynarray = packed record
     refcount : ptrint;
     high : tdynarrayindex;
  end;

procedure fpc_dynarray_incr_ref(p : pointer);
 var
    realp : pdynarray;
 begin
    if p=nil then
      exit;

    realp:=pdynarray(p-sizeof(tdynarray));
    if realp^.refcount=0 then
      HandleErrorFrame(204,get_frame);

    inclocked(realp^.refcount);
 end;

Type
 PAnsiRec = ^TAnsiRec;
 TAnsiRec = Packed Record
   Ref,
   Len   : SizeInt;
   First : Char;
 end;

Const
 AnsiRecLen = SizeOf(TAnsiRec);
 FirstOff   = SizeOf(TAnsiRec)-1;

Function NewAnsiString(Len : SizeInt) : Pointer;
{  Allocate a new AnsiString on the heap.
 initialize it to zero length and reference count 1.}
Var
 P : Pointer;
begin
 { request a multiple of 16 because the heap manager alloctes anyways chunks of 16 bytes }
 GetMem(P,Len+AnsiRecLen);
 If P<>Nil then
  begin
    PAnsiRec(P)^.Ref:=1;         { Set reference count }
    PAnsiRec(P)^.Len:=0;         { Initial length }
    PAnsiRec(P)^.First:=#0;      { Terminating #0 }
    inc(p,firstoff);             { Points to string now }
  end;
 NewAnsiString:=P;
end;

Type
 PWideRec = ^TWideRec;
 TWideRec = Packed Record
   Len   : DWord;
   First : WideChar;
 end;

Const
 WideRecLen = SizeOf(TWideRec);
 WideFirstOff = SizeOf(TWideRec)-sizeof(WideChar);

Function NewWideString(Len : SizeInt) : Pointer;
{  Allocate a new WideString on the heap.
 initialize it to zero length and reference count 1.}
Var
 P : Pointer;
begin
{$ifdef MSWINDOWS}
 if winwidestringalloc then
   begin
     P:=SysAllocStringLen(nil,Len);
     if P=nil then
       WideStringError;
   end
 else
{$endif MSWINDOWS}
   begin
     GetMem(P,Len*sizeof(WideChar)+WideRecLen);
     If P<>Nil then
       begin
        PWideRec(P)^.Len:=Len*2;     { Initial length }
        PWideRec(P)^.First:=#0;      { Terminating #0 }
        inc(p,WideFirstOff);         { Points to string now }
       end
     else
       WideStringError;
   end;
 NewWideString:=P;
end;

Type
 PUnicodeRec = ^TUnicodeRec;
 TUnicodeRec = Packed Record
   Ref : SizeInt;
   Len : SizeInt;
   First : UnicodeChar;
 end;

Const
 UnicodeRecLen = SizeOf(TUnicodeRec);
 UnicodeFirstOff = SizeOf(TUnicodeRec)-sizeof(UnicodeChar);

Function NewUnicodeString(Len : SizeInt) : Pointer;
{
 Allocate a new UnicodeString on the heap.
 initialize it to zero length and reference count 1.
}
Var
 P : Pointer;
begin
 GetMem(P,Len*sizeof(UnicodeChar)+UnicodeRecLen);
 If P<>Nil then
   begin
    PUnicodeRec(P)^.Len:=Len*2;     { Initial length }
    PUnicodeRec(P)^.Ref:=1;         { Initial Refcount }
    PUnicodeRec(P)^.First:=#0;      { Terminating #0 }
    inc(p,UnicodeFirstOff);         { Points to string now }
   end
 else
   UnicodeStringError;
 NewUnicodeString:=P;
end;


 
Мистер Хэ   (2014-02-11 18:02) [5]

> NoUser ©   (11.02.14 17:48) [4]

ого
спасибо большое!

размер Char в FPC равен 1?

и это... разве в FPC нет строк типа...
type
 CyrillicString = type AnsiString(1251);


 
Мистер Хэ   (2014-02-11 18:02) [6]

All,

осталось посмотреть Delphi 2009 :)
ребят, у кого он есть - посмотрите пожалуйста


 
Чайник ©   (2014-02-11 18:11) [7]

Д2010

type
 PStrRec = ^StrRec;
 StrRec = packed record
   codePage: Word;
   elemSize: Word;
   refCnt: Longint;
   length: Longint;
 end;

TDynArrayRec – отсутствует

rocedure _DynArrayAddRef;
asm
{     ->EAX     Pointer to heap object }
       TEST    EAX,EAX
       JE      @@exit
  LOCK INC     dword ptr [EAX-8]
@@exit:
end;

function _NewUnicodeString(CharLength: Longint): Pointer;
{$IFDEF PUREPASCAL}
var
 P: PStrRec;
begin
 Result := nil;
 if CharLength <= 0 then Exit;
 // Allocate a memory with record and extra wide-null terminator.
 GetMem(P, SizeOf(StrRec) + (CharLength + 1) * SizeOf(WideChar));
 Result := Pointer(Integer(P) + sizeof(StrRec));
 P.length := CharLength;
 P.refCnt := 1;
 P.elemSize := SizeOf(WideChar);
 P.codePage := Word(DefaultUnicodeCodePage);
 PWideChar(Result)[CharLength] := #0;
end;
{$ELSE}
asm
       { ->    EAX     length                  }
       { <-    EAX pointer to new string       }
       TEST    EAX,EAX
       JLE     @@lengthLEZero  // length <= 0?
       PUSH    EAX             // save length
       ADD     EAX,EAX         // convert to bytes
       JO      @@overflow
       ADD     EAX,rOff+2      // + record + terminator
       JO      @@overflow
       CALL    _GetMem
       ADD     EAX,rOff
       POP     EDX                              // requested string length
       MOV     [EAX-skew].StrRec.refCnt,1
       MOV     [EAX-skew].StrRec.length,EDX
       MOV     word ptr [EAX+EDX*2],0           // wide null terminator
       MOV     word ptr [EAX-skew].StrRec.elemSize,2
       MOVZX   EDX,Word Ptr DefaultUnicodeCodePage
       MOV     word ptr [EAX-skew].StrRec.codePage,DX
       RET
@@overflow:
       JMP     _IntOver  
@@lengthLEZero:
       XOR     EAX,EAX
end;
{$ENDIF}

function _NewAnsiString(length: Longint; CodePage: Word): Pointer;
{$IFDEF PUREPASCAL}
var
 P: PStrRec;
begin
 Result := nil;
 if length <= 0 then Exit;
 // Alloc an extra null for strings with even length.  This has no actual cost
 // since the allocator will round up the request to an even size anyway.
 // All widestring allocations have even length, and need a double null terminator.
 GetMem(P, length + sizeof(StrRec) + 1 + ((length + 1) and 1));
 Result := Pointer(Integer(P) + sizeof(StrRec));
 P.length := length;
 P.refcnt := 1;
 P.codePage := Word(DefaultSystemCodePage);
 P.elemSize := 1;
 PWideChar(Result)[length div 2] := #0;  // length guaranteed >= 2
end;
{$ELSE}
asm
 { ->    EAX     length                  }
 { <-    EAX pointer to new string       }

         TEST    EAX,EAX
         JLE     @@lengthLEZero
         PUSH    EAX
         ADD     EAX,rOff+2                       // one or two nulls (Ansi/Wide)
         JO      @@overflow
         AND     EAX, not 1                   // round up to even length
         PUSH    EDX
         PUSH    EAX
         CALL    _GetMem
         POP     EDX                              // actual allocated length (>= 2)
         POP     ECX
         MOV     word ptr [EAX+EDX-2],0           // double null terminator
         ADD     EAX,rOff
         POP     EDX                              // requested string length
         MOV     [EAX-skew].StrRec.length,EDX
         MOV     [EAX-skew].StrRec.refCnt,1
         TEST    ECX,ECX
         JNE     @@NotDefault
         MOV     ECX,DefaultSystemCodePage
@@NotDefault:
         MOV     EDX,ECX
         MOV     word ptr [EAX-skew].StrRec.codePage,DX
         MOV     word ptr [EAX-skew].StrRec.elemSize,1
         RET

@@overflow:
         JMP     _IntOver          
         
@@lengthLEZero:
         XOR     EAX,EAX
end;
{$ENDIF}
function _NewWideString(CharLength: Longint): Pointer;
{$IF defined(LINUX) or defined(MACOSX)}
begin
  { MACOSXTODO: check code page on this }
  Result := _NewAnsiString(CharLength*2, 0);
//  Result := _NewAnsiString(CharLength*2);
end;
{$IFEND}
{$IFDEF MSWINDOWS}
asm
       TEST    EAX,EAX
       JE      @@1
       PUSH    EAX
       PUSH    0
       CALL    SysAllocStringLen
       TEST    EAX,EAX
       JE      WStrError
@@1:
end;
{$ENDIF}


 
Мистер Хэ   (2014-02-11 21:51) [8]

> Чайник ©   (11.02.14 18:11) [7]

Спасибо!
Ну чтож, осталось понять, такой же ли код в Delphi 2009
Таки это переходный период, возможно там что-то не так как сейчас :)


 
ХэХеХэ   (2014-02-11 22:55) [9]

Просим не публиковать серийные номера, коды, а также алгоритмы взлома того или иного программного обеспечения.

Выкладывание таких огромных кусков исходников RTL онлайн нарушает все мыслимые лицензии. Неспроста в триальной версии Delphi исходников нет.


 
NoUser ©   (2014-02-11 23:58) [10]


> размер Char в FPC равен 1?
> и это... разве в FPC нет строк типа...

Да, и это
type
   UTF8String = type ansistring;
+
http://www.freepascal.ru/article/freepascal/20051026001249/


 
Мистер Хэ   (2014-02-12 01:00) [11]

> NoUser ©   (11.02.14 23:58) [10]

Интересно
Спасибо

Ребят,у кого Delphi 2009, признавайтесь?


 
Inovet ©   (2014-02-12 01:14) [12]

> [11] Мистер Хэ   (12.02.14 01:00)
> Delphi 2009

Он же глючный был, кажись.


 
Мистер Хэ   (2014-02-12 09:31) [13]

> Inovet ©   (12.02.14 01:14) [12]

Да они все глючные по своему :)
Просто это "недостающее звено", которое надо "восстановить" :)


 
Мистер Хэ   (2014-02-13 09:50) [14]

Меня пока больше всего смущает реализация WideString вне Windows

По Delphi 2010 включительно она
 _NewAnsiString(CharLength*2)

В FreePascal примерно так же

А вот в XE2 и позже уже такая реализация:
 _NewUnicodeString(CharLength);

Между 2010 и XE2 есть только одна версия - XE1
Ни у кого нет?


 
Мистер Хэ   (2014-02-13 10:56) [15]

Всё, теперь ясно
В XE тоже  _NewUnicodeString(CharLength);

Всем спасибо


 
Мистер Хэ   (2014-02-13 10:56) [16]

Всё, теперь ясно
В XE тоже  _NewUnicodeString(CharLength);

Всем спасибо



Страницы: 1 вся ветка

Форум: "Прочее";
Текущий архив: 2014.09.21;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.52 MB
Время: 0.004 c
2-1382260841
dis12345
2013-10-20 13:20
2014.09.21
предопределенные константы в DrawFrameControl


15-1392299840
alex_
2014-02-13 17:57
2014.09.21
задача на С++


2-1382155371
Павел
2013-10-19 08:02
2014.09.21
Звук при нажатие хоткея


15-1390926828
Rouse_
2014-01-28 20:33
2014.09.21
Голосование на знак "Мастер Delphi"


2-1381845372
Алексей1
2013-10-15 17:56
2014.09.21
Login Form





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский