1/* Marshalling and unmarshalling.
2   Copyright (C) 2014 Free Software Foundation, Inc.
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8Software Foundation; either version 3, or (at your option) any later
9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14for more details.
15
16You should have received a copy of the GNU General Public License
17along with GCC; see the file COPYING3.  If not see
18<http://www.gnu.org/licenses/>.  */
19
20#include <cc1plugin-config.h>
21#include <new>
22#include <string.h>
23#include "marshall.hh"
24#include "connection.hh"
25
26cc1_plugin::status
27cc1_plugin::unmarshall_check (connection *conn, unsigned long long check)
28{
29  unsigned long long r;
30
31  if (!unmarshall (conn, &r))
32    return FAIL;
33  return check == r ? OK : FAIL;
34}
35
36cc1_plugin::status
37cc1_plugin::marshall_intlike (connection *conn, unsigned long long val)
38{
39  if (!conn->send ('i'))
40    return FAIL;
41  return conn->send (&val, sizeof (val));
42}
43
44cc1_plugin::status
45cc1_plugin::unmarshall_intlike (connection *conn, unsigned long long *result)
46{
47  if (!conn->require ('i'))
48    return FAIL;
49  return conn->get (result, sizeof (*result));
50}
51
52cc1_plugin::status
53cc1_plugin::unmarshall (connection *conn, enum gcc_c_symbol_kind *result)
54{
55  protocol_int p;
56  if (!unmarshall_intlike (conn, &p))
57    return FAIL;
58  *result = (enum gcc_c_symbol_kind) p;
59  return OK;
60}
61
62cc1_plugin::status
63cc1_plugin::unmarshall (connection *conn, enum gcc_c_oracle_request *result)
64{
65  protocol_int p;
66  if (!unmarshall_intlike (conn, &p))
67    return FAIL;
68  *result = (enum gcc_c_oracle_request) p;
69  return OK;
70}
71
72cc1_plugin::status
73cc1_plugin::unmarshall (connection *conn, enum gcc_qualifiers *result)
74{
75  protocol_int p;
76  if (!unmarshall_intlike (conn, &p))
77    return FAIL;
78  *result = (enum gcc_qualifiers) p;
79  return OK;
80}
81
82cc1_plugin::status
83cc1_plugin::marshall (connection *conn, const char *str)
84{
85  if (!conn->send ('s'))
86    return FAIL;
87
88  unsigned long long len = str == NULL ? -1ULL : strlen (str);
89  if (!conn->send (&len, sizeof (len)))
90    return FAIL;
91
92  if (str == NULL)
93    return OK;
94
95  return conn->send (str, len);
96}
97
98cc1_plugin::status
99cc1_plugin::unmarshall (connection *conn, char **result)
100{
101  unsigned long long len;
102
103  if (!conn->require ('s'))
104    return FAIL;
105  if (!conn->get (&len, sizeof (len)))
106    return FAIL;
107
108  if (len == -1ULL)
109    {
110      *result = NULL;
111      return OK;
112    }
113
114  char *str = new (std::nothrow) char[len + 1];
115  if (str == NULL)
116    return FAIL;
117
118  if (!conn->get (str, len))
119    {
120      delete[] str;
121      return FAIL;
122    }
123
124  str[len] = '\0';
125  *result = str;
126
127  return OK;
128}
129
130cc1_plugin::status
131cc1_plugin::marshall (connection *conn, const gcc_type_array *a)
132{
133  if (!conn->send ('a'))
134    return FAIL;
135
136  unsigned long long r = a->n_elements;
137  if (!conn->send (&r, sizeof (r)))
138    return FAIL;
139
140  return conn->send (a->elements, r * sizeof (a->elements[0]));
141}
142
143cc1_plugin::status
144cc1_plugin::unmarshall (connection *conn, gcc_type_array **result)
145{
146  unsigned long long len;
147
148  if (!conn->require ('a'))
149    return FAIL;
150  if (!conn->get (&len, sizeof (len)))
151    return FAIL;
152
153  *result = new gcc_type_array;
154
155  (*result)->n_elements = len;
156  (*result)->elements = new gcc_type[len];
157
158  if (!conn->get ((*result)->elements, len * sizeof ((*result)->elements[0])))
159    {
160      delete[] (*result)->elements;
161      delete *result;
162      return FAIL;
163    }
164
165  return OK;
166}
167