|
| 1 | +#include "hashFO.h" |
| 2 | + |
| 3 | +#include <stdio.h> |
| 4 | +#include <stdlib.h> |
| 5 | +#include <string.h> |
| 6 | + |
| 7 | +/** |
| 8 | + * Creates a .hash file with empty buckets. |
| 9 | + * Returns 0 if success, -1 if error. |
| 10 | + */ |
| 11 | +int createEmptyHashFile(char *hashFile){ |
| 12 | + FILE *hFile; |
| 13 | + Bucket b; |
| 14 | + int i, nBuckets; |
| 15 | + |
| 16 | + if(NULL == (hFile = fopen(hashFile, "wb"))) |
| 17 | + return -1; |
| 18 | + |
| 19 | + |
| 20 | + memset(&b, 0, sizeof(Bucket)); |
| 21 | + nBuckets = BUCKETS + OVERFLOW_BUCKETS; |
| 22 | + |
| 23 | + for(i=0; i<nBuckets; i++){ |
| 24 | + fwrite(&b, sizeof(Bucket), 1, hFile); |
| 25 | + } |
| 26 | + |
| 27 | + fclose(hFile); |
| 28 | + return 0; |
| 29 | +} |
| 30 | + |
| 31 | + |
| 32 | +/** |
| 33 | + * Creates a .hash file from a .dat file. It reads people info from |
| 34 | + * a .dat file and inserts it to buckets in .hash file. |
| 35 | + * It returns: |
| 36 | + * - (-1) if params error |
| 37 | + * - (-2) if cannot open .dat file |
| 38 | + * - number of overflowing registers that where inserted. |
| 39 | + */ |
| 40 | +int createHashFromBinaryFile(char *binaryFile, char *hashFile){ |
| 41 | + if(-1 == createEmptyHashFile(hashFile)) |
| 42 | + return -1; |
| 43 | + |
| 44 | + FILE *inFile, *outFile; |
| 45 | + if(NULL == (inFile = fopen(binaryFile, "rb"))) return -2; |
| 46 | + |
| 47 | + Person p; |
| 48 | + Bucket b; |
| 49 | + int nOverflows = 0; |
| 50 | + int insertedBucket; |
| 51 | + |
| 52 | + while(fread(&p, sizeof(Person), 1, inFile)){ |
| 53 | + insertedBucket = insertRegister(&p, hashFile); |
| 54 | + |
| 55 | + if(insertedBucket >= BUCKETS) |
| 56 | + nOverflows++; |
| 57 | + } |
| 58 | + return nOverflows; |
| 59 | +} |
| 60 | + |
| 61 | + |
| 62 | +/** |
| 63 | + * Reads, interprets and prints a .hash file to see how data is stored. |
| 64 | + * Returns the total number of buckets the .hash file stores (including |
| 65 | + * buckets in overflowing area), or -1 if cannot open the .hash file. |
| 66 | + */ |
| 67 | +int readHashFile(char *hashFile){ |
| 68 | + FILE *hFile; |
| 69 | + Bucket b; |
| 70 | + int i,j,n; |
| 71 | + |
| 72 | + if(NULL == (hFile = fopen(hashFile, "rb"))) |
| 73 | + return -1; |
| 74 | + |
| 75 | + rewind(hFile); |
| 76 | + |
| 77 | + i = 0; |
| 78 | + fread(&b, sizeof(Bucket), 1, hFile); |
| 79 | + while(!feof(hFile)){ |
| 80 | + for(j=0; j<CAPACITY; j++){ |
| 81 | + if(j == 0){ |
| 82 | + printf("\x1b[36;1m==============================================================\n"); |
| 83 | + printf("\x1b[33;3;4mBucket %2d (%02d registers assigned)\n\x1b[0m",i, b.size); |
| 84 | + } |
| 85 | + |
| 86 | + if(j < b.size) |
| 87 | + printf("\t\t\t%-8s %-19s %-19s %-19s %-11s\n", b.registers[j].dni, b.registers[j].name, |
| 88 | + b.registers[j].surname1,b.registers[j].surname2,b.registers[j].province); |
| 89 | + else |
| 90 | + printf("\n"); |
| 91 | + } |
| 92 | + |
| 93 | + i++; |
| 94 | + fread(&b, sizeof(Bucket), 1, hFile); |
| 95 | + } |
| 96 | + |
| 97 | + printf("\x1b[36;1m==============================================================\n\x1b[0m"); |
| 98 | + fclose(hFile); |
| 99 | + return i; |
| 100 | +} |
| 101 | + |
| 102 | + |
| 103 | +/** |
| 104 | + * Searches for a register in a .hash file given a dni. |
| 105 | + * It returns: |
| 106 | + * - (-1) if params error |
| 107 | + * - (-2) if cannot open .hash file |
| 108 | + * - (-3) if dni is not stored in .hash file |
| 109 | + * - bucket number where dni has been found |
| 110 | + */ |
| 111 | +int searchRegister(char *dni, char *hashFile, Person *p){ |
| 112 | + if(dni == NULL || hashFile == NULL || p == NULL) |
| 113 | + return -1; |
| 114 | + |
| 115 | + FILE *hFile; |
| 116 | + if(NULL == (hFile = fopen(hashFile, "rb"))) |
| 117 | + return -2; |
| 118 | + |
| 119 | + int i; |
| 120 | + Bucket b; |
| 121 | + |
| 122 | + //Move to the bucket where dni should be stored according to the hashFile |
| 123 | + fseek(hFile, HASH_BUCKET(atoi(dni)), SEEK_SET); |
| 124 | + fread(&b, sizeof(Bucket), 1, hFile); |
| 125 | + |
| 126 | + //Look if the dni is in that bucket. If it is not in the cube: |
| 127 | + // - If bucket size < CAPACITY -> dni is not stored anywhere |
| 128 | + // - If bucket size >= CAPACITY -> dni might be stored in overflow zone |
| 129 | + for(i=0; i<CAPACITY && i<b.size; i++){ |
| 130 | + if(strcmp(b.registers[i].dni, dni) == 0){ |
| 131 | + *p = b.registers[i]; |
| 132 | + return HASH(atoi(dni)); |
| 133 | + } |
| 134 | + } |
| 135 | + |
| 136 | + if(b.size < CAPACITY) |
| 137 | + return -3; |
| 138 | + else{ |
| 139 | + int bucketReaded; |
| 140 | + |
| 141 | + //Move to overflow zone |
| 142 | + fseek(hFile, OVERFLOW_ZONE, SEEK_SET); |
| 143 | + |
| 144 | + bucketReaded = 0; |
| 145 | + while(fread(&b, sizeof(Bucket), 1, hFile)){ |
| 146 | + for(i=0; i<CAPACITY && i<b.size; i++){ |
| 147 | + if(strcmp(b.registers[i].dni, dni) == 0){ |
| 148 | + *p = b.registers[i]; |
| 149 | + return BUCKETS + bucketReaded; |
| 150 | + } |
| 151 | + } |
| 152 | + |
| 153 | + //If the last bucket is reached (last is not full) and |
| 154 | + // dni was not found, dni is not stored anywhere. |
| 155 | + if(b.size < CAPACITY) |
| 156 | + return -3; |
| 157 | + |
| 158 | + bucketReaded++; |
| 159 | + } |
| 160 | + } |
| 161 | +} |
| 162 | + |
| 163 | + |
| 164 | +/** |
| 165 | + * Inserts a new register (person) in a .hash file. |
| 166 | + * - (-1) if params error |
| 167 | + * - (-2) if cannot open .hash file |
| 168 | + * - (-3) if there is no more available space to store people |
| 169 | + * - bucket number where dni has been stored if success |
| 170 | + */ |
| 171 | +int insertRegister(Person *p, char *hashFile){ |
| 172 | + if(p == NULL || hashFile == NULL) |
| 173 | + return -1; |
| 174 | + |
| 175 | + FILE *hFile; |
| 176 | + if(NULL == (hFile = fopen(hashFile, "rb+"))){ |
| 177 | + return -2; |
| 178 | + } |
| 179 | + |
| 180 | + Bucket b; |
| 181 | + |
| 182 | + //Move pointer to the cube where the register in going to be |
| 183 | + // stored, according to the DNI hash |
| 184 | + fseek(hFile, HASH_BUCKET(atoi(p->dni)), SEEK_SET); |
| 185 | + |
| 186 | + //Reads the cube from the file: |
| 187 | + // - If bucket size < CAPACITY -> Bucket has space to store the registers |
| 188 | + // - If bucket size >= CAPACITY -> Bucket has no space, register is stores in overflow zone. |
| 189 | + fread(&b, sizeof(Bucket), 1, hFile); |
| 190 | + |
| 191 | + if(b.size < CAPACITY){ |
| 192 | + b.registers[b.size] = *p; |
| 193 | + (b.size)++; |
| 194 | + |
| 195 | + //Move pointer back to the bucket again and overwrite it |
| 196 | + fseek(hFile, -sizeof(Bucket), SEEK_CUR); |
| 197 | + fwrite(&b, sizeof(Bucket), 1, hFile); |
| 198 | + |
| 199 | + fclose(hFile); |
| 200 | + return HASH(atoi(p->dni)); |
| 201 | + |
| 202 | + }else{ |
| 203 | + int i, bucketToRead; |
| 204 | + |
| 205 | + //Increment size and rewrite the register that is full. |
| 206 | + b.size++; |
| 207 | + fseek(hFile, -sizeof(Bucket), SEEK_CUR); |
| 208 | + fwrite(&b, sizeof(Bucket), 1, hFile); |
| 209 | + |
| 210 | + //Move to overflow zone and search for a empty space to |
| 211 | + // store the register. If there is no more space available, |
| 212 | + // it returns -3. |
| 213 | + fseek(hFile, OVERFLOW_ZONE, SEEK_SET); |
| 214 | + |
| 215 | + bucketToRead = 0; |
| 216 | + fread(&b, sizeof(Bucket), 1, hFile); |
| 217 | + |
| 218 | + while(!(b.size < CAPACITY)){ |
| 219 | + bucketToRead++; |
| 220 | + if(bucketToRead == OVERFLOW_BUCKETS){ |
| 221 | + fclose(hFile); |
| 222 | + return -3; |
| 223 | + } |
| 224 | + |
| 225 | + fread(&b, sizeof(Bucket), 1, hFile); |
| 226 | + } |
| 227 | + |
| 228 | + |
| 229 | + //If there is a bucket with available space, inserts the register |
| 230 | + // and overwrites the bucket in the file. |
| 231 | + b.registers[b.size] = *p; |
| 232 | + fseek(hFile, -sizeof(Bucket), SEEK_CUR); |
| 233 | + fwrite(&b, sizeof(Bucket), 1, hFile); |
| 234 | + |
| 235 | + //Finally, increments the number of registers assigned in all |
| 236 | + // overflow buckets located before the bucket where the register |
| 237 | + // was saved |
| 238 | + fseek(hFile, OVERFLOW_ZONE, SEEK_SET); |
| 239 | + for(i=0; i<=bucketToRead; i++){ |
| 240 | + //Read cube |
| 241 | + fread(&b, sizeof(Bucket), 1, hFile); |
| 242 | + //Increment size |
| 243 | + b.size++; |
| 244 | + //Overwrite cube |
| 245 | + fseek(hFile, -sizeof(Bucket), SEEK_CUR); |
| 246 | + fwrite(&b, sizeof(Bucket), 1, hFile); |
| 247 | + } |
| 248 | + |
| 249 | + fclose(hFile); |
| 250 | + return (BUCKETS + bucketToRead); |
| 251 | + } |
| 252 | +} |
| 253 | + |
| 254 | + |
0 commit comments