summaryrefslogtreecommitdiff
path: root/lib/IO/Write.cpp
blob: 5d1b11e7d93bec1396cf2f06252b80f415068e6c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include <stdio.h>
#include <string.h>
#include "IO/Write.h"

#ifdef _MSC_VER
#define snprintf _snprintf
#endif

static void InvalidSizeError(WriteController *Controller, int32_t Size) {
  // FIXME
}

template<typename T>
static T getValue(const void *Ptr) {
  return *(reinterpret_cast<const T*>(Ptr));
}

template<typename T>
static T getValue(const void *Ptr,size_t I) {
  return (reinterpret_cast<const T*>(Ptr))[I];
}

static int getIntValue(WriteController *Controller, const void *Ptr, int32_t Size) {
  switch(Size) {
  case 1:
    return getValue<int8_t>(Ptr);
  case 2:
    return getValue<int16_t>(Ptr);
  case 4:
    return getValue<int32_t>(Ptr);
  case 8:
    return int(getValue<int64_t>(Ptr));
  default:
    InvalidSizeError(Controller, Size);
    break;
  }
  return 0;
}

static FILE *getFilePtr(WriteController *Controller) {
  return stdin;
}

class Buffer {
  enum {
    kStorageSize = 128
  };
  size_t Offset;
  char Storage[kStorageSize];

public:
  Buffer() : Offset(0) {}

  template <typename T>
  void Print(const char *FMT, T Value) {
    auto Remaining = size_t(kStorageSize)-Offset;
    if(Remaining)
      Offset += snprintf(Storage + Offset, Remaining, FMT, Value);
  }

  void Write(WriteController *Controller) {
    fwrite(Storage, 1, Offset, getFilePtr(Controller));
  }
};

template <typename T>
static inline void SmallPrintf(WriteController *Controller, const char *FMT, T Value) {
  Buffer Buf;
  Buf.Print(FMT, Value);
  Buf.Write(Controller);
}

template <typename T1, typename T2>
static inline void SmallPrintf(WriteController *Controller, const char *FMT1, T1 Value1, const char *FMT2, T2 Value2) {
  Buffer Buf;
  Buf.Print(FMT1, Value1);
  Buf.Print(FMT2, Value2);
  Buf.Write(Controller);
}

LIBFLANG_ABI void libflang_write_start(WriteController *Controller) {

}

LIBFLANG_ABI void libflang_write_integer(WriteController *Controller, const void *Ptr, int32_t Size) {
  SmallPrintf(Controller, "%i", getIntValue(Controller, Ptr, Size));
}

LIBFLANG_ABI void libflang_write_real(WriteController *Controller, const void *Ptr, int32_t Size) {
  switch(Size) {
  case 4:
    SmallPrintf(Controller, "%g", getValue<float>(Ptr));
    break;
  case 8:
    SmallPrintf(Controller, "%g", getValue<double>(Ptr));
    break;
  default:
    InvalidSizeError(Controller, Size);
    break;
  }
}

LIBFLANG_ABI void libflang_write_complex(WriteController *Controller, const void *Ptr, int32_t Size) {
  switch(Size) {
  case 4:
    SmallPrintf(Controller, "(%g, ", getValue<float>(Ptr), "%g)", getValue<float>(Ptr,1));
    break;
  case 8:
    SmallPrintf(Controller, "(%g, ", getValue<double>(Ptr), "%g)", getValue<double>(Ptr,1));
    break;
  default:
    InvalidSizeError(Controller, Size);
    break;
  }
}

LIBFLANG_ABI void libflang_write_logical(WriteController *Controller, const void *Ptr, int32_t Size) {
  SmallPrintf(Controller, "%s", getIntValue(Controller, Ptr, Size) != 0? "true" : "false");
}

LIBFLANG_ABI void libflang_write_character(WriteController *Controller, const char *Ptr, size_t Length) {
  fwrite(Ptr, 1, Length, getFilePtr(Controller));
}

LIBFLANG_ABI void libflang_write_end(WriteController *Controller) {
  fwrite("\n", 1, 1, getFilePtr(Controller));
}