#include #include #include typedef struct HASHITEM { struct HASHITEM *pNext; struct HASHITEM *pPrev; char aKey[5]; char *pszData; } HASHITEM, *PHASHITEM; PHASHITEM g_aHashTable[26]; static PHASHITEM getItemFromHash(const char *pszHash) { /* calculate HashKey */ int iHash = 0; while (*pszHash != '\0') { iHash += *pszHash; pszHash++; } iHash = iHash % 26; PHASHITEM pCurr = g_aHashTable[iHash]; while ( pCurr && strcmp(pszHash, pCurr->aKey)) { pCurr = pCurr->pNext; } return pCurr; } static int parseCmd(const char *pszCmdLine) { char aCmd[6 + 1]; char aKey[5 + 10]; int iCmdPos = 0; int iKeyPos = 0; while ( *pszCmdLine != ' ' && *pszCmdLine != '\0' && iCmdPos < sizeof(aCmd) - 1) { aCmd[iCmdPos] = *pszCmdLine; iCmdPos++; pszCmdLine++; } aCmd[iCmdPos] = '\0'; if (!strcmp(aCmd, "quit")) return -1; else { /* Skip ' ' */ pszCmdLine++; /* All other commands require at least the hash. */ while ( *pszCmdLine != ' ' && *pszCmdLine != '\0' && iKeyPos < sizeof(aKey) - 1) { aKey[iKeyPos] = *pszCmdLine; iKeyPos++; pszCmdLine++; } aKey[iKeyPos] = '\0'; if (!strcmp(aCmd, "insert")) { char *pszData = NULL; char *pszCurr = NULL; size_t cbHashLen = 0; /* Skip ' ' */ pszCmdLine++; cbHashLen = strlen(pszCmdLine); pszData = (char *)calloc(cbHashLen+1, 1); pszCurr = pszData; while (*pszCmdLine != '\0') { *pszCurr = *pszCmdLine; pszCmdLine++; pszCurr++; } PHASHITEM pItem = getItemFromHash(aKey); if (pItem) { printf("Item with hash '%s' exists already\n", aKey); } else { unsigned i = 0; /* insert Hash */ PHASHITEM pItem = (PHASHITEM)malloc(sizeof(HASHITEM)); /* calculate HashKey */ int iHash = 0; const char *pszHash = aKey; while (*pszHash != '\0') { iHash += *pszHash; pszHash++; } iHash = iHash % 26; PHASHITEM pFirst = g_aHashTable[iHash]; pItem->pNext = pFirst; if (pFirst) pFirst->pPrev = pFirst; g_aHashTable[iHash] = pItem; pItem->pszData = pszData; for (i = 0; i < strlen(pszHash) + 1; i++) pItem->aKey[i] = pszHash[i]; printf("%s %p %p\n", pItem->aKey, pItem->pPrev, pItem->pNext); } } else if (!strcmp(aCmd, "get")) { /* get Hash */ PHASHITEM pItem = getItemFromHash(aKey); if (pItem) { printf("Item with hash '%s':\n", aKey); printf("%s", pItem->pszData); printf("\n"); } else printf("Could not get item with hash '%s'\n", aKey); } else if (!strcmp(aCmd, "remove")) { /* remove Hash */ PHASHITEM pItem = getItemFromHash(aKey); if (pItem) { PHASHITEM pPrev = pItem->pPrev; PHASHITEM pNext = pItem->pNext; if (pPrev) pPrev->pNext = pNext; else { /* calculate HashKey */ int iHash = 0; const char *pszHash = aKey; while (*pszHash != '\0') { iHash += *pszHash; pszHash++; } iHash = iHash % 26; g_aHashTable[iHash] = pNext; } if (pNext) pNext->pPrev = pPrev; free(pItem->pszData); free(pItem); } else printf("Could not get item with hash '%s'\n", aKey); } else printf("Command %s is not known\n", aCmd); } int rc = 0; return 0; } int main(void) { unsigned fRunning = 1; memset(g_aHashTable, 0, sizeof(g_aHashTable)); while (fRunning) { char *pszCmdLine; ssize_t cbRead; size_t cbCmdLen; printf("#: "); /* read line */ size_t *pcbRead = &cbRead; char *pszDst = NULL; char *pCurr = NULL; size_t cbBuffer = 50; /* Set initial buffer. This will grow if needed. */ pszDst = (char *)malloc(cbBuffer); pCurr = pszDst; *pcbRead = 0; for (;;) { *pCurr = fgetc(stdin); *pcbRead++; if (*pCurr == '\n') break; pCurr++; if (*pcbRead == cbBuffer) { /* Buffer is full. Expand */ cbBuffer += 50; char *pszNew = realloc(pszDst, cbBuffer); if (!pszNew) { unsigned i; pszNew = malloc(cbBuffer); for (i = 0; i < *pcbRead; i++) pszNew[i] = pszDst[i]; free(pszDst); } pszDst = pszNew; pCurr = pszDst + *pcbRead; } } pszCmdLine = pszDst; /* Remove \n */ pszCmdLine[cbRead - 1] = '\0'; int rc = parseCmd(pszCmdLine); if (rc == -1) fRunning = 0; free(pszCmdLine); } return 0; }