• MorphOS Developer
    itix
    Posts: 1520 from 2003/2/24
    From: Finland
    Quote:

    Jose wrote:

    -- API --
    To serialize a set of data you call the SS_SaveData (). To scatter load a serialized stream into memory SS_LoadData () is used.

    Code:

    The prototypes for both functions are:
    BOOL SS_LoadData (ULONG *DataInfo, struct *Window, ULONG ID, ...);
    BOOL SS_SaveData (ULONG *DataInfo, struct *Window, ULONG ID, ...);




    You maybe would like to take a look at Ambient prefspool implementation. It is not serialization API but it has many similarities to your idea.

    Quote:


    - DataInfo is a descriptor (sometimes also called DataInfo or data info) for the group of data to be serialized, that the user makes using macros (described bellow) that try to minimize the required input to make the descriptors to the maximum, but having low descriptor size and efficiency as priority.



    Instead of just having a descriptor there could be maybe an API call to create one in fly with the data? Something like SS_SaveDataItem(). Building descriptors sound clunky.

    Quote:


    - Window is a pointer to a window to which error messages should be output, can be NULL.



    Passing a low level intuition window pointer is bad idea IMO. For error messages it could be better define callback API that is called on each error?

    For more practical handling you maybe want to create a black box context for all this stuff.

    Quote:


    - Making a descriptor -
    Currently a descriptor is made by declaring a ULONG array which is initialized by macros. At the top level there must allways be a group, at least for the DataInfo passed to the serializing functions. There can be a hierarchy of groups inside each descriptor.
    To declare a group you use one of the SS_GROUP() or SS_GROUPf() macros. Both are function like macros wich take an ID and a FileName as arguments. SS_GROUPf() also takes DefaultFileName as an extra argument.
    - ID is an identifier for the group.
    - FileName is the file name of the group data, when serialized to a file
    - DefaultFileName is used only by SS_GROUPf() and is the file name of a file containing the default data to be used in case an ID is not present when loading a stream with SS_LoadData(). When there are subgroups the top level group's defaults file has priority over the others. The hierarchy of defaults established by declaring groups with SS_GROUPf() only makes sense when reusage is involved (description of reusage bellow).



    Having full example code would help. It could be also good idea create a proto to test design if you dont have one already?

    Quote:


    Example:

    Imagine there is a boolean variable somewhere defining if there should be warnings in a GUI.
    Code:

    BOOL BasicWarnings;
    #define ID_BasicWarnings 101

    /* Suggestion: As above, IDs should be defined next to the variable they apply to for more readable code */
    #define ID_ROOTGROUP 100
    ULONG SettingsDescriptor[] = /* Contains references to all the data we want to include in this group, in this case only a BOOL variable */
    {
    SS_GROUPf (ID_ROOTGROUP, “RootGroup”, “RootGroupDefaultsFile”)
    SS_ELd (ID_BasicWarnings, BasicWarnings, TRUE),
    0
    };

    /* Descriptor is done, now load every variable in root group */
    if (!SS_LoadData (SettingsDescriptor, NULL, ID_ROOTGROUP, NULL))
    printf (“Error loading datan”);


    /* Save every variable in root group */
    if (!SS_SaveData (SettingsDescriptor, NULL, ID_ROOTGROUP, NULL))
    printf (“Error saving datan”);

    ...




    Should not you define datatype and datatype size somewhere? For example string pointer, floats, 8/16/32/64 bit integers and so on?

    Quote:


    - Structures
    For structs the principle is the same, it's elements being added as the basic C types. At first this might not seem possible, because to get at struct elements one has to use offsets instead of the address. However very elaborate macros take care of that and the input “syntax” is the same! This was an achievement that made me happy and consider this a bit more seriously. SS_ST() is used first to define the base address. After that SS_STNM must be defined with the struct's type name, after which the elements are added.

    Example:

    Suppose in the previous example there is also a structure called TestStruct.
    The new data info including it to the serialized stream after BasicWarnings would be:
    Code:

    struct TestStruct
    {
    int a;
    char b;
    int c;
    } TstSt;
    /* Element IDs */
    enum TestStructIDs
    {
    ID_TSTST = 120,
    ID_TS_a,
    ID_TS_b,
    ID_TS_c
    };

    ULONG SettingsDescriptor[] =
    {
    SS_GROUPf (ID_ROOTGROUP, “RootGroup”, “RootGroupDefaultsFile”)
    SS_ELd (ID_BasicWarnings, BasicWarnings, TRUE),
    SS_ST (ID_TSTST, TstSt)
    #define SS_STNM TestStruct
    EL (ID_TS_a, a),
    ELd (ID_TS_b, b, 10), /* As an example, this element has a default value if no value is found on the input stream when loading */
    EL (ID_TS_c, c),
    0,
    #undef SS_STNM
    0
    };




    Macros look very non-descriptive. From a developer POV it could be easier if one could just:

    SS_ReadItem(context, ID, to_pointer, to_offset);
    SS_SaveItem(context, ID, from_pointer, from_offset);

    This is more flexible if member variables in the struct are shuffled.

    Quote:


    - TagItem lists
    For TagItem lists the macros SS_TAGITEM() and SS_TAGITEMd() are used. Both work like SS_EL() and SS_ELd() and take an ID and the variable name of the array holding the TagItem list as arguments. SS_TAGITEMd() takes one extra argument that's the name of the default TagItem list to use for default values.



    Actually, it could be nice if an entire taglist could be saved with just one call:

    SS_SaveTagList(context, CONST struct TagItem *taglist);

    Tag lists are NULL terminated, they have ID, position is already in the taglist. What is missing is datatype (32-bit integer or ptr to other datatype, like a string). Some bits from the tag ID could be allocated to this purpose.

    Quote:


    If there is interest in this (I honestly think there probably isn't, but as I said, just checking it with this post) I can add examples, the API to do it is pretty simple...



    Probably not much users :) although developers have often need to save settings in flexible manner. Everyone is using his own system.

    MUI has this system built-in but is not flexible for user data (btw also consider how to save an array of strings!).
    1 + 1 = 3 with very large values of 1
  • »22.07.15 - 08:04
    Profile