home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1998 / MacHack 1998.toast / Programming Contest / Secret Solutions Folder / Problem 05 - Database / Solution.p < prev   
Encoding:
Text File  |  1998-06-12  |  6.3 KB  |  200 lines  |  [TEXT/CWIE]

  1. (*
  2. Problem 05 - Database
  3.  
  4. type
  5.     StringsHandle = Handle; // Sequence of Pascal Strings packed together
  6.     DatabaseHandle = Handle; // Must be a real handle
  7.     
  8. procedure DatabaseInit( var database: Handle; field_count: UInt32 );
  9. procedure DatabaseAddEntry( database: Handle; entry: StringsHandle );
  10. procedure DatabaseFindEntry( database: Handle; field: UInt32; const match: Str255; var entry: StringsHandle );
  11. procedure DatabaseDeleteEntry( database: Handle; field: UInt32; const match: Str255 );
  12. function DatabaseCount( database: Handle ): UInt32;
  13. procedure DatabaseGetIndEntry( database: Handle; index: UInt32; var entry: StringsHandle );
  14.  
  15. All strings are case sensitive (ie, treated as eight bit binary data).
  16.  
  17. DatabaseInit creates a new, empty database ready to accept records with field_count string fields.  All the database information must be stored in the real Mac memory manager handle - it will be disposed with DisposeHandle and that must release all memory, so dont store any extra information outside the handle.  Also, you must be able to deal with having multiple databases instantiated simultaneously.
  18.  
  19. DatabaseAddEntry adds an entry (which is a Handle to field_count pascal strings packed together conceptually numbered 1 to field_count)
  20.  
  21. DatabaseFindEntry finds an entry whose field (between 1 and field_count) string is exactly equal to match.  The entry is returned in a newly created handle (which will be disposed of using DisposeHandle).  Return nil if no match is found.  If more than one entry matches, you must return the earliest added entry.
  22.  
  23. DatabaseDeleteEntry finds the entry that DatabaseFindEntry would find, and if found removes it from the database.
  24.  
  25. DatabaseCount returns the number fo entries in the database.
  26.  
  27. DatabaseGetIndEntry returns the entries in the Database in the order they were entered, 1 for the earliest entered, DatabaseCount the last entered.
  28.  
  29. You will not be given invalid parameters so you don't need to handle error checking, and there will be plenty of memory.
  30. *)
  31.  
  32. unit Solution;
  33.  
  34. interface
  35.  
  36. // Do not modify the interface
  37.  
  38.     uses
  39.         Types, Files, TextUtils;
  40.         
  41.     type
  42.         StringsHandle = Handle; // Sequence of Pascal Strings packed together
  43.         DatabaseHandle = Handle; // Must be a real handle
  44.         
  45.     procedure DatabaseInit( var database: Handle; field_count: UInt32 );
  46.     procedure DatabaseAddEntry( database: Handle; entry: StringsHandle );
  47.     procedure DatabaseFindEntry( database: Handle; field: UInt32; const match: Str255; var entry: StringsHandle );
  48.     procedure DatabaseDeleteEntry( database: Handle; field: UInt32; const match: Str255 );
  49.     function DatabaseCount( database: Handle ): UInt32;
  50.     procedure DatabaseGetIndEntry( database: Handle; index: UInt32; var entry: StringsHandle );
  51.  
  52. implementation
  53.  
  54. // Fill in your solution and then submit this folder
  55.  
  56. // Team Name: Example Solution
  57. // 18 minutes
  58.  
  59.     const
  60.         first_entry_pos = SizeOf(UInt32);
  61.     type
  62.         UInt32Ptr = ^UInt32;
  63.         UInt32Handle = ^UInt32Ptr;
  64.         
  65.     function GetCount( database: Handle ): UInt32;
  66.     begin
  67.         GetCount := UInt32Handle(database)^^;
  68.     end;
  69.     
  70.     function GetHandleOffset( data: Handle; offset: UInt32 ): Ptr;
  71.     begin
  72.         GetHandleOffset := Ptr(longint(data^)+offset);
  73.     end;
  74.     
  75.     function GetByteAtPtr( p: Ptr ): integer;
  76.     begin
  77.         GetByteAtPtr := band( p^, $00FF );
  78.     end;
  79.     
  80.     function GetNextEntry( database: Handle; var offset: UInt32; entry: StringsHandle ): boolean;
  81.         var
  82.             i, count, orgoffset: UInt32;
  83.     begin
  84.         if offset >= GetHandleSize( database ) then begin
  85.             GetNextEntry := false;
  86.         end else begin
  87.             GetNextEntry := true;
  88.             count := getCount( database );
  89.             orgoffset := offset;
  90.             for i := 1 to count do begin
  91.                 offset := offset + GetByteAtPtr( GetHandleOffset( database, offset ) ) + 1;
  92.             end;
  93.             SetHandleSize( entry, offset - orgoffset );
  94.             BlockMoveData( GetHandleOffset( database, orgoffset ), entry^, offset - orgoffset );
  95.         end;
  96.     end;
  97.     
  98.     procedure GetNthString( entry: StringsHandle; index: UInt32; var s: Str255 );
  99.         var
  100.             offset: UInt32;
  101.             len: integer;
  102.             i: UInt32;
  103.     begin
  104.         offset := 0;
  105.         for i := 1 to index-1 do begin
  106.             offset := offset + GetByteAtPtr( GetHandleOffset( entry, offset ) ) + 1;
  107.         end;
  108.         len := GetByteAtPtr( GetHandleOffset( entry, offset ) );
  109.         BlockMoveData( GetHandleOffset( entry, offset ), @s, len + 1 );
  110.     end;
  111.  
  112.     procedure DatabaseInit( var database: Handle; field_count: UInt32 );
  113.     begin
  114.         database := NewHandle( SizeOf(field_count) );
  115.         if database <> nil then begin
  116.             UInt32Handle(database)^^ := field_count;
  117.         end;
  118.     end;
  119.     
  120.     procedure DatabaseAddEntry( database: Handle; entry: StringsHandle );
  121.         var
  122.             junk: OSErr;
  123.     begin
  124.         junk := HandAndHand( entry, database );
  125.     end;
  126.     
  127.     procedure FindEntry( database: Handle; field: UInt32; const match: Str255; var entryoffset: UInt32; var entry: StringsHandle );
  128.         var
  129.             offset: UInt32;
  130.             found: boolean;
  131.             s: Str255;
  132.     begin
  133.         offset := first_entry_pos;
  134.         entry := NewHandle( 0 );
  135.         found := false;
  136.         entryoffset := offset;
  137.         while not found & GetNextEntry( database, offset, entry ) do begin
  138.             GetNthString( entry, field, s );
  139.             found := s = match;
  140.             if not found then begin
  141.                 entryoffset := offset;
  142.             end;
  143.         end;
  144.         if not found then begin
  145.             DisposeHandle( entry );
  146.             entry := nil;
  147.         end;
  148.     end;
  149.     
  150.     procedure DatabaseFindEntry( database: Handle; field: UInt32; const match: Str255; var entry: StringsHandle );
  151.         var
  152.             entryoffset: UInt32;
  153.     begin
  154.         FindEntry( database, field, match, entryoffset, entry );
  155.     end;
  156.     
  157.     procedure DatabaseDeleteEntry( database: Handle; field: UInt32; const match: Str255 );
  158.         var
  159.             entryoffset: UInt32;
  160.             junkl: longint;
  161.             entry: Handle;
  162.     begin
  163.         FindEntry( database, field, match, entryoffset, entry );
  164.         if entry <> nil then begin
  165.             junkl := Munger( database, entryoffset, nil, GetHandleSize(entry),@junkl, 0);
  166.             DisposeHandle(entry);
  167.         end;
  168.     end;
  169.     
  170.     function DatabaseCount( database: Handle ): UInt32;
  171.         var
  172.             offset, count: UInt32;
  173.             entry: Handle;
  174.     begin
  175.         offset := first_entry_pos;
  176.         count := 0;
  177.         entry := NewHandle( 0 );
  178.         while GetNextEntry( database, offset, entry ) do begin
  179.             Inc(count);
  180.         end;
  181.         DisposeHandle( entry );
  182.         DatabaseCount := count;
  183.     end;
  184.  
  185.     procedure DatabaseGetIndEntry( database: Handle; index: UInt32; var entry: StringsHandle );
  186.         var
  187.             offset: UInt32;
  188.     begin
  189.         offset := first_entry_pos;
  190.         entry := NewHandle( 0 );
  191.         while GetNextEntry( database, offset, entry ) do begin
  192.             Dec(index);
  193.             if index = 0 then begin
  194.                 leave;
  195.             end;
  196.         end;
  197.     end;
  198.  
  199. end.
  200.