summaryrefslogtreecommitdiff
path: root/src/lib/libetonyek_xml.cpp
blob: b85cfdbef211d5b870b9f14c7dd55f4f6994bb03 (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
128
129
130
131
132
133
134
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
 * This file is part of the libetonyek project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "libetonyek_xml.h"

#include <cassert>

#include <boost/lexical_cast.hpp>
#include <boost/none.hpp>
#include <boost/optional.hpp>

#include "libetonyek_utils.h"
#include "IWORKToken.h"
#include "IWORKTokenizer.h"

using boost::bad_lexical_cast;
using boost::lexical_cast;
using boost::none;
using boost::optional;

using std::string;

extern "C" int readFromStream(void *context, char *buffer, int len)
{
  try
  {
    auto *const input = reinterpret_cast<librevenge::RVNGInputStream *>(context);

    unsigned long bytesRead = 0;
    const unsigned char *const bytes = input->read((unsigned long)len, bytesRead);

    std::memcpy(buffer, bytes, static_cast<size_t>(bytesRead));
    return static_cast<int>(bytesRead);
  }
  catch (...)
  {
  }

  return -1;
}

extern "C" int closeStream(void * /* context */)
{
  return 0;
}

namespace libetonyek
{

std::unique_ptr<xmlTextReader, void (*)(xmlTextReaderPtr)> xmlReaderForStream(const RVNGInputStreamPtr_t &input)
{
  return std::unique_ptr<xmlTextReader, void (*)(xmlTextReaderPtr)>(
           xmlReaderForIO(readFromStream, closeStream, input.get(), "", nullptr, XML_PARSE_NONET),
           xmlFreeTextReader
         );
}

bool bool_cast(const char *value)
{
  return get(try_bool_cast(value));
}

boost::optional<bool> try_bool_cast(const char *value)
{
  const IWORKTokenizer &tok(IWORKToken::getTokenizer());
  switch (tok.getId(value))
  {
  case IWORKToken::_1 :
  case IWORKToken::true_ :
    return true;
  case IWORKToken::_0 :
  case IWORKToken::false_ :
    return false;
  default:
    break;
  }

  return none;
}

double double_cast(const char *value)
{
  return lexical_cast<double, const char *>(value);
}

boost::optional<double> try_double_cast(const char *value) try
{
  return double_cast(value);
}
catch (const bad_lexical_cast &)
{
  ETONYEK_DEBUG_MSG(("'%s' is not a valid double\n", value));
  return none;
}

int int_cast(const char *value)
{
  return lexical_cast<int, const char *>(value);
}

boost::optional<int> try_int_cast(const char *value) try
{
  return int_cast(value);
}
catch (const bad_lexical_cast &)
{
  ETONYEK_DEBUG_MSG(("'%s' is not a valid integer\n", value));
  return none;
}

const char *char_cast(const char *const c)
{
  return c;
}

const char *char_cast(const signed char *const c)
{
  return reinterpret_cast<const char *>(c);
}

const char *char_cast(const unsigned char *const c)
{
  return reinterpret_cast<const char *>(c);
}

}

/* vim:set shiftwidth=2 softtabstop=2 expandtab: */