blob: 6a5f99c0332616fb91f6d1beffd5cb0d41080677 [file] [log] [blame]
/**
*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.
*/
/*
* hessian_in.c
*
* \date Aug 1, 2011
* \author <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
* \copyright Apache License, Version 2.0
*/
#include <stdlib.h>
#include <string.h>
#include "hessian_2.0.h"
static int END_OF_DATA = -2;
int hessian_parseChar(hessian_in_pt in, char *c);
int hessian_parseLong(hessian_in_pt in, long *value);
int hessian_parseInt16(hessian_in_pt in, int *value);
int hessian_parseInt(hessian_in_pt in, int *value);
char hessian_read(hessian_in_pt in) {
return (in->buffer[in->offset++] & 0xFF);
}
int hessian_readBoolean(hessian_in_pt in, bool *value) {
char tag = hessian_read(in);
switch (tag) {
case 'T':
*value = true;
break;
case 'F':
default:
*value = false;
break;
}
return 0;
}
int hessian_readInt(hessian_in_pt in, int *value) {
unsigned char tag = hessian_read(in);
switch (tag) {
// direct integer
case 0x80: case 0x81: case 0x82: case 0x83:
case 0x84: case 0x85: case 0x86: case 0x87:
case 0x88: case 0x89: case 0x8a: case 0x8b:
case 0x8c: case 0x8d: case 0x8e: case 0x8f:
case 0x90: case 0x91: case 0x92: case 0x93:
case 0x94: case 0x95: case 0x96: case 0x97:
case 0x98: case 0x99: case 0x9a: case 0x9b:
case 0x9c: case 0x9d: case 0x9e: case 0x9f:
case 0xa0: case 0xa1: case 0xa2: case 0xa3:
case 0xa4: case 0xa5: case 0xa6: case 0xa7:
case 0xa8: case 0xa9: case 0xaa: case 0xab:
case 0xac: case 0xad: case 0xae: case 0xaf:
case 0xb0: case 0xb1: case 0xb2: case 0xb3:
case 0xb4: case 0xb5: case 0xb6: case 0xb7:
case 0xb8: case 0xb9: case 0xba: case 0xbb:
case 0xbc: case 0xbd: case 0xbe: case 0xbf:
*value = tag - INT_ZERO;
break;
/* byte int */
case 0xc0: case 0xc1: case 0xc2: case 0xc3:
case 0xc4: case 0xc5: case 0xc6: case 0xc7:
case 0xc8: case 0xc9: case 0xca: case 0xcb:
case 0xcc: case 0xcd: case 0xce: case 0xcf:
*value = ((tag - INT_BYTE_ZERO) << 8) + hessian_read(in);
break;
/* short int */
case 0xd0: case 0xd1: case 0xd2: case 0xd3:
case 0xd4: case 0xd5: case 0xd6: case 0xd7:
*value = ((tag - INT_SHORT_ZERO) << 16) + 256 * hessian_read(in) + hessian_read(in);
break;
case 'I':
hessian_readInt(in, value);
break;
default:
*value = 0;
break;
}
return 1;
}
int hessian_readLong(hessian_in_pt in, long *value) {
unsigned char tag = hessian_read(in);
switch (tag) {
// direct long
case 0xd8: case 0xd9: case 0xda: case 0xdb:
case 0xdc: case 0xdd: case 0xde: case 0xdf:
case 0xe0: case 0xe1: case 0xe2: case 0xe3:
case 0xe4: case 0xe5: case 0xe6: case 0xe7:
case 0xe8: case 0xe9: case 0xea: case 0xeb:
case 0xec: case 0xed: case 0xee: case 0xef:
*value = tag - LONG_ZERO;
break;
/* byte long */
case 0xf0: case 0xf1: case 0xf2: case 0xf3:
case 0xf4: case 0xf5: case 0xf6: case 0xf7:
case 0xf8: case 0xf9: case 0xfa: case 0xfb:
case 0xfc: case 0xfd: case 0xfe: case 0xff:
*value = ((tag - LONG_BYTE_ZERO) << 8) + hessian_read(in);
break;
/* short long */
case 0x38: case 0x39: case 0x3a: case 0x3b:
case 0x3c: case 0x3d: case 0x3e: case 0x3f:
*value = ((tag - LONG_SHORT_ZERO) << 16) + 256
* hessian_read(in) + hessian_read(in);
break;
case 'L':
hessian_parseLong(in, value);
break;
default:
return 0l;
}
return 0;
}
int hessian_readDouble(hessian_in_pt in, double *value) {
unsigned char tag = hessian_read(in);
long l;
int i;
double *d;
switch (tag) {
case 0x67:
*value = 0;
break;
case 0x68:
*value = 1;
break;
case 0x69:
*value = (double) hessian_read(in);
break;
case 0x6a:
*value = (short) (256 * hessian_read(in) + hessian_read(in));
break;
case 0x6b:
hessian_parseInt(in, &i);
*value = (double) *((float *) &i);
break;
case 'D':
hessian_parseLong(in, &l);
d = (double *) &l;
*value = *d;
break;
}
return 0;
}
int hessian_readUTCDate(hessian_in_pt in, long *value) {
unsigned char tag = hessian_read(in);
if (tag == 'd') {
hessian_parseLong(in, value);
}
return 0;
}
int hessian_readNull(hessian_in_pt in) {
unsigned char tag = hessian_read(in);
switch (tag) {
case 'N':
break;
default:
break;
}
return 0;
}
int hessian_readChar(hessian_in_pt in, char *value) {
char *readC;
unsigned int read;
hessian_readNString(in, 0, 1, &readC, &read);
*value = readC[0];
return 0;
}
int hessian_readString(hessian_in_pt in, char **value, unsigned int *readLength) {
return hessian_readNString(in, 0, -1, value, readLength);
}
int hessian_readNString(hessian_in_pt in, int offset, int length, char **value, unsigned int *readLength) {
*readLength = 0;
bool done = false;
if (in->chunkLength == END_OF_DATA) {
done = true;
} else if (in->chunkLength == 0) {
unsigned char tag = hessian_read(in);
switch (tag) {
case 'N':
in->chunkLength = 0;
in->lastChunk = true;
break;
case 'S':
case 's':
in->lastChunk = tag == 'S';
hessian_parseInt16(in, &(in->chunkLength));
break;
case 0x00: case 0x01: case 0x02: case 0x03:
case 0x04: case 0x05: case 0x06: case 0x07:
case 0x08: case 0x09: case 0x0a: case 0x0b:
case 0x0c: case 0x0d: case 0x0e: case 0x0f:
case 0x10: case 0x11: case 0x12: case 0x13:
case 0x14: case 0x15: case 0x16: case 0x17:
case 0x18: case 0x19: case 0x1a: case 0x1b:
case 0x1c: case 0x1d: case 0x1e: case 0x1f:
in->chunkLength = tag - 0x00;
in->lastChunk = true;
break;
case 0x30: case 0x31: case 0x32: case 0x33:
in->chunkLength = (tag - 0x30) * 256 + hessian_read(in);
in->lastChunk = true;
break;
default:
in->chunkLength = 0;
in->lastChunk = true;
break;
}
}
while (!done) {
unsigned int newSize = *readLength + in->chunkLength + 1;
*value = realloc(*value, sizeof(char) * (*readLength + in->chunkLength + 1));
if (in->chunkLength > 0) {
char c;
hessian_parseChar(in, &c);
(*value)[(*readLength) + offset] = c;
(*value)[(*readLength) + offset + 1] = '\0';
in->chunkLength--;
(*readLength)++;
length--;
if (length == 0) {
done = true;
}
} else if (in->lastChunk) {
done = true;
if (*readLength != 0) {
in->chunkLength = END_OF_DATA;
}
} else {
unsigned char tag = hessian_read(in);
switch (tag) {
case 'S':
case 's':
done = tag == 'S';
hessian_parseInt16(in, &in->chunkLength);
break;
case 0x00: case 0x01: case 0x02: case 0x03:
case 0x04: case 0x05: case 0x06: case 0x07:
case 0x08: case 0x09: case 0x0a: case 0x0b:
case 0x0c: case 0x0d: case 0x0e: case 0x0f:
case 0x10: case 0x11: case 0x12: case 0x13:
case 0x14: case 0x15: case 0x16: case 0x17:
case 0x18: case 0x19: case 0x1a: case 0x1b:
case 0x1c: case 0x1d: case 0x1e: case 0x1f:
in->chunkLength = tag - 0x00;
in->lastChunk = true;
break;
case 0x30: case 0x31: case 0x32: case 0x33:
in->chunkLength = (tag - 0x30) * 256 + hessian_read(in);
in->lastChunk = true;
break;
default:
in->chunkLength = 0;
in->lastChunk = true;
break;
}
}
}
if (in->lastChunk && in->chunkLength == 0) {
in->chunkLength = END_OF_DATA;
}
return 0;
}
int hessian_readByte(hessian_in_pt in, unsigned char *value) {
unsigned char *readC;
unsigned int read;
hessian_readNBytes(in, 0, 1, &readC, &read);
*value = readC[0];
return 0;
}
int hessian_readBytes(hessian_in_pt in, unsigned char **value, unsigned int *readLength) {
return hessian_readNBytes(in, 0, -1, value, readLength);
}
int hessian_readNBytes(hessian_in_pt in, int offset, int length, unsigned char **value, unsigned int *readLength) {
*readLength = 0;
bool done = false;
if (in->chunkLength == END_OF_DATA) {
done = true;
} else if (in->chunkLength == 0) {
unsigned char tag = hessian_read(in);
switch (tag) {
case 'N':
in->chunkLength = 0;
in->lastChunk = true;
break;
case 'B':
case 'b':
in->lastChunk = tag == 'B';
hessian_parseInt16(in, &(in->chunkLength));
break;
case 0x20: case 0x21: case 0x22: case 0x23:
case 0x24: case 0x25: case 0x26: case 0x27:
case 0x28: case 0x29: case 0x2a: case 0x2b:
case 0x2c: case 0x2d: case 0x2e: case 0x2f:
in->chunkLength = tag - 0x20;
in->lastChunk = true;
break;
default:
in->chunkLength = 0;
in->lastChunk = true;
break;
}
}
while (!done) {
unsigned int newSize = *readLength + in->chunkLength;
*value = realloc(*value, sizeof(char) * (*readLength + in->chunkLength));
if (in->chunkLength > 0) {
unsigned char c = hessian_read(in);
(*value)[(*readLength) + offset] = c;
in->chunkLength--;
(*readLength)++;
length--;
if (length == 0) {
done = true;
}
} else if (in->lastChunk) {
done = true;
if (*readLength != 0) {
in->chunkLength = END_OF_DATA;
}
} else {
unsigned char tag = hessian_read(in);
switch (tag) {
case 'B':
case 'b':
done = tag == 'S';
hessian_parseInt16(in, &in->chunkLength);
break;
case 0x20: case 0x21: case 0x22: case 0x23:
case 0x24: case 0x25: case 0x26: case 0x27:
case 0x28: case 0x29: case 0x2a: case 0x2b:
case 0x2c: case 0x2d: case 0x2e: case 0x2f:
in->chunkLength = tag - 0x20;
in->lastChunk = true;
break;
default:
in->chunkLength = 0;
in->lastChunk = true;
break;
}
}
}
if (in->lastChunk && in->chunkLength == 0) {
in->chunkLength = END_OF_DATA;
}
return 0;
}
int hessian_parseChar(hessian_in_pt in, char *c) {
unsigned char ch = hessian_read(in);
if (ch < 0x80) {
*c = ch;
} else if ((ch & 0xe0) == 0xc0) {
char ch1 = hessian_read(in);
*c = ((ch & 0x1f) << 6) + (ch1 & 0x3f);
} else if ((ch & 0xf0) == 0xe0) {
char ch1 = hessian_read(in);
char ch2 = hessian_read(in);
*c = ((ch & 0x0f) << 12) + ((ch1 & 0x3f) << 6) + (ch2 & 0x3f);
} else {
*c = '\0';
}
return 0;
}
int hessian_parseInt16(hessian_in_pt in, int *value) {
int b16 = hessian_read(in) & 0xFF;
int b8 = hessian_read(in) & 0xFF;
*value = (b16 << 8)
+ b8;
return 0;
}
int hessian_parseInt(hessian_in_pt in, int *value) {
int b32 = hessian_read(in) & 0xFF;
int b24 = hessian_read(in) & 0xFF;
int b16 = hessian_read(in) & 0xFF;
int b8 = hessian_read(in) & 0xFF;
*value = (b32 << 24)
+ (b24 << 16)
+ (b16 << 8)
+ b8;
return 0;
}
int hessian_parseLong(hessian_in_pt in, long *value) {
long b64 = hessian_read(in) & 0xFF;
long b56 = hessian_read(in) & 0xFF;
long b48 = hessian_read(in) & 0xFF;
long b40 = hessian_read(in) & 0xFF;
long b32 = hessian_read(in) & 0xFF;
long b24 = hessian_read(in) & 0xFF;
long b16 = hessian_read(in) & 0xFF;
long b8 = hessian_read(in) & 0xFF;
long v = (b64 << 56)
+ (b56 << 48)
+ (b48 << 40)
+ (b40 << 32)
+ (b32 << 24)
+ (b24 << 16)
+ (b16 << 8)
+ b8;
*value = v;
return 0;
}