Some refactoring, better templates

1.) tl::Stream now can read from resources
    (:<path> URL's)
2.) LVS/DRC templates are kept as resource,
    "create_template" uses the URL to read them.
3.) Added samples for LVS
4.) Configured LVS to match sample
This commit is contained in:
matthias 2019-07-13 18:40:00 +02:00
parent ebca5e1ce6
commit 5f27341995
12 changed files with 555 additions and 149 deletions

BIN
samples/lvs/ringo.gds Normal file

Binary file not shown.

27
samples/lvs/schematic.cir Normal file
View File

@ -0,0 +1,27 @@
.SUBCKT RINGO VSS VDD FB ENABLE OUT
X$1 VDD 1 VSS VDD FB ENABLE VSS ND2X1
X$2 VDD 2 VSS VDD 1 VSS INVX1
X$3 VDD 3 VSS VDD 2 VSS INVX1
X$4 VDD 4 VSS VDD 3 VSS INVX1
X$5 VDD 5 VSS VDD 4 VSS INVX1
X$6 VDD 6 VSS VDD 5 VSS INVX1
X$7 VDD 7 VSS VDD 6 VSS INVX1
X$8 VDD 8 VSS VDD 7 VSS INVX1
X$9 VDD 9 VSS VDD 8 VSS INVX1
X$10 VDD 10 VSS VDD 9 VSS INVX1
X$11 VDD FB VSS VDD 10 VSS INVX1
X$12 VDD OUT VSS VDD FB VSS INVX1
.ENDS RINGO
.SUBCKT ND2X1 VDD OUT VSS NWELL B A BULK
M$1 OUT A VDD NWELL PMOS L=0.25U W=1.5U
M$2 VDD B OUT NWELL PMOS L=0.25U W=1.5U
M$3 VSS A 1 BULK NMOS L=0.25U W=0.95U
M$4 1 B OUT BULK NMOS L=0.25U W=0.95U
.ENDS ND2X1
.SUBCKT INVX1 VDD OUT VSS NWELL IN BULK
M$1 VDD IN OUT NWELL PMOS L=0.25U W=1.5U
M$2 VSS IN OUT BULK NMOS L=0.25U W=0.95U
.ENDS INVX1

303
samples/lvs/tech.lyp Normal file
View File

@ -0,0 +1,303 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-properties>
<properties>
<frame-color>#c0c0c0</frame-color>
<fill-color>#c0c0c0</fill-color>
<frame-brightness>0</frame-brightness>
<fill-brightness>0</fill-brightness>
<dither-pattern>I9</dither-pattern>
<line-style>I2</line-style>
<valid>true</valid>
<visible>true</visible>
<transparent>false</transparent>
<width>2</width>
<marked>false</marked>
<xfill>false</xfill>
<animation>0</animation>
<name>1 - NWELL</name>
<source>1/0@1</source>
</properties>
<properties>
<frame-color>#c0c0c0</frame-color>
<fill-color>#c0c0c0</fill-color>
<frame-brightness>48</frame-brightness>
<fill-brightness>48</fill-brightness>
<dither-pattern>C0</dither-pattern>
<line-style>I4</line-style>
<valid>true</valid>
<visible>true</visible>
<transparent>false</transparent>
<width>1</width>
<marked>false</marked>
<xfill>false</xfill>
<animation>0</animation>
<name>3 - PPLUS</name>
<source>3/0@1</source>
</properties>
<properties>
<frame-color>#c0c0c0</frame-color>
<fill-color>#c0c0c0</fill-color>
<frame-brightness>48</frame-brightness>
<fill-brightness>48</fill-brightness>
<dither-pattern>C1</dither-pattern>
<line-style>I4</line-style>
<valid>true</valid>
<visible>true</visible>
<transparent>false</transparent>
<width>1</width>
<marked>false</marked>
<xfill>false</xfill>
<animation>0</animation>
<name>4 - NPLUS</name>
<source>4/0@1</source>
</properties>
<properties>
<frame-color>#ff0000</frame-color>
<fill-color>#ff9d9d</fill-color>
<frame-brightness>-64</frame-brightness>
<fill-brightness>-64</fill-brightness>
<dither-pattern>I3</dither-pattern>
<line-style>I2</line-style>
<valid>true</valid>
<visible>true</visible>
<transparent>false</transparent>
<width>2</width>
<marked>false</marked>
<xfill>false</xfill>
<animation>0</animation>
<name>2 - DIFF</name>
<source>2/0@1</source>
</properties>
<properties>
<frame-color>#91ff00</frame-color>
<fill-color>#91ff00</fill-color>
<frame-brightness>-48</frame-brightness>
<fill-brightness>-48</fill-brightness>
<dither-pattern>I8</dither-pattern>
<line-style/>
<valid>true</valid>
<visible>true</visible>
<transparent>false</transparent>
<width>2</width>
<marked>false</marked>
<xfill>false</xfill>
<animation>0</animation>
<name>5 - POLY</name>
<source>5/0@1</source>
</properties>
<properties>
<frame-color>#008000</frame-color>
<fill-color>#808000</fill-color>
<frame-brightness>0</frame-brightness>
<fill-brightness>0</fill-brightness>
<dither-pattern>I3</dither-pattern>
<line-style>I4</line-style>
<valid>true</valid>
<visible>true</visible>
<transparent>false</transparent>
<width>1</width>
<marked>false</marked>
<xfill>false</xfill>
<animation>0</animation>
<name>6 - THICKOX</name>
<source>THICKOX 6/0@1</source>
</properties>
<properties>
<frame-color>#805000</frame-color>
<fill-color>#805000</fill-color>
<frame-brightness>0</frame-brightness>
<fill-brightness>0</fill-brightness>
<dither-pattern>I3</dither-pattern>
<line-style>I4</line-style>
<valid>true</valid>
<visible>true</visible>
<transparent>false</transparent>
<width>1</width>
<marked>false</marked>
<xfill>false</xfill>
<animation>0</animation>
<name>7 - POLYRES</name>
<source>'7 - SALBL' 7/0@1</source>
</properties>
<properties>
<frame-color>#ff00ff</frame-color>
<fill-color>#ffffff</fill-color>
<frame-brightness>0</frame-brightness>
<fill-brightness>0</fill-brightness>
<dither-pattern>I0</dither-pattern>
<line-style/>
<valid>true</valid>
<visible>true</visible>
<transparent>false</transparent>
<width>2</width>
<marked>false</marked>
<xfill>true</xfill>
<animation>0</animation>
<name>8 - CONTACT</name>
<source>8/0@1</source>
</properties>
<properties>
<frame-color>#8000ff</frame-color>
<fill-color>#9580ff</fill-color>
<frame-brightness>0</frame-brightness>
<fill-brightness>0</fill-brightness>
<dither-pattern>I4</dither-pattern>
<line-style/>
<valid>true</valid>
<visible>true</visible>
<transparent>false</transparent>
<width>2</width>
<marked>false</marked>
<xfill>false</xfill>
<animation>0</animation>
<name>9 - METAL1</name>
<source>9/0@1</source>
</properties>
<properties>
<frame-color>#e872ff</frame-color>
<fill-color>#e872ff</fill-color>
<frame-brightness>-48</frame-brightness>
<fill-brightness>-48</fill-brightness>
<dither-pattern>I1</dither-pattern>
<line-style/>
<valid>true</valid>
<visible>true</visible>
<transparent>false</transparent>
<width>2</width>
<marked>false</marked>
<xfill>true</xfill>
<animation>0</animation>
<name>10 - VIA</name>
<source>10/0@1</source>
</properties>
<properties>
<frame-color>#0000ff</frame-color>
<fill-color>#8086ff</fill-color>
<frame-brightness>0</frame-brightness>
<fill-brightness>0</fill-brightness>
<dither-pattern>I8</dither-pattern>
<line-style/>
<valid>true</valid>
<visible>true</visible>
<transparent>false</transparent>
<width>2</width>
<marked>false</marked>
<xfill>false</xfill>
<animation>0</animation>
<name>11 - METAL2</name>
<source>11/0@1</source>
</properties>
<properties>
<frame-color>#808080</frame-color>
<fill-color>#c0c0c0</fill-color>
<frame-brightness>0</frame-brightness>
<fill-brightness>128</fill-brightness>
<dither-pattern>I43</dither-pattern>
<line-style/>
<valid>true</valid>
<visible>true</visible>
<transparent>true</transparent>
<width>1</width>
<marked>false</marked>
<xfill>false</xfill>
<animation>0</animation>
<name>12 - PAD</name>
<source>12/0@1</source>
</properties>
<properties>
<frame-color>#c0c0c0</frame-color>
<fill-color>#c0c0c0</fill-color>
<frame-brightness>0</frame-brightness>
<fill-brightness>0</fill-brightness>
<dither-pattern>I1</dither-pattern>
<line-style>I4</line-style>
<valid>true</valid>
<visible>true</visible>
<transparent>false</transparent>
<width>1</width>
<marked>false</marked>
<xfill>false</xfill>
<animation>0</animation>
<name>13 - BORDER</name>
<source>13/0@1</source>
</properties>
<properties>
<frame-color>#606060</frame-color>
<fill-color>#606060</fill-color>
<frame-brightness>0</frame-brightness>
<fill-brightness>0</fill-brightness>
<dither-pattern>I1</dither-pattern>
<line-style>I2</line-style>
<valid>true</valid>
<visible>true</visible>
<transparent>false</transparent>
<width>1</width>
<marked>false</marked>
<xfill>true</xfill>
<animation>0</animation>
<name>1000 - MARKING 1</name>
<source>1000/0@1</source>
</properties>
<properties>
<frame-color>#000000</frame-color>
<fill-color>#000000</fill-color>
<frame-brightness>0</frame-brightness>
<fill-brightness>0</fill-brightness>
<dither-pattern>I1</dither-pattern>
<line-style>I2</line-style>
<valid>true</valid>
<visible>true</visible>
<transparent>false</transparent>
<width>1</width>
<marked>false</marked>
<xfill>false</xfill>
<animation>0</animation>
<name>1001 - MARKING 2</name>
<source>1001/0@1</source>
</properties>
<name/>
<custom-dither-pattern>
<pattern>
<line>................</line>
<line>...*............</line>
<line>...*............</line>
<line>...*............</line>
<line>*******.........</line>
<line>...*............</line>
<line>...*............</line>
<line>...*............</line>
<line>................</line>
<line>...........*....</line>
<line>...........*....</line>
<line>...........*....</line>
<line>........*******.</line>
<line>...........*....</line>
<line>...........*....</line>
<line>...........*....</line>
</pattern>
<order>1</order>
<name>custom plus</name>
</custom-dither-pattern>
<custom-dither-pattern>
<pattern>
<line>................</line>
<line>................</line>
<line>................</line>
<line>................</line>
<line>*******.........</line>
<line>................</line>
<line>................</line>
<line>................</line>
<line>................</line>
<line>................</line>
<line>................</line>
<line>................</line>
<line>........*******.</line>
<line>................</line>
<line>................</line>
<line>................</line>
</pattern>
<order>2</order>
<name/>
</custom-dither-pattern>
</layer-properties>

View File

@ -68,13 +68,7 @@ module DRC
register("drc-dsl-xml")
# create a template for the macro editor:
mt = create_template("drc")
mt.text = "# Read about DRC scripts in the User Manual under \"Design Rule Check (DRC)\"\n# This is a sample:\n\npoly = input(6)\nactive = input(1)\ngate = poly &amp; active\ngate.width(0.25.micron).output(100, 0)"
mt.show_in_menu = true
mt.menu_path = "tools_menu.drc.end"
mt.group_name = "drc_scripts"
mt.description = "General;;DRC script (*.lydrc)\nA DRC script using KLayout's DRC language"
mt.category = "drc"
create_template(":/drc-templates/drc.lym")
end

View File

@ -9,4 +9,7 @@
<file alias="drc_interpreters.lym">built-in-macros/drc_interpreters.lym</file>
<file alias="drc_install.lym">built-in-macros/drc_install.lym</file>
</qresource>
<qresource prefix="/drc-templates">
<file alias="drc.lym">templates/drc.lym</file>
</qresource>
</RCC>

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<klayout-macro>
<description>General;;DRC script (*.lydrc)\nA DRC script using KLayout's DRC language</description>
<version/>
<category>drc</category>
<prolog/>
<epilog/>
<doc/>
<autorun>false</autorun>
<autorun-early>false</autorun-early>
<shortcut/>
<show-in-menu>true</show-in-menu>
<group-name>drc_scripts</group-name>
<menu-path>tools_menu.drc.end</menu-path>
<interpreter>ruby</interpreter>
<dsl-interpreter-name/>
<text>
# Read about DRC scripts in the User Manual in "Design Rule Check (DRC)"
# This is a sample:
poly = input(6)
active = input(1)
gate = poly &amp; active
gate.width(0.25.micron).output(100, 0)
</text>
</klayout-macro>

View File

@ -43,6 +43,7 @@
#include "tlString.h"
#include "tlClassRegistry.h"
#include "tlExceptions.h"
#include "tlFileUtils.h"
#include <cstdio>
#include <limits>
@ -487,21 +488,12 @@ MacroEditorDialog::MacroEditorDialog (lay::PluginRoot *pr, lym::MacroCollection
}
std::string url = ":/macro-templates/" + ll;
QResource res (tl::to_qstring (url));
if (res.size () > 0) {
QByteArray data;
if (res.isCompressed ()) {
data = qUncompress ((const unsigned char *)res.data (), (int)res.size ());
} else {
data = QByteArray ((const char *)res.data (), (int)res.size ());
}
lym::Macro *m = new lym::Macro ();
try {
m->rename (tl::to_string (QFileInfo (QUrl (tl::to_qstring (url)).path ()).baseName ()));
m->load_from_string (std::string (data.constData (), data.size ()), url);
m->rename (tl::basename (url));
m->load_from (url);
if (! description.empty ()) {
m->set_description (description_prefix + description);
} else {
@ -522,10 +514,6 @@ MacroEditorDialog::MacroEditorDialog (lay::PluginRoot *pr, lym::MacroCollection
tl::error << "Reading " << url << ": " << ex.msg ();
}
} else {
tl::error << "Macro template resource " << url << " not found";
}
}
}

View File

@ -68,101 +68,7 @@ module LVS
register("lvs-dsl-xml")
# create a template for the macro editor:
mt = create_template("lvs")
mt.text = &lt;&lt;"END"
# Try this sample script with this layout:
# https://github.com/KLayout/klayout/tree/master/samples/lvs/ringo.gds
# and this schematic:
# https://github.com/KLayout/klayout/tree/master/samples/lvs/schematic.cir
# Reference schematic (if not absolute: path relative to original layout)
schematic("schematic.cir")
# Tip: you can also use:
# schematic(source.path.sub(/\.(oas|gds)/, ".cir"))
# to derive the schematic name from the layout file's name
# by substituting .oas or .gsd with .cir.
# Enable hierarchical mode
deep
# Produce LVS report
report_lvs
# -------------------------------------------------------------------
# Layers
# Drawing layers
nwell = input(1, 0)
active = input(2, 0)
pplus = input(3, 0)
nplus = input(4, 0)
poly = input(5, 0)
contact = input(8, 0)
metal1 = input(9, 0) # includes labels
via1 = input(10, 0)
metal2 = input(11, 0) # includes labels
# Bulk layer for terminal provisioning
bulk = polygon_layer
# Computed layers
active_in_nwell = active &amp; nwell
pactive = active_in_nwell &amp; pplus
pgate = pactive &amp; poly
psd = pactive - pgate
ntie = active_in_nwell &amp; nplus
active_outside_nwell = active - nwell
nactive = active_outside_nwell &amp; nplus
ngate = nactive &amp; poly
nsd = nactive - ngate
ptie = active_outside_nwell &amp; pplus
# -------------------------------------------------------------------
# Device extraction
# PMOS transistor device extraction
extract_devices(mos4("PMOS"), { "SD" => psd, "G" => pgate, "W" => nwell,
"tS" => psd, "tD" => psd, "tG" => poly, "tW" => nwell })
# NMOS transistor device extraction
extract_devices(mos4("NMOS"), { "SD" => nsd, "G" => ngate, "W" => bulk,
"tS" => nsd, "tD" => nsd, "tG" => poly, "tW" => bulk })
# -------------------------------------------------------------------
# Connectivity
# Inter-layer
connect(psd, contact)
connect(nsd, contact)
connect(poly, contact)
connect(ntie, contact)
connect(nwell, ntie)
connect(ptie, contact)
connect(contact, metal1)
connect(metal1, via1)
connect(via1, metal2)
# Global
connect_global(bulk, "SUBSTRATE")
connect_global(ptie, "SUBSTRATE")
# -------------------------------------------------------------------
# Netlist and compare
# Netlist normalization
netlist.simplify
# Netlist vs. netlist
compare
END
mt.show_in_menu = true
mt.menu_path = "tools_menu.lvs.end"
mt.group_name = "lvs_scripts"
mt.description = "General;;LVS script (*.lylvs)\nA LVS script using KLayout's LVS language"
mt.category = "lvs"
create_template(":/lvs-templates/lvs.lym")
# if available, create a menu branch
if RBA::Application::instance &amp;&amp; RBA::Application::instance.main_window

View File

@ -5,4 +5,7 @@
<file alias="lvs_interpreters.lym">built-in-macros/lvs_interpreters.lym</file>
<file alias="lvs_install.lym">built-in-macros/lvs_install.lym</file>
</qresource>
<qresource prefix="/lvs-templates">
<file alias="lvs.lym">templates/lvs.lym</file>
</qresource>
</RCC>

View File

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="utf-8"?>
<klayout-macro>
<description>General;;LVS script (*.lylvs)\nA LVS script using KLayout's LVS language</description>
<version/>
<category>lvs</category>
<prolog/>
<epilog/>
<doc/>
<autorun>false</autorun>
<autorun-early>false</autorun-early>
<shortcut/>
<show-in-menu>true</show-in-menu>
<group-name>lvs_scripts</group-name>
<menu-path>tools_menu.lvs.end</menu-path>
<interpreter></interpreter>
<dsl-interpreter-name/>
<text>
# Read about LVS scripts in the User Manual in "Layout vs. Schematic (LVS)"
# Try this sample script with this layout:
# https://github.com/KLayout/klayout/tree/master/samples/lvs/ringo.gds
# and this schematic:
# https://github.com/KLayout/klayout/tree/master/samples/lvs/schematic.cir
# Reference schematic (if not absolute: path relative to original layout)
schematic("schematic.cir")
# Tip: you can also use:
# schematic(source.path.sub(/\.(oas|gds)/, ".cir"))
# to derive the schematic name from the layout file's name
# by substituting .oas or .gsd with .cir.
# Enable hierarchical mode
deep
# Produce LVS report
report_lvs
# -------------------------------------------------------------------
# Layers
# Drawing layers
nwell = input(1, 0)
active = input(2, 0)
pplus = input(3, 0)
nplus = input(4, 0)
poly = input(5, 0)
contact = input(8, 0)
metal1 = input(9, 0) # includes labels
via1 = input(10, 0)
metal2 = input(11, 0) # includes labels
# Bulk layer for terminal provisioning
bulk = polygon_layer
# Computed layers
active_in_nwell = active &amp; nwell
pactive = active_in_nwell &amp; pplus
pgate = pactive &amp; poly
psd = pactive - pgate
ntie = active_in_nwell &amp; nplus
active_outside_nwell = active - nwell
nactive = active_outside_nwell &amp; nplus
ngate = nactive &amp; poly
nsd = nactive - ngate
ptie = active_outside_nwell &amp; pplus
# -------------------------------------------------------------------
# Device extraction
# PMOS transistor device extraction
extract_devices(mos4("PMOS"), { "SD" => psd, "G" => pgate, "W" => nwell,
"tS" => psd, "tD" => psd, "tG" => poly, "tW" => nwell })
# NMOS transistor device extraction
extract_devices(mos4("NMOS"), { "SD" => nsd, "G" => ngate, "W" => bulk,
"tS" => nsd, "tD" => nsd, "tG" => poly, "tW" => bulk })
# -------------------------------------------------------------------
# Connectivity
# Inter-layer
connect(psd, contact)
connect(nsd, contact)
connect(poly, contact)
connect(ntie, contact)
connect(nwell, ntie)
connect(ptie, contact)
connect(contact, metal1)
connect(metal1, via1)
connect(via1, metal2)
# Global
connect_global(bulk, "SUBSTRATE")
connect_global(ptie, "SUBSTRATE")
# -------------------------------------------------------------------
# Netlist and compare
# Netlist normalization
netlist.simplify
# Netlist vs. netlist
compare
</text>
</klayout-macro>

View File

@ -29,6 +29,7 @@
#include "rba.h"
#include "tlClassRegistry.h"
#include "tlFileUtils.h"
#include <cstdio>
@ -189,15 +190,19 @@ public:
return m_suffix;
}
lym::Macro *create_template (const std::string &name)
lym::Macro *create_template (const std::string &url)
{
if (! mp_registration) {
throw std::runtime_error (tl::to_string (QObject::tr ("MacroInterpreter::create_template must be called after register")));
}
lym::Macro *m = new lym::Macro ();
if (! url.empty ()) {
m->load_from (url);
}
m->rename (tl::basename (url));
m->rename (name);
m->set_readonly (true);
m->set_dsl_interpreter (m_name);
m->set_interpreter (lym::Macro::DSLInterpreter);
@ -281,10 +286,9 @@ Class<gsi::MacroInterpreter> decl_MacroInterpreter ("lay", "MacroInterpreter",
"is set to 'dsl' can use this object to run the script. For executing a script, the system will "
"call the interpreter's \\execute method.\n"
) +
gsi::method ("create_template", &MacroInterpreter::create_template,
gsi::method ("create_template", &MacroInterpreter::create_template, gsi::arg ("url"),
"@brief Creates a new macro template\n"
"@args name\n"
"@param name The template name. This is an arbitrary string which should be unique.\n"
"@url The template will be initialized from that URL.\n"
"\n"
"This method will create a register a new macro template. It returns a \\Macro object which "
"can be modified in order to adjust the template (for example to set description, add a content, "

View File

@ -44,6 +44,11 @@
#include "tlString.h"
#include "tlUri.h"
#if defined(HAVE_QT)
# include <QByteArray>
# include <QResource>
#endif
namespace tl
{
@ -155,9 +160,34 @@ InputStream::InputStream (const std::string &abstract_path)
{
m_bcap = 4096; // initial buffer capacity
m_blen = 0;
mp_buffer = new char [m_bcap];
mp_buffer = 0;
tl::Extractor ex (abstract_path.c_str ());
#if defined(HAVE_QT)
if (ex.test (":")) {
QResource res (tl::to_qstring (abstract_path));
if (res.size () > 0) {
QByteArray data;
if (res.isCompressed ()) {
data = qUncompress ((const unsigned char *)res.data (), (int)res.size ());
} else {
data = QByteArray ((const char *)res.data (), (int)res.size ());
}
mp_buffer = new char[data.size ()];
memcpy (mp_buffer, data.constData (), data.size ());
mp_bptr = mp_buffer;
m_bcap = data.size ();
m_blen = m_bcap;
}
} else
#endif
#if defined(HAVE_CURL) || defined(HAVE_QT)
if (ex.test ("http:") || ex.test ("https:")) {
mp_delegate = new InputHttpStream (abstract_path);
@ -165,15 +195,17 @@ InputStream::InputStream (const std::string &abstract_path)
#endif
if (ex.test ("pipe:")) {
mp_delegate = new InputPipe (ex.get ());
} else
if (ex.test ("file:")) {
} else if (ex.test ("file:")) {
tl::URI uri (abstract_path);
mp_delegate = new InputZLibFile (uri.path ());
} else
{
} else {
mp_delegate = new InputZLibFile (abstract_path);
}
if (! mp_buffer) {
mp_buffer = new char [m_bcap];
}
m_owns_delegate = true;
}
@ -182,9 +214,17 @@ std::string InputStream::absolute_path (const std::string &abstract_path)
// TODO: align this implementation with InputStream ctor
tl::Extractor ex (abstract_path.c_str ());
#if defined(HAVE_QT)
if (ex.test (":")) {
return abstract_path;
} else
#endif
#if defined(HAVE_CURL) || defined(HAVE_QT)
if (ex.test ("http:") || ex.test ("https:")) {
return abstract_path;
} else if (ex.test ("pipe:")) {
} else
#endif
if (ex.test ("pipe:")) {
return abstract_path;
} else if (ex.test ("file:")) {
tl::URI uri (abstract_path);
@ -247,7 +287,9 @@ InputStream::get (size_t n, bool bypass_inflate)
memmove (mp_buffer, mp_bptr, m_blen);
}
if (mp_delegate) {
m_blen += mp_delegate->read (mp_buffer + m_blen, m_bcap - m_blen);
}
mp_bptr = mp_buffer;
}
@ -308,12 +350,12 @@ InputStream::read_all ()
return str;
}
void InputStream::copy_to(tl::OutputStream &os)
void InputStream::copy_to (tl::OutputStream &os)
{
const size_t chunk = 65536;
char b [chunk];
size_t read;
while ((read = mp_delegate->read (b, sizeof (b))) > 0) {
while (mp_delegate && (read = mp_delegate->read (b, sizeof (b))) > 0) {
os.put (b, read);
}
}