2014-11-18 3 views
1

У меня есть эта структура RPC T_Struct, которая пришла с провода. Я хотел бы сделать его копию, но я не хочу писать отдельную функцию для обработки всех структур, распределений и массивов ее членов (особенно, что мне придется делать то же самое для тонов других структур .)Имеет ли смысл эта копия RPC xdr?

Так как у меня уже есть способ декодирования, кодирования и бесплатно, что это имеет смысл, чтобы иметь что-то вроде этого:

void copy_T_Struct(T_Struct* destination, T_Struct* source) 
{ 
    XDR xdr ; 

    /* Is there a way I can know the size of the buffer for the struct? */ 
    char buffer[ 10240 ] ; 

    xdrmem_create(&xdr, buffer, sizeof(buffer), XDR_ENCODE) ; 
    (*xdr_T_Struct)(&xdr, source) ; /* serialize to buffer */ 
    xdr.x_op = XDR_DECODE ; 
    memset(destination, 0, sizeof(*destination)) ; /* without it I see segfault */ 
    (*xdr_T_Struct)(&xdr, destination) ; /* serialize back to T_Struct */ 
    xdr_destroy(&xdr) ; 
} 

Я понимаю, что в конце концов, я также буду иметь возможность звонок xdr_free((xdrproc_t)xdr_T_Struct, (char *)destination) ;

+0

Похоже, он будет работать вообще. Что нужно добавить, это проверка вывода вызова функции xdr_T_Struct() при XDR_ENCODE-ing и увеличение размера буфера в случае сбоя. – Grzegorz

ответ

1

Вот окончательное решение. Обратите внимание, что это версия C.

Использование статического перераспределяемого буфера. Пример ниже.

xdr_copy.h

#define XDR_COPY(T, d, s) xdr_copy_((xdrproc_t)xdr_##T, (char*)d, (const char*)s, sizeof(T)) 
extern bool_t xdr_copy(xdrproc_t proc, char* d, const char* s) ; 
extern bool_t xdr_copy_(xdrproc_t proc, char* d, const char* s, const unsigned size) ; 

xdr_copy.c

... /* removing all #includes for clarity */ 
#define XDR_BUFFER_SIZE (100 * 1024) 
#define XDR_BUFFER_DELTA (10 * 1024) 

static char* xdr_buffer = NULL ; 
static unsigned xdr_buffer_size = 0 ; 

static char* xdr_buffer_realloc(const unsigned delta) 
{ 
    char* rv = realloc(xdr_buffer, xdr_buffer_size + delta) ; 

    if (rv) 
    { 
     xdr_buffer_size += delta ; 
     xdr_buffer = rv ; 
    } 

    return rv ; 
} 

static char* get_xdr_buffer() 
{ 
    if (!xdr_buffer) 
     xdr_buffer = xdr_buffer_realloc(XDR_BUFFER_SIZE) ; 

    return xdr_buffer ; 
} 

bool_t xdr_copy(xdrproc_t proc, char* d, const char* s) 
{ 
    XDR x ; 
    char* buffer = get_xdr_buffer() ; 

    while (buffer) 
    { 
     xdrmem_create(&x, buffer, xdr_buffer_size, XDR_ENCODE) ; 
     if ((*proc)(&x, (caddr_t*)s)) 
     { 
     xdr_destroy(&x) ; 
     xdrmem_create(&x, buffer, xdr_buffer_size, XDR_DECODE) ; 
     (*proc)(&x, (caddr_t*)d) ; 
     break ; 
     } 
     else 
     { 
     buffer = xdr_buffer_realloc(XDR_BUFFER_DELTA) ; 
     xdr_destroy(&x) ; 
     } 
    } 

    if (buffer) 
    { 
     xdr_destroy(&x) ; 
     return 1 ; 
    } 
    else 
     return 0 ; 
} 

bool_t xdr_copy_(xdrproc_t proc, char* d, const char* s, const unsigned size) 
{ 
    memset(d, 0, size) ; 
    return xdr_copy(proc, d, s) ; 
} 

Пример

MyRPCArgs copy ; 

if (!XDR_COPY(MyRPCArgs, &copy, source_ptr)) 
    ... /* report memory allocation issue */ 
Смежные вопросы