| /* |
| ******************************************************************************* |
| * |
| * Copyright (C) 1998-2000, International Business Machines |
| * Corporation and others. All Rights Reserved. |
| * |
| ******************************************************************************* |
| * |
| * File list.c |
| * |
| * Modification History: |
| * |
| * Date Name Description |
| * 06/01/99 stephen Creation. |
| ******************************************************************************* |
| */ |
| |
| #include "list.h" |
| #include "cmemory.h" |
| #include "cstring.h" |
| #include "unicode/ustring.h" |
| |
| /* Protos */ |
| static void strlist_grow(struct SList *list, UErrorCode *status); |
| static void strlist2d_grow(struct SList *list, UErrorCode *status); |
| static void strlist2d_growRows(struct SList *list, UErrorCode *status); |
| static void taglist_grow(struct SList *list, UErrorCode *status); |
| |
| /* String list */ |
| |
| struct SList* |
| strlist_open(UErrorCode *status) |
| { |
| struct SList *list; |
| |
| if(U_FAILURE(*status)) return 0; |
| |
| list = (struct SList*) uprv_malloc(sizeof(struct SList)); |
| if(list == 0) { |
| *status = U_MEMORY_ALLOCATION_ERROR; |
| return 0; |
| } |
| |
| list->fType = eStringList; |
| |
| list->u.fStringList.fData = 0; |
| list->u.fStringList.fCount = 0; |
| list->u.fStringList.fCapacity = 32; |
| |
| strlist_grow(list, status); |
| |
| return list; |
| } |
| |
| void |
| strlist_close(struct SList *list, |
| UErrorCode *status) |
| { |
| int32_t i; |
| |
| if(U_FAILURE(*status)) return; |
| |
| if(list->fType != eStringList) { |
| *status = U_ILLEGAL_ARGUMENT_ERROR; |
| return; |
| } |
| |
| /* deallocate each string */ |
| for(i = 0; i < list->u.fStringList.fCount; ++i) { |
| uprv_free(list->u.fStringList.fData[i]); |
| } |
| uprv_free(list->u.fStringList.fData); |
| |
| list->fType = eEmpty; |
| uprv_free(list); |
| } |
| |
| void |
| strlist_add(struct SList *list, |
| const UChar *s, |
| UErrorCode *status) |
| { |
| int32_t index; |
| |
| if(U_FAILURE(*status)) return; |
| |
| if(list->fType != eStringList) { |
| *status = U_ILLEGAL_ARGUMENT_ERROR; |
| return; |
| } |
| |
| index = list->u.fStringList.fCount; |
| |
| if(list->u.fStringList.fCount == list->u.fStringList.fCapacity) |
| strlist_grow(list, status); |
| |
| list->u.fStringList.fData[index] = (UChar*) |
| uprv_malloc(sizeof(UChar) * (u_strlen(s) + 1)); |
| if(list->u.fStringList.fData[index] == 0) { |
| *status = U_MEMORY_ALLOCATION_ERROR; |
| return; |
| } |
| |
| u_strcpy(list->u.fStringList.fData[index], s); |
| ++(list->u.fStringList.fCount); |
| } |
| |
| static void |
| strlist_grow(struct SList *list, |
| UErrorCode *status) |
| { |
| int32_t i, j; |
| int32_t newCapacity; |
| UChar **newData; |
| |
| if(U_FAILURE(*status)) return; |
| |
| if(list->fType != eStringList) { |
| *status = U_ILLEGAL_ARGUMENT_ERROR; |
| return; |
| } |
| |
| newCapacity = list->u.fStringList.fCapacity << 1; |
| |
| /* allocate space for the array of strings */ |
| newData = (UChar**) uprv_malloc(sizeof(UChar*) * newCapacity); |
| if(newData == 0) { |
| *status = U_MEMORY_ALLOCATION_ERROR; |
| return; |
| } |
| |
| /* allocate and copy each string */ |
| for(i = 0; i < list->u.fStringList.fCount; ++i) { |
| newData[i] = (UChar*) |
| uprv_malloc(sizeof(UChar) * (u_strlen(list->u.fStringList.fData[i]) + 1)); |
| if(newData[i] == 0) { |
| *status = U_MEMORY_ALLOCATION_ERROR; |
| for(j = 0; j < i; ++j) |
| uprv_free(newData[j]); |
| uprv_free(newData); |
| return; |
| } |
| u_strcpy(newData[i], list->u.fStringList.fData[i]); |
| } |
| |
| uprv_free(list->u.fStringList.fData); |
| list->u.fStringList.fData = newData; |
| list->u.fStringList.fCapacity = newCapacity; |
| } |
| |
| /* 2-d String list*/ |
| |
| struct SList* |
| strlist2d_open(UErrorCode *status) |
| { |
| struct SList *list; |
| |
| if(U_FAILURE(*status)) return 0; |
| |
| list = (struct SList*) uprv_malloc(sizeof(struct SList)); |
| if(list == 0) { |
| *status = U_MEMORY_ALLOCATION_ERROR; |
| return 0; |
| } |
| |
| list->fType = eStringList2d; |
| |
| list->u.fStringList2d.fData = 0; |
| list->u.fStringList2d.fCount = 0; |
| list->u.fStringList2d.fCapacity = 32; |
| |
| list->u.fStringList2d.fRows = 0; |
| list->u.fStringList2d.fRowCount = 0; |
| list->u.fStringList2d.fRowCapacity = 32; |
| |
| strlist2d_grow(list, status); |
| strlist2d_growRows(list, status); |
| |
| if(U_SUCCESS(*status)) { |
| list->u.fStringList2d.fRows[0] = 0; |
| list->u.fStringList2d.fRowCount = 1; |
| } |
| |
| return list; |
| } |
| |
| void |
| strlist2d_close(struct SList *list, |
| UErrorCode *status) |
| { |
| int32_t i; |
| |
| if(U_FAILURE(*status)) return; |
| |
| if(list->fType != eStringList2d) { |
| *status = U_ILLEGAL_ARGUMENT_ERROR; |
| return; |
| } |
| |
| /* deallocate each string */ |
| for(i = 0; i < list->u.fStringList2d.fCount; ++i) { |
| uprv_free(list->u.fStringList2d.fData[i]); |
| } |
| uprv_free(list->u.fStringList2d.fData); |
| |
| uprv_free(list->u.fStringList2d.fRows); |
| |
| list->fType = eEmpty; |
| uprv_free(list); |
| } |
| |
| void |
| strlist2d_newRow(struct SList *list, |
| UErrorCode *status) |
| { |
| if(U_FAILURE(*status)) return; |
| |
| if(list->fType != eStringList2d) { |
| *status = U_ILLEGAL_ARGUMENT_ERROR; |
| return; |
| } |
| |
| if(list->u.fStringList2d.fRowCount == list->u.fStringList2d.fRowCapacity) |
| strlist2d_growRows(list, status); |
| if(U_FAILURE(*status)) return; |
| list->u.fStringList2d.fRows[(list->u.fStringList2d.fRowCount)++] = |
| list->u.fStringList2d.fCount; |
| } |
| |
| void strlist2d_add(struct SList *list, |
| const UChar *s, |
| UErrorCode *status) |
| { |
| int32_t index; |
| |
| if(U_FAILURE(*status)) return; |
| |
| if(list->fType != eStringList2d) { |
| *status = U_ILLEGAL_ARGUMENT_ERROR; |
| return; |
| } |
| |
| index = list->u.fStringList2d.fCount; |
| |
| if(list->u.fStringList2d.fCount == list->u.fStringList2d.fCapacity) |
| strlist2d_grow(list, status); |
| |
| list->u.fStringList2d.fData[index] = (UChar*) |
| uprv_malloc(sizeof(UChar) * (u_strlen(s) + 1)); |
| if(list->u.fStringList2d.fData[index] == 0) { |
| *status = U_MEMORY_ALLOCATION_ERROR; |
| return; |
| } |
| |
| u_strcpy(list->u.fStringList2d.fData[index], s); |
| ++(list->u.fStringList2d.fCount); |
| } |
| |
| static void |
| strlist2d_grow(struct SList *list, |
| UErrorCode *status) |
| { |
| int32_t i, j; |
| int32_t newCapacity; |
| UChar **newData; |
| |
| if(U_FAILURE(*status)) return; |
| |
| if(list->fType != eStringList2d) { |
| *status = U_ILLEGAL_ARGUMENT_ERROR; |
| return; |
| } |
| |
| newCapacity = list->u.fStringList2d.fCapacity << 1; |
| |
| /* allocate space for the array of strings */ |
| newData = (UChar**) uprv_malloc(sizeof(UChar*) * newCapacity); |
| if(newData == 0) { |
| *status = U_MEMORY_ALLOCATION_ERROR; |
| return; |
| } |
| |
| /* allocate and copy each string */ |
| for(i = 0; i < list->u.fStringList2d.fCount; ++i) { |
| newData[i] = (UChar*) |
| uprv_malloc(sizeof(UChar) * (u_strlen(list->u.fStringList2d.fData[i]) + 1)); |
| if(newData[i] == 0) { |
| *status = U_MEMORY_ALLOCATION_ERROR; |
| for(j = 0; j < i; ++j) |
| uprv_free(newData[j]); |
| uprv_free(newData); |
| return; |
| } |
| u_strcpy(newData[i], list->u.fStringList2d.fData[i]); |
| } |
| |
| uprv_free(list->u.fStringList2d.fData); |
| list->u.fStringList2d.fData = newData; |
| list->u.fStringList2d.fCapacity = newCapacity; |
| } |
| |
| static void |
| strlist2d_growRows(struct SList *list, |
| UErrorCode *status) |
| { |
| int32_t i; |
| int32_t newCapacity; |
| int32_t *newRows; |
| |
| if(U_FAILURE(*status)) return; |
| |
| if(list->fType != eStringList2d) { |
| *status = U_ILLEGAL_ARGUMENT_ERROR; |
| return; |
| } |
| |
| newCapacity = list->u.fStringList2d.fRowCapacity << 1; |
| |
| /* allocate space for the array of ints */ |
| newRows = (int32_t*) uprv_malloc(sizeof(int32_t) * newCapacity); |
| if(newRows == 0) { |
| *status = U_MEMORY_ALLOCATION_ERROR; |
| } |
| |
| /* copy each int */ |
| for(i = 0; i < list->u.fStringList2d.fRowCount; ++i) |
| newRows[i] = list->u.fStringList2d.fRows[i]; |
| |
| /* clean up */ |
| uprv_free(list->u.fStringList2d.fRows); |
| list->u.fStringList2d.fRows = newRows; |
| list->u.fStringList2d.fRowCapacity = newCapacity; |
| } |
| |
| /* Tagged list */ |
| |
| struct SList* |
| taglist_open(UErrorCode *status) |
| { |
| struct SList *list; |
| |
| if(U_FAILURE(*status)) return 0; |
| |
| list = (struct SList*) uprv_malloc(sizeof(struct SList)); |
| if(list == 0) { |
| *status = U_MEMORY_ALLOCATION_ERROR; |
| return 0; |
| } |
| |
| list->fType = eTaggedList; |
| |
| /*list->u.fTaggedList.fData = 0;*/ |
| list->u.fTaggedList.fFirst = NULL; |
| list->u.fTaggedList.fCount = 0; |
| /*list->u.fTaggedList.fCapacity = 32;*/ |
| |
| /*taglist_grow(list, status);*/ |
| |
| return list; |
| } |
| |
| void |
| taglist_close(struct SList *list, |
| UErrorCode *status) |
| { |
| struct SStringPair *current; |
| struct SStringPair *prev; |
| if(U_FAILURE(*status)) return; |
| |
| if(list->fType != eTaggedList) { |
| *status = U_ILLEGAL_ARGUMENT_ERROR; |
| return; |
| } |
| |
| current = list->u.fTaggedList.fFirst; |
| |
| while(current != NULL) { |
| prev = current; |
| current = current->fNext; |
| uprv_free(prev); |
| } |
| |
| |
| /*uprv_free(list->u.fTaggedList.fData);*/ |
| |
| list->fType = eEmpty; |
| uprv_free(list); |
| } |
| |
| |
| void |
| taglist_add(struct SList *list, |
| const UChar *tag, |
| const UChar *data, |
| UErrorCode *status) |
| { |
| /*int32_t index;*/ |
| struct SStringPair *pair = NULL; |
| struct SStringPair *current = NULL; |
| struct SStringPair *prev = NULL; |
| |
| if(U_FAILURE(*status)) return; |
| |
| if(list->fType != eTaggedList) { |
| *status = U_ILLEGAL_ARGUMENT_ERROR; |
| return; |
| } |
| |
| pair = (struct SStringPair *) uprv_malloc(sizeof(struct SStringPair)); |
| if(pair->fKey == 0) { |
| *status = U_MEMORY_ALLOCATION_ERROR; |
| return; |
| } |
| |
| |
| pair->fKey = (char*) uprv_malloc(sizeof(char) * (u_strlen(tag) + 1)); |
| if(pair->fKey == 0) { |
| *status = U_MEMORY_ALLOCATION_ERROR; |
| uprv_free(pair); |
| return; |
| } |
| |
| pair->fValue = (UChar*) uprv_malloc(sizeof(UChar) * (u_strlen(data) + 1)); |
| if(pair->fValue == 0) { |
| *status = U_MEMORY_ALLOCATION_ERROR; |
| uprv_free(pair->fKey); |
| uprv_free(pair); |
| return; |
| } |
| |
| ++(list->u.fTaggedList.fCount); |
| |
| /*u_strcpy(pair.fKey, tag);*/ |
| u_UCharsToChars(tag, pair->fKey, u_strlen(tag)+1); |
| u_strcpy(pair->fValue, data); |
| |
| /* is list still empty? */ |
| if(list->u.fTaggedList.fFirst == NULL) { |
| list->u.fTaggedList.fFirst = pair; |
| pair->fNext = NULL; |
| return; |
| } else { |
| current = list->u.fTaggedList.fFirst; |
| } |
| |
| while(current != NULL) { |
| if(uprv_strcmp(current->fKey, pair->fKey)<0) { |
| prev = current; |
| current = current->fNext; |
| } else { /*we're either in front of list, or in middle*/ |
| if(prev == NULL) { /*front of the list*/ |
| list->u.fTaggedList.fFirst = pair; |
| } else { /*middle of the list*/ |
| prev->fNext = pair; |
| } |
| pair->fNext = current; |
| return; |
| } |
| } |
| |
| /* end of list */ |
| prev->fNext = pair; |
| pair->fNext = NULL; |
| |
| /*index = list->u.fTaggedList.fCount;*/ |
| |
| /*if(list->u.fTaggedList.fCount == list->u.fTaggedList.fCapacity)*/ |
| /*taglist_grow(list, status);*/ |
| |
| /*list->u.fTaggedList.fData[index] = pair;*/ |
| } |
| |
| const UChar* |
| taglist_get(const struct SList *list, |
| const char *tag, |
| UErrorCode *status) |
| { |
| /*int32_t i;*/ |
| struct SStringPair *current; |
| |
| if(U_FAILURE(*status)) return 0; |
| |
| if(list->fType != eTaggedList) { |
| *status = U_ILLEGAL_ARGUMENT_ERROR; |
| return 0; |
| } |
| |
| /* is list still empty? */ |
| if(list->u.fTaggedList.fFirst == NULL) { |
| return NULL; |
| } else { |
| current = list->u.fTaggedList.fFirst; |
| } |
| |
| while(current != NULL) { |
| if(uprv_strcmp(current->fKey, tag)!=0) { |
| current = current->fNext; |
| } else { /*we're either in front of list, or in middle*/ |
| return current->fValue; |
| } |
| } |
| |
| return NULL; |
| } |