rx: Make identity and opaque usable with NULL vals
[openafs.git] / src / rx / rx_opaque.c
1 /*
2  * Copyright (c) 2010 Your File System Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #include <afsconfig.h>
26 #include <afs/param.h>
27
28 #ifndef KERNEL
29 # include <roken.h>
30 #else
31 # include "afs/sysincludes.h"
32 # include "afsincludes.h"
33 #endif
34
35 #include <rx/rx.h>
36 #include <rx/rx_opaque.h>
37
38
39 /*!
40  * Generate a new opaque object
41  *
42  * Allocate a new opaque object, and copy datalen bytes from data into it.
43  * The caller should dispose of the resulting object using rx_opaque_free or
44  * rx_opaque_zeroFree.
45  *
46  * @param data
47  *      A pointer to the data to copy into the object
48  * @param datalen
49  *      The number of bytes of data to copy
50  * @returns
51  *      A pointer to the allocated opaque object.
52  */
53
54 struct rx_opaque *
55 rx_opaque_new(void *data, size_t datalen)
56 {
57     struct rx_opaque *opaque = rxi_Alloc(sizeof(struct rx_opaque));
58     if (opaque != NULL)
59         rx_opaque_populate(opaque, data, datalen);
60     return opaque;
61 }
62
63 /*!
64  * Allocate space within an existing opaque object
65  *
66  * Allocate length bytes of data within an existing opaque object. This will
67  * overwrite (without freeing) any data that is already held within the
68  * object.
69  *
70  * @param buf
71  *      The opaque object
72  * @param length
73  *      The number of bytes to allocate
74  * @returns
75  *      0 on success, ENOMEM if the memory cannot be allocated.
76  */
77
78 int
79 rx_opaque_alloc(struct rx_opaque *buf, size_t length)
80 {
81     void *mem = rxi_Alloc(length);
82     if (mem == NULL)
83         return ENOMEM;
84     buf->val = mem;
85     buf->len = length;
86     memset(buf->val, 0, buf->len);
87
88     return 0;
89 }
90
91 /*!
92  * Populate an existing opaque object
93  *
94  * Copy datalen bytes from data into an existing opaque object. This allocates
95  * new data space within the object, and will replace (without freeing) any
96  * data that is already held within the object.
97  *
98  * @param to
99  *      The opaque object to populate
100  * @param length
101  *      The number of bytes to allocate
102  * @returns
103  *      0 on sucess, ENOMEM if memory cannot be allocated
104  */
105
106 int
107 rx_opaque_populate(struct rx_opaque *to, void *data, size_t datalen)
108 {
109     int code;
110     to->len = 0;
111     to->val = NULL;
112
113     if (data == NULL || datalen == 0)
114         return 0;
115
116     code = rx_opaque_alloc(to, datalen);
117     if (code)
118         return code;
119     memcpy(to->val, data, datalen);
120     return 0;
121 }
122
123 /*!
124  * Copy data from one opaque object to another
125  *
126  * Make a copy of the data held within one existing opaque object into
127  * another. This allocates new data space within the destination object,
128  * and will replace (without freeing) any data that is already held within
129  * this object.
130  *
131  * @param to
132  *      To object to copy to
133  * @param from
134  *      The object to copy data from
135  * @returns
136  *      0 on success, ENOMEM if memory cannot be allocated
137  */
138
139 int
140 rx_opaque_copy(struct rx_opaque *to, const struct rx_opaque *from)
141 {
142     return rx_opaque_populate(to, from->val, from->len);
143 }
144
145 /*!
146  * Free the contents of an opaque object
147  *
148  */
149 void
150 rx_opaque_freeContents(struct rx_opaque *buf) {
151     if (buf->val) {
152         rxi_Free(buf->val, buf->len);
153     }
154     buf->len = 0;
155     buf->val = NULL;
156 }
157
158 /*!
159  * Zero, then free, the contents of an opaque object
160  */
161 void
162 rx_opaque_zeroFreeContents(struct rx_opaque *buf) {
163     if (buf->val)
164         memset(buf->val, 0, buf->len);
165     rx_opaque_freeContents(buf);
166 }
167
168 /*!
169  * Free an opaque object
170  *
171  * This frees the contents of the object, then frees the object itself
172  */
173
174 void
175 rx_opaque_free(struct rx_opaque **buf) {
176     rx_opaque_freeContents(*buf);
177     rxi_Free(*buf, sizeof(struct rx_opaque));
178     *buf = NULL;
179 }
180
181 /*!
182  * Zero, then free an opaque object
183  *
184  * This zeros the contents of an opaque object, frees those contents,
185  * then frees the object itself.
186  */
187
188 void
189 rx_opaque_zeroFree(struct rx_opaque **buf) {
190     rx_opaque_zeroFreeContents(*buf);
191     rxi_Free(*buf, sizeof(struct rx_opaque));
192     *buf = NULL;
193 }