Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
L
libcifpp
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
open
libcifpp
Commits
e0777e74
Unverified
Commit
e0777e74
authored
Apr 08, 2021
by
Maarten L. Hekkelman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
minor updates
parent
cf465134
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
631 additions
and
555 deletions
+631
-555
include/cif++/Cif++.hpp
+19
-7
include/cif++/Point.hpp
+10
-0
src/Cif++.cpp
+50
-1
src/CifUtils.cpp
+552
-547
No files found.
include/cif++/Cif++.hpp
View file @
e0777e74
...
...
@@ -686,7 +686,7 @@ class Row
}
template
<
typename
...
Ts
,
size_t
N
>
std
::
tuple
<
Ts
...
>
get
(
char
const
*
const
(
&
columns
)[
N
])
std
::
tuple
<
Ts
...
>
get
(
char
const
*
const
(
&
columns
)[
N
])
const
{
static_assert
(
sizeof
...(
Ts
)
==
N
,
"Number of columns should be equal to number of types to return"
);
...
...
@@ -1087,7 +1087,7 @@ template<typename T>
Condition
operator
==
(
const
Key
&
key
,
const
T
&
v
)
{
std
::
ostringstream
s
;
s
<<
"== "
<<
v
;
s
<<
"
== "
<<
v
;
return
Condition
(
new
detail
::
KeyCompareConditionImpl
(
key
.
mItemTag
,
[
tag
=
key
.
mItemTag
,
v
](
const
Category
&
c
,
const
Row
&
r
,
bool
icase
)
{
return
r
[
tag
].
template
compare
<
T
>
(
v
,
icase
)
==
0
;
},
s
.
str
()));
...
...
@@ -1123,7 +1123,7 @@ template<typename T>
Condition
operator
>
(
const
Key
&
key
,
const
T
&
v
)
{
std
::
ostringstream
s
;
s
<<
"
>
"
<<
v
;
s
<<
"
>
"
<<
v
;
return
Condition
(
new
detail
::
KeyCompareConditionImpl
(
key
.
mItemTag
,
[
tag
=
key
.
mItemTag
,
v
](
const
Category
&
c
,
const
Row
&
r
,
bool
icase
)
{
return
r
[
tag
].
template
compare
<
T
>
(
v
,
icase
)
>
0
;
},
s
.
str
()));
...
...
@@ -1133,7 +1133,7 @@ template<typename T>
Condition
operator
>=
(
const
Key
&
key
,
const
T
&
v
)
{
std
::
ostringstream
s
;
s
<<
"
>=
"
<<
v
;
s
<<
"
>=
"
<<
v
;
return
Condition
(
new
detail
::
KeyCompareConditionImpl
(
key
.
mItemTag
,
[
tag
=
key
.
mItemTag
,
v
](
const
Category
&
c
,
const
Row
&
r
,
bool
icase
)
{
return
r
[
tag
].
template
compare
<
T
>
(
v
,
icase
)
>=
0
;
},
s
.
str
()));
...
...
@@ -1143,7 +1143,7 @@ template<typename T>
Condition
operator
<
(
const
Key
&
key
,
const
T
&
v
)
{
std
::
ostringstream
s
;
s
<<
"
<
"
<<
v
;
s
<<
"
<
"
<<
v
;
return
Condition
(
new
detail
::
KeyCompareConditionImpl
(
key
.
mItemTag
,
[
tag
=
key
.
mItemTag
,
v
](
const
Category
&
c
,
const
Row
&
r
,
bool
icase
)
{
return
r
[
tag
].
template
compare
<
T
>
(
v
,
icase
)
<
0
;
},
s
.
str
()));
...
...
@@ -1153,7 +1153,7 @@ template<typename T>
Condition
operator
<=
(
const
Key
&
key
,
const
T
&
v
)
{
std
::
ostringstream
s
;
s
<<
"
<=
"
<<
v
;
s
<<
"
<=
"
<<
v
;
return
Condition
(
new
detail
::
KeyCompareConditionImpl
(
key
.
mItemTag
,
[
tag
=
key
.
mItemTag
,
v
](
const
Category
&
c
,
const
Row
&
r
,
bool
icase
)
{
return
r
[
tag
].
template
compare
<
T
>
(
v
,
icase
)
<=
0
;
},
s
.
str
()));
...
...
@@ -1824,6 +1824,12 @@ class Category
RowSet
getChildren
(
Row
r
,
Category
&
childCat
);
RowSet
getChildren
(
Row
r
,
const
char
*
childCat
);
RowSet
getParents
(
Row
r
,
Category
&
parentCat
);
RowSet
getParents
(
Row
r
,
const
char
*
parentCat
);
RowSet
getLinked
(
Row
r
,
Category
&
cat
);
RowSet
getLinked
(
Row
r
,
const
char
*
cat
);
bool
isValid
();
void
validateLinks
()
const
;
...
...
@@ -1904,7 +1910,13 @@ class File
bool
isValid
();
void
validateLinks
()
const
;
Datablock
&
firstDatablock
()
{
return
*
mHead
;
}
Datablock
&
firstDatablock
()
{
if
(
mHead
==
nullptr
)
throw
std
::
runtime_error
(
"No datablocks in file"
);
return
*
mHead
;
}
void
append
(
Datablock
*
e
);
Datablock
*
get
(
const
std
::
string
&
name
)
const
;
...
...
include/cif++/Point.hpp
View file @
e0777e74
...
...
@@ -340,6 +340,16 @@ double CosinusAngle(const PointF<F>& p1, const PointF<F>& p2, const PointF<F>& p
return
result
;
}
template
<
typename
F
>
auto
DistancePointToLine
(
const
PointF
<
F
>
&
l1
,
const
PointF
<
F
>
&
l2
,
const
PointF
<
F
>
&
p
)
{
auto
line
=
l2
-
l1
;
auto
p_to_l1
=
p
-
l1
;
auto
p_to_l2
=
p
-
l2
;
auto
cross
=
CrossProduct
(
p_to_l1
,
p_to_l2
);
return
cross
.
length
()
/
line
.
length
();
}
// --------------------------------------------------------------------
// For e.g. simulated annealing, returns a new point that is moved in
// a random direction with a distance randomly chosen from a normal
...
...
src/Cif++.cpp
View file @
e0777e74
...
...
@@ -1904,6 +1904,55 @@ RowSet Category::getChildren(Row r, Category& childCat)
return
result
;
}
RowSet
Category
::
getParents
(
Row
r
,
const
char
*
parentCat
)
{
return
getParents
(
r
,
mDb
[
parentCat
]);
}
RowSet
Category
::
getParents
(
Row
r
,
Category
&
parentCat
)
{
assert
(
mValidator
!=
nullptr
);
assert
(
mCatValidator
!=
nullptr
);
RowSet
result
(
parentCat
);
for
(
auto
&
link
:
mValidator
->
getLinksForChild
(
mName
))
{
if
(
link
->
mParentCategory
!=
parentCat
.
mName
)
continue
;
Condition
cond
;
for
(
size_t
ix
=
0
;
ix
<
link
->
mChildKeys
.
size
();
++
ix
)
{
const
char
*
value
=
r
[
link
->
mChildKeys
[
ix
]].
c_str
();
cond
=
std
::
move
(
cond
)
&&
(
Key
(
link
->
mParentKeys
[
ix
])
==
value
);
}
auto
parents
=
parentCat
.
find
(
std
::
move
(
cond
));
result
.
insert
(
result
.
end
(),
parents
.
begin
(),
parents
.
end
());
}
// remove duplicates
result
.
make_unique
();
return
result
;
}
RowSet
Category
::
getLinked
(
Row
r
,
const
char
*
cat
)
{
return
getLinked
(
r
,
mDb
[
cat
]);
}
RowSet
Category
::
getLinked
(
Row
r
,
Category
&
cat
)
{
RowSet
result
=
getChildren
(
r
,
cat
);
if
(
result
.
empty
())
result
=
getParents
(
r
,
cat
);
return
result
;
}
bool
Category
::
isValid
()
{
bool
result
=
true
;
...
...
@@ -2582,7 +2631,7 @@ void Row::assign(size_t column, const std::string& value, bool skipUpdateLinked)
}
}
if
(
cif
::
VERBOSE
>
=
2
)
if
(
cif
::
VERBOSE
>
2
)
{
std
::
cerr
<<
"Parent: "
<<
linked
->
mParentCategory
<<
" Child: "
<<
linked
->
mChildCategory
<<
std
::
endl
<<
cond
<<
std
::
endl
;
...
...
src/CifUtils.cpp
View file @
e0777e74
...
...
@@ -28,25 +28,25 @@
#include "Config.hpp"
#endif
#include <tuple>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <atomic>
#include <mutex>
#include <thread>
#include <chrono>
#include <cmath>
#include <cstdio>
#include <filesystem>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <map>
#include <
chrono
>
#include <
mutex
>
#include <regex>
#include <iomanip>
#include <thread>
#include <tuple>
#if defined(_MSC_VER)
#define TERM_WIDTH 80
#else
#include <termios.h>
#include <sys/ioctl.h>
#include <termios.h>
#endif
#include <boost/algorithm/string.hpp>
...
...
@@ -74,13 +74,13 @@ std::string get_version_nr()
#if __has_include("revision.hpp")
#include "revision.hpp"
#else
const
char
*
kRevision
=
""
;
const
char
*
kRevision
=
""
;
#endif
struct
membuf
:
public
std
::
streambuf
{
membuf
(
char
*
data
,
size_t
length
)
{
this
->
setg
(
data
,
data
,
data
+
length
);
}
}
buffer
(
const_cast
<
char
*>
(
kRevision
),
sizeof
(
kRevision
));
membuf
(
char
*
data
,
size_t
length
)
{
this
->
setg
(
data
,
data
,
data
+
length
);
}
}
buffer
(
const_cast
<
char
*>
(
kRevision
),
sizeof
(
kRevision
));
std
::
istream
is
(
&
buffer
);
...
...
@@ -110,28 +110,27 @@ const char* kRevision = "";
// This really makes a difference, having our own tolower routines
const
uint8_t
kCharToLowerMap
[
256
]
=
{
0x00
,
0x01
,
0x02
,
0x03
,
0x04
,
0x05
,
0x06
,
0x07
,
0x08
,
0x09
,
0x0a
,
0x0b
,
0x0c
,
0x0d
,
0x0e
,
0x0f
,
0x10
,
0x11
,
0x12
,
0x13
,
0x14
,
0x15
,
0x16
,
0x17
,
0x18
,
0x19
,
0x1a
,
0x1b
,
0x1c
,
0x1d
,
0x1e
,
0x1f
,
0x20
,
0x21
,
0x22
,
0x23
,
0x24
,
0x25
,
0x26
,
0x27
,
0x28
,
0x29
,
0x2a
,
0x2b
,
0x2c
,
0x2d
,
0x2e
,
0x2f
,
0x30
,
0x31
,
0x32
,
0x33
,
0x34
,
0x35
,
0x36
,
0x37
,
0x38
,
0x39
,
0x3a
,
0x3b
,
0x3c
,
0x3d
,
0x3e
,
0x3f
,
0x40
,
0x61
,
0x62
,
0x63
,
0x64
,
0x65
,
0x66
,
0x67
,
0x68
,
0x69
,
0x6a
,
0x6b
,
0x6c
,
0x6d
,
0x6e
,
0x6f
,
0x70
,
0x71
,
0x72
,
0x73
,
0x74
,
0x75
,
0x76
,
0x77
,
0x78
,
0x79
,
0x7a
,
0x5b
,
0x5c
,
0x5d
,
0x5e
,
0x5f
,
0x60
,
0x61
,
0x62
,
0x63
,
0x64
,
0x65
,
0x66
,
0x67
,
0x68
,
0x69
,
0x6a
,
0x6b
,
0x6c
,
0x6d
,
0x6e
,
0x6f
,
0x70
,
0x71
,
0x72
,
0x73
,
0x74
,
0x75
,
0x76
,
0x77
,
0x78
,
0x79
,
0x7a
,
0x7b
,
0x7c
,
0x7d
,
0x7e
,
0x7f
,
0x80
,
0x81
,
0x82
,
0x83
,
0x84
,
0x85
,
0x86
,
0x87
,
0x88
,
0x89
,
0x8a
,
0x8b
,
0x8c
,
0x8d
,
0x8e
,
0x8f
,
0x90
,
0x91
,
0x92
,
0x93
,
0x94
,
0x95
,
0x96
,
0x97
,
0x98
,
0x99
,
0x9a
,
0x9b
,
0x9c
,
0x9d
,
0x9e
,
0x9f
,
0xa0
,
0xa1
,
0xa2
,
0xa3
,
0xa4
,
0xa5
,
0xa6
,
0xa7
,
0xa8
,
0xa9
,
0xaa
,
0xab
,
0xac
,
0xad
,
0xae
,
0xaf
,
0xb0
,
0xb1
,
0xb2
,
0xb3
,
0xb4
,
0xb5
,
0xb6
,
0xb7
,
0xb8
,
0xb9
,
0xba
,
0xbb
,
0xbc
,
0xbd
,
0xbe
,
0xbf
,
0xc0
,
0xc1
,
0xc2
,
0xc3
,
0xc4
,
0xc5
,
0xc6
,
0xc7
,
0xc8
,
0xc9
,
0xca
,
0xcb
,
0xcc
,
0xcd
,
0xce
,
0xcf
,
0xd0
,
0xd1
,
0xd2
,
0xd3
,
0xd4
,
0xd5
,
0xd6
,
0xd7
,
0xd8
,
0xd9
,
0xda
,
0xdb
,
0xdc
,
0xdd
,
0xde
,
0xdf
,
0xe0
,
0xe1
,
0xe2
,
0xe3
,
0xe4
,
0xe5
,
0xe6
,
0xe7
,
0xe8
,
0xe9
,
0xea
,
0xeb
,
0xec
,
0xed
,
0xee
,
0xef
,
0xf0
,
0xf1
,
0xf2
,
0xf3
,
0xf4
,
0xf5
,
0xf6
,
0xf7
,
0xf8
,
0xf9
,
0xfa
,
0xfb
,
0xfc
,
0xfd
,
0xfe
,
0xff
};
{
0x00
,
0x01
,
0x02
,
0x03
,
0x04
,
0x05
,
0x06
,
0x07
,
0x08
,
0x09
,
0x0a
,
0x0b
,
0x0c
,
0x0d
,
0x0e
,
0x0f
,
0x10
,
0x11
,
0x12
,
0x13
,
0x14
,
0x15
,
0x16
,
0x17
,
0x18
,
0x19
,
0x1a
,
0x1b
,
0x1c
,
0x1d
,
0x1e
,
0x1f
,
0x20
,
0x21
,
0x22
,
0x23
,
0x24
,
0x25
,
0x26
,
0x27
,
0x28
,
0x29
,
0x2a
,
0x2b
,
0x2c
,
0x2d
,
0x2e
,
0x2f
,
0x30
,
0x31
,
0x32
,
0x33
,
0x34
,
0x35
,
0x36
,
0x37
,
0x38
,
0x39
,
0x3a
,
0x3b
,
0x3c
,
0x3d
,
0x3e
,
0x3f
,
0x40
,
0x61
,
0x62
,
0x63
,
0x64
,
0x65
,
0x66
,
0x67
,
0x68
,
0x69
,
0x6a
,
0x6b
,
0x6c
,
0x6d
,
0x6e
,
0x6f
,
0x70
,
0x71
,
0x72
,
0x73
,
0x74
,
0x75
,
0x76
,
0x77
,
0x78
,
0x79
,
0x7a
,
0x5b
,
0x5c
,
0x5d
,
0x5e
,
0x5f
,
0x60
,
0x61
,
0x62
,
0x63
,
0x64
,
0x65
,
0x66
,
0x67
,
0x68
,
0x69
,
0x6a
,
0x6b
,
0x6c
,
0x6d
,
0x6e
,
0x6f
,
0x70
,
0x71
,
0x72
,
0x73
,
0x74
,
0x75
,
0x76
,
0x77
,
0x78
,
0x79
,
0x7a
,
0x7b
,
0x7c
,
0x7d
,
0x7e
,
0x7f
,
0x80
,
0x81
,
0x82
,
0x83
,
0x84
,
0x85
,
0x86
,
0x87
,
0x88
,
0x89
,
0x8a
,
0x8b
,
0x8c
,
0x8d
,
0x8e
,
0x8f
,
0x90
,
0x91
,
0x92
,
0x93
,
0x94
,
0x95
,
0x96
,
0x97
,
0x98
,
0x99
,
0x9a
,
0x9b
,
0x9c
,
0x9d
,
0x9e
,
0x9f
,
0xa0
,
0xa1
,
0xa2
,
0xa3
,
0xa4
,
0xa5
,
0xa6
,
0xa7
,
0xa8
,
0xa9
,
0xaa
,
0xab
,
0xac
,
0xad
,
0xae
,
0xaf
,
0xb0
,
0xb1
,
0xb2
,
0xb3
,
0xb4
,
0xb5
,
0xb6
,
0xb7
,
0xb8
,
0xb9
,
0xba
,
0xbb
,
0xbc
,
0xbd
,
0xbe
,
0xbf
,
0xc0
,
0xc1
,
0xc2
,
0xc3
,
0xc4
,
0xc5
,
0xc6
,
0xc7
,
0xc8
,
0xc9
,
0xca
,
0xcb
,
0xcc
,
0xcd
,
0xce
,
0xcf
,
0xd0
,
0xd1
,
0xd2
,
0xd3
,
0xd4
,
0xd5
,
0xd6
,
0xd7
,
0xd8
,
0xd9
,
0xda
,
0xdb
,
0xdc
,
0xdd
,
0xde
,
0xdf
,
0xe0
,
0xe1
,
0xe2
,
0xe3
,
0xe4
,
0xe5
,
0xe6
,
0xe7
,
0xe8
,
0xe9
,
0xea
,
0xeb
,
0xec
,
0xed
,
0xee
,
0xef
,
0xf0
,
0xf1
,
0xf2
,
0xf3
,
0xf4
,
0xf5
,
0xf6
,
0xf7
,
0xf8
,
0xf9
,
0xfa
,
0xfb
,
0xfc
,
0xfd
,
0xfe
,
0xff
};
// --------------------------------------------------------------------
bool
iequals
(
const
std
::
string
&
a
,
const
std
::
string
&
b
)
bool
iequals
(
const
std
::
string
&
a
,
const
std
::
string
&
b
)
{
bool
result
=
a
.
length
()
==
b
.
length
();
for
(
auto
ai
=
a
.
begin
(),
bi
=
b
.
begin
();
result
and
ai
!=
a
.
end
()
and
bi
!=
b
.
end
();
++
ai
,
++
bi
)
...
...
@@ -139,7 +138,7 @@ bool iequals(const std::string& a, const std::string& b)
return
result
;
}
bool
iequals
(
const
char
*
a
,
const
char
*
b
)
bool
iequals
(
const
char
*
a
,
const
char
*
b
)
{
bool
result
=
true
;
for
(;
result
and
*
a
and
*
b
;
++
a
,
++
b
)
...
...
@@ -148,11 +147,11 @@ bool iequals(const char* a, const char* b)
return
result
and
*
a
==
*
b
;
}
int
icompare
(
const
std
::
string
&
a
,
const
std
::
string
&
b
)
int
icompare
(
const
std
::
string
&
a
,
const
std
::
string
&
b
)
{
int
d
=
0
;
auto
ai
=
a
.
begin
(),
bi
=
b
.
begin
();
for
(;
d
==
0
and
ai
!=
a
.
end
()
and
bi
!=
b
.
end
();
++
ai
,
++
bi
)
d
=
tolower
(
*
ai
)
-
tolower
(
*
bi
);
...
...
@@ -163,14 +162,14 @@ int icompare(const std::string& a, const std::string& b)
else
if
(
bi
!=
b
.
end
())
d
=
-
1
;
}
return
d
;
}
int
icompare
(
const
char
*
a
,
const
char
*
b
)
int
icompare
(
const
char
*
a
,
const
char
*
b
)
{
int
d
=
0
;
for
(;
d
==
0
and
*
a
!=
0
and
*
b
!=
0
;
++
a
,
++
b
)
d
=
tolower
(
*
a
)
-
tolower
(
*
b
);
...
...
@@ -181,27 +180,27 @@ int icompare(const char* a, const char* b)
else
if
(
*
b
!=
0
)
d
=
-
1
;
}
return
d
;
}
void
toLower
(
std
::
string
&
s
)
void
toLower
(
std
::
string
&
s
)
{
for
(
auto
&
c
:
s
)
for
(
auto
&
c
:
s
)
c
=
tolower
(
c
);
}
std
::
string
toLowerCopy
(
const
std
::
string
&
s
)
std
::
string
toLowerCopy
(
const
std
::
string
&
s
)
{
std
::
string
result
(
s
);
for
(
auto
&
c
:
result
)
for
(
auto
&
c
:
result
)
c
=
tolower
(
c
);
return
result
;
}
// --------------------------------------------------------------------
std
::
tuple
<
std
::
string
,
std
::
string
>
splitTagName
(
const
std
::
string
&
tag
)
std
::
tuple
<
std
::
string
,
std
::
string
>
splitTagName
(
const
std
::
string
&
tag
)
{
if
(
tag
.
empty
())
throw
std
::
runtime_error
(
"empty tag"
);
...
...
@@ -211,10 +210,9 @@ std::tuple<std::string,std::string> splitTagName(const std::string& tag)
auto
s
=
tag
.
find
(
'.'
);
if
(
s
==
std
::
string
::
npos
)
throw
std
::
runtime_error
(
"tag does not contain dot"
);
return
std
::
tuple
<
std
::
string
,
std
::
string
>
{
tag
.
substr
(
1
,
s
-
1
),
tag
.
substr
(
s
+
1
)
};
}
return
std
::
tuple
<
std
::
string
,
std
::
string
>
{
tag
.
substr
(
1
,
s
-
1
),
tag
.
substr
(
s
+
1
)};
}
// --------------------------------------------------------------------
// Simplified line breaking code taken from a decent text editor.
...
...
@@ -263,85 +261,84 @@ enum LineBreakClass
};
const
LineBreakClass
kASCII_LBTable
[
128
]
=
{
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_BreakAfter
,
kLBC_LineFeed
,
kLBC_MandatoryBreak
,
kLBC_MandatoryBreak
,
kLBC_CarriageReturn
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_Space
,
kLBC_Exlamation
,
kLBC_Quotation
,
kLBC_Alphabetic
,
kLBC_PrefixNumeric
,
kLBC_PostfixNumeric
,
kLBC_Alphabetic
,
kLBC_Quotation
,
kLBC_OpenPunctuation
,
kLBC_CloseParenthesis
,
kLBC_Alphabetic
,
kLBC_PrefixNumeric
,
// comma treated differently here, it is not a numeric separator in PDB
kLBC_SymbolAllowingBreakAfter
/* kLBC_InfixNumericSeparator */
,
kLBC_Hyphen
,
kLBC_InfixNumericSeparator
,
kLBC_SymbolAllowingBreakAfter
,
kLBC_Numeric
,
kLBC_Numeric
,
kLBC_Numeric
,
kLBC_Numeric
,
kLBC_Numeric
,
kLBC_Numeric
,
kLBC_Numeric
,
kLBC_Numeric
,
kLBC_Numeric
,
kLBC_Numeric
,
kLBC_InfixNumericSeparator
,
kLBC_InfixNumericSeparator
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Exlamation
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_OpenPunctuation
,
kLBC_PrefixNumeric
,
kLBC_CloseParenthesis
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_OpenPunctuation
,
kLBC_BreakAfter
,
kLBC_ClosePunctuation
,
kLBC_Alphabetic
,
kLBC_CombiningMark
};
{
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_BreakAfter
,
kLBC_LineFeed
,
kLBC_MandatoryBreak
,
kLBC_MandatoryBreak
,
kLBC_CarriageReturn
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_CombiningMark
,
kLBC_Space
,
kLBC_Exlamation
,
kLBC_Quotation
,
kLBC_Alphabetic
,
kLBC_PrefixNumeric
,
kLBC_PostfixNumeric
,
kLBC_Alphabetic
,
kLBC_Quotation
,
kLBC_OpenPunctuation
,
kLBC_CloseParenthesis
,
kLBC_Alphabetic
,
kLBC_PrefixNumeric
,
// comma treated differently here, it is not a numeric separator in PDB
kLBC_SymbolAllowingBreakAfter
/* kLBC_InfixNumericSeparator */
,
kLBC_Hyphen
,
kLBC_InfixNumericSeparator
,
kLBC_SymbolAllowingBreakAfter
,
kLBC_Numeric
,
kLBC_Numeric
,
kLBC_Numeric
,
kLBC_Numeric
,
kLBC_Numeric
,
kLBC_Numeric
,
kLBC_Numeric
,
kLBC_Numeric
,
kLBC_Numeric
,
kLBC_Numeric
,
kLBC_InfixNumericSeparator
,
kLBC_InfixNumericSeparator
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Exlamation
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_OpenPunctuation
,
kLBC_PrefixNumeric
,
kLBC_CloseParenthesis
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_Alphabetic
,
kLBC_OpenPunctuation
,
kLBC_BreakAfter
,
kLBC_ClosePunctuation
,
kLBC_Alphabetic
,
kLBC_CombiningMark
};
std
::
string
::
const_iterator
nextLineBreak
(
std
::
string
::
const_iterator
text
,
std
::
string
::
const_iterator
end
)
{
if
(
text
==
end
)
return
text
;
enum
breakAction
{
{
DBK
=
0
,
// direct break (blank in table)
IBK
,
// indirect break (% in table)
PBK
,
// prohibited break (^ in table)
CIB
,
// combining indirect break
CPB
// combining prohibited break
IBK
,
// indirect break (% in table)
PBK
,
// prohibited break (^ in table)
CIB
,
// combining indirect break
CPB
// combining prohibited break
};
const
breakAction
brkTable
[
27
][
27
]
=
{
// OP CL CP QU GL NS EX SY IS PR PO NU AL ID IN HY BA BB B2 ZW CM WJ H2 H3 JL JV
JT
/* OP */
{
PBK
,
PBK
,
PBK
,
PBK
,
PBK
,
PBK
,
PBK
,
PBK
,
PBK
,
PBK
,
PBK
,
PBK
,
PBK
,
PBK
,
PBK
,
PBK
,
PBK
,
PBK
,
PBK
,
PBK
,
CPB
,
PBK
,
PBK
,
PBK
,
PBK
,
PBK
,
PBK
},
/* CL */
{
DBK
,
PBK
,
PBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
PBK
,
IBK
,
IBK
,
DBK
,
DBK
,
DBK
,
DBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
},
/* CP */
{
DBK
,
PBK
,
PBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
IBK
,
DBK
,
DBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
},
/* QU */
{
PBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
PBK
,
CIB
,
PBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
},
/* GL */
{
IBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
PBK
,
CIB
,
PBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
},
/* NS */
{
DBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
},
/* EX */
{
DBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
},
/* SY */
{
DBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
DBK
,
IBK
,
DBK
,
DBK
,
DBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
},
/* IS */
{
DBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
DBK
,
IBK
,
IBK
,
DBK
,
DBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
},
/* PR */
{
IBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
DBK
,
IBK
,
IBK
,
IBK
,
DBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
},
/* PO */
{
IBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
DBK
,
IBK
,
IBK
,
DBK
,
DBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
},
/* NU */
{
DBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
IBK
,
DBK
,
IBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
},
/* AL */
{
DBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
DBK
,
IBK
,
IBK
,
DBK
,
IBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
},
/* ID */
{
DBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
IBK
,
DBK
,
DBK
,
DBK
,
IBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
},
/* IN */
{
DBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
IBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
},
/* HY */
{
DBK
,
PBK
,
PBK
,
IBK
,
DBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
DBK
,
IBK
,
DBK
,
DBK
,
DBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
},
/* BA */
{
DBK
,
PBK
,
PBK
,
IBK
,
DBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
},
/* BB */
{
IBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
PBK
,
CIB
,
PBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
},
/* B2 */
{
DBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
IBK
,
IBK
,
DBK
,
PBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
},
/* ZW */
{
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
},
/* CM */
{
DBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
DBK
,
IBK
,
IBK
,
DBK
,
IBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
},
/* WJ */
{
IBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
PBK
,
CIB
,
PBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
},
/* H2 */
{
DBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
IBK
,
DBK
,
DBK
,
DBK
,
IBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
IBK
,
IBK
},
/* H3 */
{
DBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
IBK
,
DBK
,
DBK
,
DBK
,
IBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
IBK
},
/* JL */
{
DBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
IBK
,
DBK
,
DBK
,
DBK
,
IBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
IBK
,
IBK
,
IBK
,
IBK
,
DBK
},
/* JV */
{
DBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
IBK
,
DBK
,
DBK
,
DBK
,
IBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
IBK
,
IBK
},
/* JT */
{
DBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
IBK
,
DBK
,
DBK
,
DBK
,
IBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
IBK
},
};
// OP CL CP QU GL NS EX SY IS PR PO NU AL ID IN HY BA BB B2 ZW CM WJ H2 H3 JL JV
JT
/* OP */
{
PBK
,
PBK
,
PBK
,
PBK
,
PBK
,
PBK
,
PBK
,
PBK
,
PBK
,
PBK
,
PBK
,
PBK
,
PBK
,
PBK
,
PBK
,
PBK
,
PBK
,
PBK
,
PBK
,
PBK
,
CPB
,
PBK
,
PBK
,
PBK
,
PBK
,
PBK
,
PBK
},
/* CL */
{
DBK
,
PBK
,
PBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
PBK
,
IBK
,
IBK
,
DBK
,
DBK
,
DBK
,
DBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
},
/* CP */
{
DBK
,
PBK
,
PBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
IBK
,
DBK
,
DBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
},
/* QU */
{
PBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
PBK
,
CIB
,
PBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
},
/* GL */
{
IBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
PBK
,
CIB
,
PBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
},
/* NS */
{
DBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
},
/* EX */
{
DBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
},
/* SY */
{
DBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
DBK
,
IBK
,
DBK
,
DBK
,
DBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
},
/* IS */
{
DBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
DBK
,
IBK
,
IBK
,
DBK
,
DBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
},
/* PR */
{
IBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
DBK
,
IBK
,
IBK
,
IBK
,
DBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
},
/* PO */
{
IBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
DBK
,
IBK
,
IBK
,
DBK
,
DBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
},
/* NU */
{
DBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
IBK
,
DBK
,
IBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
},
/* AL */
{
DBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
DBK
,
IBK
,
IBK
,
DBK
,
IBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
},
/* ID */
{
DBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
IBK
,
DBK
,
DBK
,
DBK
,
IBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
},
/* IN */
{
DBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
IBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
},
/* HY */
{
DBK
,
PBK
,
PBK
,
IBK
,
DBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
DBK
,
IBK
,
DBK
,
DBK
,
DBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
},
/* BA */
{
DBK
,
PBK
,
PBK
,
IBK
,
DBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
},
/* BB */
{
IBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
PBK
,
CIB
,
PBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
},
/* B2 */
{
DBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
IBK
,
IBK
,
DBK
,
PBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
},
/* ZW */
{
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
},
/* CM */
{
DBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
DBK
,
IBK
,
IBK
,
DBK
,
IBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
DBK
},
/* WJ */
{
IBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
,
PBK
,
CIB
,
PBK
,
IBK
,
IBK
,
IBK
,
IBK
,
IBK
},
/* H2 */
{
DBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
IBK
,
DBK
,
DBK
,
DBK
,
IBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
IBK
,
IBK
},
/* H3 */
{
DBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
IBK
,
DBK
,
DBK
,
DBK
,
IBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
IBK
},
/* JL */
{
DBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
IBK
,
DBK
,
DBK
,
DBK
,
IBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
IBK
,
IBK
,
IBK
,
IBK
,
DBK
},
/* JV */
{
DBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
IBK
,
DBK
,
DBK
,
DBK
,
IBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
IBK
,
IBK
},
/* JT */
{
DBK
,
PBK
,
PBK
,
IBK
,
IBK
,
IBK
,
PBK
,
PBK
,
PBK
,
DBK
,
IBK
,
DBK
,
DBK
,
DBK
,
IBK
,
IBK
,
IBK
,
DBK
,
DBK
,
PBK
,
CIB
,
PBK
,
DBK
,
DBK
,
DBK
,
DBK
,
IBK
},
};
uint8_t
ch
=
static_cast
<
uint8_t
>
(
*
text
);
LineBreakClass
cls
;
if
(
ch
==
'\n'
)
cls
=
kLBC_MandatoryBreak
;
else
if
(
ch
<
128
)
{
cls
=
kASCII_LBTable
[
ch
];
if
(
cls
>
kLBC_MandatoryBreak
and
cls
!=
kLBC_Space
)
// duh...
if
(
cls
>
kLBC_MandatoryBreak
and
cls
!=
kLBC_Space
)
// duh...
cls
=
kLBC_Alphabetic
;
}
else
...
...
@@ -355,9 +352,9 @@ std::string::const_iterator nextLineBreak(std::string::const_iterator text, std:
while
(
++
text
!=
end
and
cls
!=
kLBC_MandatoryBreak
)
{
ch
=
*
text
;
LineBreakClass
lcls
=
ncls
;
if
(
ch
==
'\n'
)
{
++
text
;
...
...
@@ -365,42 +362,42 @@ std::string::const_iterator nextLineBreak(std::string::const_iterator text, std:
}
ncls
=
kASCII_LBTable
[
ch
];
if
(
ncls
==
kLBC_Space
)
continue
;
breakAction
brk
=
brkTable
[
cls
][
ncls
];
if
(
brk
==
DBK
or
(
brk
==
IBK
and
lcls
==
kLBC_Space
))
break
;
cls
=
ncls
;
}
return
text
;
}
std
::
vector
<
std
::
string
>
wrapLine
(
const
std
::
string
&
text
,
unsigned
int
width
)
std
::
vector
<
std
::
string
>
wrapLine
(
const
std
::
string
&
text
,
unsigned
int
width
)
{
std
::
vector
<
std
::
string
>
result
;
std
::
vector
<
size_t
>
offsets
=
{
0
};
std
::
vector
<
size_t
>
offsets
=
{
0
};
auto
b
=
text
.
begin
();
while
(
b
!=
text
.
end
())
{
auto
e
=
nextLineBreak
(
b
,
text
.
end
());
offsets
.
push_back
(
e
-
text
.
begin
());
b
=
e
;
}
size_t
count
=
offsets
.
size
()
-
1
;
std
::
vector
<
size_t
>
minima
(
count
+
1
,
1000000
);
minima
[
0
]
=
0
;
std
::
vector
<
size_t
>
breaks
(
count
+
1
,
0
);
for
(
size_t
i
=
0
;
i
<
count
;
++
i
)
{
size_t
j
=
i
+
1
;
...
...
@@ -415,7 +412,7 @@ std::vector<std::string> wrapLine(const std::string& text, unsigned int width)
--
w
;
size_t
cost
=
minima
[
i
];
if
(
j
<
count
)
// last line may be shorter
if
(
j
<
count
)
// last line may be shorter
cost
+=
(
width
-
w
)
*
(
width
-
w
);
if
(
cost
<
minima
[
j
])
...
...
@@ -427,34 +424,34 @@ std::vector<std::string> wrapLine(const std::string& text, unsigned int width)
++
j
;
}
}
size_t
j
=
count
;
while
(
j
>
0
)
{
size_t
i
=
breaks
[
j
];
result
.
push_back
(
text
.
substr
(
offsets
[
i
],
offsets
[
j
]
-
offsets
[
i
]));
result
.
push_back
(
text
.
substr
(
offsets
[
i
],
offsets
[
j
]
-
offsets
[
i
]));
j
=
i
;
}
reverse
(
result
.
begin
(),
result
.
end
());
return
result
;
}
std
::
vector
<
std
::
string
>
wordWrap
(
const
std
::
string
&
text
,
unsigned
int
width
)
std
::
vector
<
std
::
string
>
wordWrap
(
const
std
::
string
&
text
,
unsigned
int
width
)
{
std
::
vector
<
std
::
string
>
paragraphs
;
ba
::
split
(
paragraphs
,
text
,
ba
::
is_any_of
(
"
\n
"
));
std
::
vector
<
std
::
string
>
result
;
for
(
auto
&
p
:
paragraphs
)
for
(
auto
&
p
:
paragraphs
)
{
if
(
p
.
empty
())
{
result
.
push_back
(
""
);
continue
;
}
auto
lines
=
wrapLine
(
p
,
width
);
result
.
insert
(
result
.
end
(),
lines
.
begin
(),
lines
.
end
());
}
...
...
@@ -467,8 +464,8 @@ std::vector<std::string> wordWrap(const std::string& text, unsigned int width)
#ifdef _MSC_VER
}
#include <Windows.h>
#include <wincon.h>
#include <libloaderapi.h>
#include <wincon.h>
namespace
cif
{
...
...
@@ -494,15 +491,15 @@ std::string GetExecutablePath()
#else
uint32_t
get_terminal_width
()
{
uint32_t
result
=
80
;
if
(
isatty
(
STDOUT_FILENO
))
{
struct
winsize
w
;
ioctl
(
0
,
TIOCGWINSZ
,
&
w
);
result
=
w
.
ws_col
;
}
return
result
;
uint32_t
result
=
80
;
if
(
isatty
(
STDOUT_FILENO
))
{
struct
winsize
w
;
ioctl
(
0
,
TIOCGWINSZ
,
&
w
);
result
=
w
.
ws_col
;
}
return
result
;
}
std
::
string
get_executable_path
()
...
...
@@ -512,7 +509,7 @@ std::string get_executable_path()
char
path
[
PATH_MAX
]
=
""
;
if
(
readlink
(
"/proc/self/exe"
,
path
,
sizeof
(
path
))
==
-
1
)
throw
std
::
runtime_error
(
"could not get exe path "
s
+
strerror
(
errno
));
return
{
path
};
return
{
path
};
}
#endif
...
...
@@ -521,37 +518,42 @@ std::string get_executable_path()
struct
ProgressImpl
{
ProgressImpl
(
int64_t
inMax
,
const
std
::
string
&
inAction
)
:
mMax
(
inMax
),
mConsumed
(
0
),
mAction
(
inAction
),
mMessage
(
inAction
)
,
mThread
(
std
::
bind
(
&
ProgressImpl
::
Run
,
this
))
{}
ProgressImpl
(
int64_t
inMax
,
const
std
::
string
&
inAction
)
:
mMax
(
inMax
)
,
mConsumed
(
0
)
,
mAction
(
inAction
)
,
mMessage
(
inAction
)
,
mThread
(
std
::
bind
(
&
ProgressImpl
::
Run
,
this
))
{
}
void
Run
();
void
Stop
()
void
Run
();
void
Stop
()
{
mStop
=
true
;
if
(
mThread
.
joinable
())
mThread
.
join
();
}
void
PrintProgress
();
void
PrintDone
();
int64_t
mMax
;
std
::
atomic
<
int64_t
>
mConsumed
;
int64_t
mLastConsumed
=
0
;
int
mSpinnerIndex
=
0
;
std
::
string
mAction
,
mMessage
;
std
::
mutex
mMutex
;
std
::
thread
mThread
;
void
PrintProgress
();
void
PrintDone
();
int64_t
mMax
;
std
::
atomic
<
int64_t
>
mConsumed
;
int64_t
mLastConsumed
=
0
;
int
mSpinnerIndex
=
0
;
std
::
string
mAction
,
mMessage
;
std
::
mutex
mMutex
;
std
::
thread
mThread
;
std
::
chrono
::
time_point
<
std
::
chrono
::
system_clock
>
mStart
=
std
::
chrono
::
system_clock
::
now
();
bool
mStop
=
false
;
mStart
=
std
::
chrono
::
system_clock
::
now
();
bool
mStop
=
false
;
};
void
ProgressImpl
::
Run
()
{
bool
printedAny
=
false
;
try
{
for
(;;)
...
...
@@ -559,7 +561,7 @@ void ProgressImpl::Run()
std
::
this_thread
::
sleep_for
(
std
::
chrono
::
milliseconds
(
100
));
std
::
unique_lock
lock
(
mMutex
);
if
(
mStop
or
mConsumed
==
mMax
)
break
;
...
...
@@ -570,43 +572,44 @@ void ProgressImpl::Run()
PrintProgress
();
printedAny
=
true
;
}
}
catch
(...)
{}
catch
(...)
{
}
if
(
printedAny
)
PrintDone
();
}
void
ProgressImpl
::
PrintProgress
()
{
// const char* kBlocks[] = {
// " ", // 0
// u8"\u258F", // 1
// u8"\u258E", // 2
// u8"\u258D", // 3
// u8"\u258C", // 4
// u8"\u258B", // 5
// u8"\u258A", // 6
// u8"\u2589", // 7
// u8"\u2588", // 8
// };
const
char
*
kBlocks
[]
=
{
" "
,
// 0
" "
,
// 1
" "
,
// 2
"-"
,
// 3
"-"
,
// 4
"-"
,
// 5
"="
,
// 6
"="
,
// 7
"="
,
// 8
// const char* kBlocks[] = {
// " ", // 0
// u8"\u258F", // 1
// u8"\u258E", // 2
// u8"\u258D", // 3
// u8"\u258C", // 4
// u8"\u258B", // 5
// u8"\u258A", // 6
// u8"\u2589", // 7
// u8"\u2588", // 8
// };
const
char
*
kBlocks
[]
=
{
" "
,
// 0
" "
,
// 1
" "
,
// 2
"-"
,
// 3
"-"
,
// 4
"-"
,
// 5
"="
,
// 6
"="
,
// 7
"="
,
// 8
};
uint32_t
width
=
get_terminal_width
();
std
::
string
msg
;
msg
.
reserve
(
width
+
1
);
if
(
mMessage
.
length
()
<=
20
)
...
...
@@ -617,16 +620,16 @@ void ProgressImpl::PrintProgress()
}
else
msg
=
mMessage
.
substr
(
0
,
17
)
+
"..."
;
msg
+=
" |"
;
int64_t
consumed
=
mConsumed
;
float
progress
=
static_cast
<
float
>
(
consumed
)
/
mMax
;
int
pi
=
static_cast
<
int
>
(
std
::
ceil
(
progress
*
33
*
8
));
// int tw = width - 28;
// int twd = static_cast<int>(tw * progress + 0.5f);
// msg.append(twd, '=');
// msg.append(tw - twd, ' ');
// int tw = width - 28;
// int twd = static_cast<int>(tw * progress + 0.5f);
// msg.append(twd, '=');
// msg.append(tw - twd, ' ');
for
(
int
i
=
0
;
i
<
33
;
++
i
)
{
...
...
@@ -641,27 +644,27 @@ void ProgressImpl::PrintProgress()
msg
.
append
(
"| "
);
// const char kSpinner[] = { '|', '/', '-', '\\' };
const
char
kSpinner
[]
=
{
' '
,
'.'
,
'o'
,
'O'
,
'0'
,
'O'
,
'o'
,
'.'
};
const
size_t
kSpinnerCount
=
sizeof
(
kSpinner
);
// const char kSpinner[] = { '|', '/', '-', '\\' };
const
char
kSpinner
[]
=
{
' '
,
'.'
,
'o'
,
'O'
,
'0'
,
'O'
,
'o'
,
'.'
};
const
size_t
kSpinnerCount
=
sizeof
(
kSpinner
);
if
(
mLastConsumed
<
consumed
)
{
mLastConsumed
=
consumed
;
mSpinnerIndex
=
(
mSpinnerIndex
+
1
)
%
kSpinnerCount
;
}
const
char
spinner
[
2
]
=
{
kSpinner
[
mSpinnerIndex
],
0
};
const
char
spinner
[
2
]
=
{
kSpinner
[
mSpinnerIndex
],
0
};
msg
.
append
(
spinner
);
// int perc = static_cast<int>(100 * progress);
// if (perc < 100)
// msg += ' ';
// if (perc < 10)
// msg += ' ';
// msg += to_string(perc);
// msg += '%';
// int perc = static_cast<int>(100 * progress);
// if (perc < 100)
// msg += ' ';
// if (perc < 10)
// msg += ' ';
// msg += to_string(perc);
// msg += '%';
std
::
cout
<<
'\r'
<<
msg
;
std
::
cout
.
flush
();
}
...
...
@@ -669,38 +672,38 @@ void ProgressImpl::PrintProgress()
namespace
{
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
std
::
chrono
::
duration
<
double
>&
t
)
{
uint64_t
s
=
static_cast
<
uint64_t
>
(
std
::
trunc
(
t
.
count
()));
if
(
s
>
24
*
60
*
60
)
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
std
::
chrono
::
duration
<
double
>
&
t
)
{
uint32_t
days
=
s
/
(
24
*
60
*
60
);
os
<<
days
<<
"d "
;
s
%=
24
*
60
*
60
;
}
if
(
s
>
60
*
60
)
{
uint32_t
hours
=
s
/
(
60
*
60
);
os
<<
hours
<<
"h "
;
s
%=
60
*
60
;
}
if
(
s
>
60
)
{
uint32_t
minutes
=
s
/
60
;
os
<<
minutes
<<
"m "
;
s
%=
60
;
}
double
ss
=
s
+
1e-6
*
(
t
.
count
()
-
s
);
os
<<
std
::
fixed
<<
std
::
setprecision
(
1
)
<<
ss
<<
's'
;
uint64_t
s
=
static_cast
<
uint64_t
>
(
std
::
trunc
(
t
.
count
()));
if
(
s
>
24
*
60
*
60
)
{
uint32_t
days
=
s
/
(
24
*
60
*
60
);
os
<<
days
<<
"d "
;
s
%=
24
*
60
*
60
;
}
return
os
;
}
if
(
s
>
60
*
60
)
{
uint32_t
hours
=
s
/
(
60
*
60
);
os
<<
hours
<<
"h "
;
s
%=
60
*
60
;
}
}
if
(
s
>
60
)
{
uint32_t
minutes
=
s
/
60
;
os
<<
minutes
<<
"m "
;
s
%=
60
;
}
double
ss
=
s
+
1e-6
*
(
t
.
count
()
-
s
);
os
<<
std
::
fixed
<<
std
::
setprecision
(
1
)
<<
ss
<<
's'
;
return
os
;
}
}
// namespace
void
ProgressImpl
::
PrintDone
()
{
...
...
@@ -714,11 +717,11 @@ void ProgressImpl::PrintDone()
if
(
msg
.
length
()
<
width
)
msg
+=
std
::
string
(
width
-
msg
.
length
(),
' '
);
std
::
cout
<<
'\r'
<<
msg
<<
std
::
endl
;
}
Progress
::
Progress
(
int64_t
inMax
,
const
std
::
string
&
inAction
)
Progress
::
Progress
(
int64_t
inMax
,
const
std
::
string
&
inAction
)
:
mImpl
(
nullptr
)
{
if
(
isatty
(
STDOUT_FILENO
))
...
...
@@ -732,10 +735,10 @@ Progress::~Progress()
delete
mImpl
;
}
void
Progress
::
consumed
(
int64_t
inConsumed
)
{
if
(
mImpl
!=
nullptr
and
if
(
mImpl
!=
nullptr
and
(
mImpl
->
mConsumed
+=
inConsumed
)
>=
mImpl
->
mMax
)
{
mImpl
->
Stop
();
...
...
@@ -744,14 +747,14 @@ void Progress::consumed(int64_t inConsumed)
void
Progress
::
progress
(
int64_t
inProgress
)
{
if
(
mImpl
!=
nullptr
and
if
(
mImpl
!=
nullptr
and
(
mImpl
->
mConsumed
=
inProgress
)
>=
mImpl
->
mMax
)
{
mImpl
->
Stop
();
}
}
void
Progress
::
message
(
const
std
::
string
&
inMessage
)
void
Progress
::
message
(
const
std
::
string
&
inMessage
)
{
if
(
mImpl
!=
nullptr
)
{
...
...
@@ -760,7 +763,7 @@ void Progress::message(const std::string& inMessage)
}
}
}
}
// namespace cif
#if USE_RSRC
...
...
@@ -774,16 +777,16 @@ void Progress::message(const std::string& inMessage)
namespace
mrsrc
{
/// \brief Internal data structure as generated by mrc
struct
rsrc_imp
{
unsigned
int
m_next
;
unsigned
int
m_child
;
unsigned
int
m_name
;
unsigned
int
m_size
;
unsigned
int
m_data
;
};
}
/// \brief Internal data structure as generated by mrc
struct
rsrc_imp
{
unsigned
int
m_next
;
unsigned
int
m_child
;
unsigned
int
m_name
;
unsigned
int
m_size
;
unsigned
int
m_data
;
};
}
// namespace mrsrc
extern
const
__attribute__
((
weak
))
mrsrc
::
rsrc_imp
gResourceIndex
[];
extern
const
__attribute__
((
weak
))
char
gResourceData
[];
...
...
@@ -791,384 +794,386 @@ extern const __attribute__((weak)) char gResourceName[];
namespace
mrsrc
{
class
rsrc_data
class
rsrc_data
{
public
:
static
rsrc_data
&
instance
()
{
public
:
static
rsrc_data
&
instance
()
{
static
rsrc_data
s_instance
;
return
s_instance
;
}
static
rsrc_data
s_instance
;
return
s_instance
;
}
const
rsrc_imp
*
index
()
const
{
return
m_index
;
}
const
rsrc_imp
*
index
()
const
{
return
m_index
;
}
const
char
*
data
(
unsigned
int
offset
)
const
{
return
m_data
+
offset
;
}
const
char
*
name
(
unsigned
int
offset
)
const
{
return
m_name
+
offset
;
}
const
char
*
data
(
unsigned
int
offset
)
const
{
return
m_data
+
offset
;
}
private
:
const
char
*
name
(
unsigned
int
offset
)
const
{
return
m_name
+
offset
;
}
rsrc_data
()
private
:
rsrc_data
()
{
if
(
gResourceIndex
and
gResourceIndex
and
gResourceName
)
{
if
(
gResourceIndex
and
gResourceIndex
and
gResourceName
)
{
m_index
=
gResourceIndex
;
m_data
=
gResourceData
;
m_name
=
gResourceName
;
}
m_index
=
gResourceIndex
;
m_data
=
gResourceData
;
m_name
=
gResourceName
;
}
}
rsrc_imp
m_dummy
=
{};
const
rsrc_imp
*
m_index
=
&
m_dummy
;
const
char
*
m_data
=
""
;
const
char
*
m_name
=
""
;
};
rsrc_imp
m_dummy
=
{};
const
rsrc_imp
*
m_index
=
&
m_dummy
;
const
char
*
m_data
=
""
;
const
char
*
m_name
=
""
;
};
/// \brief Class mrsrc::rsrc contains a pointer to the data in the
/// resource, as well as offering an iterator interface to its
/// children.
/// \brief Class mrsrc::rsrc contains a pointer to the data in the
/// resource, as well as offering an iterator interface to its
/// children.
class
rsrc
{
public
:
rsrc
()
:
m_impl
(
rsrc_data
::
instance
().
index
())
{
}
class
rsrc
rsrc
(
const
rsrc
&
other
)
:
m_impl
(
other
.
m_impl
)
{
public
:
}
rsrc
()
:
m_impl
(
rsrc_data
::
instance
().
index
())
{}
rsrc
&
operator
=
(
const
rsrc
&
other
)
{
m_impl
=
other
.
m_impl
;
return
*
this
;
}
rsrc
(
const
rsrc
&
other
)
:
m_impl
(
other
.
m_impl
)
{}
rsrc
(
std
::
filesystem
::
path
path
);
rsrc
&
operator
=
(
const
rsrc
&
other
)
{
m_impl
=
other
.
m_impl
;
return
*
this
;
}
std
::
string
name
()
const
{
return
rsrc_data
::
instance
().
name
(
m_impl
->
m_name
);
}
rsrc
(
std
::
filesystem
::
path
path
);
const
char
*
data
()
const
{
return
rsrc_data
::
instance
().
data
(
m_impl
->
m_data
);
}
std
::
string
name
()
const
{
return
rsrc_data
::
instance
().
name
(
m_impl
->
m_name
)
;
}
unsigned
long
size
()
const
{
return
m_impl
->
m_size
;
}
const
char
*
data
()
const
{
return
rsrc_data
::
instance
().
data
(
m_impl
->
m_data
)
;
}
explicit
operator
bool
()
const
{
return
m_impl
!=
NULL
and
m_impl
->
m_size
>
0
;
}
unsigned
long
size
()
const
{
return
m_impl
->
m_size
;
}
template
<
typename
RSRC
>
class
iterator_t
{
public
:
using
iterator_category
=
std
::
input_iterator_tag
;
using
value_type
=
RSRC
;
using
difference_type
=
std
::
ptrdiff_t
;
using
pointer
=
value_type
*
;
using
reference
=
value_type
&
;
iterator_t
(
const
rsrc_imp
*
cur
)
:
m_cur
(
cur
)
{
}
explicit
operator
bool
()
const
{
return
m_impl
!=
NULL
and
m_impl
->
m_size
>
0
;
}
iterator_t
(
const
iterator_t
&
i
)
:
m_cur
(
i
.
m_cur
)
{
}
template
<
typename
RSRC
>
class
iterator_t
iterator_t
&
operator
=
(
const
iterator_t
&
i
)
{
public
:
m_cur
=
i
.
m_cur
;
return
*
this
;
}
using
iterator_category
=
std
::
input_iterator_tag
;
using
value_type
=
RSRC
;
using
difference_type
=
std
::
ptrdiff_t
;
using
pointer
=
value_type
*
;
using
reference
=
value_type
&
;
reference
operator
*
()
{
return
m_cur
;
}
pointer
operator
->
()
{
return
&
m_cur
;
}
iterator_t
(
const
rsrc_imp
*
cur
)
:
m_cur
(
cur
)
{}
iterator_t
&
operator
++
()
{
if
(
m_cur
.
m_impl
->
m_next
)
m_cur
.
m_impl
=
rsrc_data
::
instance
().
index
()
+
m_cur
.
m_impl
->
m_next
;
else
m_cur
.
m_impl
=
nullptr
;
return
*
this
;
}
iterator_t
(
const
iterator_t
&
i
)
:
m_cur
(
i
.
m_cur
)
{
}
iterator_t
&
operator
=
(
const
iterator_t
&
i
)
{
m_cur
=
i
.
m_cur
;
return
*
this
;
}
iterator_t
operator
++
(
int
)
{
auto
tmp
(
*
this
);
this
->
operator
++
();
return
tmp
;
}
reference
operator
*
()
{
return
m_cur
;
}
pointer
operator
->
()
{
return
&
m_cur
;
}
bool
operator
==
(
const
iterator_t
&
rhs
)
const
{
return
m_cur
.
m_impl
==
rhs
.
m_cur
.
m_impl
;
}
bool
operator
!=
(
const
iterator_t
&
rhs
)
const
{
return
m_cur
.
m_impl
!=
rhs
.
m_cur
.
m_impl
;
}
iterator_t
&
operator
++
()
{
if
(
m_cur
.
m_impl
->
m_next
)
m_cur
.
m_impl
=
rsrc_data
::
instance
().
index
()
+
m_cur
.
m_impl
->
m_next
;
else
m_cur
.
m_impl
=
nullptr
;
return
*
this
;
}
private
:
value_type
m_cur
;
};
iterator_t
operator
++
(
int
)
{
auto
tmp
(
*
this
);
this
->
operator
++
();
return
tmp
;
}
using
iterator
=
iterator_t
<
rsrc
>
;
bool
operator
==
(
const
iterator_t
&
rhs
)
const
{
return
m_cur
.
m_impl
==
rhs
.
m_cur
.
m_impl
;
}
bool
operator
!=
(
const
iterator_t
&
rhs
)
const
{
return
m_cur
.
m_impl
!=
rhs
.
m_cur
.
m_impl
;
}
iterator
begin
()
const
{
const
rsrc_imp
*
impl
=
nullptr
;
if
(
m_impl
and
m_impl
->
m_child
)
impl
=
rsrc_data
::
instance
().
index
()
+
m_impl
->
m_child
;
return
iterator
(
impl
);
}
private
:
value_type
m_cur
;
};
iterator
end
()
const
{
return
iterator
(
nullptr
);
}
using
iterator
=
iterator_t
<
rsrc
>
;
private
:
rsrc
(
const
rsrc_imp
*
imp
)
:
m_impl
(
imp
)
{
}
iterator
begin
()
const
{
const
rsrc_imp
*
impl
=
nullptr
;
if
(
m_impl
and
m_impl
->
m_child
)
impl
=
rsrc_data
::
instance
().
index
()
+
m_impl
->
m_child
;
return
iterator
(
impl
);
}
const
rsrc_imp
*
m_impl
;
};
iterator
end
()
const
{
return
iterator
(
nullptr
);
}
inline
rsrc
::
rsrc
(
std
::
filesystem
::
path
p
)
{
m_impl
=
rsrc_data
::
instance
().
index
();
private
:
rsrc
(
const
rsrc_imp
*
imp
)
:
m_impl
(
imp
)
{}
// using std::filesytem::path would have been natural here of course...
const
rsrc_imp
*
m_impl
;
}
;
auto
pb
=
p
.
begin
()
;
auto
pe
=
p
.
end
()
;
inline
rsrc
::
rsrc
(
std
::
filesystem
::
path
p
)
while
(
m_impl
!=
nullptr
and
pb
!=
pe
)
{
m_impl
=
rsrc_data
::
instance
().
index
()
;
auto
name
=
*
pb
++
;
// using std::filesytem::path would have been natural here of course...
auto
pb
=
p
.
begin
();
auto
pe
=
p
.
end
();
while
(
m_impl
!=
nullptr
and
pb
!=
pe
)
const
rsrc_imp
*
impl
=
nullptr
;
for
(
rsrc
child
:
*
this
)
{
auto
name
=
*
pb
++
;
const
rsrc_imp
*
impl
=
nullptr
;
for
(
rsrc
child
:
*
this
)
if
(
child
.
name
()
==
name
)
{
if
(
child
.
name
()
==
name
)
{
impl
=
child
.
m_impl
;
break
;
}
impl
=
child
.
m_impl
;
break
;
}
m_impl
=
impl
;
}
if
(
pb
!=
pe
)
// not found
m_impl
=
nullptr
;
m_impl
=
impl
;
}
// --------------------------------------------------------------------
template
<
typename
CharT
,
typename
Traits
>
class
basic_streambuf
:
public
std
::
basic_streambuf
<
CharT
,
Traits
>
{
public
:
if
(
pb
!=
pe
)
// not found
m_impl
=
nullptr
;
}
typedef
CharT
char_type
;
typedef
Traits
traits_type
;
typedef
typename
traits_type
::
int_type
int_type
;
typedef
typename
traits_type
::
pos_type
pos_type
;
typedef
typename
traits_type
::
off_type
off_type
;
// --------------------------------------------------------------------
/// \brief constructor taking a \a path to the resource in memory
basic_streambuf
(
const
std
::
string
&
path
)
:
m_rsrc
(
path
)
{
init
();
}
template
<
typename
CharT
,
typename
Traits
>
class
basic_streambuf
:
public
std
::
basic_streambuf
<
CharT
,
Traits
>
{
public
:
typedef
CharT
char_type
;
typedef
Traits
traits_type
;
typedef
typename
traits_type
::
int_type
int_type
;
typedef
typename
traits_type
::
pos_type
pos_type
;
typedef
typename
traits_type
::
off_type
off_type
;
/// \brief constructor taking a \a path to the resource in memory
basic_streambuf
(
const
std
::
string
&
path
)
:
m_rsrc
(
path
)
{
init
();
}
/// \brief constructor taking a \a rsrc
basic_streambuf
(
const
rsrc
&
rsrc
)
:
m_rsrc
(
rsrc
)
{
init
();
}
/// \brief constructor taking a \a rsrc
basic_streambuf
(
const
rsrc
&
rsrc
)
:
m_rsrc
(
rsrc
)
{
init
();
}
basic_streambuf
(
const
basic_streambuf
&
)
=
delete
;
basic_streambuf
(
const
basic_streambuf
&
)
=
delete
;
basic_streambuf
(
basic_streambuf
&&
rhs
)
:
basic_streambuf
(
rhs
.
m_rsrc
)
{
}
basic_streambuf
(
basic_streambuf
&&
rhs
)
:
basic_streambuf
(
rhs
.
m_rsrc
)
{
}
basic_streambuf
&
operator
=
(
const
basic_streambuf
&
)
=
delete
;
basic_streambuf
&
operator
=
(
const
basic_streambuf
&
)
=
delete
;
basic_streambuf
&
operator
=
(
basic_streambuf
&&
rhs
)
{
swap
(
rhs
);
return
*
this
;
}
basic_streambuf
&
operator
=
(
basic_streambuf
&&
rhs
)
{
swap
(
rhs
);
return
*
this
;
}
void
swap
(
basic_streambuf
&
rhs
)
{
std
::
swap
(
m_begin
,
rhs
.
m_begin
);
std
::
swap
(
m_end
,
rhs
.
m_end
);
std
::
swap
(
m_current
,
rhs
.
m_current
);
}
void
swap
(
basic_streambuf
&
rhs
)
{
std
::
swap
(
m_begin
,
rhs
.
m_begin
);
std
::
swap
(
m_end
,
rhs
.
m_end
);
std
::
swap
(
m_current
,
rhs
.
m_current
);
}
private
:
private
:
void
init
()
{
m_begin
=
reinterpret_cast
<
const
char_type
*>
(
m_rsrc
.
data
());
m_end
=
reinterpret_cast
<
const
char_type
*>
(
m_rsrc
.
data
()
+
m_rsrc
.
size
());
m_current
=
m_begin
;
}
void
init
()
{
m_begin
=
reinterpret_cast
<
const
char_type
*>
(
m_rsrc
.
data
());
m_end
=
reinterpret_cast
<
const
char_type
*>
(
m_rsrc
.
data
()
+
m_rsrc
.
size
());
m_current
=
m_begin
;
}
int_type
underflow
()
{
if
(
m_current
==
m_end
)
return
traits_type
::
eof
();
int_type
underflow
()
{
if
(
m_current
==
m_end
)
return
traits_type
::
eof
();
return
traits_type
::
to_int_type
(
*
m_current
);
}
return
traits_type
::
to_int_type
(
*
m_current
);
}
int_type
uflow
()
{
if
(
m_current
==
m_end
)
return
traits_type
::
eof
();
int_type
uflow
()
{
if
(
m_current
==
m_end
)
return
traits_type
::
eof
();
return
traits_type
::
to_int_type
(
*
m_current
++
);
}
return
traits_type
::
to_int_type
(
*
m_current
++
);
}
int_type
pbackfail
(
int_type
ch
)
{
if
(
m_current
==
m_begin
or
(
ch
!=
traits_type
::
eof
()
and
ch
!=
m_current
[
-
1
]))
return
traits_type
::
eof
();
int_type
pbackfail
(
int_type
ch
)
{
if
(
m_current
==
m_begin
or
(
ch
!=
traits_type
::
eof
()
and
ch
!=
m_current
[
-
1
]))
return
traits_type
::
eof
();
return
traits_type
::
to_int_type
(
*--
m_current
);
}
return
traits_type
::
to_int_type
(
*--
m_current
);
}
std
::
streamsize
showmanyc
()
{
assert
(
std
::
less_equal
<
const
char
*>
()(
m_current
,
m_end
));
return
m_end
-
m_current
;
}
std
::
streamsize
showmanyc
()
pos_type
seekoff
(
off_type
off
,
std
::
ios_base
::
seekdir
dir
,
std
::
ios_base
::
openmode
which
)
{
switch
(
dir
)
{
assert
(
std
::
less_equal
<
const
char
*>
()(
m_current
,
m_end
));
return
m_end
-
m_current
;
}
case
std
:
:
ios_base
::
beg
:
m_current
=
m_begin
+
off
;
break
;
pos_type
seekoff
(
off_type
off
,
std
::
ios_base
::
seekdir
dir
,
std
::
ios_base
::
openmode
which
)
{
switch
(
dir
)
{
case
std
:
:
ios_base
::
beg
:
m_current
=
m_begin
+
off
;
break
;
case
std
:
:
ios_base
::
end
:
m_current
=
m_end
+
off
;
break
;
case
std
:
:
ios_base
::
cur
:
m_current
+=
off
;
break
;
default
:
break
;
}
case
std
:
:
ios_base
::
end
:
m_current
=
m_end
+
off
;
break
;
if
(
m_current
<
m_begin
)
m_current
=
m_begin
;
if
(
m_current
>
m_end
)
m_current
=
m_end
;
case
std
:
:
ios_base
::
cur
:
m_current
+=
off
;
break
;
return
m_current
-
m_begin
;
default
:
break
;
}
pos_type
seekpos
(
pos_type
pos
,
std
::
ios_base
::
openmode
which
)
{
m_current
=
m_begin
+
pos
;
if
(
m_current
<
m_begin
)
m_current
=
m_begin
;
if
(
m_current
<
m_begin
)
m_current
=
m_begin
;
if
(
m_current
>
m_end
)
m_current
=
m_end
;
if
(
m_current
>
m_end
)
m_current
=
m_end
;
return
m_current
-
m_begin
;
}
return
m_current
-
m_begin
;
}
private
:
rsrc
m_rsrc
;
const
char_type
*
m_begin
;
const
char_type
*
m_end
;
const
char_type
*
m_current
;
};
pos_type
seekpos
(
pos_type
pos
,
std
::
ios_base
::
openmode
which
)
{
m_current
=
m_begin
+
pos
;
using
streambuf
=
basic_streambuf
<
char
,
std
::
char_traits
<
char
>>
;
if
(
m_current
<
m_begin
)
m_current
=
m_begin
;
// --------------------------------------------------------------------
// class mrsrc::istream
if
(
m_current
>
m_end
)
m_current
=
m_end
;
template
<
typename
CharT
,
typename
Traits
>
class
basic_istream
:
public
std
::
basic_istream
<
CharT
,
Traits
>
{
public
:
typedef
CharT
char_type
;
typedef
Traits
traits_type
;
typedef
typename
traits_type
::
int_type
int_type
;
typedef
typename
traits_type
::
pos_type
pos_type
;
typedef
typename
traits_type
::
off_type
off_type
;
return
m_current
-
m_begin
;
}
private
:
private
:
rsrc
m_rsrc
;
const
char_type
*
m_begin
;
const
char_type
*
m_end
;
const
char_type
*
m_current
;
};
using
__streambuf_type
=
basic_streambuf
<
CharT
,
Traits
>
;
using
__istream_type
=
std
::
basic_istream
<
CharT
,
Traits
>
;
using
streambuf
=
basic_streambuf
<
char
,
std
::
char_traits
<
char
>>
;
__streambuf_type
m_buffer
;
public
:
// --------------------------------------------------------------------
// class mrsrc::istream
basic_istream
(
const
std
::
string
&
path
)
:
__istream_type
(
&
m_buffer
)
,
m_buffer
(
path
)
{
this
->
init
(
&
m_buffer
);
}
basic_istream
(
rsrc
&
resource
)
:
__istream_type
(
&
m_buffer
)
,
m_buffer
(
resource
)
\
{
this
->
init
(
&
m_buffer
);
}
basic_istream
(
const
basic_istream
&
)
=
delete
;
template
<
typename
CharT
,
typename
Traits
>
class
basic_istream
:
public
std
::
basic_istream
<
CharT
,
Traits
>
{
public
:
typedef
CharT
char_type
;
typedef
Traits
traits_type
;
typedef
typename
traits_type
::
int_type
int_type
;
typedef
typename
traits_type
::
pos_type
pos_type
;
typedef
typename
traits_type
::
off_type
off_type
;
private
:
using
__streambuf_type
=
basic_streambuf
<
CharT
,
Traits
>
;
using
__istream_type
=
std
::
basic_istream
<
CharT
,
Traits
>
;
__streambuf_type
m_buffer
;
public
:
basic_istream
(
const
std
::
string
&
path
)
:
__istream_type
(
&
m_buffer
)
,
m_buffer
(
path
)
{
this
->
init
(
&
m_buffer
);
}
basic_istream
(
basic_istream
&&
rhs
)
:
__istream_type
(
std
::
move
(
rhs
)
)
,
m_buffer
(
std
::
move
(
rhs
.
m_buffer
)
)
{
__istream_type
::
set_rdbuf
(
&
m_buffer
);
}
basic_istream
(
rsrc
&
resource
)
:
__istream_type
(
&
m_buffer
)
,
m_buffer
(
resource
)
{
this
->
init
(
&
m_buffer
);
}
basic_istream
&
operator
=
(
const
basic_istream
&
)
=
delete
;
basic_istream
(
const
basic_istream
&
)
=
delete
;
basic_istream
&
operator
=
(
basic_istream
&&
rhs
)
{
__istream_type
::
operator
=
(
std
::
move
(
rhs
));
m_buffer
=
std
::
move
(
rhs
.
m_buffer
);
return
*
this
;
}
basic_istream
(
basic_istream
&&
rhs
)
:
__istream_type
(
std
::
move
(
rhs
))
,
m_buffer
(
std
::
move
(
rhs
.
m_buffer
))
{
__istream_type
::
set_rdbuf
(
&
m_buffer
)
;
}
void
swap
(
basic_istream
&
rhs
)
{
__istream_type
::
swap
(
rhs
);
m_buffer
.
swap
(
rhs
.
m_buffer
);
}
basic_istream
&
operator
=
(
const
basic_istream
&
)
=
delete
;
__streambuf_type
*
rdbuf
()
const
{
return
const_cast
<
__streambuf_type
*>
(
&
m_buffer
);
}
};
basic_istream
&
operator
=
(
basic_istream
&&
rhs
)
{
__istream_type
::
operator
=
(
std
::
move
(
rhs
));
m_buffer
=
std
::
move
(
rhs
.
m_buffer
);
return
*
this
;
}
using
istream
=
basic_istream
<
char
,
std
::
char_traits
<
char
>>
;
}
void
swap
(
basic_istream
&
rhs
)
{
__istream_type
::
swap
(
rhs
);
m_buffer
.
swap
(
rhs
.
m_buffer
);
}
__streambuf_type
*
rdbuf
()
const
{
return
const_cast
<
__streambuf_type
*>
(
&
m_buffer
);
}
};
using
istream
=
basic_istream
<
char
,
std
::
char_traits
<
char
>>
;
}
// namespace mrsrc
#endif
...
...
@@ -1188,7 +1193,7 @@ std::unique_ptr<std::istream> loadResource(std::filesystem::path name)
#if defined(CACHE_DIR) and defined(DATA_DIR)
if
(
not
fs
::
exists
(
p
))
{
for
(
const
char
*
dir
:
{
CACHE_DIR
,
DATA_DIR
})
for
(
const
char
*
dir
:
{
CACHE_DIR
,
DATA_DIR
})
{
auto
p2
=
fs
::
path
(
dir
)
/
p
;
if
(
fs
::
exists
(
p2
))
...
...
@@ -1219,4 +1224,4 @@ std::unique_ptr<std::istream> loadResource(std::filesystem::path name)
return
result
;
}
}
}
// namespace cif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment