home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1998 / MacHack 1998.toast / Programming Contest / ~Solutions Submitted / Problem 05 - Three And One / Solution.cp < prev    next >
Encoding:
Text File  |  1998-06-19  |  5.2 KB  |  172 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:
  11. Str255; var entry: StringsHandle );
  12. procedure DatabaseDeleteEntry( database: Handle; field: UInt32; const match:
  13. Str255 );
  14. function DatabaseCount( database: Handle ): UInt32;
  15. procedure DatabaseGetIndEntry( database: Handle; index: UInt32; var entry:
  16. StringsHandle );
  17.  
  18. Your task is to write a set of routines to maintain a database.
  19.  
  20. DatabaseInit creates a new, empty database ready to accept records with
  21. field_count string fields.  The database is stored in the database Handle.
  22.  
  23. DatabaseAddEntry adds an entry (which is a Handle to field_count pascal strings
  24. packed together conceptually numbered 1 to field_count)
  25.  
  26. DatabaseFindEntry finds an entry whose field (between 1 and field_count) string
  27. is exactly equal to match.  The entry is returned in a newly created handle
  28. (which will be disposed of using DisposeHandle).  Return nil if no match is
  29. found.  If more than one entry matches, you must return the earliest added
  30. entry.
  31.  
  32. DatabaseDeleteEntry finds the entry that DatabaseFindEntry would find, and if
  33. found removes it from the database.
  34.  
  35. DatabaseCount returns the number of entries in the database.
  36.  
  37. DatabaseGetIndEntry returns the entries in the Database in the order they were
  38. entered, 1 for the earliest entered, DatabaseCount the last entered.
  39.  
  40. All the database information must be stored in the real Mac memory manager
  41. handle - it will be disposed with DisposeHandle and that must release all
  42. memory, so do not store any extra information outside the handle.  Also, you
  43. must be able to deal with having multiple databases instantiated
  44. simultaneously.
  45.  
  46. You will not be given invalid parameters so you don't need to handle error
  47. checking, and there will be plenty of memory.
  48.  
  49. All strings are case sensitive (ie, treated as eight bit binary data).
  50. */
  51.  
  52. #include "Solution.h"
  53.  
  54. #include <string.h>
  55.  
  56. UInt32 gFieldCount;
  57. // Fill in your solution and then submit this folder
  58.  
  59. // Team Name: Three And One
  60.  
  61. pascal void DatabaseInit( DatabaseHandle *database, UInt32 field_count )
  62.     {
  63.     gFieldCount = field_count;
  64.     *database = NewHandle(0);
  65.     }
  66.  
  67. pascal void DatabaseAddEntry( DatabaseHandle database, StringsHandle entry )
  68.     {
  69.     HandAndHand(entry, database);
  70.     }
  71.  
  72. static unsigned char *
  73. FindNextEntry(unsigned char * entry)
  74.     {
  75.     for (UInt32 currentField = 1; currentField <= gFieldCount; currentField++)
  76.         entry += entry[0] + 1;
  77.     
  78.     return entry;
  79.     }
  80.  
  81. static unsigned char *
  82. FindField(unsigned char * entry, UInt32 field)
  83.     {
  84.     for (UInt32 currentField = 1; currentField < field; currentField++)
  85.         entry += entry[0] + 1;
  86.     
  87.     return entry;
  88.     }
  89.  
  90. UInt32
  91. EntrySize(unsigned char *entry)
  92.     {
  93.     UInt32 size = 0;
  94.     unsigned char *field = entry;
  95.     for (short i = 1; i <= gFieldCount; i++)
  96.         {
  97.         size += field[0] + 1;
  98.         field += field[0] + 1;
  99.         }
  100.     return size;
  101.     }
  102.     
  103. StringsHandle
  104. NewEntryHandle(unsigned char *entry)
  105.     {
  106.     UInt32 entrySize = EntrySize(entry);
  107.     Handle entryHandle = NewHandle(entrySize);
  108.     memcpy(*entryHandle, entry, entrySize);
  109.     return entryHandle;
  110.     }
  111.  
  112. pascal void DatabaseFindEntry( DatabaseHandle database, UInt32 field, ConstStr255Param match, StringsHandle *entry )
  113.     {
  114.     UInt32 matchLength = match[0];
  115.     unsigned char *currentEntry = (unsigned char*)*database;
  116.     
  117.     while (currentEntry < GetHandleSize(database) + (unsigned char*)*database)
  118.         {
  119.         unsigned char *currentField = FindField(currentEntry, field);
  120.         if (matchLength == currentField[0] && !strncmp((const char *)currentField, (const char *)match, matchLength + 1))
  121.             {
  122.             *entry = NewEntryHandle(currentEntry);
  123.             return;
  124.             }
  125.         
  126.         currentEntry = FindNextEntry(currentEntry);
  127.         }
  128.         
  129.     *entry = NULL;
  130.     }
  131.  
  132. pascal void DatabaseDeleteEntry( DatabaseHandle database, UInt32 field, ConstStr255Param match )
  133.     {
  134.     UInt32 matchLength = match[0];
  135.     unsigned char *    currentEntry = (unsigned char*)*database;
  136.     UInt32 databaseSize = GetHandleSize(database);
  137.     
  138.     while (currentEntry < databaseSize + (unsigned char*)*database)
  139.         {
  140.         unsigned char *currentField = FindField(currentEntry, field);
  141.         if (matchLength == currentField[0] && !strncmp((const char *)currentField, (const char *)match, matchLength + 1))
  142.             {
  143.             UInt32 entrySize = EntrySize(currentEntry);
  144.             memmove(currentEntry, currentEntry + entrySize, (unsigned char*)*database + databaseSize - currentEntry - entrySize);
  145.             SetHandleSize(database, databaseSize - entrySize);
  146.             return;
  147.             }
  148.         
  149.         currentEntry = FindNextEntry(currentEntry);
  150.         }
  151.     }
  152.  
  153. pascal UInt32 DatabaseCount( DatabaseHandle database )
  154.     {
  155.     unsigned char *    currentEntry = (unsigned char*)*database;
  156.     short count;
  157.     for (count = 0; currentEntry < GetHandleSize(database) + (unsigned char*)*database; count++)
  158.         currentEntry = FindNextEntry(currentEntry);
  159.     return count;
  160.     }
  161.  
  162. pascal void DatabaseGetIndEntry( DatabaseHandle database, UInt32 index, StringsHandle *entry )
  163.     {
  164.     unsigned char *currentEntry = (unsigned char*)*database;
  165.     
  166.     for (short i = 1; i < index; i++)
  167.         currentEntry = FindNextEntry(currentEntry);
  168.     
  169.     *entry = NewEntryHandle(currentEntry);
  170.     }
  171.  
  172.