1 // export.cc -- Export declarations in Go frontend.
3 // Copyright 2009 The Go Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file.
14 #include "statements.h"
17 #include "go-linemap.h"
20 // This file handles exporting global declarations.
24 const int Export::magic_len
;
26 // Current version magic string.
27 const char Export::cur_magic
[Export::magic_len
] =
32 // Magic strings for previous versions (still supported).
33 const char Export::v1_magic
[Export::magic_len
] =
37 const char Export::v2_magic
[Export::magic_len
] =
42 const int Export::checksum_len
;
46 Export::Export(Stream
* stream
)
47 : stream_(stream
), type_refs_(), type_index_(1), packages_()
49 go_assert(Export::checksum_len
== Go_sha1_helper::checksum_len
);
52 // A functor to sort Named_object pointers by name.
57 operator()(const Named_object
* n1
, const Named_object
* n2
) const
58 { return n1
->name() < n2
->name(); }
61 // Return true if we should export NO.
64 should_export(Named_object
* no
)
66 // We only export objects which are locally defined.
67 if (no
->package() != NULL
)
70 // We don't export packages.
74 // We don't export hidden names.
75 if (Gogo::is_hidden_name(no
->name()))
78 // We don't export various special functions.
79 if (Gogo::is_special_name(no
->name()))
82 // Methods are exported with the type, not here.
84 && no
->func_value()->type()->is_method())
86 if (no
->is_function_declaration()
87 && no
->func_declaration_value()->type()->is_method())
90 // Don't export dummy global variables created for initializers when
92 if (no
->is_variable() && no
->name()[0] == '_' && no
->name()[1] == '.')
98 // Export those identifiers marked for exporting.
101 Export::export_globals(const std::string
& package_name
,
102 const std::string
& prefix
,
103 const std::string
& pkgpath
,
104 const std::map
<std::string
, Package
*>& packages
,
105 const std::map
<std::string
, Package
*>& imports
,
106 const std::string
& import_init_fn
,
107 const Import_init_set
& imported_init_fns
,
108 const Bindings
* bindings
)
110 // If there have been any errors so far, don't try to export
111 // anything. That way the export code doesn't have to worry about
112 // mismatched types or other confusions.
116 // Export the symbols in sorted order. That will reduce cases where
117 // irrelevant changes to the source code affect the exported
119 std::vector
<Named_object
*> exports
;
120 exports
.reserve(bindings
->size_definitions());
122 for (Bindings::const_definitions_iterator p
= bindings
->begin_definitions();
123 p
!= bindings
->end_definitions();
125 if (should_export(*p
))
126 exports
.push_back(*p
);
128 for (Bindings::const_declarations_iterator p
=
129 bindings
->begin_declarations();
130 p
!= bindings
->end_declarations();
133 // We export a function declaration as it may be implemented in
134 // supporting C code. We do not export type declarations.
135 if (p
->second
->is_function_declaration()
136 && should_export(p
->second
))
137 exports
.push_back(p
->second
);
140 std::sort(exports
.begin(), exports
.end(), Sort_bindings());
142 // Find all packages not explicitly imported but mentioned by types.
143 Unordered_set(const Package
*) type_imports
;
144 this->prepare_types(&exports
, &type_imports
);
146 // Although the export data is readable, at least this version is,
147 // it is conceptually a binary format. Start with a four byte
149 this->write_bytes(Export::cur_magic
, Export::magic_len
);
152 this->write_c_string("package ");
153 this->write_string(package_name
);
154 this->write_c_string("\n");
156 // The prefix or package path, used for all global symbols.
159 go_assert(!pkgpath
.empty());
160 this->write_c_string("pkgpath ");
161 this->write_string(pkgpath
);
165 this->write_c_string("prefix ");
166 this->write_string(prefix
);
168 this->write_c_string("\n");
170 this->write_packages(packages
);
172 this->write_imports(imports
, type_imports
);
174 this->write_imported_init_fns(package_name
, import_init_fn
,
177 // FIXME: It might be clever to add something about the processor
178 // and ABI being used, although ideally any problems in that area
179 // would be caught by the linker.
181 for (std::vector
<Named_object
*>::const_iterator p
= exports
.begin();
184 (*p
)->export_named_object(this);
186 std::string checksum
= this->stream_
->checksum();
187 std::string s
= "checksum ";
188 for (std::string::const_iterator p
= checksum
.begin();
192 unsigned char c
= *p
;
193 unsigned int dig
= c
>> 4;
194 s
+= dig
< 10 ? '0' + dig
: 'A' + dig
- 10;
196 s
+= dig
< 10 ? '0' + dig
: 'A' + dig
- 10;
199 this->stream_
->write_checksum(s
);
202 // Traversal class to find referenced types.
204 class Find_types_to_prepare
: public Traverse
207 Find_types_to_prepare(Unordered_set(const Package
*)* imports
)
208 : Traverse(traverse_types
),
215 // Traverse the components of a function type.
217 traverse_function(Function_type
*);
219 // Traverse the methods of a named type, and register its package.
221 traverse_named_type(Named_type
*);
224 // List of packages we are building.
225 Unordered_set(const Package
*)* imports_
;
231 Find_types_to_prepare::type(Type
* type
)
234 if (type
->forward_declaration_type() != NULL
)
235 return TRAVERSE_CONTINUE
;
237 // At this stage of compilation traversing interface types traverses
238 // the final list of methods, but we export the locally defined
239 // methods. If there is an embedded interface type we need to make
240 // sure to export that. Check classification, rather than calling
241 // the interface_type method, because we want to handle named types
243 if (type
->classification() == Type::TYPE_INTERFACE
)
245 Interface_type
* it
= type
->interface_type();
246 const Typed_identifier_list
* methods
= it
->local_methods();
249 for (Typed_identifier_list::const_iterator p
= methods
->begin();
253 if (p
->name().empty())
254 Type::traverse(p
->type(), this);
256 this->traverse_function(p
->type()->function_type());
259 return TRAVERSE_SKIP_COMPONENTS
;
262 Named_type
* nt
= type
->named_type();
264 this->traverse_named_type(nt
);
266 return TRAVERSE_CONTINUE
;
269 // Traverse the types in a function type. We don't need the function
270 // type tself, just the receiver, parameter, and result types.
273 Find_types_to_prepare::traverse_function(Function_type
* type
)
275 go_assert(type
!= NULL
);
276 if (this->remember_type(type
))
278 const Typed_identifier
* receiver
= type
->receiver();
279 if (receiver
!= NULL
)
280 Type::traverse(receiver
->type(), this);
281 const Typed_identifier_list
* parameters
= type
->parameters();
282 if (parameters
!= NULL
)
283 parameters
->traverse(this);
284 const Typed_identifier_list
* results
= type
->results();
286 results
->traverse(this);
289 // Traverse the methods of a named type, and record its package.
292 Find_types_to_prepare::traverse_named_type(Named_type
* nt
)
294 const Package
* package
= nt
->named_object()->package();
296 this->imports_
->insert(package
);
298 // We have to traverse the methods of named types, because we are
299 // going to export them. This is not done by ordinary type
301 const Bindings
* methods
= nt
->local_methods();
304 for (Bindings::const_definitions_iterator pm
=
305 methods
->begin_definitions();
306 pm
!= methods
->end_definitions();
308 this->traverse_function((*pm
)->func_value()->type());
310 for (Bindings::const_declarations_iterator pm
=
311 methods
->begin_declarations();
312 pm
!= methods
->end_declarations();
315 Named_object
* mno
= pm
->second
;
316 if (mno
->is_function_declaration())
317 this->traverse_function(mno
->func_declaration_value()->type());
322 // Collect all the pacakges we see in types, so that if we refer to
323 // any types from indirectly importe packages we can tell the importer
324 // about the package.
327 Export::prepare_types(const std::vector
<Named_object
*>* exports
,
328 Unordered_set(const Package
*)* imports
)
330 // Use a single index of the traversal class because traversal
331 // classes keep track of which types they've already seen. That
332 // lets us avoid type reference loops.
333 Find_types_to_prepare
find(imports
);
335 // Traverse all the exported objects.
336 for (std::vector
<Named_object
*>::const_iterator p
= exports
->begin();
340 Named_object
* no
= *p
;
341 switch (no
->classification())
343 case Named_object::NAMED_OBJECT_CONST
:
345 Type
* t
= no
->const_value()->type();
346 if (t
!= NULL
&& !t
->is_abstract())
347 Type::traverse(t
, &find
);
351 case Named_object::NAMED_OBJECT_TYPE
:
352 Type::traverse(no
->type_value(), &find
);
355 case Named_object::NAMED_OBJECT_VAR
:
356 Type::traverse(no
->var_value()->type(), &find
);
359 case Named_object::NAMED_OBJECT_FUNC
:
360 find
.traverse_function(no
->func_value()->type());
363 case Named_object::NAMED_OBJECT_FUNC_DECLARATION
:
364 find
.traverse_function(no
->func_declaration_value()->type());
368 // We shouldn't see anything else. If we do we'll give an
369 // error later when we try to actually export it.
378 packages_compare(const Package
* a
, const Package
* b
)
380 return a
->package_name() < b
->package_name();
383 // Write out all the known packages whose pkgpath symbol is not a
384 // simple transformation of the pkgpath, so that the importing code
385 // can reliably know it.
388 Export::write_packages(const std::map
<std::string
, Package
*>& packages
)
390 // Sort for consistent output.
391 std::vector
<Package
*> out
;
392 for (std::map
<std::string
, Package
*>::const_iterator p
= packages
.begin();
396 if (p
->second
->pkgpath_symbol()
397 != Gogo::pkgpath_for_symbol(p
->second
->pkgpath()))
398 out
.push_back(p
->second
);
401 std::sort(out
.begin(), out
.end(), packages_compare
);
403 for (std::vector
<Package
*>::const_iterator p
= out
.begin();
407 this->write_c_string("package ");
408 this->write_string((*p
)->package_name());
409 this->write_c_string(" ");
410 this->write_string((*p
)->pkgpath());
411 this->write_c_string(" ");
412 this->write_string((*p
)->pkgpath_symbol());
413 this->write_c_string("\n");
417 // Sort imported packages.
420 import_compare(const std::pair
<std::string
, Package
*>& a
,
421 const std::pair
<std::string
, Package
*>& b
)
423 return a
.first
< b
.first
;
426 // Write out the imported packages.
429 Export::write_imports(const std::map
<std::string
, Package
*>& imports
,
430 const Unordered_set(const Package
*)& type_imports
)
432 // Sort the imports for more consistent output.
433 Unordered_set(const Package
*) seen
;
434 std::vector
<std::pair
<std::string
, Package
*> > sorted_imports
;
435 for (std::map
<std::string
, Package
*>::const_iterator p
= imports
.begin();
439 sorted_imports
.push_back(std::make_pair(p
->first
, p
->second
));
440 seen
.insert(p
->second
);
443 std::sort(sorted_imports
.begin(), sorted_imports
.end(), import_compare
);
445 for (std::vector
<std::pair
<std::string
, Package
*> >::const_iterator p
=
446 sorted_imports
.begin();
447 p
!= sorted_imports
.end();
450 this->write_c_string("import ");
451 this->write_string(p
->second
->package_name());
452 this->write_c_string(" ");
453 this->write_string(p
->second
->pkgpath());
454 this->write_c_string(" \"");
455 this->write_string(p
->first
);
456 this->write_c_string("\"\n");
458 this->packages_
.insert(p
->second
);
461 // Write out a separate list of indirectly imported packages.
462 std::vector
<const Package
*> indirect_imports
;
463 for (Unordered_set(const Package
*)::const_iterator p
=
464 type_imports
.begin();
465 p
!= type_imports
.end();
468 if (seen
.find(*p
) == seen
.end())
469 indirect_imports
.push_back(*p
);
472 std::sort(indirect_imports
.begin(), indirect_imports
.end(),
475 for (std::vector
<const Package
*>::const_iterator p
=
476 indirect_imports
.begin();
477 p
!= indirect_imports
.end();
480 this->write_c_string("indirectimport ");
481 this->write_string((*p
)->package_name());
482 this->write_c_string(" ");
483 this->write_string((*p
)->pkgpath());
484 this->write_c_string("\n");
489 Export::add_init_graph_edge(Init_graph
* init_graph
, unsigned src
, unsigned sink
)
491 Init_graph::iterator it
= init_graph
->find(src
);
492 if (it
!= init_graph
->end())
493 it
->second
.insert(sink
);
496 std::set
<unsigned> succs
;
498 (*init_graph
)[src
] = succs
;
502 // Constructs the imported portion of the init graph, e.g. those
503 // edges that we read from imported packages.
506 Export::populate_init_graph(Init_graph
* init_graph
,
507 const Import_init_set
& imported_init_fns
,
508 const std::map
<std::string
, unsigned>& init_idx
)
510 for (Import_init_set::const_iterator p
= imported_init_fns
.begin();
511 p
!= imported_init_fns
.end();
514 const Import_init
* ii
= *p
;
515 std::map
<std::string
, unsigned>::const_iterator srcit
=
516 init_idx
.find(ii
->init_name());
517 go_assert(srcit
!= init_idx
.end());
518 unsigned src
= srcit
->second
;
519 for (std::set
<std::string
>::const_iterator pci
= ii
->precursors().begin();
520 pci
!= ii
->precursors().end();
523 std::map
<std::string
, unsigned>::const_iterator it
=
525 go_assert(it
!= init_idx
.end());
526 unsigned sink
= it
->second
;
527 add_init_graph_edge(init_graph
, src
, sink
);
532 // Write out the initialization functions which need to run for this
536 Export::write_imported_init_fns(const std::string
& package_name
,
537 const std::string
& import_init_fn
,
538 const Import_init_set
& imported_init_fns
)
540 if (import_init_fn
.empty() && imported_init_fns
.empty()) return;
542 // Maps a given init function to the its index in the exported "init" clause.
543 std::map
<std::string
, unsigned> init_idx
;
545 this->write_c_string("init");
547 if (!import_init_fn
.empty())
549 this->write_c_string(" ");
550 this->write_string(package_name
);
551 this->write_c_string(" ");
552 this->write_string(import_init_fn
);
553 init_idx
[import_init_fn
] = 0;
556 if (imported_init_fns
.empty())
558 this->write_c_string("\n");
562 typedef std::map
<int, std::vector
<std::string
> > level_map
;
563 Init_graph init_graph
;
564 level_map inits_at_level
;
566 // Walk through the set of import inits (already sorted by
567 // init fcn name) and write them out to the exports.
568 for (Import_init_set::const_iterator p
= imported_init_fns
.begin();
569 p
!= imported_init_fns
.end();
572 const Import_init
* ii
= *p
;
574 if (ii
->init_name() == import_init_fn
)
577 this->write_c_string(" ");
578 this->write_string(ii
->package_name());
579 this->write_c_string(" ");
580 this->write_string(ii
->init_name());
582 // Populate init_idx.
583 go_assert(init_idx
.find(ii
->init_name()) == init_idx
.end());
584 unsigned idx
= init_idx
.size();
585 init_idx
[ii
->init_name()] = idx
;
587 // If the init function has a non-negative priority value, this
588 // is an indication that it was referred to in an older version
589 // export data section (e.g. we read a legacy object
590 // file). Record such init fcns so that we can fix up the graph
591 // for them (handled later in this function).
592 if (ii
->priority() > 0)
594 level_map::iterator it
= inits_at_level
.find(ii
->priority());
595 if (it
== inits_at_level
.end())
597 std::vector
<std::string
> l
;
598 l
.push_back(ii
->init_name());
599 inits_at_level
[ii
->priority()] = l
;
602 it
->second
.push_back(ii
->init_name());
605 this->write_c_string("\n");
607 // Create the init graph. Start by populating the graph with
608 // all the edges we inherited from imported packages.
609 populate_init_graph(&init_graph
, imported_init_fns
, init_idx
);
611 // Now add edges from the local init function to each of the
613 if (!import_init_fn
.empty())
616 go_assert(init_idx
[import_init_fn
] == 0);
617 for (Import_init_set::const_iterator p
= imported_init_fns
.begin();
618 p
!= imported_init_fns
.end();
621 const Import_init
* ii
= *p
;
622 unsigned sink
= init_idx
[ii
->init_name()];
623 add_init_graph_edge(&init_graph
, src
, sink
);
627 // In the scenario where one or more of the packages we imported
628 // was written with the legacy export data format, add dummy edges
629 // to capture the priority relationships. Here is a package import
630 // graph as an example:
643 // Let's suppose that the object for package "C" is from an old
644 // gccgo, e.g. it has the old export data format. All other
645 // packages are compiled with the new compiler and have the new
646 // format. Packages with *'s have init functions. The scenario is
647 // that we're compiling a package "A"; during this process we'll
648 // read the export data for "C". It should look something like
650 // init F F..import 1 G G..import 1 D D..import 2 E E..import 2;
652 // To capture this information and convey it to the consumers of
653 // "A", the code below adds edges to the graph from each priority K
654 // function to every priority K-1 function for appropriate values
655 // of K. This will potentially add more edges than we need (for
656 // example, an edge from D to G), but given that we don't expect
657 // to see large numbers of old objects, this will hopefully be OK.
659 if (inits_at_level
.size() > 0)
661 for (level_map::reverse_iterator it
= inits_at_level
.rbegin();
662 it
!= inits_at_level
.rend(); ++it
)
664 int level
= it
->first
;
665 if (level
< 2) break;
666 const std::vector
<std::string
>& fcns_at_level
= it
->second
;
667 for (std::vector
<std::string
>::const_iterator sit
=
668 fcns_at_level
.begin();
669 sit
!= fcns_at_level
.end(); ++sit
)
671 unsigned src
= init_idx
[*sit
];
672 level_map::iterator it2
= inits_at_level
.find(level
- 1);
673 if (it2
!= inits_at_level
.end())
675 const std::vector
<std::string
> fcns_at_lm1
= it2
->second
;
676 for (std::vector
<std::string
>::const_iterator mit
=
678 mit
!= fcns_at_lm1
.end(); ++mit
)
680 unsigned sink
= init_idx
[*mit
];
681 add_init_graph_edge(&init_graph
, src
, sink
);
688 // Write out the resulting graph.
689 this->write_c_string("init_graph");
690 for (Init_graph::const_iterator ki
= init_graph
.begin();
691 ki
!= init_graph
.end(); ++ki
)
693 unsigned src
= ki
->first
;
694 const std::set
<unsigned>& successors
= ki
->second
;
695 for (std::set
<unsigned>::const_iterator vi
= successors
.begin();
696 vi
!= successors
.end(); ++vi
)
698 this->write_c_string(" ");
699 this->write_unsigned(src
);
700 unsigned sink
= (*vi
);
701 this->write_c_string(" ");
702 this->write_unsigned(sink
);
705 this->write_c_string("\n");
708 // Write a name to the export stream.
711 Export::write_name(const std::string
& name
)
714 this->write_c_string("?");
716 this->write_string(Gogo::message_name(name
));
719 // Write an integer value to the export stream.
722 Export::write_int(int value
)
725 snprintf(buf
, sizeof buf
, "%d", value
);
726 this->write_c_string(buf
);
729 // Write an integer value to the export stream.
732 Export::write_unsigned(unsigned value
)
735 snprintf(buf
, sizeof buf
, "%u", value
);
736 this->write_c_string(buf
);
739 // Export a type. We have to ensure that on import we create a single
740 // Named_type node for each named type. We do this by keeping a hash
741 // table mapping named types to reference numbers. The first time we
742 // see a named type we assign it a reference number by making an entry
743 // in the hash table. If we see it again, we just refer to the
746 // Named types are, of course, associated with packages. Note that we
747 // may see a named type when importing one package, and then later see
748 // the same named type when importing a different package. The home
749 // package may or may not be imported during this compilation. The
750 // reference number scheme has to get this all right. Basic approach
751 // taken from "On the Linearization of Graphs and Writing Symbol
752 // Files" by Robert Griesemer.
755 Export::write_type(const Type
* type
)
757 // We don't want to assign a reference number to a forward
758 // declaration to a type which was defined later.
759 type
= type
->forwarded();
761 Type_refs::const_iterator p
= this->type_refs_
.find(type
);
762 if (p
!= this->type_refs_
.end())
764 // This type was already in the table.
765 int index
= p
->second
;
766 go_assert(index
!= 0);
768 snprintf(buf
, sizeof buf
, "<type %d>", index
);
769 this->write_c_string(buf
);
773 const Named_type
* named_type
= type
->named_type();
774 const Forward_declaration_type
* forward
= type
->forward_declaration_type();
776 int index
= this->type_index_
;
780 snprintf(buf
, sizeof buf
, "<type %d ", index
);
781 this->write_c_string(buf
);
783 if (named_type
!= NULL
|| forward
!= NULL
)
785 const Named_object
* named_object
;
786 if (named_type
!= NULL
)
788 // The builtin types should have been predefined.
789 go_assert(!Linemap::is_predeclared_location(named_type
->location())
790 || (named_type
->named_object()->package()->package_name()
792 named_object
= named_type
->named_object();
795 named_object
= forward
->named_object();
797 const Package
* package
= named_object
->package();
799 std::string s
= "\"";
800 if (package
!= NULL
&& !Gogo::is_hidden_name(named_object
->name()))
802 s
+= package
->pkgpath();
805 s
+= named_object
->name();
807 this->write_string(s
);
809 // We must add a named type to the table now, since the
810 // definition of the type may refer to the named type via a
812 this->type_refs_
[type
] = index
;
814 if (named_type
!= NULL
&& named_type
->is_alias())
815 this->write_c_string("= ");
818 type
->export_type(this);
820 this->write_c_string(">");
822 if (named_type
== NULL
)
823 this->type_refs_
[type
] = index
;
826 // Export escape note.
829 Export::write_escape(std::string
* note
)
831 if (note
!= NULL
&& *note
!= "esc:0x0")
833 this->write_c_string(" ");
835 go_assert(note
->find("esc:") != std::string::npos
);
836 snprintf(buf
, sizeof buf
, "<%s>", note
->c_str());
837 this->write_c_string(buf
);
841 // Add the builtin types to the export table.
844 Export::register_builtin_types(Gogo
* gogo
)
846 this->register_builtin_type(gogo
, "int8", BUILTIN_INT8
);
847 this->register_builtin_type(gogo
, "int16", BUILTIN_INT16
);
848 this->register_builtin_type(gogo
, "int32", BUILTIN_INT32
);
849 this->register_builtin_type(gogo
, "int64", BUILTIN_INT64
);
850 this->register_builtin_type(gogo
, "uint8", BUILTIN_UINT8
);
851 this->register_builtin_type(gogo
, "uint16", BUILTIN_UINT16
);
852 this->register_builtin_type(gogo
, "uint32", BUILTIN_UINT32
);
853 this->register_builtin_type(gogo
, "uint64", BUILTIN_UINT64
);
854 this->register_builtin_type(gogo
, "float32", BUILTIN_FLOAT32
);
855 this->register_builtin_type(gogo
, "float64", BUILTIN_FLOAT64
);
856 this->register_builtin_type(gogo
, "complex64", BUILTIN_COMPLEX64
);
857 this->register_builtin_type(gogo
, "complex128", BUILTIN_COMPLEX128
);
858 this->register_builtin_type(gogo
, "int", BUILTIN_INT
);
859 this->register_builtin_type(gogo
, "uint", BUILTIN_UINT
);
860 this->register_builtin_type(gogo
, "uintptr", BUILTIN_UINTPTR
);
861 this->register_builtin_type(gogo
, "bool", BUILTIN_BOOL
);
862 this->register_builtin_type(gogo
, "string", BUILTIN_STRING
);
863 this->register_builtin_type(gogo
, "error", BUILTIN_ERROR
);
864 this->register_builtin_type(gogo
, "byte", BUILTIN_BYTE
);
865 this->register_builtin_type(gogo
, "rune", BUILTIN_RUNE
);
868 // Register one builtin type in the export table.
871 Export::register_builtin_type(Gogo
* gogo
, const char* name
, Builtin_code code
)
873 Named_object
* named_object
= gogo
->lookup_global(name
);
874 go_assert(named_object
!= NULL
&& named_object
->is_type());
875 std::pair
<Type_refs::iterator
, bool> ins
=
876 this->type_refs_
.insert(std::make_pair(named_object
->type_value(), code
));
877 go_assert(ins
.second
);
879 // We also insert the underlying type. We can see the underlying
880 // type at least for string and bool. We skip the type aliases byte
882 if (code
!= BUILTIN_BYTE
&& code
!= BUILTIN_RUNE
)
884 Type
* real_type
= named_object
->type_value()->real_type();
885 ins
= this->type_refs_
.insert(std::make_pair(real_type
, code
));
886 go_assert(ins
.second
);
890 // Class Export::Stream.
892 Export::Stream::Stream()
894 this->sha1_helper_
= go_create_sha1_helper();
895 go_assert(this->sha1_helper_
!= NULL
);
898 Export::Stream::~Stream()
902 // Write bytes to the stream. This keeps a checksum of bytes as they
906 Export::Stream::write_and_sum_bytes(const char* bytes
, size_t length
)
908 this->sha1_helper_
->process_bytes(bytes
, length
);
909 this->do_write(bytes
, length
);
915 Export::Stream::checksum()
917 std::string rval
= this->sha1_helper_
->finish();
918 delete this->sha1_helper_
;
922 // Write the checksum string to the export data.
925 Export::Stream::write_checksum(const std::string
& s
)
927 this->do_write(s
.data(), s
.length());
930 // Class Stream_to_section.
932 Stream_to_section::Stream_to_section(Backend
* backend
)
937 // Write data to a section.
940 Stream_to_section::do_write(const char* bytes
, size_t length
)
942 this->backend_
->write_export_data (bytes
, length
);