$Header: /cvsroot/aolserver/aolserver.com/docs/devel/c/index.html,v 1.1 2002/03/07 19:15:35 kriston Exp $
Append the specified argument plus a terminating null character to the end of the Ns_DString. It is useful for making strings like: "foo\0bar\0baz\0". It returns the string associated with the current Ns_DString.
    
    char *Ns_DStringExport(
    Ns_DString *src
    );
    Ns_DString ds;
    char *stringdest;
    Ns_DStringInit(&ds);
    Ns_DStringAppend(&ds, "foo");
    stringdest = Ns_DStringExport(&ds);
    /* do something with `stringdest' */
    Ns_Free(stringdest);
   
    
    void Ns_DStringFree(
    Ns_DString *dsPtr
    );
    Ns_DString ds;
    Ns_DStringInit(&ds);
    Ns_DStringAppend(&ds, "foo");
    /* do something with the dstring */
    printf ("%s\n", ds.string);
    Ns_DStringFree(&ds); /* finished with dstring */
    
    void Ns_DStringInit(
    Ns_DString *dsPtr
    );
    int MyFunctions(int a, int b)
    {
        Ns_DString ds;
        Ns_DStringInit(&ds);
        /* ds is now initialized and ready to pass to
          another function */
        ...
    }
   
    
    int Ns_DStringLength(
    Ns_DString *dsPtr
    );
    Ns_DString ds;
    Ns_DStringInit(&ds);
    Ns_DStringAppend(&ds, "");
    printf("len=%d\n", Ns_DStringLength(&ds));
    Ns_DStringFree(&ds); /* finished with dstring */
   
    
    char *Ns_DStringNAppend(
    Ns_DString *dsPtr,
    char *string,
    int length
    );
   The resulting Ns_DString in this example, ds, would contain "foo\0"
   and have a length of 3:
    Ns_DString ds;
    Ns_DStringInit(&ds);
    Ns_DStringNAppend(&ds, "fooasdf", 3);
    printf("%s\n", ds.string);
    Ns_DStringFree(&ds); /* finished with dstring */
   If you need a null-terminated list of null-terminated strings, such as
   "foo\0bar\0\0", you would add one to the length of the appended
   strings to get the extra terminating null character. For example:
    Ns_DString ds;
    Ns_DStringInit(&ds);
    Ns_DStringNAppend(&ds, "foo", 4);
    Ns_DStringNAppend(&ds, "bar", 4);
   
    
    char *Ns_DStringPrintf(
    Ns_DString *dsPtr,
    char *fmt,
    ...
    );
    Ns_DString ds;
    Ns_DStringInit(&ds);
    Ns_DStringPrintf(&ds, "/path%d", getpid());
    /* do something with dstring */
    printf ("%s\n", ds.string);
    Ns_DStringFree(&ds); /* finished with dstring */
   
    
    void Ns_DStringTrunc(
    Ns_DString *dsPtr,
    int length
    );
    Ns_DString ds;
    int i;
    Ns_DStringInit(&ds);
    for (i=0; i < 50; i++) {
        Ns_DStringPrintf(&ds, "%s%d", "aBigString", i);
        /* do something with the dstring constructed above*/
        Ns_DStringTrunc(&ds, 0);
    }
    Ns_DStringFree(&ds); /* finished with dstring */
   
    
    char *Ns_DStringValue(
    Ns_DString *dsPtr
    );
    Ns_DString ds;
    Ns_DStringInit(&ds);
    Ns_DStringAppend(&ds, "foo");
    /* do something with the dstring */
    printf ("%s\n", Ns_DStringValue(&ds));
    Ns_DStringFree(&ds); /* finished with dstring */
   
    
    char *Ns_DStringVarAppend(
    Ns_DString *dsPtr,
    ...
    );
    Ns_DString ds;
    Ns_DStringInit(&ds);
    Ns_DStringVarAppend(&ds, "foo", "bar", NULL);
    /* do something with the dstring */
    printf ("%s\n", ds.string);
    Ns_DStringFree(&ds); /* finished with dstring */
    
    int Ns_QueryToSet (
    char* query,
    Ns_Set* set
    );
    
    int Ns_ServerSpecificAlloc(void);
    
    void *Ns_ServerSpecificDestroy(
    char *handle,
    int id,
    int flags
    );
    
    void *Ns_ServerSpecificGet(
    char *handle,
    int id
    );
    
    void Ns_ServerSpecificSet(
    char *handle,
    int id,
    void *data,
    int flags,
    void (*deletefunc) (void *)
    );
    
    Ns_Set *Ns_SetCopy(
    Ns_Set *old
    );
    Ns_Set *setA;
    Ns_Set *setB;
    setA = Ns_SetCreate("setA");
    Ns_SetPut(setA, "foo", "foovalue");
    setB = Ns_SetCopy(setA);
    Ns_SetFree(setA);
    /* do something with setB */
    Ns_SetFree(setB);
    
    Ns_Set *Ns_SetCreate(
    char *name
    );
    Ns_Set *aSet;
    aSet = Ns_SetCreate(""); /* set name can be NULL */
    Ns_SetPut(aSet, "foo", "foovalue");
    /* do something with aSet */
    Ns_SetFree(aSet);
   
    
    void Ns_SetDelete(
    Ns_Set *set,
    int index
    );
    Ns_Set *aSet;
    aSet = Ns_SetCreate("");
    Ns_SetPut(aSet, "foo", "foovalue");
    Ns_SetPut(aSet, "bar", "barvalue");
    Ns_SetDelete(aSet, 0); /* deletes foo->foovalue */
    /* finish processing of aSet */
    Ns_SetFree(aSet);
   
    
    void Ns_SetDeleteKey(
    Ns_Set *set,
    char *key
    );
The Ns_SetIDeleteKey function is this function's case-insensitive counterpart.
    Ns_Set *aSet;
    aSet = Ns_SetCreate("");
    Ns_SetPut(aSet, "foo", "foovalue");
    Ns_SetPut(aSet, "bar", "barvalue");
    Ns_SetDeleteKey(aSet, "foo"); /* deletes foo->foovalue */
    /* finish processing of aSet */
    Ns_SetFree(aSet);
   
    
    int Ns_SetDriverProc (
    Ns_Driver driver,
    Ns_DrvId id,
    void* proc
    );
    
    int Ns_SetEvent(
    Ns_Event * event
    );
    
    int Ns_SetFind(
    Ns_Set *set,
    char *key
    );
The Ns_SetIFind function is this function's case-insensitive counterpart.
    Ns_Set *aSet;
    int index;
    aSet = Ns_SetCreate("");
    Ns_SetPut(aSet, "Foo", "foovalue");
    Ns_SetPut(aSet, "Bar", "barvalue");
    index = Ns_SetFind(aSet, "Foo"); /* case sensitive search*/
    if (index == -1) {
        Ns_Log(Warning, "set key Foo not found");
    } else {
        Ns_Log(Notice, "Value for Foo is %s",
                        Ns_SetGet(aSet, "Foo"));
    }
    Ns_SetFree(aSet);
   
    
    void Ns_SetFree(
    Ns_Set *set
    );
    Ns_Set *aSet;
    aSet = Ns_SetCreate(""); /* set name can be NULL */
    Ns_SetPut(aSet, "foo", "foovalue");
    /* do something with aSet */
    Ns_SetFree(aSet);
   
    
    char *Ns_SetGet(
    Ns_Set *set,
    char *key
    );
The Ns_SetIGet function is this function's case-insensitive counterpart.
    Ns_Set *aSet;
    int index;
    aSet = Ns_SetCreate("");
    Ns_SetPut(aSet, "Foo", "foovalue");
    Ns_SetPut(aSet, "Bar", "barvalue");
    Ns_Log(Notice, "Value for Foo is %s", Ns_SetGet(aSet, "Foo"));
    Ns_SetFree(aSet);
   
    
    void Ns_SetIDeleteKey(
    Ns_Set *set,
    char *key
    );
    Ns_Set *aSet;
    aSet = Ns_SetCreate("");
    Ns_SetPut(aSet, "foo", "foovalue");
    Ns_SetPut(aSet, "bar", "barvalue");
    Ns_SetIDeleteKey(aSet, "Foo"); /* deletes foo->foovalue */
    /* finish processing of aSet */
    Ns_SetFree(aSet);
   
    
    int Ns_SetIFind(
    Ns_Set *set,
    char *key
    );
    Ns_Set *aSet;
    int index;
    aSet = Ns_SetCreate("");
    Ns_SetPut(aSet, "Foo", "foovalue");
    Ns_SetPut(aSet, "Bar", "barvalue");
    index = Ns_SetIFind(aSet, "foo"); /* case insensitive search*/
    if (index == -1) {
        Ns_Log(Warning, "set key foo not found");
    } else {
        Ns_Log(Notice, "Value for Foo is %s",
                        Ns_SetGet(aSet, "ooo"));
    }
    Ns_SetFree(aSet);
   
    
    char *Ns_SetIGet(
    Ns_Set *set,
    char *key
    );
    Ns_Set *aSet;
    int index;
    aSet = Ns_SetCreate("");
    Ns_SetPut(aSet, "Foo", "foovalue");
    Ns_SetPut(aSet, "Bar", "barvalue");
    Ns_Log(Notice, "Value for foo is %s", Ns_SetIGet(aSet, "foo"));
    Ns_SetFree(aSet);
   
    
    int Ns_SetIUnique(
    Ns_Set *set,
    char *key
    );
For example, a client could send multiple "Accept:" headers which would end up in the header set for the connection. Ns_SetIUnique would then return 0 for the header set and the "Accept" key, because there are multiple fields with the key "Accept".
    
    char *Ns_SetKey(
    Ns_Set *set,
    int index
    );
    Ns_Set *aSet;
    aSet = Ns_SetCreate("");
    Ns_SetPut(aSet, "foo", "foovalue");
    Ns_SetPut(aSet, "bar", "barvalue");
    printf("Key at index 0 is %s\n", Ns_SetKey(aSet, 0));
    /* finish processing of aSet */
    Ns_SetFree(aSet);
   
    
    void Ns_SetLast(
    Ns_Set *set
    );
    
    Ns_Set *Ns_SetListFind(
    Ns_Set **sets,
    char *name
    );
    
    void Ns_SetListFree(
    Ns_Set **sets
    );
    
    void Ns_SetMerge(
    Ns_Set *high,
    Ns_Set *low
    );
    
    void Ns_SetMove(
    Ns_Set *to,
    Ns_Set *from
    );
    
    char *Ns_SetName(
    Ns_Set *set
    );
    
    void Ns_SetPrint(
    Ns_Set *set
    );
    
    int Ns_SetPut(
    Ns_Set *set,
    char *key,
    char *value
    );
    Ns_Set *aSet;
    aSet = Ns_SetCreate("");
    Ns_SetPut(aSet, "foo", "foovalue");
    Ns_SetPut(aSet, "bar", "barvalue");
    /* finish processing of aSet */
    Ns_SetFree(aSet);
   
    
    void Ns_SetPutValue(
    Ns_Set *set,
    int index,
    char *value
    );
    
    typedef int (Ns_RequestAuthorizeProc) (
    char *hServer,
    char *method,
    char *url,
    char *authuser,
    char *authpasswd,
    char *peeraddr
    );
    void Ns_SetRequestAuthorizeProc(
    char *hServer,
    Ns_RequestAuthorizeProc *proc
    );
The AOLserver permissions module calls Ns_SetRequestAuthorizeProc at startup to register its file-based permission system. If your site already has a permission system in place, you could write a C module whose initialization function opens a connected to the existing system and then calls Ns_SetRequestAuthorizeProc to override the permission module's authentication system.
    
    void Ns_SetRequestUrl (
    Ns_Request* request,
    char* url
    );
    
    int Ns_SetSize(
    Ns_Set *set
    );
    
    Ns_Set **Ns_SetSplit(
    Ns_Set *set,
    char sep
    );
Ns_SetSplit returns a newly allocated NULL-terminated array of new sets. The original set is left unaltered. The list of new sets can be freed at once with the Ns_SetListFree function.
    
    void Ns_SetTrunc(
    Ns_Set *set,
    int size
    );
        /* Eliminate the headers sent by a browser. */
        Ns_SetTrunc(conn->headers, 0);
   
    
    int Ns_SetUnique(
    Ns_Set *set,
    char *key
    );
    
    void Ns_SetUpdate (
    Ns_Set* set,
    char* key,
    char* value
    );
    
    char *Ns_SetValue(
    Ns_Set *set,
    int index
    );
    
    int Ns_TclEnterSet(
    Tcl_Interp *interp,
    Ns_Set *set,
    int flags
    );
NS_TCL_SET_TEMPORARY:
The set is temporary and private to the Tcl interpreter. The set ID will be automatically deleted by Ns_TclDeAllocateInterp().
NS_TCL_SET_PERSISTENT:
The set can be accessed by any Tcl interpreter in the server and the set ID will persist beyond the interpreter's next call to Ns_TclDeAllocateInterp().
NS_TCL_SET_DYNAMIC:
The set was dynamically allocated for use by Tcl and will be garbage-collected when the cooresponding set ID is deleted through either Ns_TclFreeSet() or Ns_TclDeAllocateInterp().
Sets created by Tcl are normally DYNAMIC and TEMPORARY unless the -persist option is used in the Tcl function when creating the set.
    set = Ns_SetCreate(name);
    return Ns_TclEnterSet(interp, set,
        NS_TCL_SET_TEMPORARY | NS_TCL_SET_DYNAMIC);
   
    
    int Ns_TclFreeSet(
    Tcl_Interp *interp,
    char *setId
    );
The ns_set free Tcl function calls this function.
    
    Ns_Set *Ns_TclGetSet(
    Tcl_Interp *interp,
    char *setId
    );
    
    int Ns_TclGetSet2(
    Tcl_Interp *interp,
    char *setId,
    Ns_Set **setPtr
    );
    if (Ns_TclGetSet2(interp, argv[1], &set) != TCL_OK {
        return TCL_ERROR;
    }
   You can then access the Ns_Set pointed to by set.
    
    int Ns_UrlSpecificAlloc(void);
    static int myId;
    void
    Init(void)
    {
        /* Allocate the id once at startup. */
        myId = Ns_UrlSpecificAlloc();
    }
    void
    Store(char *server, char *method, char *url, char *data)
    {
        Ns_UrlSpecificSet(server, method, url, myId,
                data, 0, NULL);
    }
    char *
    Fetch(char *server, char *method, char *url)
    {
        char *data;
        data = Ns_UrlSpecificGet(server, method, url, myId);
        return (char *) data;
    }
   
    
    void *Ns_UrlSpecificDestroy(
    char *handle,
    char *method,
    char *url,
    int id,
    int flags
    );
The flags argument can be NS_OP_NODELETE, NS_OP_RECURSE, or NS_OP_NOINHERIT. NS_OP_NODELETE determines whether the deletefunc specified in Ns_UrlSpecificSet is called. If NS_OP_RECURSE is set, then data for all URLs more specific than the passed-in URL is also destroyed. If the flags argument specifies NS_OP_NOINHERIT in Ns_UrlSpecificDestroy, the data stored with the NS_OP_NOINHERIT flag in Ns_UrlSpecificSet will be deleted. If the flags argument does not specify NS_OP_NOINHERIT, the data stored without the NS_OP_NOINHERIT flag will be deleted.
An id of -1 matches all ids. For example, Ns_UrlSpecificDestroy("myserver", "GET", "/", -1, NS_OP_RECURSE) removes all data for the method GET for server "myserver".
    
    void *Ns_UrlSpecificGet(
    char *handle,
    char *method,
    char *url,
    int id
    );
    See the example for Ns_UrlSpecificAlloc.
   
    
    void *Ns_UrlSpecificGetExact(
    char *handle,
    char *method,
    char *url,
    int id,
    int flags
    );
If the flags argument is set to NS_OP_NOINHERIT in Ns_UrlSpecificGetExact, the data stored with the NS_OP_NOINHERIT flag in Ns_UrlSpecificSet will be retrieved. If the flags argument is set to 0, the data stored without the NS_OP_NOINHERIT flag will be retrieved.
    
    void Ns_UrlSpecificSet(
    char *handle,
    char *method,
    char *url,
    int id,
    void *data,
    int flags
    void (*deletefunc) (void *)
    );
The flags argument can be NS_OP_NOINHERIT or NS_OP_NODELETE. You can store two sets of data based on the same handle, method, url, and id combination-- one set with inheritance on and one set with inheritance off. If the NS_OP_NOINHERIT flag is set, the data is stored based on the exact URL. If NS_OP_NOINHERIT is omitted, the data is stored based on the specified URL and any URL below it. In this case, Ns_UrlSpecificGetExact will match to the closest URL when retrieving the data.
The deletefunc argument is called with data as an argument when this handle/url/method/id combination is re-registered or deleted, or when this server shuts down. unless NS_OP_NODELETE is set.
Normally, calling Ns_UrlSpecificSet on a handle/url/method/id combination which already has an operation registered for it causes the previous operation's delete procedure to be called. You can override this behavior by adding the NS_OP_NODELETE flag.
    See the example for Ns_UrlSpecificAlloc.