Skip to content

Commit 76bee27

Browse files
authored
PDF typed strings (#347)
1 parent 21dc909 commit 76bee27

15 files changed

Lines changed: 192 additions & 72 deletions

src/odr/document_element.hpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ class Element;
1313
class TextRoot;
1414
class Slide;
1515
class Sheet;
16-
class SheetColumn;
17-
class SheetRow;
1816
class SheetCell;
1917
class Page;
2018
class MasterPage;

src/odr/internal/html/text_file.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ Html html::translate_text_file(const TextFile &text_file,
5656
out.write_element_begin("td");
5757

5858
std::ostringstream ss_out;
59-
util::stream::pipe_line(*in, ss_out);
59+
util::stream::pipe_line(*in, ss_out, false);
6060
out.out() << escape_text(ss_out.str());
6161

6262
out.write_element_end("td");

src/odr/internal/pdf/pdf_document_parser.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ const FileParser &DocumentParser::parser() const { return m_parser; }
154154
const Xref &DocumentParser::xref() const { return m_xref; }
155155

156156
IndirectObject DocumentParser::read_object(const ObjectReference &reference) {
157-
std::uint32_t position = m_xref.table[reference.first].position;
157+
std::uint32_t position = m_xref.table[reference.id].position;
158158
in().seekg(position);
159159
return parser().read_indirect_object();
160160
}

src/odr/internal/pdf/pdf_file_parser.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ const ObjectParser &FileParser::parser() const { return m_parser; }
2020
IndirectObject FileParser::read_indirect_object() const {
2121
IndirectObject result;
2222

23-
result.reference.first = m_parser.read_unsigned_integer();
23+
result.reference.id = m_parser.read_unsigned_integer();
2424
m_parser.skip_whitespace();
25-
result.reference.second = m_parser.read_unsigned_integer();
25+
result.reference.gen = m_parser.read_unsigned_integer();
2626
m_parser.skip_whitespace();
2727
if (std::string line = m_parser.read_line(); line != "obj") {
2828
throw std::runtime_error("expected obj");

src/odr/internal/pdf/pdf_graphics_operator.cpp

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,29 @@
66

77
namespace odr::internal::pdf {
88

9+
const std::string &SimpleArrayElement::as_string() const {
10+
if (is_standard_string()) {
11+
return as_standard_string();
12+
}
13+
if (is_hex_string()) {
14+
return as_hex_string();
15+
}
16+
return as_name();
17+
}
18+
919
void SimpleArrayElement::to_stream(std::ostream &out) const {
1020
if (is_integer()) {
1121
out << as_integer();
1222
} else if (is_real()) {
1323
out << std::setprecision(4) << as_real();
14-
} else if (is_string()) {
15-
// TODO restore original format
16-
out << as_string();
24+
} else if (is_standard_string()) {
25+
// TODO escape
26+
out << "(" << as_standard_string() << ")";
27+
} else if (is_hex_string()) {
28+
// TODO hex
29+
out << "<" << as_hex_string() << ">";
30+
} else if (is_name()) {
31+
out << "/" << as_name();
1732
} else {
1833
throw std::runtime_error("unhandled type");
1934
}
@@ -42,14 +57,29 @@ std::string SimpleArray::to_string() const {
4257
return ss.str();
4358
}
4459

60+
const std::string &GraphicsArgument::as_string() const {
61+
if (is_standard_string()) {
62+
return as_standard_string();
63+
}
64+
if (is_hex_string()) {
65+
return as_hex_string();
66+
}
67+
return as_name();
68+
}
69+
4570
void GraphicsArgument::to_stream(std::ostream &out) const {
4671
if (is_integer()) {
4772
out << as_integer();
4873
} else if (is_real()) {
4974
out << std::setprecision(4) << as_real();
50-
} else if (is_string()) {
51-
// TODO restore original format
52-
out << as_string();
75+
} else if (is_standard_string()) {
76+
// TODO escape
77+
out << "(" << as_standard_string() << ")";
78+
} else if (is_hex_string()) {
79+
// TODO hex
80+
out << "<" << as_hex_string() << ">";
81+
} else if (is_name()) {
82+
out << "/" << as_name();
5383
} else if (is_array()) {
5484
as_array().to_stream(out);
5585
} else {

src/odr/internal/pdf/pdf_graphics_operator.hpp

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,34 @@ namespace odr::internal::pdf {
1212

1313
class SimpleArrayElement {
1414
public:
15-
using Holder = std::variant<Integer, Real, std::string>;
15+
using Holder = std::variant<Integer, Real, StandardString, HexString, Name>;
1616

1717
SimpleArrayElement(Integer integer) : m_holder{integer} {}
1818
SimpleArrayElement(Real real) : m_holder{real} {}
19-
SimpleArrayElement(std::string string) : m_holder{std::move(string)} {}
19+
SimpleArrayElement(StandardString string) : m_holder{std::move(string)} {}
20+
SimpleArrayElement(HexString string) : m_holder{std::move(string)} {}
21+
SimpleArrayElement(Name name) : m_holder{std::move(name)} {}
2022

2123
Holder &holder() { return m_holder; }
2224
const Holder &holder() const { return m_holder; }
2325

2426
bool is_integer() const { return is<Integer>(); }
2527
bool is_real() const { return is<Real>() || is_integer(); }
26-
bool is_string() const { return is<std::string>(); }
28+
bool is_standard_string() const { return is<StandardString>(); }
29+
bool is_hex_string() const { return is<HexString>(); }
30+
bool is_name() const { return is<Name>(); }
31+
bool is_string() const {
32+
return is_standard_string() || is_hex_string() || is_name();
33+
}
2734

2835
Integer as_integer() const { return as<Integer>(); }
2936
Real as_real() const { return is<Real>() ? as<Real>() : as_integer(); }
30-
const std::string &as_string() const { return as<std::string>(); }
37+
const std::string &as_standard_string() const {
38+
return as<StandardString>().string;
39+
}
40+
const std::string &as_hex_string() const { return as<HexString>().string; }
41+
const std::string &as_name() const { return as<Name>().string; }
42+
const std::string &as_string() const;
3143

3244
void to_stream(std::ostream &) const;
3345
std::string to_string() const;
@@ -70,24 +82,37 @@ class SimpleArray {
7082

7183
class GraphicsArgument {
7284
public:
73-
using Holder = std::variant<Integer, Real, std::string, SimpleArray>;
85+
using Holder =
86+
std::variant<Integer, Real, StandardString, HexString, Name, SimpleArray>;
7487

7588
GraphicsArgument(Integer integer) : m_holder{integer} {}
7689
GraphicsArgument(Real real) : m_holder{real} {}
77-
GraphicsArgument(std::string string) : m_holder{std::move(string)} {}
90+
GraphicsArgument(StandardString string) : m_holder{std::move(string)} {}
91+
GraphicsArgument(HexString string) : m_holder{std::move(string)} {}
92+
GraphicsArgument(Name name) : m_holder{std::move(name)} {}
7893
GraphicsArgument(SimpleArray array) : m_holder(std::move(array)) {}
7994

8095
Holder &holder() { return m_holder; }
8196
const Holder &holder() const { return m_holder; }
8297

8398
bool is_integer() const { return is<Integer>(); }
8499
bool is_real() const { return is<Real>() || is_integer(); }
85-
bool is_string() const { return is<std::string>(); }
100+
bool is_standard_string() const { return is<StandardString>(); }
101+
bool is_hex_string() const { return is<HexString>(); }
102+
bool is_name() const { return is<Name>(); }
103+
bool is_string() const {
104+
return is_standard_string() || is_hex_string() || is_name();
105+
}
86106
bool is_array() const { return is<SimpleArray>(); }
87107

88108
Integer as_integer() const { return as<Integer>(); }
89109
Real as_real() const { return is<Real>() ? as<Real>() : as_integer(); }
90-
const std::string &as_string() const { return as<std::string>(); }
110+
const std::string &as_standard_string() const {
111+
return as<StandardString>().string;
112+
}
113+
const std::string &as_hex_string() const { return as<HexString>().string; }
114+
const std::string &as_name() const { return as<Name>().string; }
115+
const std::string &as_string() const;
91116
const SimpleArray &as_array() const { return as<SimpleArray>(); }
92117

93118
void to_stream(std::ostream &) const;

src/odr/internal/pdf/pdf_graphics_operator_parser.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,8 @@ SimpleArrayElement GraphicsOperatorParser::read_array_element() const {
147147
return m_parser.read_name();
148148
}
149149
if (m_parser.peek_string()) {
150-
return m_parser.read_string();
150+
return std::visit([](auto s) { return SimpleArrayElement(std::move(s)); },
151+
m_parser.read_string());
151152
}
152153

153154
throw std::runtime_error("unknown element");
@@ -183,7 +184,8 @@ GraphicsOperator GraphicsOperatorParser::read_operator() const {
183184
} else if (m_parser.peek_name()) {
184185
result.arguments.push_back(m_parser.read_name());
185186
} else if (m_parser.peek_string()) {
186-
result.arguments.push_back(m_parser.read_string());
187+
std::visit([&](auto s) { result.arguments.push_back(std::move(s)); },
188+
m_parser.read_string());
187189
} else if (m_parser.peek_array()) {
188190
result.arguments.push_back(read_array());
189191
} else {

src/odr/internal/pdf/pdf_object.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ Object::Object(Array array) : m_holder{std::move(array)} {}
1111

1212
Object::Object(Dictionary dictionary) : m_holder{std::move(dictionary)} {}
1313

14+
const std::string &Object::as_string() const {
15+
if (is_standard_string()) {
16+
return as_standard_string();
17+
}
18+
if (is_hex_string()) {
19+
return as_hex_string();
20+
}
21+
return as_name();
22+
}
23+
1424
void Object::to_stream(std::ostream &out) const {
1525
if (is_null()) {
1626
out << "null";
@@ -24,15 +34,20 @@ void Object::to_stream(std::ostream &out) const {
2434
out << as_integer();
2535
} else if (is_real()) {
2636
out << std::setprecision(4) << as_real();
27-
} else if (is_string()) {
28-
// TODO restore original format
29-
out << as_string();
37+
} else if (is_standard_string()) {
38+
// TODO escape
39+
out << "(" << as_standard_string() << ")";
40+
} else if (is_hex_string()) {
41+
// TODO hex
42+
out << "<" << as_hex_string() << ">";
43+
} else if (is_name()) {
44+
out << "/" << as_name();
3045
} else if (is_array()) {
3146
as_array().to_stream(out);
3247
} else if (is_dictionary()) {
3348
as_dictionary().to_stream(out);
3449
} else if (is_reference()) {
35-
out << as_reference().first << " " << as_reference().second << " R";
50+
out << as_reference().id << " " << as_reference().gen << " R";
3651
} else {
3752
throw std::runtime_error("unhandled type");
3853
}

src/odr/internal/pdf/pdf_object.hpp

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,33 @@ namespace odr::internal::pdf {
1414
using UnsignedInteger = std::uint64_t;
1515
using Integer = std::int64_t;
1616
using Real = double;
17-
using IntegerOrReal = std::variant<Integer, Real>;
18-
using String = std::string;
19-
using Name = std::string;
2017
using Boolean = bool;
21-
using ObjectReference = std::pair<UnsignedInteger, UnsignedInteger>;
18+
19+
struct StandardString {
20+
std::string string;
21+
22+
StandardString(std::string _string) : string{std::move(_string)} {}
23+
};
24+
25+
struct HexString {
26+
std::string string;
27+
28+
HexString(std::string _string) : string{std::move(_string)} {}
29+
};
30+
31+
struct Name {
32+
std::string string;
33+
34+
Name(std::string _string) : string{std::move(_string)} {}
35+
};
36+
37+
struct ObjectReference {
38+
std::uint64_t id{};
39+
std::uint64_t gen{};
40+
41+
ObjectReference() = default;
42+
ObjectReference(std::uint64_t _id, std::uint64_t _gen) : id{_id}, gen{_gen} {}
43+
};
2244

2345
class Array;
2446
class Dictionary;
@@ -31,7 +53,9 @@ class Object {
3153
Object(Boolean boolean) : m_holder{boolean} {}
3254
Object(Integer integer) : m_holder{integer} {}
3355
Object(Real real) : m_holder{real} {}
34-
Object(std::string string) : m_holder{std::move(string)} {}
56+
Object(StandardString string) : m_holder{std::move(string)} {}
57+
Object(HexString string) : m_holder{std::move(string)} {}
58+
Object(Name name) : m_holder{std::move(name)} {}
3559
Object(Array);
3660
Object(Dictionary);
3761
Object(ObjectReference reference) : m_holder{std::move(reference)} {}
@@ -43,15 +67,27 @@ class Object {
4367
bool is_bool() const { return is<Boolean>(); }
4468
bool is_integer() const { return is<Integer>(); }
4569
bool is_real() const { return is<Real>() || is_integer(); }
46-
bool is_string() const { return is<std::string>(); }
70+
bool is_standard_string() const { return is<StandardString>(); }
71+
bool is_hex_string() const { return is<HexString>(); }
72+
bool is_name() const { return is<Name>(); }
73+
bool is_string() const {
74+
return is_standard_string() || is_hex_string() || is_name();
75+
}
4776
bool is_array() const { return is<Array>(); }
4877
bool is_dictionary() const { return is<Dictionary>(); }
4978
bool is_reference() const { return is<ObjectReference>(); }
5079

5180
Boolean as_bool() const { return as<Boolean>(); }
5281
Integer as_integer() const { return as<Integer>(); }
5382
Real as_real() const { return is<Real>() ? as<Real>() : as_integer(); }
54-
const std::string &as_string() const { return as<const std::string &>(); }
83+
const std::string &as_standard_string() const {
84+
return as<const StandardString &>().string;
85+
}
86+
const std::string &as_hex_string() const {
87+
return as<const HexString &>().string;
88+
}
89+
const std::string &as_name() const { return as<const Name &>().string; }
90+
const std::string &as_string() const;
5591
const Array &as_array() const { return as<const Array &>(); }
5692
const Dictionary &as_dictionary() const { return as<const Dictionary &>(); }
5793
const ObjectReference &as_reference() const {
@@ -100,7 +136,7 @@ class Array {
100136

101137
class Dictionary {
102138
public:
103-
using Holder = std::map<Name, Object>;
139+
using Holder = std::map<std::string, Object>;
104140

105141
Dictionary() = default;
106142
explicit Dictionary(Holder holder) : m_holder{std::move(holder)} {}
@@ -112,9 +148,11 @@ class Dictionary {
112148
Holder::const_iterator begin() const { return std::begin(m_holder); }
113149
Holder::const_iterator end() const { return std::end(m_holder); }
114150

115-
const Object &operator[](const Name &name) const { return m_holder.at(name); }
151+
const Object &operator[](const std::string &name) const {
152+
return m_holder.at(name);
153+
}
116154

117-
bool has_key(const Name &name) const {
155+
bool has_key(const std::string &name) const {
118156
return m_holder.find(name) != std::end(m_holder);
119157
}
120158

0 commit comments

Comments
 (0)