| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <recordio.h> |
| #include <string.h> |
| #include <stdio.h> |
| #include <errno.h> |
| #include <stdlib.h> |
| #ifndef WIN32 |
| #include <netinet/in.h> |
| #else |
| #include <winsock2.h> /* for _htonl and _ntohl */ |
| #endif |
| |
| void deallocate_String(char **s) |
| { |
| if (*s) |
| free(*s); |
| *s = 0; |
| } |
| |
| void deallocate_Buffer(struct buffer *b) |
| { |
| if (b->buff) |
| free(b->buff); |
| b->buff = 0; |
| } |
| |
| struct buff_struct { |
| int32_t len; |
| int32_t off; |
| char *buffer; |
| }; |
| |
| static int resize_buffer(struct buff_struct *s, int newlen) |
| { |
| char *buffer= NULL; |
| while (s->len < newlen) { |
| s->len *= 2; |
| } |
| buffer = (char*)realloc(s->buffer, s->len); |
| if (!buffer) { |
| s->buffer = 0; |
| return -ENOMEM; |
| } |
| s->buffer = buffer; |
| return 0; |
| } |
| |
| int oa_start_record(struct oarchive *oa, const char *tag) |
| { |
| return 0; |
| } |
| int oa_end_record(struct oarchive *oa, const char *tag) |
| { |
| return 0; |
| } |
| int oa_serialize_int(struct oarchive *oa, const char *tag, const int32_t *d) |
| { |
| struct buff_struct *priv = oa->priv; |
| int32_t i = htonl(*d); |
| if ((priv->len - priv->off) < sizeof(i)) { |
| int rc = resize_buffer(priv, priv->len + sizeof(i)); |
| if (rc < 0) return rc; |
| } |
| memcpy(priv->buffer+priv->off, &i, sizeof(i)); |
| priv->off+=sizeof(i); |
| return 0; |
| } |
| int64_t zoo_htonll(int64_t v) |
| { |
| int i = 0; |
| char *s = (char *)&v; |
| if (htonl(1) == 1) { |
| return v; |
| } |
| for (i = 0; i < 4; i++) { |
| int tmp = s[i]; |
| s[i] = s[8-i-1]; |
| s[8-i-1] = tmp; |
| } |
| |
| return v; |
| } |
| |
| int oa_serialize_long(struct oarchive *oa, const char *tag, const int64_t *d) |
| { |
| const int64_t i = zoo_htonll(*d); |
| struct buff_struct *priv = oa->priv; |
| if ((priv->len - priv->off) < sizeof(i)) { |
| int rc = resize_buffer(priv, priv->len + sizeof(i)); |
| if (rc < 0) return rc; |
| } |
| memcpy(priv->buffer+priv->off, &i, sizeof(i)); |
| priv->off+=sizeof(i); |
| return 0; |
| } |
| int oa_start_vector(struct oarchive *oa, const char *tag, const int32_t *count) |
| { |
| return oa_serialize_int(oa, tag, count); |
| } |
| int oa_end_vector(struct oarchive *oa, const char *tag) |
| { |
| return 0; |
| } |
| int oa_serialize_bool(struct oarchive *oa, const char *name, const int32_t *i) |
| { |
| //return oa_serialize_int(oa, name, i); |
| struct buff_struct *priv = oa->priv; |
| if ((priv->len - priv->off) < 1) { |
| int rc = resize_buffer(priv, priv->len + 1); |
| if (rc < 0) |
| return rc; |
| } |
| priv->buffer[priv->off] = (*i == 0 ? '\0' : '\1'); |
| priv->off++; |
| return 0; |
| } |
| static const int32_t negone = -1; |
| int oa_serialize_buffer(struct oarchive *oa, const char *name, |
| const struct buffer *b) |
| { |
| struct buff_struct *priv = oa->priv; |
| int rc; |
| if (!b) { |
| return oa_serialize_int(oa, "len", &negone); |
| } |
| rc = oa_serialize_int(oa, "len", &b->len); |
| if (rc < 0) |
| return rc; |
| // this means a buffer of NUll |
| // with size of -1. This is |
| // waht we use in java serialization for NULL |
| if (b->len == -1) { |
| return rc; |
| } |
| if ((priv->len - priv->off) < b->len) { |
| rc = resize_buffer(priv, priv->len + b->len); |
| if (rc < 0) |
| return rc; |
| } |
| memcpy(priv->buffer+priv->off, b->buff, b->len); |
| priv->off += b->len; |
| return 0; |
| } |
| int oa_serialize_string(struct oarchive *oa, const char *name, char **s) |
| { |
| struct buff_struct *priv = oa->priv; |
| int32_t len; |
| int rc; |
| if (!*s) { |
| oa_serialize_int(oa, "len", &negone); |
| return 0; |
| } |
| len = strlen(*s); |
| rc = oa_serialize_int(oa, "len", &len); |
| if (rc < 0) |
| return rc; |
| if ((priv->len - priv->off) < len) { |
| rc = resize_buffer(priv, priv->len + len); |
| if (rc < 0) |
| return rc; |
| } |
| memcpy(priv->buffer+priv->off, *s, len); |
| priv->off += len; |
| return 0; |
| } |
| int ia_start_record(struct iarchive *ia, const char *tag) |
| { |
| return 0; |
| } |
| int ia_end_record(struct iarchive *ia, const char *tag) |
| { |
| return 0; |
| } |
| int ia_deserialize_int(struct iarchive *ia, const char *tag, int32_t *count) |
| { |
| struct buff_struct *priv = ia->priv; |
| if ((priv->len - priv->off) < sizeof(*count)) { |
| return -E2BIG; |
| } |
| memcpy(count, priv->buffer+priv->off, sizeof(*count)); |
| priv->off+=sizeof(*count); |
| *count = ntohl(*count); |
| return 0; |
| } |
| |
| int ia_deserialize_long(struct iarchive *ia, const char *tag, int64_t *count) |
| { |
| struct buff_struct *priv = ia->priv; |
| int64_t v = 0; |
| if ((priv->len - priv->off) < sizeof(*count)) { |
| return -E2BIG; |
| } |
| memcpy(count, priv->buffer+priv->off, sizeof(*count)); |
| priv->off+=sizeof(*count); |
| v = zoo_htonll(*count); // htonll and ntohll do the same |
| *count = v; |
| return 0; |
| } |
| int ia_start_vector(struct iarchive *ia, const char *tag, int32_t *count) |
| { |
| return ia_deserialize_int(ia, tag, count); |
| } |
| int ia_end_vector(struct iarchive *ia, const char *tag) |
| { |
| return 0; |
| } |
| int ia_deserialize_bool(struct iarchive *ia, const char *name, int32_t *v) |
| { |
| struct buff_struct *priv = ia->priv; |
| //fprintf(stderr, "Deserializing bool %d\n", priv->off); |
| //return ia_deserialize_int(ia, name, v); |
| if ((priv->len - priv->off) < 1) { |
| return -E2BIG; |
| } |
| *v = priv->buffer[priv->off]; |
| priv->off+=1; |
| //fprintf(stderr, "Deserializing bool end %d\n", priv->off); |
| return 0; |
| } |
| int ia_deserialize_buffer(struct iarchive *ia, const char *name, |
| struct buffer *b) |
| { |
| struct buff_struct *priv = ia->priv; |
| int rc = ia_deserialize_int(ia, "len", &b->len); |
| if (rc < 0) |
| return rc; |
| if ((priv->len - priv->off) < b->len) { |
| return -E2BIG; |
| } |
| // set the buffer to null |
| if (b->len == -1) { |
| b->buff = NULL; |
| return rc; |
| } |
| b->buff = malloc(b->len); |
| if (!b->buff) { |
| return -ENOMEM; |
| } |
| memcpy(b->buff, priv->buffer+priv->off, b->len); |
| priv->off += b->len; |
| return 0; |
| } |
| int ia_deserialize_string(struct iarchive *ia, const char *name, char **s) |
| { |
| struct buff_struct *priv = ia->priv; |
| int32_t len; |
| int rc = ia_deserialize_int(ia, "len", &len); |
| if (rc < 0) |
| return rc; |
| if ((priv->len - priv->off) < len) { |
| return -E2BIG; |
| } |
| if (len < 0) { |
| return -EINVAL; |
| } |
| *s = malloc(len+1); |
| if (!*s) { |
| return -ENOMEM; |
| } |
| memcpy(*s, priv->buffer+priv->off, len); |
| (*s)[len] = '\0'; |
| priv->off += len; |
| return 0; |
| } |
| |
| static struct iarchive ia_default = { |
| ia_start_record, |
| ia_end_record, |
| ia_start_vector, |
| ia_end_vector, |
| ia_deserialize_bool, |
| ia_deserialize_int, |
| ia_deserialize_long , |
| ia_deserialize_buffer, |
| ia_deserialize_string}; |
| |
| static struct oarchive oa_default = { |
| oa_start_record, |
| oa_end_record, |
| oa_start_vector, |
| oa_end_vector, |
| oa_serialize_bool, |
| oa_serialize_int, |
| oa_serialize_long , |
| oa_serialize_buffer, |
| oa_serialize_string}; |
| |
| struct iarchive *create_buffer_iarchive(char *buffer, int len) |
| { |
| struct iarchive *ia; |
| struct buff_struct *buff; |
| ia = malloc(sizeof(*ia)); |
| if (!ia) return 0; |
| buff = malloc(sizeof(struct buff_struct)); |
| if (!buff) { |
| free(ia); |
| return 0; |
| } |
| *ia = ia_default; |
| buff->off = 0; |
| buff->buffer = buffer; |
| buff->len = len; |
| ia->priv = buff; |
| return ia; |
| } |
| |
| struct oarchive *create_buffer_oarchive() |
| { |
| struct oarchive *oa; |
| struct buff_struct *buff; |
| oa = malloc(sizeof(*oa)); |
| if (!oa) return 0; |
| buff = malloc(sizeof(struct buff_struct)); |
| if (!buff) { |
| free(oa); |
| return 0; |
| } |
| *oa = oa_default; |
| buff->off = 0; |
| buff->buffer = malloc(128); |
| buff->len = 128; |
| oa->priv = buff; |
| return oa; |
| } |
| |
| void close_buffer_iarchive(struct iarchive **ia) |
| { |
| free((*ia)->priv); |
| free(*ia); |
| *ia = 0; |
| } |
| |
| void close_buffer_oarchive(struct oarchive **oa, int free_buffer) |
| { |
| if (free_buffer) { |
| struct buff_struct *buff = (struct buff_struct *)(*oa)->priv; |
| if (buff->buffer) { |
| free(buff->buffer); |
| } |
| } |
| free((*oa)->priv); |
| free(*oa); |
| *oa = 0; |
| } |
| |
| char *get_buffer(struct oarchive *oa) |
| { |
| struct buff_struct *buff = oa->priv; |
| return buff->buffer; |
| } |
| int get_buffer_len(struct oarchive *oa) |
| { |
| struct buff_struct *buff = oa->priv; |
| return buff->off; |
| } |