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 nested functions.
79 if (no
->is_function() && no
->func_value()->enclosing() != NULL
)
82 // We don't export thunks.
83 if (no
->is_function() && Gogo::is_thunk(no
))
86 // Methods are exported with the type, not here.
88 && no
->func_value()->type()->is_method())
90 if (no
->is_function_declaration()
91 && no
->func_declaration_value()->type()->is_method())
94 // Don't export dummy global variables created for initializers when
96 if (no
->is_variable() && no
->name()[0] == '_' && no
->name()[1] == '.')
102 // Export those identifiers marked for exporting.
105 Export::export_globals(const std::string
& package_name
,
106 const std::string
& prefix
,
107 const std::string
& pkgpath
,
108 const std::map
<std::string
, Package
*>& packages
,
109 const std::map
<std::string
, Package
*>& imports
,
110 const std::string
& import_init_fn
,
111 const Import_init_set
& imported_init_fns
,
112 const Bindings
* bindings
)
114 // If there have been any errors so far, don't try to export
115 // anything. That way the export code doesn't have to worry about
116 // mismatched types or other confusions.
120 // Export the symbols in sorted order. That will reduce cases where
121 // irrelevant changes to the source code affect the exported
123 std::vector
<Named_object
*> exports
;
124 exports
.reserve(bindings
->size_definitions());
126 for (Bindings::const_definitions_iterator p
= bindings
->begin_definitions();
127 p
!= bindings
->end_definitions();
129 if (should_export(*p
))
130 exports
.push_back(*p
);
132 for (Bindings::const_declarations_iterator p
=
133 bindings
->begin_declarations();
134 p
!= bindings
->end_declarations();
137 // We export a function declaration as it may be implemented in
138 // supporting C code. We do not export type declarations.
139 if (p
->second
->is_function_declaration()
140 && should_export(p
->second
))
141 exports
.push_back(p
->second
);
144 std::sort(exports
.begin(), exports
.end(), Sort_bindings());
146 // Find all packages not explicitly imported but mentioned by types.
147 Unordered_set(const Package
*) type_imports
;
148 this->prepare_types(&exports
, &type_imports
);
150 // Although the export data is readable, at least this version is,
151 // it is conceptually a binary format. Start with a four byte
153 this->write_bytes(Export::cur_magic
, Export::magic_len
);
156 this->write_c_string("package ");
157 this->write_string(package_name
);
158 this->write_c_string("\n");
160 // The prefix or package path, used for all global symbols.
163 go_assert(!pkgpath
.empty());
164 this->write_c_string("pkgpath ");
165 this->write_string(pkgpath
);
169 this->write_c_string("prefix ");
170 this->write_string(prefix
);
172 this->write_c_string("\n");
174 this->write_packages(packages
);
176 this->write_imports(imports
, type_imports
);
178 this->write_imported_init_fns(package_name
, import_init_fn
,
181 // FIXME: It might be clever to add something about the processor
182 // and ABI being used, although ideally any problems in that area
183 // would be caught by the linker.
185 for (std::vector
<Named_object
*>::const_iterator p
= exports
.begin();
188 (*p
)->export_named_object(this);
190 std::string checksum
= this->stream_
->checksum();
191 std::string s
= "checksum ";
192 for (std::string::const_iterator p
= checksum
.begin();
196 unsigned char c
= *p
;
197 unsigned int dig
= c
>> 4;
198 s
+= dig
< 10 ? '0' + dig
: 'A' + dig
- 10;
200 s
+= dig
< 10 ? '0' + dig
: 'A' + dig
- 10;
203 this->stream_
->write_checksum(s
);
206 // Traversal class to find referenced types.
208 class Find_types_to_prepare
: public Traverse
211 Find_types_to_prepare(Unordered_set(const Package
*)* imports
)
212 : Traverse(traverse_types
),
219 // Traverse the components of a function type.
221 traverse_function(Function_type
*);
223 // Traverse the methods of a named type, and register its package.
225 traverse_named_type(Named_type
*);
228 // List of packages we are building.
229 Unordered_set(const Package
*)* imports_
;
235 Find_types_to_prepare::type(Type
* type
)
238 if (type
->forward_declaration_type() != NULL
)
239 return TRAVERSE_CONTINUE
;
241 // At this stage of compilation traversing interface types traverses
242 // the final list of methods, but we export the locally defined
243 // methods. If there is an embedded interface type we need to make
244 // sure to export that. Check classification, rather than calling
245 // the interface_type method, because we want to handle named types
247 if (type
->classification() == Type::TYPE_INTERFACE
)
249 Interface_type
* it
= type
->interface_type();
250 const Typed_identifier_list
* methods
= it
->local_methods();
253 for (Typed_identifier_list::const_iterator p
= methods
->begin();
257 if (p
->name().empty())
258 Type::traverse(p
->type(), this);
260 this->traverse_function(p
->type()->function_type());
263 return TRAVERSE_SKIP_COMPONENTS
;
266 Named_type
* nt
= type
->named_type();
268 this->traverse_named_type(nt
);
270 return TRAVERSE_CONTINUE
;
273 // Traverse the types in a function type. We don't need the function
274 // type tself, just the receiver, parameter, and result types.
277 Find_types_to_prepare::traverse_function(Function_type
* type
)
279 go_assert(type
!= NULL
);
280 if (this->remember_type(type
))
282 const Typed_identifier
* receiver
= type
->receiver();
283 if (receiver
!= NULL
)
284 Type::traverse(receiver
->type(), this);
285 const Typed_identifier_list
* parameters
= type
->parameters();
286 if (parameters
!= NULL
)
287 parameters
->traverse(this);
288 const Typed_identifier_list
* results
= type
->results();
290 results
->traverse(this);
293 // Traverse the methods of a named type, and record its package.
296 Find_types_to_prepare::traverse_named_type(Named_type
* nt
)
298 const Package
* package
= nt
->named_object()->package();
300 this->imports_
->insert(package
);
302 // We have to traverse the methods of named types, because we are
303 // going to export them. This is not done by ordinary type
305 const Bindings
* methods
= nt
->local_methods();
308 for (Bindings::const_definitions_iterator pm
=
309 methods
->begin_definitions();
310 pm
!= methods
->end_definitions();
312 this->traverse_function((*pm
)->func_value()->type());
314 for (Bindings::const_declarations_iterator pm
=
315 methods
->begin_declarations();
316 pm
!= methods
->end_declarations();
319 Named_object
* mno
= pm
->second
;
320 if (mno
->is_function_declaration())
321 this->traverse_function(mno
->func_declaration_value()->type());
326 // Collect all the pacakges we see in types, so that if we refer to
327 // any types from indirectly importe packages we can tell the importer
328 // about the package.
331 Export::prepare_types(const std::vector
<Named_object
*>* exports
,
332 Unordered_set(const Package
*)* imports
)
334 // Use a single index of the traversal class because traversal
335 // classes keep track of which types they've already seen. That
336 // lets us avoid type reference loops.
337 Find_types_to_prepare
find(imports
);
339 // Traverse all the exported objects.
340 for (std::vector
<Named_object
*>::const_iterator p
= exports
->begin();
344 Named_object
* no
= *p
;
345 switch (no
->classification())
347 case Named_object::NAMED_OBJECT_CONST
:
349 Type
* t
= no
->const_value()->type();
350 if (t
!= NULL
&& !t
->is_abstract())
351 Type::traverse(t
, &find
);
355 case Named_object::NAMED_OBJECT_TYPE
:
356 Type::traverse(no
->type_value(), &find
);
359 case Named_object::NAMED_OBJECT_VAR
:
360 Type::traverse(no
->var_value()->type(), &find
);
363 case Named_object::NAMED_OBJECT_FUNC
:
364 find
.traverse_function(no
->func_value()->type());
367 case Named_object::NAMED_OBJECT_FUNC_DECLARATION
:
368 find
.traverse_function(no
->func_declaration_value()->type());
372 // We shouldn't see anything else. If we do we'll give an
373 // error later when we try to actually export it.
382 packages_compare(const Package
* a
, const Package
* b
)
384 return a
->package_name() < b
->package_name();
387 // Write out all the known packages whose pkgpath symbol is not a
388 // simple transformation of the pkgpath, so that the importing code
389 // can reliably know it.
392 Export::write_packages(const std::map
<std::string
, Package
*>& packages
)
394 // Sort for consistent output.
395 std::vector
<Package
*> out
;
396 for (std::map
<std::string
, Package
*>::const_iterator p
= packages
.begin();
400 if (p
->second
->pkgpath_symbol()
401 != Gogo::pkgpath_for_symbol(p
->second
->pkgpath()))
402 out
.push_back(p
->second
);
405 std::sort(out
.begin(), out
.end(), packages_compare
);
407 for (std::vector
<Package
*>::const_iterator p
= out
.begin();
411 this->write_c_string("package ");
412 this->write_string((*p
)->package_name());
413 this->write_c_string(" ");
414 this->write_string((*p
)->pkgpath());
415 this->write_c_string(" ");
416 this->write_string((*p
)->pkgpath_symbol());
417 this->write_c_string("\n");
421 // Sort imported packages.
424 import_compare(const std::pair
<std::string
, Package
*>& a
,
425 const std::pair
<std::string
, Package
*>& b
)
427 return a
.first
< b
.first
;
430 // Write out the imported packages.
433 Export::write_imports(const std::map
<std::string
, Package
*>& imports
,
434 const Unordered_set(const Package
*)& type_imports
)
436 // Sort the imports for more consistent output.
437 Unordered_set(const Package
*) seen
;
438 std::vector
<std::pair
<std::string
, Package
*> > sorted_imports
;
439 for (std::map
<std::string
, Package
*>::const_iterator p
= imports
.begin();
443 sorted_imports
.push_back(std::make_pair(p
->first
, p
->second
));
444 seen
.insert(p
->second
);
447 std::sort(sorted_imports
.begin(), sorted_imports
.end(), import_compare
);
449 for (std::vector
<std::pair
<std::string
, Package
*> >::const_iterator p
=
450 sorted_imports
.begin();
451 p
!= sorted_imports
.end();
454 this->write_c_string("import ");
455 this->write_string(p
->second
->package_name());
456 this->write_c_string(" ");
457 this->write_string(p
->second
->pkgpath());
458 this->write_c_string(" \"");
459 this->write_string(p
->first
);
460 this->write_c_string("\"\n");
462 this->packages_
.insert(p
->second
);
465 // Write out a separate list of indirectly imported packages.
466 std::vector
<const Package
*> indirect_imports
;
467 for (Unordered_set(const Package
*)::const_iterator p
=
468 type_imports
.begin();
469 p
!= type_imports
.end();
472 if (seen
.find(*p
) == seen
.end())
473 indirect_imports
.push_back(*p
);
476 std::sort(indirect_imports
.begin(), indirect_imports
.end(),
479 for (std::vector
<const Package
*>::const_iterator p
=
480 indirect_imports
.begin();
481 p
!= indirect_imports
.end();
484 this->write_c_string("indirectimport ");
485 this->write_string((*p
)->package_name());
486 this->write_c_string(" ");
487 this->write_string((*p
)->pkgpath());
488 this->write_c_string("\n");
493 Export::add_init_graph_edge(Init_graph
* init_graph
, unsigned src
, unsigned sink
)
495 Init_graph::iterator it
= init_graph
->find(src
);
496 if (it
!= init_graph
->end())
497 it
->second
.insert(sink
);
500 std::set
<unsigned> succs
;
502 (*init_graph
)[src
] = succs
;
506 // Constructs the imported portion of the init graph, e.g. those
507 // edges that we read from imported packages.
510 Export::populate_init_graph(Init_graph
* init_graph
,
511 const Import_init_set
& imported_init_fns
,
512 const std::map
<std::string
, unsigned>& init_idx
)
514 for (Import_init_set::const_iterator p
= imported_init_fns
.begin();
515 p
!= imported_init_fns
.end();
518 const Import_init
* ii
= *p
;
519 std::map
<std::string
, unsigned>::const_iterator srcit
=
520 init_idx
.find(ii
->init_name());
521 go_assert(srcit
!= init_idx
.end());
522 unsigned src
= srcit
->second
;
523 for (std::set
<std::string
>::const_iterator pci
= ii
->precursors().begin();
524 pci
!= ii
->precursors().end();
527 std::map
<std::string
, unsigned>::const_iterator it
=
529 go_assert(it
!= init_idx
.end());
530 unsigned sink
= it
->second
;
531 add_init_graph_edge(init_graph
, src
, sink
);
536 // Write out the initialization functions which need to run for this
540 Export::write_imported_init_fns(const std::string
& package_name
,
541 const std::string
& import_init_fn
,
542 const Import_init_set
& imported_init_fns
)
544 if (import_init_fn
.empty() && imported_init_fns
.empty()) return;
546 // Maps a given init function to the its index in the exported "init" clause.
547 std::map
<std::string
, unsigned> init_idx
;
549 this->write_c_string("init");
551 if (!import_init_fn
.empty())
553 this->write_c_string(" ");
554 this->write_string(package_name
);
555 this->write_c_string(" ");
556 this->write_string(import_init_fn
);
557 init_idx
[import_init_fn
] = 0;
560 if (imported_init_fns
.empty())
562 this->write_c_string("\n");
566 typedef std::map
<int, std::vector
<std::string
> > level_map
;
567 Init_graph init_graph
;
568 level_map inits_at_level
;
570 // Walk through the set of import inits (already sorted by
571 // init fcn name) and write them out to the exports.
572 for (Import_init_set::const_iterator p
= imported_init_fns
.begin();
573 p
!= imported_init_fns
.end();
576 const Import_init
* ii
= *p
;
578 if (ii
->init_name() == import_init_fn
)
581 this->write_c_string(" ");
582 this->write_string(ii
->package_name());
583 this->write_c_string(" ");
584 this->write_string(ii
->init_name());
586 // Populate init_idx.
587 go_assert(init_idx
.find(ii
->init_name()) == init_idx
.end());
588 unsigned idx
= init_idx
.size();
589 init_idx
[ii
->init_name()] = idx
;
591 // If the init function has a non-negative priority value, this
592 // is an indication that it was referred to in an older version
593 // export data section (e.g. we read a legacy object
594 // file). Record such init fcns so that we can fix up the graph
595 // for them (handled later in this function).
596 if (ii
->priority() > 0)
598 level_map::iterator it
= inits_at_level
.find(ii
->priority());
599 if (it
== inits_at_level
.end())
601 std::vector
<std::string
> l
;
602 l
.push_back(ii
->init_name());
603 inits_at_level
[ii
->priority()] = l
;
606 it
->second
.push_back(ii
->init_name());
609 this->write_c_string("\n");
611 // Create the init graph. Start by populating the graph with
612 // all the edges we inherited from imported packages.
613 populate_init_graph(&init_graph
, imported_init_fns
, init_idx
);
615 // Now add edges from the local init function to each of the
617 if (!import_init_fn
.empty())
620 go_assert(init_idx
[import_init_fn
] == 0);
621 for (Import_init_set::const_iterator p
= imported_init_fns
.begin();
622 p
!= imported_init_fns
.end();
625 const Import_init
* ii
= *p
;
626 unsigned sink
= init_idx
[ii
->init_name()];
627 add_init_graph_edge(&init_graph
, src
, sink
);
631 // In the scenario where one or more of the packages we imported
632 // was written with the legacy export data format, add dummy edges
633 // to capture the priority relationships. Here is a package import
634 // graph as an example:
647 // Let's suppose that the object for package "C" is from an old
648 // gccgo, e.g. it has the old export data format. All other
649 // packages are compiled with the new compiler and have the new
650 // format. Packages with *'s have init functions. The scenario is
651 // that we're compiling a package "A"; during this process we'll
652 // read the export data for "C". It should look something like
654 // init F F..import 1 G G..import 1 D D..import 2 E E..import 2;
656 // To capture this information and convey it to the consumers of
657 // "A", the code below adds edges to the graph from each priority K
658 // function to every priority K-1 function for appropriate values
659 // of K. This will potentially add more edges than we need (for
660 // example, an edge from D to G), but given that we don't expect
661 // to see large numbers of old objects, this will hopefully be OK.
663 if (inits_at_level
.size() > 0)
665 for (level_map::reverse_iterator it
= inits_at_level
.rbegin();
666 it
!= inits_at_level
.rend(); ++it
)
668 int level
= it
->first
;
669 if (level
< 2) break;
670 const std::vector
<std::string
>& fcns_at_level
= it
->second
;
671 for (std::vector
<std::string
>::const_iterator sit
=
672 fcns_at_level
.begin();
673 sit
!= fcns_at_level
.end(); ++sit
)
675 unsigned src
= init_idx
[*sit
];
676 level_map::iterator it2
= inits_at_level
.find(level
- 1);
677 if (it2
!= inits_at_level
.end())
679 const std::vector
<std::string
> fcns_at_lm1
= it2
->second
;
680 for (std::vector
<std::string
>::const_iterator mit
=
682 mit
!= fcns_at_lm1
.end(); ++mit
)
684 unsigned sink
= init_idx
[*mit
];
685 add_init_graph_edge(&init_graph
, src
, sink
);
692 // Write out the resulting graph.
693 this->write_c_string("init_graph");
694 for (Init_graph::const_iterator ki
= init_graph
.begin();
695 ki
!= init_graph
.end(); ++ki
)
697 unsigned src
= ki
->first
;
698 const std::set
<unsigned>& successors
= ki
->second
;
699 for (std::set
<unsigned>::const_iterator vi
= successors
.begin();
700 vi
!= successors
.end(); ++vi
)
702 this->write_c_string(" ");
703 this->write_unsigned(src
);
704 unsigned sink
= (*vi
);
705 this->write_c_string(" ");
706 this->write_unsigned(sink
);
709 this->write_c_string("\n");
712 // Write a name to the export stream.
715 Export::write_name(const std::string
& name
)
718 this->write_c_string("?");
720 this->write_string(Gogo::message_name(name
));
723 // Write an integer value to the export stream.
726 Export::write_int(int value
)
729 snprintf(buf
, sizeof buf
, "%d", value
);
730 this->write_c_string(buf
);
733 // Write an integer value to the export stream.
736 Export::write_unsigned(unsigned value
)
739 snprintf(buf
, sizeof buf
, "%u", value
);
740 this->write_c_string(buf
);
743 // Export a type. We have to ensure that on import we create a single
744 // Named_type node for each named type. We do this by keeping a hash
745 // table mapping named types to reference numbers. The first time we
746 // see a named type we assign it a reference number by making an entry
747 // in the hash table. If we see it again, we just refer to the
750 // Named types are, of course, associated with packages. Note that we
751 // may see a named type when importing one package, and then later see
752 // the same named type when importing a different package. The home
753 // package may or may not be imported during this compilation. The
754 // reference number scheme has to get this all right. Basic approach
755 // taken from "On the Linearization of Graphs and Writing Symbol
756 // Files" by Robert Griesemer.
759 Export::write_type(const Type
* type
)
761 // We don't want to assign a reference number to a forward
762 // declaration to a type which was defined later.
763 type
= type
->forwarded();
765 Type_refs::const_iterator p
= this->type_refs_
.find(type
);
766 if (p
!= this->type_refs_
.end())
768 // This type was already in the table.
769 int index
= p
->second
;
770 go_assert(index
!= 0);
772 snprintf(buf
, sizeof buf
, "<type %d>", index
);
773 this->write_c_string(buf
);
777 const Named_type
* named_type
= type
->named_type();
778 const Forward_declaration_type
* forward
= type
->forward_declaration_type();
780 int index
= this->type_index_
;
784 snprintf(buf
, sizeof buf
, "<type %d ", index
);
785 this->write_c_string(buf
);
787 if (named_type
!= NULL
|| forward
!= NULL
)
789 const Named_object
* named_object
;
790 if (named_type
!= NULL
)
792 // The builtin types should have been predefined.
793 go_assert(!Linemap::is_predeclared_location(named_type
->location())
794 || (named_type
->named_object()->package()->package_name()
796 named_object
= named_type
->named_object();
799 named_object
= forward
->named_object();
801 const Package
* package
= named_object
->package();
803 std::string s
= "\"";
804 if (package
!= NULL
&& !Gogo::is_hidden_name(named_object
->name()))
806 s
+= package
->pkgpath();
809 s
+= named_object
->name();
811 this->write_string(s
);
813 // We must add a named type to the table now, since the
814 // definition of the type may refer to the named type via a
816 this->type_refs_
[type
] = index
;
818 if (named_type
!= NULL
&& named_type
->is_alias())
819 this->write_c_string("= ");
822 type
->export_type(this);
824 this->write_c_string(">");
826 if (named_type
== NULL
)
827 this->type_refs_
[type
] = index
;
830 // Export escape note.
833 Export::write_escape(std::string
* note
)
835 if (note
!= NULL
&& *note
!= "esc:0x0")
837 this->write_c_string(" ");
839 go_assert(note
->find("esc:") != std::string::npos
);
840 snprintf(buf
, sizeof buf
, "<%s>", note
->c_str());
841 this->write_c_string(buf
);
845 // Add the builtin types to the export table.
848 Export::register_builtin_types(Gogo
* gogo
)
850 this->register_builtin_type(gogo
, "int8", BUILTIN_INT8
);
851 this->register_builtin_type(gogo
, "int16", BUILTIN_INT16
);
852 this->register_builtin_type(gogo
, "int32", BUILTIN_INT32
);
853 this->register_builtin_type(gogo
, "int64", BUILTIN_INT64
);
854 this->register_builtin_type(gogo
, "uint8", BUILTIN_UINT8
);
855 this->register_builtin_type(gogo
, "uint16", BUILTIN_UINT16
);
856 this->register_builtin_type(gogo
, "uint32", BUILTIN_UINT32
);
857 this->register_builtin_type(gogo
, "uint64", BUILTIN_UINT64
);
858 this->register_builtin_type(gogo
, "float32", BUILTIN_FLOAT32
);
859 this->register_builtin_type(gogo
, "float64", BUILTIN_FLOAT64
);
860 this->register_builtin_type(gogo
, "complex64", BUILTIN_COMPLEX64
);
861 this->register_builtin_type(gogo
, "complex128", BUILTIN_COMPLEX128
);
862 this->register_builtin_type(gogo
, "int", BUILTIN_INT
);
863 this->register_builtin_type(gogo
, "uint", BUILTIN_UINT
);
864 this->register_builtin_type(gogo
, "uintptr", BUILTIN_UINTPTR
);
865 this->register_builtin_type(gogo
, "bool", BUILTIN_BOOL
);
866 this->register_builtin_type(gogo
, "string", BUILTIN_STRING
);
867 this->register_builtin_type(gogo
, "error", BUILTIN_ERROR
);
868 this->register_builtin_type(gogo
, "byte", BUILTIN_BYTE
);
869 this->register_builtin_type(gogo
, "rune", BUILTIN_RUNE
);
872 // Register one builtin type in the export table.
875 Export::register_builtin_type(Gogo
* gogo
, const char* name
, Builtin_code code
)
877 Named_object
* named_object
= gogo
->lookup_global(name
);
878 go_assert(named_object
!= NULL
&& named_object
->is_type());
879 std::pair
<Type_refs::iterator
, bool> ins
=
880 this->type_refs_
.insert(std::make_pair(named_object
->type_value(), code
));
881 go_assert(ins
.second
);
883 // We also insert the underlying type. We can see the underlying
884 // type at least for string and bool. We skip the type aliases byte
886 if (code
!= BUILTIN_BYTE
&& code
!= BUILTIN_RUNE
)
888 Type
* real_type
= named_object
->type_value()->real_type();
889 ins
= this->type_refs_
.insert(std::make_pair(real_type
, code
));
890 go_assert(ins
.second
);
894 // Class Export::Stream.
896 Export::Stream::Stream()
898 this->sha1_helper_
= go_create_sha1_helper();
899 go_assert(this->sha1_helper_
!= NULL
);
902 Export::Stream::~Stream()
906 // Write bytes to the stream. This keeps a checksum of bytes as they
910 Export::Stream::write_and_sum_bytes(const char* bytes
, size_t length
)
912 this->sha1_helper_
->process_bytes(bytes
, length
);
913 this->do_write(bytes
, length
);
919 Export::Stream::checksum()
921 std::string rval
= this->sha1_helper_
->finish();
922 delete this->sha1_helper_
;
926 // Write the checksum string to the export data.
929 Export::Stream::write_checksum(const std::string
& s
)
931 this->do_write(s
.data(), s
.length());
934 // Class Stream_to_section.
936 Stream_to_section::Stream_to_section(Backend
* backend
)
941 // Write data to a section.
944 Stream_to_section::do_write(const char* bytes
, size_t length
)
946 this->backend_
->write_export_data (bytes
, length
);