a smart & perfect queue(list), support all the structures

1. c source code

/****************************************************************************
* File: lib_queue.h
* Descript:
* Author: Wenxy, wen_kernel@163.com
* Fix history:
* 1, Wenxy, 20090317,a.m.,     unite with something, :-)
*
*****************************************************************************/


#ifndef _LIB_QUEUE_H
#define _LIB_QUEUE_H

/*  *********************************************************************
    *  Macros
    ********************************************************************* */

#define q_init(q) (q)->q_prev = (q), (q)->q_next = (q)
#define q_isempty(q) ((q)->q_next == (q))
#define q_getfirst(q) ((q)->q_next)
#define q_getlast(q) ((q)->q_prev)

/*  *********************************************************************
    *  Types
    ********************************************************************* */


typedef struct queue_s {
    struct queue_s *q_next;
    struct queue_s *q_prev;
} queue_t;


/*  *********************************************************************
    *  Prototypes
    ********************************************************************* */

void q_enqueue(queue_t *,queue_t *);
void q_dequeue(queue_t *);
queue_t *q_deqnext(queue_t *);
int q_map(queue_t *qb,int (*func)(queue_t *,unsigned int,unsigned int),
      unsigned int a,unsigned int b);
int q_count(queue_t *);
int q_find(queue_t *,queue_t *);


#endif



/****************************************************************************
* File: lib_types.h
* Descript: 
* Author: Wenxy, wen_kernel@163.com
* Fix history:
* 1, Wenxy, 20090317,a.m.,     unite with something, :-)
*
*****************************************************************************/


#ifndef _LIB_TYPES_H
#define _LIB_TYPES_H

/*  *********************************************************************
    *  Constants
    ********************************************************************* */

#ifndef NULL
#define NULL 0
#endif

#ifndef TRUE
#define TRUE 1
#endif

#ifndef FALSE
#define FALSE 0
#endif

/*  *********************************************************************
    *  Basic types
    ********************************************************************* */

typedef int size_t;

typedef char int8_t;
typedef unsigned char uint8_t;

typedef short int16_t;
typedef unsigned short uint16_t;

#ifdef __long64
typedef int int32_t;
typedef unsigned int uint32_t;
#else
typedef long int32_t;
typedef unsigned long uint32_t;
#endif

#if 0
typedef long long int64_t;
typedef unsigned long long uint64_t;


#define unsigned signed        /* Kludge to get unsigned size-shaped type. */
typedef __SIZE_TYPE__ intptr_t;
#undef unsigned
typedef __SIZE_TYPE__ uintptr_t;

#endif

/*  *********************************************************************
    *  Macros
    ********************************************************************* */

#ifndef offsetof
#define offsetof(type,memb) ((size_t)&((type *)0)->memb)
#endif

/*  *********************************************************************
    *  Structures
    ********************************************************************* */

typedef struct cons_s {
    char *str;
    int num;
} cons_t;

#endif


/****************************************************************************
* File: enve_subr.h
* Descript:
* Author: Wenxy, wen_kernel@163.com
* Fix history:
* 1, Wenxy, 20090317,a.m.,     unite with something, :-)
*
*****************************************************************************/



/*  *********************************************************************
    *  Constants
    ********************************************************************* */


/*
 * TLV types.  These codes are used in the "type-length-value"
 * encoding of the items stored in the NVRAM device (flash or EEPROM)
 *
 * The layout of the flash/nvram is as follows:
 *
 * <type> <length> <data ...> <type> <length> <data ...> <type_end>
 *
 * The type code of "ENV_TLV_TYPE_END" marks the end of the list.
 * The "length" field marks the length of the data section, not
 * including the type and length fields.
 *
 * Environment variables are stored as follows:
 *
 * <type_env> <length> <flags> <name> = <value>
 *
 * If bit 0 (low bit) is set, the length is an 8-bit value.
 * If bit 0 (low bit) is clear, the length is a 16-bit value
 *
 * Bit 7 set indicates "user" TLVs.  In this case, bit 0 still
 * indicates the size of the length field.
 *
 * Flags are from the constants below:
 *
 */

#define ENV_LENGTH_16BITS    0x00    /* for low bit */
#define ENV_LENGTH_8BITS    0x01

#define ENV_TYPE_USER        0x80

#define ENV_CODE_SYS(n,l) (((n)<<1)|(l))
#define ENV_CODE_USER(n,l) ((((n)<<1)|(l)) | ENV_TYPE_USER)

/*
 * The actual TLV types we support
 */

#define ENV_TLV_TYPE_END    0x00  
#define ENV_TLV_TYPE_ENV    ENV_CODE_SYS(0,ENV_LENGTH_8BITS)

/*
 * Environment variable flags
 */

#define ENV_FLG_NORMAL        0x00    /* normal read/write */
#define ENV_FLG_BUILTIN        0x01    /* builtin - not stored in flash */
#define ENV_FLG_READONLY    0x02    /* read-only - cannot be changed */

#define ENV_FLG_MASK        0xFF    /* mask of attributes we keep */
#define ENV_FLG_ADMIN        0x100    /* lets us internally override permissions */

/*  *********************************************************************
    *  Prototypes
    ********************************************************************* */

int env_delenv(const char *name);
char *env_getenv(const char *name);
int env_setenv(const char *name,char *value,int flags);
int env_load(void);
int env_save(void);
int env_enum(int idx,char *name,int *namelen,char *val,int *vallen);
int env_envtype(const char *name);
int env_getval(const char *name);


/****************************************************************************
* File: env_subr.c
* Descript:
* Author: unkown
* Fix history:
* 1, Wenxy, 20090317,a.m.,     unite with pack and unpack.
*
*****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>

#include "lib_queue.h"
#include "lib_types.h"
#include "env_subr.h"


#define CFE_ERR_ENVNOTFOUND -1
#define CFE_ERR_ENVREADONLY -2
#define CFE_ERR_NOMEM        -3
#define CFE_INIT_SAFE        -4
#define CFE_ERR_IOERR        -5

#ifndef LINUX_KERNEL

#define KFREE        free
#define KMALLOC        malloc
#define lib_atoi    atoi
#define strnchr        strchr
int nvram_read(char *p, int n1, int n2)
{
    return 0;
};

int nvram_getsize()
{
    return 0;
}

int nvram_open()
{
    return 0;
}

int    cfe_startflags;

int nvram_close()
{
    return 0;
}

int    nvram_write()
{
    return 0;
}

int nvram_erase()
{
    return 0;
}
#endif

/*  *********************************************************************
    *  Types
    ********************************************************************* */

typedef struct cfe_envvar_s {
    queue_t qb;
    int flags;
    char *name;
    char *value;
    /* name and value go here */
} cfe_envvar_t;

/*  *********************************************************************
    *  Globals
    ********************************************************************* */

queue_t env_envvars = {&env_envvars,&env_envvars};
extern unsigned int cfe_startflags;

/*  *********************************************************************
    *  env_findenv(name)
    * 
    *  Locate an environment variable in the in-memory list
    * 
    *  Input parameters:
    *         name - name of env var to find
    *        
    *  Return value:
    *         cfe_envvar_t pointer, or NULL if not found
    ********************************************************************* */

static cfe_envvar_t *env_findenv(const char *name)
{
    queue_t *qb;
    cfe_envvar_t *env;

    for (qb = env_envvars.q_next; qb != &env_envvars; qb = qb->q_next) {
    env = (cfe_envvar_t *) qb;
    if (strcmp(env->name,name) == 0) break;
    }

    if (qb == &env_envvars) return NULL;

    return (cfe_envvar_t *) qb;

}

/*  *********************************************************************
    *  env_enum(idx,name,namelen,val,vallen)
    * 
    *  Enumerate environment variables.  This routine locates
    *  the nth environment variable and copies its name and value
    *  to user buffers.
    *
    *  The namelen and vallen variables must be preinitialized to
    *  the maximum size of the output buffer.
    * 
    *  Input parameters:
    *         idx - variable index to find (starting with zero)
    *         name,namelen - name buffer and length
    *         val,vallen - value buffer and length
    *        
    *  Return value:
    *         0 if ok
    *         else error code
    ********************************************************************* */

int env_enum(int idx,char *name,int *namelen,char *val,int *vallen)
{
    queue_t *qb;
    cfe_envvar_t *env;

    for (qb = env_envvars.q_next; qb != &env_envvars; qb = qb->q_next) {
    if (idx == 0) break;
    idx--;
    }

    if (qb == &env_envvars) return CFE_ERR_ENVNOTFOUND;
    env = (cfe_envvar_t *) qb;

    *namelen = strncpy(name,env->name,*namelen);
    *vallen  = strncpy(val,env->value,*vallen);

    return 0;

}

/*  *********************************************************************
    *  env_envtype(name)
    * 
    *  Return the type of the environment variable
    * 
    *  Input parameters:
    *         name - name of environment variable
    *        
    *  Return value:
    *         flags, or <0 if error occured
    ********************************************************************* */
int env_envtype(const char *name)
{
    cfe_envvar_t *env;

    env = env_findenv(name);

    if (env) {
    return env->flags;
    }

    return CFE_ERR_ENVNOTFOUND;
}



/*  *********************************************************************
    *  env_delenv(name)
    * 
    *  Delete an environment variable
    * 
    *  Input parameters:
    *         name - environment variable to delete
    *        
    *  Return value:
    *         0 if ok
    *         else error code
    ********************************************************************* */

int env_delenv(const char *name)
{
    cfe_envvar_t *env;

    env = env_findenv(name);

    if (!env) return 0;

    if (!(env->flags & ENV_FLG_READONLY)) {
    q_dequeue((queue_t *) env);
    KFREE(env);
    return 0;
    }

    return CFE_ERR_ENVNOTFOUND;
}

/*  *********************************************************************
    *  env_getenv(name)
    * 
    *  Retrieve the value of an environment variable
    * 
    *  Input parameters:
    *         name - name of environment variable to find
    *        
    *  Return value:
    *         value, or NULL if variable is not found
    ********************************************************************* */

char *env_getenv(const char *name)
{
    cfe_envvar_t *env;

    env = env_findenv(name);

    if (env) {
    return env->value;
    }

    return NULL;
}


/*  *********************************************************************
    *  env_getval(name)
    * 
    *  Retrieve the integer value of an environment variable.
    * 
    *  Input parameters:
    *         name - name of environment variable to find
    *        
    *  Return value:
    *         integer value, or -1 if variable is not found
    ********************************************************************* */

int env_getval(const char *name)
{
    char *s;
    int val = -1;

    s = env_getenv(name);
    if( s )
        val = lib_atoi(s);

    return val;
}


/*  *********************************************************************
    *  env_setenv(name,value,flags)
    * 
    *  Set the value of an environment variable
    * 
    *  Input parameters:
    *         name - name of variable
    *         value - value of variable
    *         flags - flags for variable (ENV_FLG_xxx)
    *        
    *  Return value:
    *         0 if ok
    *         else error code
    ********************************************************************* */

int env_setenv(const char *name,char *value,int flags)
{
    cfe_envvar_t *env;
    int namelen;

    env = env_findenv(name);
    if (env) {
    if (!(flags & ENV_FLG_ADMIN)) {
        if (env->flags & ENV_FLG_READONLY) return CFE_ERR_ENVREADONLY;
        }
    q_dequeue((queue_t *) env);
    KFREE(env);
    }

    namelen = strlen(name);

    env = KMALLOC(sizeof(cfe_envvar_t) + namelen + 1 + strlen(value) + 1,0);
    if (!env) return CFE_ERR_NOMEM;

    env->name = (char *) (env+1);
    env->value = env->name + namelen + 1;
    env->flags = (flags & ENV_FLG_MASK);

    strcpy(env->name,name);
    strcpy(env->value,value);

    q_enqueue(&env_envvars,(queue_t *) env);

    return 0;
}


/*  *********************************************************************
    *  env_load()
    * 
    *  Load the environment from the NVRAM device.
    * 
    *  Input parameters:
    *         nothing
    *        
    *  Return value:
    *         0 if ok
    *         else error code
    ********************************************************************* */


int env_load(void)
{
    int size;
    unsigned char *buffer;
    unsigned char *ptr;
    unsigned char *envval;
    unsigned int reclen;
    unsigned int rectype;
    int offset;
    int flg;
    int retval = -1;
    char valuestr[256];

    /*
     * If in 'safe mode', don't read the environment the first time.
     */

    if (cfe_startflags & CFE_INIT_SAFE) {
    cfe_startflags &= ~CFE_INIT_SAFE;
    return 0;
    }

    flg = nvram_open();
    if (flg < 0) return flg;

    size = nvram_getsize();
    buffer = KMALLOC(size,0);

    if (buffer == NULL) return CFE_ERR_NOMEM;

    ptr = buffer;
    offset = 0;

    /* Read the record type and length */
    if (nvram_read(ptr,offset,1) != 1) {
    retval = CFE_ERR_IOERR;
    goto error;
    }

    while ((*ptr != ENV_TLV_TYPE_END)  && (size > 1)) {

    /* Adjust pointer for TLV type */
    rectype = *(ptr);
    offset++;
    size--;

    /*
     * Read the length.  It can be either 1 or 2 bytes
     * depending on the code
     */
    if (rectype & ENV_LENGTH_8BITS) {
        /* Read the record type and length - 8 bits */
        if (nvram_read(ptr,offset,1) != 1) {
        retval = CFE_ERR_IOERR;
        goto error;
        }
        reclen = *(ptr);
        size--;
        offset++;
        }
    else {
        /* Read the record type and length - 16 bits, MSB first */
        if (nvram_read(ptr,offset,2) != 2) {
        retval = CFE_ERR_IOERR;
        goto error;
        }
        reclen = (((unsigned int) *(ptr)) << 8) + (unsigned int) *(ptr+1);
        size -= 2;
        offset += 2;
        }

    if (reclen > size) break;    /* should not happen, bad NVRAM */

    switch (rectype) {
        case ENV_TLV_TYPE_ENV:
        /* Read the TLV data */
        if (nvram_read(ptr,offset,reclen) != reclen) goto error;
        flg = *ptr++;
        envval = (unsigned char *) strnchr(ptr,'=',(reclen-1));
        if (envval) {
            *envval++ = '/0';
            memcpy(valuestr,envval,(reclen-1)-(envval-ptr));
            valuestr[(reclen-1)-(envval-ptr)] = '/0';
            env_setenv(ptr,valuestr,flg);
            }
        break;
       
        default:
        /* Unknown TLV type, skip it. */
        break;
        }

    /*
     * Advance to next TLV
     */
       
    size -= (int)reclen;
    offset += reclen;

    /* Read the next record type */
    ptr = buffer;
    if (nvram_read(ptr,offset,1) != 1) goto error;
    }

    retval = 0;        /* success! */

error:
    KFREE(buffer);
    //nvram_close();

    return retval;

}


/*  *********************************************************************
    *  env_save()
    * 
    *  Write the environment to the NVRAM device.
    * 
    *  Input parameters:
    *         nothing
    *        
    *  Return value:
    *         0 if ok, else error code
    ********************************************************************* */

int env_save(void)
{
    int size;
    unsigned char *buffer;
    unsigned char *buffer_end;
    unsigned char *ptr;
    queue_t *qb;
    cfe_envvar_t *env;
    int namelen;
    int valuelen;
    int flg;

    flg = nvram_open();
    if (flg < 0) return flg;

    nvram_erase();

    size = nvram_getsize();
    buffer = KMALLOC(size,0);

    if (buffer == NULL) return CFE_ERR_NOMEM;

    buffer_end = buffer + size;

    ptr = buffer;

    for (qb = env_envvars.q_next; qb != &env_envvars; qb = qb->q_next) {
    env = (cfe_envvar_t *) qb;

    if (env->flags & (ENV_FLG_BUILTIN)) continue;

    namelen = strlen(env->name);
    valuelen = strlen(env->value);

    if ((ptr + 2 + namelen + valuelen + 1 + 1 + 1) > buffer_end) break;

    *ptr++ = ENV_TLV_TYPE_ENV;        /* TLV record type */
    *ptr++ = (namelen + valuelen + 1 + 1);    /* TLV record length */

    *ptr++ = (unsigned char)env->flags;
    memcpy(ptr,env->name,namelen);        /* TLV record data */
    ptr += namelen;
    *ptr++ = '=';
    memcpy(ptr,env->value,valuelen);
    ptr += valuelen;

    }

    *ptr++ = ENV_TLV_TYPE_END;

    size = nvram_write(buffer,0,ptr-buffer);

    KFREE(buffer);

    nvram_close();

    return (size == (ptr-buffer)) ? 0 : CFE_ERR_IOERR;
}


/****************************************************************************
* File: lib_queue.c
* Descript:
* Author: unkown
* Fix history:
* 1, Wenxy, 20090317,a.m.,     unite with pack and unpack.
*
*****************************************************************************/


#include "lib_types.h"
#include "lib_queue.h"


/*  *********************************************************************
    *  Q_ENQUEUE(qb,item)   
    *                 
    *  Add item to a queue
    *                 
    *  Input Parameters:    
    *      qb - queue block   
    *      item - item to add   
    *                 
    *  Return Value:       
    *      Nothing.       
    ********************************************************************* */

void q_enqueue(queue_t *qb,queue_t *item)
{
    qb->q_prev->q_next = item;
    item->q_next = qb;
    item->q_prev = qb->q_prev;
    qb->q_prev = item;
}


/*  *********************************************************************
    *  Q_DEQUEUE(element)   
    *                 
    *  Remove an element from the queue
    *                     
    *  Input Parameters:        
    *      element - element to remove   
    *                     
    *  Return Value:           
    *      Nothing.           
    ********************************************************************* */

void q_dequeue(queue_t *item)
{
    item->q_prev->q_next = item->q_next;
    item->q_next->q_prev = item->q_prev;
}


/*  *********************************************************************
    *  Q_DEQNEXT(qb)
    *
    *  Dequeue next element from the specified queue
    *
    *  Input Parameters:    
    *      qb - queue block   
    *                 
    *  Return Value:       
    *      next element, or NULL
    ********************************************************************* */

queue_t *q_deqnext(queue_t *qb)
{
    if (qb->q_next == qb) {
    return NULL;
    }

    qb = qb->q_next;

    qb->q_prev->q_next = qb->q_next;
    qb->q_next->q_prev = qb->q_prev;

    return qb;
}


/*  *********************************************************************
    *  Q_MAP(qb)
    *
    *  "Map" a queue, calling the specified function for each
    *  element in the queue
    * 
    *  If the function returns nonzero, q_map will terminate.
    * 
    *  Input Parameters:        
    *      qb - queue block       
    *      fn - function pointer   
    *      a,b - parameters for the function
    * 
    *  Return Value:   
    *      return value from function, or zero if entire queue
    *      was mapped.   
    ********************************************************************* */

int q_map(queue_t *qb, int (*func)(queue_t *,unsigned int,unsigned int),
      unsigned int a,unsigned int b)
{
    queue_t *qe;
    queue_t *nextq;
    int res;

    qe = qb;

    qe = qb->q_next;

    while (qe != qb) {
    nextq = qe->q_next;
    if ((res = (*func)(qe,a,b))) return res;
    qe = nextq;
    }

    return 0;
}





/*  *********************************************************************
    *  Q_COUNT(qb)                            *
    *                                      *
    *  Counts the elements on a queue (not interlocked)            *
    *                                      *
    *  Input Parameters:                         *
    *      qb - queue block                        *
    *                                      *
    *  Return Value:                            *
    *      number of elements                        *
    ********************************************************************* */
int q_count(queue_t *qb)
{
    queue_t *qe;
    int res = 0;

    qe = qb;

    while (qe->q_next != qb) {
    qe = qe->q_next;
    res++;
    }

    return res;
}




/*  *********************************************************************
    *  Q_FIND(qb,item)
    * 
    *  Determines if a particular element is on a queue.
    *                 
    *  Input Parameters:    
    *      qb - queue block
    *      item - queue element
    *         
    *  Return Value:
    *      0 - not on queue       
    *      >0 - position on queue 
    ********************************************************************* */
int q_find(queue_t *qb,queue_t *item)
{
    queue_t *q;
    int res = 1;

    q = qb->q_next;

    while (q != item) {
    if (q == qb) return 0;
    q = q->q_next;
    res++;
    }

    return res;
}


/****************************************************************************
* File: main.c
* Descript: test this queue
* Author: Wenxy, wen_kernel@163.com
* Fix history:
* 1, Wenxy, 20090317,a.m.,     unite with something, :-)
*
*****************************************************************************/


#include <stdio.h>
#include "lib_queue.h"
#include "env_subr.h"


static int ui_cmd_printenv(char *cmd,int argc,char *argv[])
{
    char varname[80];
    char value[256];
    int varlen,vallen;
    int idx;

    printf("Variable Name        Value/n");
    printf("-------------------- --------------------------------------------------/n");

    idx = 0;
    for (;;) {
    varlen = sizeof(varname);
    vallen = sizeof(value);
    if (env_enum(idx,varname,&varlen,value,&vallen) < 0) break;
    printf("%20s %s/n",varname,value);
    idx++;
    }

    return 0;
   
}


struct queue_s queue;


int main(int argc, char *argv[])
{
    printf("Test a queue(list) .../n");
    queue.q_next = queue.q_prev = NULL;

    env_setenv("name-1", "value-1", 1);
    env_setenv("name-2", "value-2", 1);
    env_setenv("name-3", "value-3", 1);
   
    ui_cmd_printenv(NULL, 0, NULL);

    return 0;
}


2. result of test by VC++ 6.0
Test a queue(list) ...
Variable Name        Value
-------------------- --------------------------------------------------
              name-1 value-1
              name-2 value-2
              name-3 value-3

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值