Structure Library

new topic     » topic index » view thread      » older message » newer message

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.

new topic     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu