Structure Library
- Posted by Derek Parnell <ddparnell at bigpond.com> Feb 27, 2002
- 428 views
Hi All, I created a library that helps you emulate structures in Euphoria. I'd like some people to test and/or inspect the code before I submit it to the RDS contributions. If you'd like to help me out, let me know and I'll email you a copy. Background ------------ A structure is a type of sequence; a sequence with specific restrictions. It has a fixed number of elements, and the elements have a fixed datatype. In normal sequences, you are free to add and remove elements at will. You can also change an element from one datatype to another (eg integer to sequence). With structures, that is not possible. Once they have been defined, their internal format (schema) cannot be changed. The advantage of this, from the programmer's point of view, is that coders don't have to continually validate that the data in both present and of the correct type. For example, when using standard sequences to hold a customer record, the programmer should make sure that the fields are present and correct before using them - every time they are used. This is because, it is possible, however remote, that some other function or process has "corrupted" the record layout. With structures, this is just not possible. In this implementation, there are a couple of other features. ** Structures are always passed by reference. This means that their contents can be modified by the called routine without that routine having to return the updated structure. ** The structure elements (record fields, if you like) can be given a programmer defined name, which can be used to reference the element's data. This is useful when writing generic routines that may not know which structure is being passed to it until run-time. Here is some sample code using the library: --------------------- -- This is a test harness for the 'dstruct.e' library. with trace include dstruct.e -- Define an Address structure constant aAddr1 = element({SEQ,20,"Address 1"}), aAddr2 = element({SEQ,20,"Address 2"}), aCity = element({SEQ, "City"}), aState = element({SEQ, 3,"State"}), -- Max size is 3 aCountry = element({SEQ, "Country"}), aZIP = element({SEQ, "ZIP"}), AddressRec = struct() -- Define a Customer structure constant cFamily = element({SEQ, 25, "Family Name"}), -- Max size is 25 cGiven = element({SEQ, 25, " Given Name "}), -- Max size is 25 cPhone = element({ATOM, "Telephone"}), cCustNo = element({INT, "Cust#"}), cHome = element({AddressRec,"Home"}), -- sub structure cMailing = element({AddressRec,"Mailing"}), -- sub structure CustRec = struct() -- declare two structure variables structure LocalCustomer, LocalCustomer2 -- Set them up as Customer records LocalCustomer = new(CustRec) LocalCustomer2 = new(CustRec) -- Example of storing a single element store (LocalCustomer, {cGiven, "Derek"}) store (LocalCustomer, {cFamily, "Parnell"}) -- Example of storing multiple elements in one call. store (LocalCustomer, { {cPhone, 6135551212}, {cCustNo,154658}, {cHome,{{aAddr1,"My House"}, {aCity,"Ormond"}, {aState,"VIC"}, {aCountry,"Australia"} } }, {cMailing,{{aAddr1,"Level 11"}, {aAddr2,"636 StKilda Road"}, {aCity,"Melbourne"}, {aState,"VICTORIA"}, -- this should truncate {aZIP,"3004"}, {aCountry,"Australia"} } } } ) printf(1, "My name is %s", {fetch(LocalCustomer, "Given Name")}) printf(1, " and I live in %s.\n\n", {fetch(LocalCustomer,{"Home",{"City"}}) }) -- And once again using the alternate syntax printf(1, "My name is still %s", {fetch(LocalCustomer, aGiven)}) printf(1, " and I still live in %s.\n\n", {fetch(LocalCustomer,{cHome,{aCity}}) }) sequence temp -- Convert a structure to a sequence. temp = cStructToSequence(LocalCustomer) -- Display the sequence printf(1, "%s\n\n", {cSequenceToString(temp)}) -- Convert the structure to a string and display it. printf(1, "%s\n\n", {cStructToString(LocalCustomer)}) -- Example of changing a single element store (LocalCustomer, {cFamily, "Flintstone"}) -- Example of changing a single nested element store (LocalCustomer, {cHome,{aAddr2,"27 Main Road"}}) -- Example of changing a multiple nested elements store (LocalCustomer, {cMailing,{{aAddr1,"Cadbury Building"}, {aAddr2,"9a The Avenue"}}}) -- Test that the variable is the correct structure type. if equal(gettype(LocalCustomer), CustRec) then -- Display its component elements. printf(1, " Name: %s %s\n" & " Phone: %8.0f\n" & " ID: %d\n" & " Home Address: %s\n" & "Mailing address: %s\n\n" , fetch(LocalCustomer,{cGiven, cFamily, "Telephone", cCustNo, cHome, cMailing}) ) else printf(1, "'LocalCustomer' is not a valid structure\n",{}) end if -- Copy the structure to another structure variable. copy(LocalCustomer, LocalCustomer2) -- Remove the original structure. destroy(LocalCustomer) -- Check that it worked. if equal(gettype(LocalCustomer), CustRec) then printf(1, "'LocalCustomer' was not destroyed!\n\n",{}) else printf(1, "'LocalCustomer' has been destroyed correctly.\n\n",{}) end if -- Print the copy printf(1, "%s\n\n", {cStructToString(LocalCustomer2)}) -- Display the structures' internal schema print(1, schema(LocalCustomer2)) puts(1,'\n') print(1, schema(CustRec)) puts(1,'\n') print(1, schema(AddressRec)) puts(1,'\n') --------------------- And here is a precis of the documentation: --------------------- -- Routines: -- element : Defines an element of a structure -- struct : Completes the definition of a structure -- new : Creates a new instance of a structure -- initialize : Reinitializes a structure's elements -- store : Sets the value of one or more elements in a structure -- fetch : Gets the value of one or more elements in a structure -- copy : Copies the values of a structure to another structure -- gettype : Returns the type of object passed to it. -- schema : Returns a sequence representing the internal -- definition of the structure. -- destroy : Removes a instance of a structure -- ElementNumber : Returns the ordinal number for a structure element name -- cStructToString : Returns a string repesentation of a structure -- cStructToSequence: Returns a sequence repesentation of a structure -- cSequenceToString: Returns a string repesentation of a sequence -- cNumberToString : Returns a string repesentation of a number -- QuoteString : Returns a string enclosed in quotes with any -- embedded quotes escaped. -- StandardName : Standardizes a string that is meant to be an identifier. -- type: -- structure : Can be used for type-checking a structure variable -- structdef : Can be used for type-checking a structdef variable -- Constants: -- ATOM : Identifies an element of type 'atom' -- INT : Identifies an element of type 'integer' -- SEQ : Identifies an element of type 'sequence' -- STRUCTDefinition: Identifies a structure definition -- STRUCTInstance: Identifies a structure instance --------------------- cheers, Derek.