Skip to content

Instantly share code, notes, and snippets.

@chao-he
Created February 25, 2014 16:27
Show Gist options
  • Save chao-he/9212346 to your computer and use it in GitHub Desktop.
Save chao-he/9212346 to your computer and use it in GitHub Desktop.
php unserialize to json, implement in c
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
struct stream {
char *beg;
char *end;
char *cur;
char *save;
char *fill;
};
static void _unserialize(struct stream *s);
static void _read_until(struct stream *s, char c)
{
s->save = s->cur;
while(s->cur != s->end && *(s->cur) != c) ++ s->cur;
}
static void _read_length(struct stream *s, size_t n)
{
s->save = s->cur;
s->cur += n;
}
static int _expect(struct stream *s, char c)
{
s->cur ++;
return c == *(s->cur - 1);
}
static void _dump(struct stream *s, const char *p, int l)
{
sprintf(s->fill, "%.*s", l, p);
s->fill += strlen(s->fill);
}
static int64_t _int(const char *s, size_t l)
{
char buf[50] = {0};
int64_t num = -1;
if(l < sizeof(buf) / sizeof(buf[0]))
{
memcpy(buf, s, l);
num = strtol(buf, NULL, 10);
}
return num;
}
static void _array(struct stream *s)
{
int size = 0;
int i = 0;
_read_until(s, ':');
size = _int(s->save, s->cur - s->save) * 2;
_expect(s, ':');
_expect(s, '{');
_dump(s, "{", 1);
for(i = 0; i < size; ++ i)
{
_unserialize(s);
if(i % 2 == 0)
{
_dump(s, ":", 1);
} else if(i != size - 1) {
_dump(s, ",", 1);
}
}
_dump(s, "}", 1);
_expect(s, '}');
}
static void _unserialize(struct stream *s)
{
char c = tolower(*(s->cur));
int64_t len = 0;
s->cur ++;
switch(c) {
case 'n':
_expect(s, ';');
_dump(s, "\"\"", 2);
break;
case 'i':
case 'd':
case 'b':
_expect(s, ':');
_read_until(s, ';');
_dump(s, s->save, s->cur - s->save);
_expect(s, ';');
break;
case 's':
_expect(s, ':');
_read_until(s, ':');
len = _int(s->save, s->cur - s->save);
_expect(s, ':');
_expect(s, '"');
_read_length(s, len);
_dump(s, "\"", 1);
_dump(s, s->save, s->cur - s->save);
_dump(s, "\"", 1);
_expect(s, '"');
_expect(s, ';');
break;
case 'a':
_expect(s, ':');
_array(s);
break;
case 'o':
_expect(s, ':');
_read_until(s, ':');
len = _int(s->save, s->cur - s->save);
_expect(s, ':');
_expect(s, '"');
_read_length(s, len);
_expect(s, '"');
_expect(s, ':');
_array(s);
break;
}
}
void unserialize(char *data, size_t size, char *buffer)
{
struct stream s = {
.beg = data,
.end = data + size,
.cur = data,
.save = NULL,
.fill = buffer
};
_unserialize(&s);
*s.fill = '\0';
}
// i:10;d:10.1;b:0;s:5:"hello";n;a:1:{i:0;s:"3":"aaa";}o:3:"key":1:{s"a"}
//
int main(int argc, char **argv)
{
char *buffer = malloc(10000);
memset(buffer, 0, 10000);
unserialize(argv[1], strlen(argv[1]), buffer);
printf("=>%s\n", buffer);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment