⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kbmmemcsvstreamformat.pas

📁 kbmMemTable v5.50 (Dec. 12 2005)内存表控件
💻 PAS
📖 第 1 页 / 共 4 页
字号:
     FreeMem(buf);
{$ENDIF}

     inherited;
end;

procedure TkbmCustomCSVStreamFormat.DetermineLoadFieldIDs(ADataset:TkbmCustomMemTable; AList:TStringList; Situation:TkbmDetermineLoadFieldsSituation);
var
   s:string;
   null:boolean;
begin
     // Dont try to get fields display names if def not yet loaded.
     if (Situation<>dlfAfterLoadDef) or (Line='') or (sfLoadNoHeader in sfNoHeader) then
     begin
          inherited;
          exit;
     end;

     // Determine which fields is present in the stream.
     // Line has already been populated by LoadDef.
     AList.Clear;

{$IFDEF DOTNET}
     if assigned (backPtr) then Marshal.FreeHGlobal(BackPtr);
     lptr:=Marshal.StringToHGlobalANSI(Line);
     backPtr:=lptr;
     try
        elptr:=IntPtr(integer(lptr)+length(Line));

        while (integer(lptr)<integer(elptr)) do
        begin
             // Get DisplayName for field.
             s:=GetWord(null);
             AList.Add(s);
        end;
     finally
        Marshal.FreeHGlobal(BackPtr);
        BackPtr:=nil;
     end;
{$ELSE}
     lptr:=PChar(Line);
     while (lptr<elptr) do
     begin
          // Get DisplayName for field.
          s:=GetWord(null);
          AList.Add(s);
     end;
{$ENDIF}
end;

procedure TkbmCUstomCSVStreamFormat.DetermineLoadFieldIndex(ADataset:TkbmCustomMemTable; ID:string; FieldCount:integer; OrigIndex:integer; var NewIndex:integer; Situation:TkbmDetermineLoadFieldsSituation);
var
   i:integer;
   s:string;
begin
     // If determined not to load field, dont.
     if (Situation<>dlfAfterLoadDef) then exit;

     // Dont want to worry about case.
     s:=UpperCase(ID);

     // Find Field index in dataset
     for i:=0 to ADataset.FieldCount-1 do
     begin
          if (UpperCase(ADataset.Fields[i].DisplayName)=s) then
          begin
               NewIndex:=i;
               exit;
          end;
     end;

     NewIndex:=-1;
end;

procedure TkbmCustomCSVStreamFormat.LoadDef(ADataset:TkbmCustomMemTable);
var
   ld,ldidx:boolean;
   i:integer;
   slist:TStringList;
   DuringTableDef,DuringIndexDef:boolean;
   null:boolean;
   FName,KName,TName,DName,EMask,DExpr:string;
   FSize,DSize:integer;
   REQ,RO,INV,CASEIN,{$IFNDEF LEVEL3}NONMT,{$ENDIF}DESC,UNIQ:boolean;
   FT:TFieldType;
   FK:TFieldKind;
   FFields:string;
   ioptions:TIndexOptions;
   AIndexDef:TIndexDef;
   AField:TField;
begin
     if (StreamSize = 0) then exit;
     ld:=sfLoadDef in sfDef;
     ldidx:=sfLoadIndexDef in sfIndexDef;

     // Read all definition lines in CSV format.
     slist:=TStringList.Create;
     DuringTableDef:=false;
     DuringIndexDef:=false;
     try
        while true do
        begin
             GetLine;
             if Line='' then break;


             // Read magic words if any.
             Word:=GetWord(null);

{$IFNDEF CSV_FILE_1XX_COMPATIBILITY}
             if Word=kbmFileVersionMagic then
             begin
                  Word:=GetWord(null);
//                     FileVersion:=StrToInt(Word);
                  continue;
             end
             else
{$ENDIF}

             if Word=kbmTableDefMagicStart then
             begin
                  DuringTableDef:=true;
                  if ld then
                  begin
                       ADataSet.Close;
                       ADataSet.FieldDefs.clear;
                       ADataSet.DeleteTable;
                  end;
                  continue;
             end

             // End of table definition?
             else if Word=kbmTableDefMagicEnd then
             begin
                  DuringTableDef:=false;
                  ADataSet.Open;
                  continue;
             end

             // Start of index definitions?
             else if Word=kbmIndexDefMagicStart then
             begin
                  if ld and ldidx then
                  begin
                       ADataSet.DestroyIndexes;
                       ADataSet.IndexDefs.Clear;
                  end;
                  DuringIndexDef:=true;
                  continue;
             end

             // End of index definitions?
             else if Word=kbmIndexDefMagicEnd then
             begin
                  DuringIndexDef:=false;
                  if ld and ldidx then ADataSet.CreateIndexes;
                  continue;
             end;

             // If not during table definitions then its the header. Break.
             if not DuringTableDef then break;

             // If its an index definition.
             if DuringIndexDef then
             begin
                  if ld and ldidx then
                  begin
                       Line:=ExtractQuoteString(Line,FCSVQuote);
                       i:=pos('=',Line);
                       slist.CommaText:=copy(Line,i+1,length(Line));
                       FName:=copy(Line,1,i-1);
                       FFields:=slist.Strings[0];
                       DName:=slist.Strings[1];
                       CASEIN:=pos(',CASE',Line)<>0;
{$IFNDEF LEVEL3}
                       NONMT:=pos(',NONMT',Line)<>0;
{$ENDIF}
                       DESC:=pos(',DESC',Line)<>0;
                       UNIQ:=pos(',UNIQ',Line)<>0;

                       // Add field definition.
                       ioptions:=[];
                       if CASEIN then ioptions:=ioptions+[ixCaseInSensitive];
                       if DESC then ioptions:=ioptions+[ixDescending];
                       if UNIQ then ioptions:=ioptions+[ixUnique];
{$IFNDEF LEVEL3}
                       if NONMT then ioptions:=ioptions+[ixNonMaintained];
                       AIndexDef := ADataSet.IndexDefs.AddIndexDef;
                       AIndexDef.Name:=FName;
                       AIndexDef.Fields:=FFields;
                       AIndexDef.Options:=ioptions;
                       AIndexDef.DisplayName:=DName;
{$ELSE}
                       IndexDefs.Add(FName,FFields,ioptions);
{$ENDIF}
                  end;
                  continue;
             end;

             // Otherwise its a field definition. Break the line apart.
             if ld then
             begin
                  Line:=ExtractQuoteString(Line,FCSVQuote);
                  i:=pos('=',Line);
                  slist.CommaText:=copy(Line,i+1,length(Line));
                  FName:=copy(Line,1,i-1);
                  TName:=slist.Strings[0];
                  FSize:=strtoint(slist.Strings[1]);
                  DName:=slist.Strings[2];
                  EMask:=slist.Strings[3];
                  DSize:=strtoint(slist.Strings[4]);
                  REQ:=pos(',REQ',Line)<>0;
                  RO:=pos(',RO',Line)<>0;
                  INV:=pos(',INV',Line)<>0;
                  i:=slist.Count;
                  DExpr:='';
                  if i>6 then
                  begin
                       DExpr:=slist.Strings[i-1];
                       dec(i);
                  end;
                  if i>5 then
                     KName:=slist.Strings[i-1]
                  else
                      KName:=FieldKindNames[0]; // fkData.

                  // Find fieldtype from fieldtypename.
                  for i:=0 to ord(High(FieldTypeNames)) do
                      if FieldTypeNames[TFieldType(i)]=TName then break;
                  FT:=TFieldType(i);
                  if not (FT in kbmSupportedFieldTypes) then
                     raise EMemTableError.Create(Format(kbmUnknownFieldErr1+kbmUnknownFieldErr2,[TName,Word]));

                  // Check if autoinc field in stream, use data from stream.
                  if FT=ftAutoInc then
                     SetIgnoreAutoIncPopulation(ADataset,true);

                  // If fieldkind specified, find fieldkind.
                  FK:=fkData;
                  for i:=0 to ord(High(FieldKindNames)) do
                      if FieldKindNames[i]=KName then
                      begin
                           FK:=TFieldKind(i);
                           break;
                      end;

                  // Add field definition.
                  ADataSet.FieldDefs.Add(FName,FT,FSize,REQ);

                  // Setup other properties.
                  i:=ADataSet.FieldDefs.IndexOf(FName);
                  AField:=ADataSet.FieldDefs.Items[i].CreateField(ADataset);
                  AField.FieldKind:=FK;
                  AField.DisplayLabel:=DName;
                  AField.EditMask:=EMask;
                  AField.ReadOnly:=RO;
                  AField.DisplayWidth:=DSize;
{$IFDEF LEVEL4}
                  AField.DefaultExpression:=DExpr;
{$ENDIF}
                  AField.Visible:=not INV;
             end;
        end;
     finally
        slist.free;
     end;
     FDefLoaded:=true;
end;


procedure TkbmCustomCSVStreamFormat.LoadData(ADataset:TkbmCustomMemTable);
var
   i,j:integer;
   nf:integer;
   null:boolean;
   s:string;
   Accept:boolean;
   LoadLine:boolean;
begin
     if (StreamSize = 0) then exit;
     if not (sfLoadData in sfData) then exit;

     // Check if data line already loaded.
     LoadLine:=not (sfLoadNoHeader in sfNoHeader);

{$IFDEF DOTNET}
     if assigned (backPtr) then Marshal.FreeHGlobal(BackPtr);
     lPtr:=marshal.StringToHGlobalANSI(Line); // Make sure word pointer is at start of line.
     BackPtr:=lPtr;
     try
{$ELSE}
        lptr:=PChar(Line);            // Make sure word pointer is at start of line.
{$ENDIF}

        ADataSet.ResetAutoInc;

        // Read all lines in CSV format.
        ADataSet.LoadCount:=0;
        ADataSet.LoadedCompletely:=true;

        while true do
        begin
             if (ADataSet.LoadLimit>0) and (ADataSet.LoadCount>=ADataSet.LoadLimit) then
             begin
                  ADataSet.LoadedCompletely:=false;
                  break;
             end;

             if LoadLine then GetLine;
             LoadLine:=true;
             if Line='' then break;

             ADataSet.append;

             i:=0;
{$IFDEF LEVEL4}
             nf:=length(LoadFields);
{$ELSE}
             nf:=LoadFieldsCount;
{$ENDIF}
{$IFDEF DOTNET}
             while (integer(lptr)<integer(elptr)) and (i<nf) do
{$ELSE}
             while (lptr<elptr) and (i<nf) do
{$ENDIF}
             begin
                  j:=LoadFields[i];
                  s:=GetWord(null);
                  if j>=0 then
                  begin
                       if not (sfLoadFieldKind in sfFieldKind) then
                       begin
                            if ADataSet.Fields[j].FieldKind<>fkData then
                            begin
                                 inc(i);
                                 continue;
                            end;
                       end;

                       if assigned(FOnFormatLoadField) then
                          FOnFormatLoadField(self,ADataSet.Fields[j],null,s);

                       if null then
                           ADataSet.Fields[j].Clear
                       else if ADataSet.Fields[j].DataType in kbmStringTypes then
                       begin
  {$IFDEF DOTNET}
                            s:=CodedStringToString(s);
                            if ADataSet.Fields[j].datasize>length(s) then
                               setlength(s,ADataSet.Fields[j].datasize+1);
                            ADataSet.Fields[j].AsString:=s;
  {$ELSE}
                            ADataSet.Fields[j].AsString:=CodedStringToString(s);
  {$ENDIF}
                       end
                       else if ADataSet.Fields[j].DataType in kbmBinaryTypes then
                            ADataSet.Fields[j].AsString:=Base64ToString(s)
  {$IFDEF LEVEL6}
                       else if ADataSet.Fields[j].DataType=ftWideString then
   {$IFDEF DOTNET}
                            ADataSet.Fields[j].Value:=s
   {$ELSE}
                            ADataSet.Fields[j].Value:=UTF8Decode(s)
   {$ENDIF}
  {$ENDIF}
                       else if ADataSet.Fields[j].DataType = ftBoolean then
                          begin
                               if s=FCSVTrueString then
                                  TBooleanField(ADataSet.Fields[j]).Value:=true
                               else
                                   TBooleanField(ADataSet.Fields[j]).Value:=false;
                          end
                       else
                           ADataSet.Fields[j].AsString:=s;

                       if Assigned(ADataSet.OnLoadField) then ADataSet.OnLoadField(ADataSet,j,ADataSet.Fields[j]);
                  end;
                  inc(i);
             end;

             Accept:=true;
             if Assigned(ADataSet.OnLoadRecord) then ADataSet.OnLoadRecord(ADataset,Accept);
             if Accept then
             begin
                  ADataSet.Post;
                  ADataSet.LoadCount:=ADataSet.LoadCount+1;
             end
             else
                 ADataSet.Cancel;
        end;
{$IFDEF DOTNET}
     finally
        Marshal.FreeHGlobal(BackPtr);
        BackPtr:=nil;
     end;
{$ENDIF}
end;

// -----------------------------------------------------------------------------------
// Registration for Delphi 3 / C++ Builder 3
// -----------------------------------------------------------------------------------

{$ifdef LEVEL3}
procedure Register;
begin
     RegisterComponents('kbmMemTable', [TkbmCSVStreamFormat]);
end;
{$endif}

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -