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
d5d96c58
Commit
d5d96c58
authored
Nov 18, 2020
by
Maarten L. Hekkelman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
resource loading
parent
9b61a06e
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
462 additions
and
31 deletions
+462
-31
changelog
+7
-0
include/cif++/CifUtils.hpp
+7
-0
src/Cif++.cpp
+8
-31
src/CifUtils.cpp
+440
-0
No files found.
changelog
0 → 100644
View file @
d5d96c58
Version 1.0.1
- Changed the way resources are looked up, local dir first,
then /var/cache and finally compiled in resources (with mrc).
Version 1.0.0
- First public release
\ No newline at end of file
include/cif++/CifUtils.hpp
View file @
d5d96c58
...
@@ -33,6 +33,8 @@
...
@@ -33,6 +33,8 @@
#include <cassert>
#include <cassert>
#include <memory>
#include <memory>
#include <list>
#include <list>
#include <iostream>
#include <filesystem>
#include <unistd.h>
#include <unistd.h>
...
@@ -190,6 +192,11 @@ class Progress
...
@@ -190,6 +192,11 @@ class Progress
struct
ProgressImpl
*
mImpl
;
struct
ProgressImpl
*
mImpl
;
};
};
// --------------------------------------------------------------------
// Resources
std
::
unique_ptr
<
std
::
istream
>
loadResource
(
std
::
filesystem
::
path
name
);
}
}
src/Cif++.cpp
View file @
d5d96c58
...
@@ -3093,39 +3093,16 @@ void File::loadDictionary()
...
@@ -3093,39 +3093,16 @@ void File::loadDictionary()
void
File
::
loadDictionary
(
const
char
*
dict
)
void
File
::
loadDictionary
(
const
char
*
dict
)
{
{
for
(;;)
fs
::
path
dict_name
(
dict
);
{
fs
::
path
name
(
dict
);
try
{
if
(
fs
::
exists
(
name
))
{
std
::
ifstream
is
(
name
);
loadDictionary
(
is
);
break
;
}
}
catch
(...)
{}
fs
::
path
datadir
=
CACHE_DIR
;
auto
data
=
loadResource
(
dict
);
if
(
not
data
and
dict_name
.
extension
().
string
()
!=
".dic"
)
if
(
not
fs
::
is_directory
(
datadir
))
data
=
loadResource
(
dict_name
.
parent_path
()
/
(
dict_name
.
filename
().
string
()
+
".dic"
));
throw
std
::
runtime_error
(
"Could not find dictionary "
+
name
.
string
()
+
" and "
CACHE_DIR
" also does not exist"
);
name
=
datadir
/
name
;
if
(
not
data
)
if
(
not
fs
::
exists
(
name
)
and
name
.
extension
().
string
()
!=
".dic"
)
throw
std
::
runtime_error
(
"Dictionary not found or defined ("
+
dict_name
.
string
()
+
")"
);
name
=
datadir
/
(
name
.
string
()
+
".dic"
);
loadDictionary
(
*
data
);
if
(
fs
::
exists
(
name
))
{
std
::
ifstream
is
(
name
);
loadDictionary
(
is
);
break
;
}
throw
std
::
runtime_error
(
"Dictionary not found or defined ("
+
name
.
string
()
+
")"
);
}
}
}
void
File
::
loadDictionary
(
std
::
istream
&
is
)
void
File
::
loadDictionary
(
std
::
istream
&
is
)
...
...
src/CifUtils.cpp
View file @
d5d96c58
...
@@ -748,3 +748,443 @@ void Progress::message(const std::string& inMessage)
...
@@ -748,3 +748,443 @@ void Progress::message(const std::string& inMessage)
}
}
}
}
// --------------------------------------------------------------------
//
// Try to find a named resource. Can be either a local file with this name,
// a file located in our cache directory or a resource linked in with mrc.
//
// We have a special, private version of mrsrc here. To be able to create
// shared libraries and still be able to link when there's no mrc used.
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
;
};
}
extern
const
__attribute__
((
weak
))
mrsrc
::
rsrc_imp
gResourceIndex
[];
extern
const
__attribute__
((
weak
))
char
gResourceData
[];
extern
const
__attribute__
((
weak
))
char
gResourceName
[];
namespace
mrsrc
{
class
rsrc_data
{
public
:
static
rsrc_data
&
instance
()
{
static
rsrc_data
s_instance
;
return
s_instance
;
}
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
;
}
private
:
rsrc_data
()
{
if
(
gResourceIndex
and
gResourceIndex
and
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
=
""
;
};
/// \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
())
{}
rsrc
(
const
rsrc
&
other
)
:
m_impl
(
other
.
m_impl
)
{}
rsrc
&
operator
=
(
const
rsrc
&
other
)
{
m_impl
=
other
.
m_impl
;
return
*
this
;
}
rsrc
(
std
::
filesystem
::
path
path
);
std
::
string
name
()
const
{
return
rsrc_data
::
instance
().
name
(
m_impl
->
m_name
);
}
const
char
*
data
()
const
{
return
rsrc_data
::
instance
().
data
(
m_impl
->
m_data
);
}
unsigned
long
size
()
const
{
return
m_impl
->
m_size
;
}
explicit
operator
bool
()
const
{
return
m_impl
!=
NULL
and
m_impl
->
m_size
>
0
;
}
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
)
{}
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
;
}
reference
operator
*
()
{
return
m_cur
;
}
pointer
operator
->
()
{
return
&
m_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
operator
++
(
int
)
{
auto
tmp
(
*
this
);
this
->
operator
++
();
return
tmp
;
}
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
;
}
private
:
value_type
m_cur
;
};
using
iterator
=
iterator_t
<
rsrc
>
;
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
);
}
iterator
end
()
const
{
return
iterator
(
nullptr
);
}
private
:
rsrc
(
const
rsrc_imp
*
imp
)
:
m_impl
(
imp
)
{}
const
rsrc_imp
*
m_impl
;
};
inline
rsrc
::
rsrc
(
std
::
filesystem
::
path
p
)
{
m_impl
=
rsrc_data
::
instance
().
index
();
// 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
)
{
auto
name
=
*
pb
++
;
const
rsrc_imp
*
impl
=
nullptr
;
for
(
rsrc
child
:
*
this
)
{
if
(
child
.
name
()
==
name
)
{
impl
=
child
.
m_impl
;
break
;
}
}
m_impl
=
impl
;
}
if
(
pb
!=
pe
)
// not found
m_impl
=
nullptr
;
}
// --------------------------------------------------------------------
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
();
}
basic_streambuf
(
const
basic_streambuf
&
)
=
delete
;
basic_streambuf
(
basic_streambuf
&&
rhs
)
:
basic_streambuf
(
rhs
.
m_rsrc
)
{
}
basic_streambuf
&
operator
=
(
const
basic_streambuf
&
)
=
delete
;
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
);
}
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
;
}
int_type
underflow
()
{
if
(
m_current
==
m_end
)
return
traits_type
::
eof
();
return
traits_type
::
to_int_type
(
*
m_current
);
}
int_type
uflow
()
{
if
(
m_current
==
m_end
)
return
traits_type
::
eof
();
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
();
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
;
}
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
;
}
if
(
m_current
<
m_begin
)
m_current
=
m_begin
;
if
(
m_current
>
m_end
)
m_current
=
m_end
;
return
m_current
-
m_begin
;
}
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_end
)
m_current
=
m_end
;
return
m_current
-
m_begin
;
}
private
:
rsrc
m_rsrc
;
const
char_type
*
m_begin
;
const
char_type
*
m_end
;
const
char_type
*
m_current
;
};
using
streambuf
=
basic_streambuf
<
char
,
std
::
char_traits
<
char
>>
;
// --------------------------------------------------------------------
// class mrsrc::istream
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
(
rsrc
&
resource
)
:
__istream_type
(
&
m_buffer
)
,
m_buffer
(
resource
)
\
{
this
->
init
(
&
m_buffer
);
}
basic_istream
(
const
basic_istream
&
)
=
delete
;
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
&
operator
=
(
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
;
}
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
cif
{
// --------------------------------------------------------------------
std
::
unique_ptr
<
std
::
istream
>
loadResource
(
std
::
filesystem
::
path
name
)
{
std
::
unique_ptr
<
std
::
istream
>
result
;
fs
::
path
p
=
name
;
if
(
not
fs
::
exists
(
p
))
p
=
fs
::
path
(
CACHE_DIR
)
/
p
;
if
(
fs
::
exists
(
p
))
{
std
::
unique_ptr
<
std
::
ifstream
>
file
(
new
std
::
ifstream
(
p
));
if
(
file
->
is_open
())
result
.
reset
(
file
.
release
());
}
if
(
not
result
)
{
mrsrc
::
rsrc
rsrc
(
name
);
if
(
rsrc
)
result
.
reset
(
new
mrsrc
::
istream
(
rsrc
));
}
return
result
;
}
}
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