blob: ab044ff367ddfe3e5cbd13a2caed560fd92bde07 [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_out.c
*
* \date Jul 31, 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"
void hessian_ensureCapacity(hessian_out_pt obj, int capacity);
int hessian_printString(hessian_out_pt out, char *value);
int hessian_printNString(hessian_out_pt out, char *value, int offset, int length);
int hessian_writeType(hessian_out_pt out, char *type);
int hessian_write(hessian_out_pt out, unsigned char byte);
int hessian_writeP(hessian_out_pt out, unsigned char *byte);
int hessian_writeBoolean(hessian_out_pt out, bool value) {
hessian_ensureCapacity(out, out->offset + 1);
if (value) {
char c = 'T';
hessian_writeP(out, &c);
} else {
out->buffer[out->offset++] = 'F';
out->length++;
}
return 0;
}
int hessian_writeInt(hessian_out_pt out, int value) {
hessian_ensureCapacity(out, out->offset + 5);
if (INT_DIRECT_MIN <= value && value <= INT_DIRECT_MAX)
hessian_write(out, (char) (value + INT_ZERO));
else if (INT_BYTE_MIN <= value && value <= INT_BYTE_MAX) {
hessian_write(out, (char) (INT_BYTE_ZERO + (value >> 8)));
hessian_write(out, (char) (value));
} else if (INT_SHORT_MIN <= value && value <= INT_SHORT_MAX) {
hessian_write(out, (char)(INT_SHORT_ZERO + (value >> 16)));
hessian_write(out, (char)(value >> 8));
hessian_write(out, (char)(value));
} else {
hessian_write(out, (char)('I'));
hessian_write(out, (char)(value >> 24));
hessian_write(out, (char)(value >> 16));
hessian_write(out, (char)(value >> 8));
hessian_write(out, (char)(value));
}
return 0;
}
int hessian_writeLong(hessian_out_pt out, long value) {
hessian_ensureCapacity(out, out->offset + 9);
if (LONG_DIRECT_MIN <= value && value <= LONG_DIRECT_MAX) {
hessian_write(out, (char)(value + LONG_ZERO));
} else if (LONG_BYTE_MIN <= value && value <= LONG_BYTE_MAX) {
hessian_write(out, (char)(LONG_BYTE_ZERO + (value >> 8)));
hessian_write(out, (char)(value));
} else if (LONG_SHORT_MIN <= value && value <= LONG_SHORT_MAX) {
hessian_write(out, (char)(LONG_SHORT_ZERO + (value >> 16)));
hessian_write(out, (char)(value >> 8));
hessian_write(out, (char)(value));
} else if (-0x80000000L <= value && value <= 0x7fffffffL) {
hessian_write(out, (char) LONG_INT);
hessian_write(out, (char)(value >> 24));
hessian_write(out, (char)(value >> 16));
hessian_write(out, (char)(value >> 8));
hessian_write(out, (char)(value));
} else {
hessian_write(out, (char) 'L');
hessian_write(out, (char)(value >> 56));
hessian_write(out, (char)(value >> 48));
hessian_write(out, (char)(value >> 40));
hessian_write(out, (char)(value >> 32));
hessian_write(out, (char)(value >> 24));
hessian_write(out, (char)(value >> 16));
hessian_write(out, (char)(value >> 8));
hessian_write(out, (char)(value));
}
return 0;
}
int hessian_writeDouble(hessian_out_pt out, double value) {
hessian_ensureCapacity(out, out->offset + 9);
int intValue = (int) value;
if (intValue == value) {
if (intValue == 0) {
hessian_write(out, (char) DOUBLE_ZERO);
} else if (intValue == 1) {
hessian_write(out, (char) DOUBLE_ONE);
} else if (-0x80 <= intValue && intValue < 0x80) {
hessian_write(out, (char) DOUBLE_BYTE);
hessian_write(out, (char) intValue);
} else if (-0x8000 <= intValue && intValue < 0x8000) {
hessian_write(out, (char) DOUBLE_SHORT);
hessian_write(out, (char) ((intValue >> 8) & 0xFF));
hessian_write(out, (char) (intValue & 0xFF));
}
} else {
float f = (float) value;
if (f == value) {
float f = value;
int bits = *((int *) &f);
hessian_write(out, (char)(DOUBLE_FLOAT));
hessian_write(out, (char)(bits >> 24));
hessian_write(out, (char)(bits >> 16));
hessian_write(out, (char)(bits >> 8));
hessian_write(out, (char)(bits));
} else {
long bits = *((long *) &value);
hessian_write(out, (char) 'D');
hessian_write(out, (char)(bits >> 56) & 0x00000000000000FF);
hessian_write(out, (char)(bits >> 48) & 0x00000000000000FF);
hessian_write(out, (char)(bits >> 40) & 0x00000000000000FF);
hessian_write(out, (char)(bits >> 32) & 0x00000000000000FF);
hessian_write(out, (char)(bits >> 24) & 0x00000000000000FF);
hessian_write(out, (char)(bits >> 16) & 0x00000000000000FF);
hessian_write(out, (char)(bits >> 8) & 0x00000000000000FF);
hessian_write(out, (char)(bits) & 0x00000000000000FF);
}
}
return 0;
}
int hessian_writeUTCDate(hessian_out_pt out, long value) {
hessian_ensureCapacity(out, out->offset + 9);
hessian_write(out, (int) ('d'));
hessian_write(out, ((int) (value >> 56)));
hessian_write(out, ((int) (value >> 48)));
hessian_write(out, ((int) (value >> 40)));
hessian_write(out, ((int) (value >> 32)));
hessian_write(out, ((int) (value >> 24)));
hessian_write(out, ((int) (value >> 16)));
hessian_write(out, ((int) (value >> 8)));
hessian_write(out, ((int) (value)));
return 0;
}
int hessian_writeNull(hessian_out_pt out) {
hessian_ensureCapacity(out, out->offset + 1);
hessian_write(out, (int) ('N'));
return 0;
}
int hessian_writeString(hessian_out_pt out, char *value) {
int length = strlen(value);
return hessian_writeNString(out, value, 0, length);
}
int hessian_writeNString(hessian_out_pt out, char *value, int offset, int length) {
if (value == NULL) {
hessian_writeNull(out);
} else {
while (length > 0x8000) {
int sublen = 0x8000;
// chunk can't end in high surrogate
int tail = value[offset + sublen - 1];
if (0xd800 <= tail && tail <= 0xdbff)
sublen--;
hessian_ensureCapacity(out, out->offset + 3);
hessian_write(out, (int) 's');
hessian_write(out, (int)(sublen >> 8));
hessian_write(out, (int)(sublen));
hessian_printNString(out, value, offset, sublen);
length -= sublen;
offset += sublen;
}
if (length <= STRING_DIRECT_MAX) {
hessian_ensureCapacity(out, out->offset + 2);
hessian_write(out, (int)(STRING_DIRECT + length));
} else {
hessian_ensureCapacity(out, out->offset + 3);
hessian_write(out, (int)('S'));
hessian_write(out, (int)(length >> 8));
hessian_write(out, (int)(length));
}
hessian_printNString(out, value, offset, length);
}
return 0;
}
int hessian_writeBytes(hessian_out_pt out, unsigned char value[], int length) {
return hessian_writeNBytes(out, value, 0, length);
}
int hessian_writeNBytes(hessian_out_pt out, unsigned char value[], int offset, int length) {
if (value == NULL) {
hessian_writeNull(out);
} else {
while (length > 0x8000) {
int sublen = 0x8000;
hessian_ensureCapacity(out, out->offset + 3);
hessian_write(out, (int) 'b');
hessian_write(out, (int)(sublen >> 8));
hessian_write(out, (int) sublen);
hessian_ensureCapacity(out, out->offset + sublen);
memcpy(out->buffer+out->offset, value+offset, sublen);
out->offset += sublen;
length -= sublen;
offset += sublen;
}
if (length < 0x10) {
hessian_ensureCapacity(out, out->offset + 1);
hessian_write(out, (int)(BYTES_DIRECT + length));
} else {
hessian_ensureCapacity(out, out->offset + 3);
hessian_write(out, (int) 'B');
hessian_write(out, (int)(length >> 8));
hessian_write(out, (int)(length));
}
hessian_ensureCapacity(out, out->offset + length);
memcpy(out->buffer+out->offset, value+offset, length);
out->offset += length;
}
return 0;
}
int hessian_writeListBegin(hessian_out_pt out, int length, char *type) {
hessian_ensureCapacity(out, out->offset + 1);
if (length < 0) {
if (type != NULL) {
hessian_write(out, (char) BC_LIST_VARIABLE);
hessian_writeType(out, type);
} else {
hessian_write(out, (char) BC_LIST_VARIABLE_UNTYPED);
}
return true;
} else if (length <= LIST_DIRECT_MAX) {
if (type != NULL) {
hessian_write(out, (char)(BC_LIST_DIRECT + length));
hessian_writeType(out, type);
} else {
hessian_write(out, (char)(BC_LIST_DIRECT_UNTYPED + length));
}
return false;
} else {
if (type != NULL) {
hessian_write(out, (char) BC_LIST_FIXED);
hessian_writeType(out, type);
} else {
hessian_write(out, (char) BC_LIST_FIXED_UNTYPED);
}
hessian_writeInt(out, length);
return false;
}
return 0;
}
int hessian_writeListEnd(hessian_out_pt out) {
hessian_ensureCapacity(out, out->offset + 1);
hessian_write(out, (char) BC_END);
return 0;
}
int hessian_writeType(hessian_out_pt out, char *type) {
int len = strlen(type);
if (len == 0) {
return 1;
}
// Do something with refs here
return hessian_writeString(out, type);
}
int hessian_startCall(hessian_out_pt out, char *method, int length) {
hessian_ensureCapacity(out, out->offset + 1);
hessian_write(out, 'C');
hessian_writeString(out, method);
hessian_writeInt(out, length);
return 0;
}
int hessian_completeCall(hessian_out_pt out) {
return 0;
}
int hessian_printString(hessian_out_pt out, char *value) {
return hessian_printNString(out, value, 0, strlen(value));
}
int hessian_printNString(hessian_out_pt out, char *value, int offset, int length) {
hessian_ensureCapacity(out, out->offset + length);
for (int i = 0; i < length; i++) {
int ch = value[i + offset];
if (ch < 0x80) {
hessian_write(out, (int)(ch));
out->length++;
} else if (ch < 0x800) {
hessian_write(out, (int)(0xc0 + ((ch >> 6) & 0x1f)));
out->length++;
hessian_write(out, (int)(0x80 + (ch & 0x3f)));
out->length++;
} else {
hessian_write(out, (int)(0xe0 + ((ch >> 12) & 0xf)));
out->length++;
hessian_write(out, (int)(0x80 + ((ch >> 6) & 0x3f)));
out->length++;
hessian_write(out, (int)(0x80 + (ch & 0x3f)));
out->length++;
}
}
return 0;
}
void hessian_ensureCapacity(hessian_out_pt obj, int capacity) {
char *newArray;
int oldCapacity;
oldCapacity = obj->capacity;
if (capacity > oldCapacity) {
int newCapacity = (oldCapacity * 3) / 2 + 1;
if (newCapacity < capacity) {
newCapacity = capacity;
}
newArray = (char *) realloc(obj->buffer, sizeof(char *) * newCapacity);
obj->capacity = newCapacity;
obj->buffer = newArray;
}
}
int hessian_write(hessian_out_pt out, unsigned char byte) {
out->buffer[out->offset++] = byte;
out->length++;
return 0;
}
int hessian_writeP(hessian_out_pt out, unsigned char *byte) {
out->buffer[out->offset++] = *byte;
out->length++;
return 0;
}