#include "cgc_countryParsers.h" #define BSIZE 40 int cgc_countryMenu( pCountry co ) { int choice = 0; cgc_size_t length = 0; char selection[BSIZE]; char *t = NULL; pBorder pb = NULL; if ( co == NULL ) { return 0; } while (1) { cgc_printf("\nCountry: @s\n", co->name); cgc_printf("1) Display CountryInfo\n"); cgc_printf("2) Set Capitol\n"); cgc_printf("3) Set Population\n"); cgc_printf("4) Add Language\n"); cgc_printf("5) Add border\n"); cgc_printf("6) Add Territory\n"); cgc_printf("7) Select Territory\n"); cgc_printf("8) Delete Country and Exit Menu\n"); cgc_printf("9) Exit menu\n"); cgc_bzero(selection, BSIZE); cgc_printf("Selection: "); cgc_receive_until( selection, '\n', 3); choice = cgc_atoi(selection); if ( choice < 1 || choice > 9 ) { cgc_printf("Invalid...\n"); continue; } if ( choice == 1 ) { cgc_printCountryInfo( co ); } else if (choice == 2 ) { cgc_printf("\n-> "); cgc_bzero(selection, BSIZE); cgc_receive_until( selection, '\n', BSIZE-1); choice = 0; while ( cgc_isalpha( selection[choice]) ) { co->capitol[choice] = selection[choice]; choice++; } co->capitol[choice] = '\x00'; } else if ( choice == 3 ) { cgc_printf("\n-> "); cgc_bzero(selection, BSIZE); cgc_receive_until(selection, '\n', 19); co->population = cgc_atoi( selection ); } else if ( choice == 4 ) { if ( co->language_count >= COUNTRYLANGUAGEMAX ) { cgc_printf("!!Max languages reached\n"); continue; } cgc_printf("\n-> "); cgc_bzero(selection, BSIZE ); cgc_receive(0, selection, 19, &length); if ( cgc_allocate( cgc_strlen(selection)+1, 0, (void**)&(t)) != 0 ) { t = NULL; continue; } cgc_bzero( t, cgc_strlen(selection)+1); choice = 0; while ( cgc_isalpha( selection[choice] ) ) { t[choice] = selection[choice]; choice++; } t[choice] = '\x00'; co->languages[ co->language_count ] = t; co->language_count++; } else if ( choice == 5 ) { if ( co->border_count >= COUNTRYBORDERMAX) { cgc_printf("!!Max borders reached\n"); continue; } if ( cgc_allocate( sizeof(Border), 0, (void**)&pb) != 0 ) { pb = NULL; continue; } cgc_printf("Lat Start: "); cgc_bzero(selection, BSIZE ); cgc_receive(0, selection, 19, &length); pb->latStart = cgc_atof(selection); cgc_printf("Long Start: "); cgc_bzero(selection, BSIZE ); cgc_receive(0, selection, 19, &length); pb->lngStart = cgc_atof(selection); cgc_printf("Lat End: "); cgc_bzero(selection, BSIZE ); cgc_receive(0, selection, 19, &length); pb->latEnd = cgc_atof(selection); cgc_printf("Long End: "); cgc_bzero(selection, BSIZE ); cgc_receive(0, selection, 19, &length); pb->lngEnd = cgc_atof(selection); co->borders[ co->border_count ] = pb; co->border_count++; } else if ( choice == 6 ) { if ( co->territory_count >= COUNTRYTERRITORYMAX) { cgc_printf("!!Max Territories reached\n"); continue; } choice = 0; while ( choice < COUNTRYTERRITORYMAX && co->territories[choice] != NULL ) { choice++; } if ( choice == COUNTRYTERRITORYMAX ) { cgc_printf("!!Max Territories reached\n"); continue; } if ( cgc_allocate( sizeof(Territory), 0, (void**)(&co->territories[ choice ]) ) != 0 ) { cgc_printf("!!Failed to allocate structure\n"); co->territories[ choice ] = NULL; continue; } cgc_initTerritory( co->territories[choice] ); cgc_printf("\nNew Territory: "); cgc_bzero(selection, BSIZE); cgc_receive_until(selection, '\n', 19); length = 0; while ( cgc_isalnum( selection[length] ) ) { co->territories[choice]->name[length] = selection[length]; length++; } co->territories[choice]->name[length] = '\x00'; co->territory_count++; } else if ( choice == 7 ) { cgc_printf("\nTerritories:\n"); for ( choice = 0; choice < COUNTRYTERRITORYMAX; choice++ ) { if ( co->territories[choice] != NULL ) { cgc_printf("@d) @s\n", choice+1, co->territories[ choice ] ); } } cgc_bzero(selection, BSIZE); cgc_printf("\n-> "); cgc_receive(0, selection, 3, &length); choice = cgc_atoi(selection); if ( choice < 1 || choice > COUNTRYTERRITORYMAX || co->territories[choice-1] == NULL ) { cgc_printf("Invalid choice...\n"); continue; } if ( cgc_territoryMenu( co->territories[choice-1]) == 0 ) { co->territories[choice-1] = NULL ; co->territory_count--; } } else if ( choice == 8 ) { cgc_freeCountry(co); return 0; } else if ( choice == 9 ) { return 1; } } end: return 1; } void cgc_printCountryInfo( pCountry co ) { int index = 0; pBorder b = NULL; if ( co == NULL ) { return; } cgc_printf("\tCountry: "); if ( co->name[0] == '\x00' ) { cgc_printf("Unknown\n"); } else { cgc_printf("@s\n", co->name); } cgc_printf("\t\tCapitol: "); if ( co->capitol[0] == '\x00' ) { cgc_printf("Unknown\n"); } else { cgc_printf("@s\n", co->capitol); } if ( co->population >= 0 ) { cgc_printf("\t\tPopulation: @d\n", co->population); } while ( index < co->language_count ) { if ( co->languages[index] != NULL ) { cgc_printf("\t\tLanguage: @s\n", co->languages[index]); } index++; } index = 0; while ( index < co->border_count ) { b = co->borders[index]; if ( b != NULL ) { cgc_printf("\t\tBorder: @f @f @f @f\n", b->latStart, b->lngStart, b->latEnd, b->lngEnd); } index++; } index = 0; while ( index < COUNTRYTERRITORYMAX ) { if ( co->territories[index] != NULL ) { cgc_printTerritoryInfo( co->territories[index] ); } index++; } return; } void cgc_freeCountry( pCountry co ) { int index = 0; if ( co == NULL ) { return; } while (index < co->border_count) { if ( co->borders[index] != NULL ) { cgc_deallocate( co->borders[index], sizeof( Border ) ); co->borders[index] = NULL; } index++; } index = 0; while ( index < co->language_count) { if ( co->languages[index] != NULL ) { cgc_deallocate( co->languages[index], cgc_strlen(co->languages[index]) + 1 ); co->languages[index] = NULL; } index++; } index = 0; while ( index < COUNTRYTERRITORYMAX) { if ( co->territories[index] != NULL ) { cgc_freeTerritory( co->territories[index] ); co->territories[index] = NULL; } index++; } cgc_deallocate( co, sizeof(Country) ); return; } void cgc_initCountry( pCountry co ) { int index = 0; if ( co == NULL ) { return; } cgc_bzero( co->name, 20 ); co->population = -1; co->language_count = 0; co->border_count = 0; cgc_bzero( co->languages, sizeof(char*) * COUNTRYLANGUAGEMAX); cgc_bzero( co->borders, sizeof(pBorder) * COUNTRYBORDERMAX); cgc_bzero( co->territories, sizeof(pTerritory) * COUNTRYTERRITORYMAX); return; } pCountry cgc_countryTopLevel( pstring str ) { pCountry newCountry = NULL; char * temp_name = NULL; int lastGood = 0; int startIndex = 0; int endIndex = 0; element el = 0; if ( str == NULL ) { goto end; } /// Allocate a new country structure if ( cgc_allocate(sizeof(Country), 0, (void**)&newCountry) != 0 ) { newCountry = NULL; goto end; } cgc_initCountry( newCountry ); cgc_skipWhiteSpace(str); lastGood = cgc_getIndex( str, &lastGood ); if ( !cgc_atChar( str, '{' ) ) { goto error; } if ( cgc_skipLength( str, 1 ) < 0 ) { goto error; } cgc_skipWhiteSpace(str); startIndex = str->index; endIndex = cgc_skipAlpha( str ); if ( endIndex == -1 || startIndex == endIndex ) { goto error; } /// Confirm the opening element; temp_name = cgc_copyData( str, startIndex, endIndex ); if ( temp_name == NULL ) { goto error; } if ( cgc_strcmp( temp_name, "Country" ) != 0 ) { cgc_printf("!!Country: Invalid opening element id\n"); cgc_deallocate( temp_name, cgc_strlen(temp_name) + 1 ); goto error; } cgc_deallocate(temp_name, cgc_strlen(temp_name) + 1 ); cgc_skipWhiteSpace(str); if ( str->buffer[ str->index ] != '}' ) { goto error; } cgc_incChar( str ); lastGood = str->index; temp_name = cgc_pullNextElementName( str ); while ( temp_name != NULL ) { el = cgc_elementNameToEnum( temp_name ); cgc_deallocate( temp_name, cgc_strlen(temp_name) + 1 ); switch (el) { case name: temp_name = cgc_extractName( str ); if ( temp_name == NULL ) { goto error; } cgc_bzero( newCountry->name, 20); cgc_strncpy( newCountry->name, temp_name, 19 ); cgc_deallocate( temp_name, cgc_strlen(temp_name)+1); temp_name = NULL; break; case capitol: temp_name = cgc_extractCapitol( str ); if ( !temp_name ) { goto error; } cgc_bzero( newCountry->capitol, 20 ); cgc_strncpy( newCountry->capitol, temp_name, 19 ); cgc_deallocate( temp_name, cgc_strlen(temp_name)+1); temp_name = NULL; break; case population: newCountry->population = cgc_extractPopulation(str); if (newCountry->population < 0 ) { goto error; } break; case language: if ( newCountry->language_count >= COUNTRYLANGUAGEMAX ) { cgc_printf("!!Max country language count is @d\n", COUNTRYLANGUAGEMAX); goto error; } newCountry->languages[newCountry->language_count] = cgc_extractLanguage(str); if ( newCountry->languages[ newCountry->language_count] == NULL ) { goto error; } newCountry->language_count++; break; case border: if ( newCountry->border_count >= COUNTRYBORDERMAX ) { cgc_printf("!!Max country border count is @d\n", COUNTRYBORDERMAX); goto error; } newCountry->borders[newCountry->border_count] = cgc_extractBorder(str); if ( newCountry->borders[ newCountry->border_count] == NULL ) { goto error; } newCountry->border_count++; break; case territory: if ( newCountry->territory_count >= COUNTRYTERRITORYMAX) { cgc_printf("!!Max territories is @d\n", COUNTRYTERRITORYMAX); goto error; } newCountry->territories[newCountry->territory_count] = cgc_territoryTopLevel(str); if (newCountry->territories[newCountry->territory_count] == NULL ) { goto error; } newCountry->territory_count++; break; default: cgc_printf("Invalid for country\n"); goto error; break; }; lastGood = str->index; temp_name = cgc_pullNextElementName( str ); } cgc_skipWhiteSpace( str ); if ( !cgc_atChar( str, '{' ) ) { goto error; } if ( cgc_skipLength( str, 1 ) < 0 ) { goto error; } cgc_skipWhiteSpace( str ); if ( !cgc_atChar( str, '#' ) ) { goto error; } if ( cgc_skipLength( str, 1 ) < 0 ) { goto error; } startIndex = str->index; endIndex = cgc_skipAlpha( str ); if ( endIndex < 0 ) { goto error; } if ( startIndex == endIndex ) { goto error; } temp_name = cgc_copyData( str, startIndex, endIndex ); if ( temp_name == NULL ) { goto error; } if ( cgc_strcmp( temp_name, "Country" ) != 0 ) { cgc_deallocate(temp_name, cgc_strlen(temp_name) + 1 ); goto error; } cgc_deallocate( temp_name, cgc_strlen(temp_name) + 1 ); cgc_skipWhiteSpace(str); if ( !cgc_atChar( str, '}' ) ) { goto error; } cgc_incChar( str ); goto end; error: if (newCountry != NULL ) { cgc_freeCountry( newCountry ); newCountry = NULL; } str->index = lastGood; cgc_printf("Error at: @s\n", str->buffer + str->index); end: return newCountry; } char* cgc_extractLanguage( pstring str ) { char *temp = NULL; char *language = NULL; register int start = 0; register int end = 0; if (str == NULL ) { return NULL; } start = cgc_skipWhiteSpace(str); if ( !cgc_atChar( str, '{' ) ) { cgc_printf("!!Failed to locate opening brace\n"); return language; } /// Skip past the curly brace if ( cgc_skipLength( str, 1 ) == -1 ) { cgc_printf("!!Failed to skip opening brace\n"); return language; } /// Skip any additional whitespace start = cgc_skipWhiteSpace(str); /// This should skip any to either whitespace or a closing '}' end = cgc_skipToNonAlphaNum( str ); if ( end == -1 ) { cgc_printf("!!Failed to locate the end of the element id\n"); return language; } /// Copy the element id from the string temp = cgc_copyData( str, start, end ); if ( temp == NULL ) { cgc_printf("!!Copy from @d to @d failed\n", start, end); return NULL; } /// If the element id is not "Language" then this is the wrong function if ( cgc_strcmp( temp, "Language") != 0 ) { cgc_printf("!!Element id is not \"Language\"\n"); cgc_deallocate( temp, cgc_strlen(temp) + 1 ); temp = NULL; return language; } /// The buffer is no longer needed so free it cgc_deallocate(temp, cgc_strlen(temp) + 1); /// Skip to the end of the element id cgc_skipWhiteSpace( str ); /// If it is not a closing brace then this is improperly formatted. if ( !cgc_atChar( str, '}' ) ) { cgc_printf("!!Failed to locate initial closing brace\n"); return NULL; } /// Skip the closing brace as well as any whitespace if ( cgc_skipLength( str, 1 ) == -1 ) { cgc_printf("!!Failed to skip initial closing brace\n"); return language; } start = cgc_skipWhiteSpace( str ); end = cgc_skipAlpha( str ); if ( start == end ) { cgc_printf("!!Failed to find language data\n"); return language; } /// Copy the language element data language = cgc_copyData( str, start, end ); if ( language == NULL ) { cgc_printf("!!Failed to copy language data\n"); return language; } /// The rest of this code is a check to ensure proper formatting except for the copy data cgc_skipWhiteSpace( str ); /// If this is not an opening curly brace then fail if ( !cgc_atChar( str, '{' ) ) { cgc_printf("!!Failed to locate the final opening brace\n"); goto error; } /// Skip past the brace if ( cgc_incChar( str) == -1 ) { cgc_printf("!!Failed to skip the final opening brace\n"); goto error; } cgc_skipWhiteSpace(str); /// If this is not a # indicating the closing brace then fail if ( !cgc_atChar( str, '#' ) ) { cgc_printf("!!Failed to locate the closing mark\n"); goto error; } /// Skip past the # but save the start start = cgc_skipLength( str, 1 ); if ( start == -1 ) { cgc_printf("!!Failed to skip closing mark\n"); goto error; } end = cgc_skipToNonAlphaNum( str ); if ( end == -1 ) { cgc_printf("!!Failed to locate the end of the closing element id\n"); goto error; } temp = cgc_copyData( str, start, end ); if ( cgc_strcmp( temp, "Language") != 0 ) { cgc_printf("!!Invalid closing element id: @s\n", temp); cgc_deallocate(temp, cgc_strlen(temp)+1); goto error; } cgc_deallocate(temp, cgc_strlen(temp)+1); cgc_skipWhiteSpace( str ); /// Check the final curly brace if ( !cgc_atChar( str, '}' ) ) { cgc_printf("!!Failed to locate final closing brace\n"); goto error; } /// Skip past the closing brace cgc_skipLength( str, 1 ); goto end; error: if (language != NULL) { cgc_deallocate( language, cgc_strlen(language) + 1 ); language = NULL; } end: return language; } char* cgc_extractCapitol( pstring str ) { char *temp = NULL; char *capitol = NULL; int start = 0; int end = 0; if (str == NULL ) { return NULL; } cgc_skipWhiteSpace(str); if ( !cgc_atChar( str, '{' ) ) { cgc_printf("!!Failed to locate opening brace\n"); return capitol; } /// Skip past the curly brace if ( cgc_skipLength( str, 1 ) == -1 ) { cgc_printf("!!Failed to skip opening brace\n"); return NULL; } /// Skip any additional whitespace start = cgc_skipWhiteSpace(str); /// This should skip any to either whitespace or a closing '}' end = cgc_skipToNonAlphaNum( str ); if ( end == -1 ) { return NULL; } /// Copy the element id from the string temp = cgc_copyData( str, start, end ); if ( temp == NULL ) { return NULL; } /// If the element id is not "Capitol" then this is the wrong function if ( cgc_strcmp( temp, "Capitol") != 0 ) { cgc_deallocate( temp, (end-start) + 1 ); temp = NULL; return temp; } /// The buffer is no longer needed so free it cgc_deallocate(temp, (end-start) + 1); /// Skip to the end of the element id cgc_skipWhiteSpace( str ); /// If it is not a closing brace then this is improperly formatted. if ( !cgc_atChar( str, '}' ) ) { return NULL; } /// Skip the closing brace as well as any whitespace if ( cgc_incChar( str ) == -1 ) { return NULL; } cgc_skipWhiteSpace( str ); cgc_getIndex( str, &start ); end = cgc_skipAlpha( str ); if ( !(start ^ end) ) { return NULL; } /// Copy the capitol element data capitol = cgc_copyData( str, start, end ); if ( capitol == NULL ) { return NULL; } /// The rest of this code is a check to ensure proper formatting except for the copy data cgc_skipWhiteSpace( str ); /// If this is not an opening curly brace then fail if ( !cgc_atChar( str, '{' ) ) { cgc_printf("!!Failed to locate the final opening brace\n"); goto error; } /// Skip past the brace if ( cgc_incChar( str) == -1 ) { cgc_printf("!!Failed to skip the final opening brace\n"); goto error; } cgc_skipWhiteSpace(str); /// If this is not a # indicating the closing brace then fail if ( !cgc_atChar( str, '#' ) ) { cgc_printf("!!Failed to locate the closing mark\n"); goto error; } /// Skip past the # but save the start start = cgc_skipLength( str, 1 ); if ( start == -1 ) { cgc_printf("!!Failed to skip closing mark\n"); goto error; } end = cgc_skipToNonAlphaNum( str ); if ( end == -1 ) { cgc_printf("!!Failed to locate the end of the closing element id\n"); goto error; } temp = cgc_copyData( str, start, end ); if ( cgc_strcmp( temp, "Capitol") != 0 ) { cgc_printf("!!Invalid closing element id: @s\n", temp); cgc_deallocate(temp, cgc_strlen(temp)+1); goto error; } cgc_deallocate(temp, cgc_strlen(temp)+1); cgc_skipWhiteSpace( str ); /// Check the final curly brace if ( !cgc_atChar( str, '}' ) ) { cgc_printf("!!Failed to locate final closing brace\n"); goto error; } /// Skip past the closing brace cgc_skipLength( str, 1 ); goto end; error: if (capitol != NULL) { cgc_deallocate( capitol, cgc_strlen(capitol) + 1 ); capitol = NULL; } end: return capitol; }