about summary refs log tree commit diff homepage
path: root/lib/Basic/KTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Basic/KTest.cpp')
-rw-r--r--lib/Basic/KTest.cpp236
1 files changed, 236 insertions, 0 deletions
diff --git a/lib/Basic/KTest.cpp b/lib/Basic/KTest.cpp
new file mode 100644
index 00000000..d17916f5
--- /dev/null
+++ b/lib/Basic/KTest.cpp
@@ -0,0 +1,236 @@
+//===-- KTest.cpp ---------------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "klee/Internal/ADT/KTest.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#define KTEST_MAGIC "BOUT\n"
+#define KTEST_MAGIC_SIZE 5
+#define KTEST_VERSION 2
+
+/***/
+
+static int read_uint32(FILE *f, unsigned *value_out) {
+  unsigned char data[4];
+  if (fread(data, 4, 1, f)!=1)
+    return 0;
+  *value_out = (((((data[0]<<8) + data[1])<<8) + data[2])<<8) + data[3];
+  return 1;
+}
+
+static int write_uint32(FILE *f, unsigned value) {
+  unsigned char data[4];
+  data[0] = value>>24;
+  data[1] = value>>16;
+  data[2] = value>> 8;
+  data[3] = value>> 0;
+  return fwrite(data, 1, 4, f)==4;
+}
+
+static int read_string(FILE *f, char **value_out) {
+  unsigned len;
+  if (!read_uint32(f, &len))
+    return 0;
+  *value_out = (char*) malloc(len+1);
+  if (!*value_out)
+    return 0;
+  if (fread(*value_out, len, 1, f)!=1)
+    return 0;
+  (*value_out)[len] = 0;
+  return 1;
+}
+
+static int write_string(FILE *f, const char *value) {
+  unsigned len = strlen(value);
+  if (!write_uint32(f, len))
+    return 0;
+  if (fwrite(value, len, 1, f)!=1)
+    return 0;
+  return 1;
+}
+
+/***/
+
+
+unsigned kTest_getCurrentVersion() {
+  return KTEST_VERSION;
+}
+
+
+static int kTest_checkHeader(FILE *f) {
+  char header[KTEST_MAGIC_SIZE];
+  if (fread(header, KTEST_MAGIC_SIZE, 1, f)!=1)
+    return 0;
+  if (memcmp(header, KTEST_MAGIC, KTEST_MAGIC_SIZE))
+    return 0;
+  return 1;
+}
+
+int kTest_isKTestFile(const char *path) {
+  FILE *f = fopen(path, "rb");
+  int res;
+
+  if (!f)
+    return 0;
+  res = kTest_checkHeader(f);
+  fclose(f);
+  
+  return res;
+}
+
+KTest *kTest_fromFile(const char *path) {
+  FILE *f = fopen(path, "rb");
+  KTest *res = 0;
+  unsigned i, version;
+
+  if (!f) 
+    goto error;
+  if (!kTest_checkHeader(f)) 
+    goto error;
+
+  res = (KTest*) calloc(1, sizeof(*res));
+  if (!res) 
+    goto error;
+
+  if (!read_uint32(f, &version)) 
+    goto error;
+  
+  if (version > kTest_getCurrentVersion())
+    goto error;
+
+  res->version = version;
+
+  if (!read_uint32(f, &res->numArgs)) 
+    goto error;
+  res->args = (char**) calloc(res->numArgs, sizeof(*res->args));
+  if (!res->args) 
+    goto error;
+  
+  for (i=0; i<res->numArgs; i++)
+    if (!read_string(f, &res->args[i]))
+      goto error;
+
+  if (version >= 2) {
+    if (!read_uint32(f, &res->symArgvs)) 
+      goto error;
+    if (!read_uint32(f, &res->symArgvLen)) 
+      goto error;
+  }
+
+  if (!read_uint32(f, &res->numObjects))
+    goto error;
+  res->objects = (KTestObject*) calloc(res->numObjects, sizeof(*res->objects));
+  if (!res->objects)
+    goto error;
+  for (i=0; i<res->numObjects; i++) {
+    KTestObject *o = &res->objects[i];
+    if (!read_string(f, &o->name))
+      goto error;
+    if (!read_uint32(f, &o->numBytes))
+      goto error;
+    o->bytes = (unsigned char*) malloc(o->numBytes);
+    if (fread(o->bytes, o->numBytes, 1, f)!=1)
+      goto error;
+  }
+
+  fclose(f);
+
+  return res;
+ error:
+  if (res) {
+    if (res->args) {
+      for (i=0; i<res->numArgs; i++)
+        if (res->args[i])
+          free(res->args[i]);
+      free(res->args);
+    }
+    if (res->objects) {
+      for (i=0; i<res->numObjects; i++) {
+        KTestObject *bo = &res->objects[i];
+        if (bo->name)
+          free(bo->name);
+        if (bo->bytes)
+          free(bo->bytes);
+      }
+      free(res->objects);
+    }
+    free(res);
+  }
+
+  if (f) fclose(f);
+
+  return 0;
+}
+
+int kTest_toFile(KTest *bo, const char *path) {
+  FILE *f = fopen(path, "wb");
+  unsigned i;
+
+  if (!f) 
+    goto error;
+  if (fwrite(KTEST_MAGIC, strlen(KTEST_MAGIC), 1, f)!=1)
+    goto error;
+  if (!write_uint32(f, KTEST_VERSION))
+    goto error;
+      
+  if (!write_uint32(f, bo->numArgs))
+    goto error;
+  for (i=0; i<bo->numArgs; i++) {
+    if (!write_string(f, bo->args[i]))
+      goto error;
+  }
+
+  if (!write_uint32(f, bo->symArgvs))
+    goto error;
+  if (!write_uint32(f, bo->symArgvLen))
+    goto error;
+  
+  if (!write_uint32(f, bo->numObjects))
+    goto error;
+  for (i=0; i<bo->numObjects; i++) {
+    KTestObject *o = &bo->objects[i];
+    if (!write_string(f, o->name))
+      goto error;
+    if (!write_uint32(f, o->numBytes))
+      goto error;
+    if (fwrite(o->bytes, o->numBytes, 1, f)!=1)
+      goto error;
+  }
+
+  fclose(f);
+
+  return 1;
+ error:
+  if (f) fclose(f);
+  
+  return 0;
+}
+
+unsigned kTest_numBytes(KTest *bo) {
+  unsigned i, res = 0;
+  for (i=0; i<bo->numObjects; i++)
+    res += bo->objects[i].numBytes;
+  return res;
+}
+
+void kTest_free(KTest *bo) {
+  unsigned i;
+  for (i=0; i<bo->numArgs; i++)
+    free(bo->args[i]);
+  free(bo->args);
+  for (i=0; i<bo->numObjects; i++) {
+    free(bo->objects[i].name);
+    free(bo->objects[i].bytes);
+  }
+  free(bo->objects);
+  free(bo);
+}