Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
C
capnproto
Project
Project
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
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
capnproto
Commits
5c851221
Commit
5c851221
authored
Aug 26, 2013
by
Kenton Varda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement 'capnp encode' command which does the opposite of 'capnp decode'.
parent
98e6519e
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
308 additions
and
78 deletions
+308
-78
capnp.c++
c++/src/capnp/compiler/capnp.c++
+194
-11
error-reporter.c++
c++/src/capnp/compiler/error-reporter.c++
+39
-2
error-reporter.h
c++/src/capnp/compiler/error-reporter.h
+13
-2
module-loader.c++
c++/src/capnp/compiler/module-loader.c++
+6
-44
node-translator.c++
c++/src/capnp/compiler/node-translator.c++
+0
-0
node-translator.h
c++/src/capnp/compiler/node-translator.h
+32
-18
dynamic.c++
c++/src/capnp/dynamic.c++
+13
-0
dynamic.h
c++/src/capnp/dynamic.h
+10
-0
schema-parser.c++
c++/src/capnp/schema-parser.c++
+1
-1
No files found.
c++/src/capnp/compiler/capnp.c++
View file @
5c851221
...
@@ -25,6 +25,7 @@
...
@@ -25,6 +25,7 @@
#include "parser.h"
#include "parser.h"
#include "compiler.h"
#include "compiler.h"
#include "module-loader.h"
#include "module-loader.h"
#include "node-translator.h"
#include <capnp/pretty-print.h>
#include <capnp/pretty-print.h>
#include <capnp/schema.capnp.h>
#include <capnp/schema.capnp.h>
#include <kj/vector.h>
#include <kj/vector.h>
...
@@ -99,8 +100,9 @@ public:
...
@@ -99,8 +100,9 @@ public:
.
addSubCommand
(
"id"
,
KJ_BIND_METHOD
(
*
this
,
getGenIdMain
),
.
addSubCommand
(
"id"
,
KJ_BIND_METHOD
(
*
this
,
getGenIdMain
),
"Generate a new unique ID."
)
"Generate a new unique ID."
)
.
addSubCommand
(
"decode"
,
KJ_BIND_METHOD
(
*
this
,
getDecodeMain
),
.
addSubCommand
(
"decode"
,
KJ_BIND_METHOD
(
*
this
,
getDecodeMain
),
"Decode binary Cap'n Proto message to text."
);
"Decode binary Cap'n Proto message to text."
)
// TODO(someday): "encode" -- requires the ability to parse text format.
.
addSubCommand
(
"encode"
,
KJ_BIND_METHOD
(
*
this
,
getEncodeMain
),
"Encode text Cap'n Proto message to binary."
);
addGlobalOptions
(
builder
);
addGlobalOptions
(
builder
);
return
builder
.
build
();
return
builder
.
build
();
}
}
...
@@ -150,6 +152,37 @@ public:
...
@@ -150,6 +152,37 @@ public:
return
builder
.
build
();
return
builder
.
build
();
}
}
kj
::
MainFunc
getEncodeMain
()
{
// Only parse the schemas we actually need for decoding.
compileEagerness
=
Compiler
::
NODE
;
// Drop annotations since we don't need them. This avoids importing files like c++.capnp.
annotationFlag
=
Compiler
::
DROP_ANNOTATIONS
;
kj
::
MainBuilder
builder
(
context
,
VERSION_STRING
,
"Encodes one or more textual Cap'n Proto messages to binary. The messages have root "
"type <type> defined in <schema-file>. Messages are read from standard input. Each "
"mesage is a parenthesized struct literal, like the format used to specify constants "
"and default values of struct type in the schema language. For example:
\n
"
" (foo = 123, bar =
\"
hello
\"
, baz = [true, false, true])
\n
"
"The input may contain any number of such values; each will be encoded as a separate "
"message."
,
"Note that the current implementation reads the entire input into memory before "
"beginning to encode. A better implementation would read and encode one message at "
"a time."
);
addGlobalOptions
(
builder
);
builder
.
addOption
({
'f'
,
"flat"
},
KJ_BIND_METHOD
(
*
this
,
codeFlat
),
"Expect only one input value, serializing it as a single-segment message "
"with no framing."
)
.
addOption
({
'p'
,
"packed"
},
KJ_BIND_METHOD
(
*
this
,
codePacked
),
"Pack the output message with standard Cap'n Proto packing, which "
"deflates zero-valued bytes."
)
.
expectArg
(
"<schema-file>"
,
KJ_BIND_METHOD
(
*
this
,
addSource
))
.
expectArg
(
"<type>"
,
KJ_BIND_METHOD
(
*
this
,
setRootType
))
.
callAfterParsing
(
KJ_BIND_METHOD
(
*
this
,
encode
));
return
builder
.
build
();
}
void
addGlobalOptions
(
kj
::
MainBuilder
&
builder
)
{
void
addGlobalOptions
(
kj
::
MainBuilder
&
builder
)
{
builder
.
addOptionWithArg
({
'I'
,
"import-path"
},
KJ_BIND_METHOD
(
*
this
,
addImportPath
),
"<dir>"
,
builder
.
addOptionWithArg
({
'I'
,
"import-path"
},
KJ_BIND_METHOD
(
*
this
,
addImportPath
),
"<dir>"
,
"Add <dir> to the list of directories searched for non-relative "
"Add <dir> to the list of directories searched for non-relative "
...
@@ -208,6 +241,19 @@ public:
...
@@ -208,6 +241,19 @@ public:
addStandardImportPaths
=
false
;
addStandardImportPaths
=
false
;
}
}
KJ_IF_MAYBE
(
module
,
loadModule
(
file
))
{
uint64_t
id
=
compiler
->
add
(
*
module
);
compiler
->
eagerlyCompile
(
id
,
compileEagerness
);
sourceFiles
.
add
(
SourceFile
{
id
,
module
->
getSourceName
(),
&*
module
});
}
else
{
return
"no such file"
;
}
return
true
;
}
private
:
kj
::
Maybe
<
const
Module
&>
loadModule
(
kj
::
StringPtr
file
)
{
size_t
longestPrefix
=
0
;
size_t
longestPrefix
=
0
;
for
(
auto
&
prefix
:
sourcePrefixes
)
{
for
(
auto
&
prefix
:
sourcePrefixes
)
{
...
@@ -217,17 +263,10 @@ public:
...
@@ -217,17 +263,10 @@ public:
}
}
kj
::
StringPtr
canonicalName
=
file
.
slice
(
longestPrefix
);
kj
::
StringPtr
canonicalName
=
file
.
slice
(
longestPrefix
);
KJ_IF_MAYBE
(
module
,
loader
.
loadModule
(
file
,
canonicalName
))
{
return
loader
.
loadModule
(
file
,
canonicalName
);
uint64_t
id
=
compiler
->
add
(
*
module
);
compiler
->
eagerlyCompile
(
id
,
compileEagerness
);
sourceFiles
.
add
(
SourceFile
{
id
,
canonicalName
,
&*
module
});
}
else
{
return
"no such file"
;
}
return
true
;
}
}
public
:
// =====================================================================================
// =====================================================================================
// "id" command
// "id" command
...
@@ -512,6 +551,150 @@ private:
...
@@ -512,6 +551,150 @@ private:
}
}
}
}
public
:
// =====================================================================================
kj
::
MainBuilder
::
Validity
encode
()
{
kj
::
Vector
<
char
>
allText
;
{
kj
::
FdInputStream
rawInput
(
STDIN_FILENO
);
kj
::
BufferedInputStreamWrapper
input
(
rawInput
);
for
(;;)
{
auto
buf
=
input
.
tryGetReadBuffer
();
if
(
buf
.
size
()
==
0
)
break
;
allText
.
addAll
(
reinterpret_cast
<
const
char
*>
(
buf
.
begin
()),
reinterpret_cast
<
const
char
*>
(
buf
.
end
()));
input
.
skip
(
buf
.
size
());
}
}
EncoderErrorReporter
errorReporter
(
*
this
,
allText
);
MallocMessageBuilder
arena
;
// Lex the input.
auto
lexedTokens
=
arena
.
initRoot
<
LexedTokens
>
();
lex
(
allText
,
lexedTokens
,
errorReporter
);
// Set up the parser.
CapnpParser
parser
(
arena
.
getOrphanage
(),
errorReporter
);
auto
tokens
=
lexedTokens
.
asReader
().
getTokens
();
CapnpParser
::
ParserInput
parserInput
(
tokens
.
begin
(),
tokens
.
end
());
// Allocate some scratch space.
kj
::
Array
<
word
>
scratch
=
kj
::
heapArray
<
word
>
(
8192
);
memset
(
scratch
.
begin
(),
0
,
scratch
.
size
()
*
sizeof
(
word
));
// Set up stuff for the ValueTranslator.
ValueResolverGlue
resolver
(
compiler
->
getLoader
(),
errorReporter
);
auto
type
=
arena
.
getOrphanage
().
newOrphan
<
schema
::
Type
>
();
type
.
get
().
setStruct
(
rootType
.
getProto
().
getId
());
// Set up output stream.
kj
::
FdOutputStream
rawOutput
(
STDOUT_FILENO
);
kj
::
BufferedOutputStreamWrapper
output
(
rawOutput
);
while
(
parserInput
.
getPosition
()
!=
tokens
.
end
())
{
KJ_IF_MAYBE
(
expression
,
parser
.
getParsers
().
parenthesizedValueExpression
(
parserInput
))
{
MallocMessageBuilder
item
(
scratch
);
ValueTranslator
translator
(
resolver
,
errorReporter
,
item
.
getOrphanage
());
KJ_IF_MAYBE
(
value
,
translator
.
compileValue
(
expression
->
getReader
(),
type
.
getReader
()))
{
writeEncoded
(
value
->
getReader
().
as
<
DynamicStruct
>
(),
output
);
}
else
{
// Errors were reported, so we'll exit with a failure status later.
}
}
else
{
auto
best
=
parserInput
.
getBest
();
if
(
best
==
tokens
.
end
())
{
context
.
exitError
(
"Premature EOF."
);
}
else
{
errorReporter
.
addErrorOn
(
*
best
,
"Parse error."
);
context
.
exit
();
}
}
}
return
true
;
}
private
:
void
writeEncoded
(
DynamicStruct
::
Reader
value
,
kj
::
BufferedOutputStream
&
output
)
{
// Always copy the message to a flat array so that the output is predictable (one segment,
// in canonical order).
size_t
size
=
value
.
totalSizeInWords
()
+
1
;
kj
::
Array
<
word
>
space
=
kj
::
heapArray
<
word
>
(
size
);
memset
(
space
.
begin
(),
0
,
size
*
sizeof
(
word
));
FlatMessageBuilder
flatMessage
(
space
);
flatMessage
.
setRoot
(
value
);
flatMessage
.
requireFilled
();
if
(
flat
)
{
output
.
write
(
space
.
begin
(),
space
.
size
()
*
sizeof
(
word
));
}
else
if
(
packed
)
{
writePackedMessage
(
output
,
flatMessage
);
}
else
{
writeMessage
(
output
,
flatMessage
);
}
}
class
EncoderErrorReporter
final
:
public
ErrorReporter
{
public
:
EncoderErrorReporter
(
GlobalErrorReporter
&
globalReporter
,
kj
::
ArrayPtr
<
const
char
>
content
)
:
globalReporter
(
globalReporter
),
lineBreaks
(
content
)
{}
void
addError
(
uint32_t
startByte
,
uint32_t
endByte
,
kj
::
StringPtr
message
)
const
override
{
globalReporter
.
addError
(
"<stdin>"
,
lineBreaks
.
toSourcePos
(
startByte
),
lineBreaks
.
toSourcePos
(
endByte
),
message
);
}
bool
hadErrors
()
const
override
{
return
globalReporter
.
hadErrors
();
}
private
:
GlobalErrorReporter
&
globalReporter
;
LineBreakTable
lineBreaks
;
};
class
ValueResolverGlue
final
:
public
ValueTranslator
::
Resolver
{
public
:
ValueResolverGlue
(
const
SchemaLoader
&
loader
,
const
ErrorReporter
&
errorReporter
)
:
loader
(
loader
),
errorReporter
(
errorReporter
)
{}
kj
::
Maybe
<
Schema
>
resolveType
(
uint64_t
id
)
{
// Don't use tryGet() here because we shouldn't even be here if there were compile errors.
return
loader
.
get
(
id
);
}
kj
::
Maybe
<
DynamicValue
::
Reader
>
resolveConstant
(
DeclName
::
Reader
name
)
{
auto
base
=
name
.
getBase
();
switch
(
base
.
which
())
{
case
DeclName
:
:
Base
::
RELATIVE_NAME
:
{
auto
value
=
base
.
getRelativeName
();
errorReporter
.
addErrorOn
(
value
,
kj
::
str
(
"Not defined: "
,
value
.
getValue
()));
return
nullptr
;
}
case
DeclName
:
:
Base
::
ABSOLUTE_NAME
:
{
auto
value
=
base
.
getAbsoluteName
();
errorReporter
.
addErrorOn
(
value
,
kj
::
str
(
"Not defined: "
,
value
.
getValue
()));
return
nullptr
;
}
case
DeclName
:
:
Base
::
IMPORT_NAME
:
{
auto
value
=
base
.
getImportName
();
errorReporter
.
addErrorOn
(
value
,
"Imports not allowed in encode input."
);
return
nullptr
;
}
}
}
private
:
const
SchemaLoader
&
loader
;
const
ErrorReporter
&
errorReporter
;
};
public
:
public
:
// =====================================================================================
// =====================================================================================
...
...
c++/src/capnp/compiler/error-reporter.c++
View file @
5c851221
...
@@ -22,12 +22,49 @@
...
@@ -22,12 +22,49 @@
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "error-reporter.h"
#include "error-reporter.h"
#include <
unistd
.h>
#include <
kj/debug
.h>
namespace
capnp
{
namespace
capnp
{
namespace
compiler
{
namespace
compiler
{
ErrorReporter
::~
ErrorReporter
()
noexcept
(
false
)
{}
namespace
{
template
<
typename
T
>
static
size_t
findLargestElementBefore
(
const
kj
::
Vector
<
T
>&
vec
,
const
T
&
key
)
{
KJ_REQUIRE
(
vec
.
size
()
>
0
&&
vec
[
0
]
<=
key
);
size_t
lower
=
0
;
size_t
upper
=
vec
.
size
();
while
(
upper
-
lower
>
1
)
{
size_t
mid
=
(
lower
+
upper
)
/
2
;
if
(
vec
[
mid
]
>
key
)
{
upper
=
mid
;
}
else
{
lower
=
mid
;
}
}
return
lower
;
}
}
// namespace
LineBreakTable
::
LineBreakTable
(
kj
::
ArrayPtr
<
const
char
>
content
)
:
lineBreaks
(
content
.
size
()
/
40
)
{
lineBreaks
.
add
(
0
);
for
(
const
char
*
pos
=
content
.
begin
();
pos
<
content
.
end
();
++
pos
)
{
if
(
*
pos
==
'\n'
)
{
lineBreaks
.
add
(
pos
+
1
-
content
.
begin
());
}
}
}
GlobalErrorReporter
::
SourcePos
LineBreakTable
::
toSourcePos
(
uint32_t
byteOffset
)
const
{
uint
line
=
findLargestElementBefore
(
lineBreaks
,
byteOffset
);
uint
col
=
byteOffset
-
lineBreaks
[
line
];
return
GlobalErrorReporter
::
SourcePos
{
byteOffset
,
line
,
col
};
}
}
// namespace compiler
}
// namespace compiler
}
// namespace capnp
}
// namespace capnp
c++/src/capnp/compiler/error-reporter.h
View file @
5c851221
...
@@ -27,6 +27,7 @@
...
@@ -27,6 +27,7 @@
#include "../common.h"
#include "../common.h"
#include <kj/string.h>
#include <kj/string.h>
#include <kj/exception.h>
#include <kj/exception.h>
#include <kj/vector.h>
namespace
capnp
{
namespace
capnp
{
namespace
compiler
{
namespace
compiler
{
...
@@ -35,8 +36,6 @@ class ErrorReporter {
...
@@ -35,8 +36,6 @@ class ErrorReporter {
// Callback for reporting errors within a particular file.
// Callback for reporting errors within a particular file.
public
:
public
:
virtual
~
ErrorReporter
()
noexcept
(
false
);
virtual
void
addError
(
uint32_t
startByte
,
uint32_t
endByte
,
kj
::
StringPtr
message
)
const
=
0
;
virtual
void
addError
(
uint32_t
startByte
,
uint32_t
endByte
,
kj
::
StringPtr
message
)
const
=
0
;
// Report an error at the given location in the input text. `startByte` and `endByte` indicate
// Report an error at the given location in the input text. `startByte` and `endByte` indicate
// the span of text that is erroneous. They may be equal, in which case the parser was only
// the span of text that is erroneous. They may be equal, in which case the parser was only
...
@@ -78,6 +77,18 @@ public:
...
@@ -78,6 +77,18 @@ public:
// of previous errors.
// of previous errors.
};
};
class
LineBreakTable
{
public
:
LineBreakTable
(
kj
::
ArrayPtr
<
const
char
>
content
);
GlobalErrorReporter
::
SourcePos
toSourcePos
(
uint32_t
byteOffset
)
const
;
private
:
kj
::
Vector
<
uint
>
lineBreaks
;
// Byte offsets of the first byte in each source line. The first element is always zero.
// Initialized the first time the module is loaded.
};
}
// namespace compiler
}
// namespace compiler
}
// namespace capnp
}
// namespace capnp
...
...
c++/src/capnp/compiler/module-loader.c++
View file @
5c851221
...
@@ -42,25 +42,6 @@ namespace compiler {
...
@@ -42,25 +42,6 @@ namespace compiler {
namespace
{
namespace
{
template
<
typename
T
>
size_t
findLargestElementBefore
(
const
kj
::
Vector
<
T
>&
vec
,
const
T
&
key
)
{
KJ_REQUIRE
(
vec
.
size
()
>
0
&&
vec
[
0
]
<=
key
);
size_t
lower
=
0
;
size_t
upper
=
vec
.
size
();
while
(
upper
-
lower
>
1
)
{
size_t
mid
=
(
lower
+
upper
)
/
2
;
if
(
vec
[
mid
]
>
key
)
{
upper
=
mid
;
}
else
{
lower
=
mid
;
}
}
return
lower
;
}
class
MmapDisposer
:
public
kj
::
ArrayDisposer
{
class
MmapDisposer
:
public
kj
::
ArrayDisposer
{
protected
:
protected
:
void
disposeImpl
(
void
*
firstElement
,
size_t
elementSize
,
size_t
elementCount
,
void
disposeImpl
(
void
*
firstElement
,
size_t
elementSize
,
size_t
elementCount
,
...
@@ -228,7 +209,7 @@ private:
...
@@ -228,7 +209,7 @@ private:
kj
::
MutexGuarded
<
std
::
map
<
kj
::
StringPtr
,
kj
::
Own
<
Module
>>>
modules
;
kj
::
MutexGuarded
<
std
::
map
<
kj
::
StringPtr
,
kj
::
Own
<
Module
>>>
modules
;
};
};
class
ModuleLoader
::
ModuleImpl
:
public
Module
{
class
ModuleLoader
::
ModuleImpl
final
:
public
Module
{
public
:
public
:
ModuleImpl
(
const
ModuleLoader
::
Impl
&
loader
,
kj
::
String
localName
,
kj
::
String
sourceName
)
ModuleImpl
(
const
ModuleLoader
::
Impl
&
loader
,
kj
::
String
localName
,
kj
::
String
sourceName
)
:
loader
(
loader
),
localName
(
kj
::
mv
(
localName
)),
sourceName
(
kj
::
mv
(
sourceName
))
{}
:
loader
(
loader
),
localName
(
kj
::
mv
(
localName
)),
sourceName
(
kj
::
mv
(
sourceName
))
{}
...
@@ -244,15 +225,8 @@ public:
...
@@ -244,15 +225,8 @@ public:
Orphan
<
ParsedFile
>
loadContent
(
Orphanage
orphanage
)
const
override
{
Orphan
<
ParsedFile
>
loadContent
(
Orphanage
orphanage
)
const
override
{
kj
::
Array
<
const
char
>
content
=
mmapForRead
(
localName
);
kj
::
Array
<
const
char
>
content
=
mmapForRead
(
localName
);
lineBreaks
.
get
([
&
](
kj
::
SpaceFor
<
kj
::
Vector
<
uint
>>&
space
)
{
lineBreaks
.
get
([
&
](
kj
::
SpaceFor
<
LineBreakTable
>&
space
)
{
auto
vec
=
space
.
construct
(
content
.
size
()
/
40
);
return
space
.
construct
(
content
);
vec
->
add
(
0
);
for
(
const
char
*
pos
=
content
.
begin
();
pos
<
content
.
end
();
++
pos
)
{
if
(
*
pos
==
'\n'
)
{
vec
->
add
(
pos
+
1
-
content
.
begin
());
}
}
return
vec
;
});
});
MallocMessageBuilder
lexedBuilder
;
MallocMessageBuilder
lexedBuilder
;
...
@@ -274,22 +248,12 @@ public:
...
@@ -274,22 +248,12 @@ public:
void
addError
(
uint32_t
startByte
,
uint32_t
endByte
,
kj
::
StringPtr
message
)
const
override
{
void
addError
(
uint32_t
startByte
,
uint32_t
endByte
,
kj
::
StringPtr
message
)
const
override
{
auto
&
lines
=
lineBreaks
.
get
(
auto
&
lines
=
lineBreaks
.
get
(
[](
kj
::
SpaceFor
<
kj
::
Vector
<
uint
>>&
space
)
{
[](
kj
::
SpaceFor
<
LineBreakTable
>&
space
)
->
kj
::
Own
<
LineBreakTable
>
{
KJ_FAIL_REQUIRE
(
"Can't report errors until loadContent() is called."
);
KJ_FAIL_REQUIRE
(
"Can't report errors until loadContent() is called."
);
return
space
.
construct
();
});
});
// TODO(someday): This counts tabs as single characters. Do we care?
uint
startLine
=
findLargestElementBefore
(
lines
,
startByte
);
uint
startCol
=
startByte
-
lines
[
startLine
];
uint
endLine
=
findLargestElementBefore
(
lines
,
endByte
);
uint
endCol
=
endByte
-
lines
[
endLine
];
loader
.
getErrorReporter
().
addError
(
loader
.
getErrorReporter
().
addError
(
localName
,
localName
,
lines
.
toSourcePos
(
startByte
),
lines
.
toSourcePos
(
endByte
),
message
);
GlobalErrorReporter
::
SourcePos
{
startByte
,
startLine
,
startCol
},
GlobalErrorReporter
::
SourcePos
{
endByte
,
endLine
,
endCol
},
message
);
}
}
bool
hadErrors
()
const
override
{
bool
hadErrors
()
const
override
{
...
@@ -301,9 +265,7 @@ private:
...
@@ -301,9 +265,7 @@ private:
kj
::
String
localName
;
kj
::
String
localName
;
kj
::
String
sourceName
;
kj
::
String
sourceName
;
kj
::
Lazy
<
kj
::
Vector
<
uint
>>
lineBreaks
;
kj
::
Lazy
<
LineBreakTable
>
lineBreaks
;
// Byte offsets of the first byte in each source line. The first element is always zero.
// Initialized the first time the module is loaded.
};
};
// =======================================================================================
// =======================================================================================
...
...
c++/src/capnp/compiler/node-translator.c++
View file @
5c851221
This diff is collapsed.
Click to expand it.
c++/src/capnp/compiler/node-translator.h
View file @
5c851221
...
@@ -169,35 +169,49 @@ private:
...
@@ -169,35 +169,49 @@ private:
schema
::
Value
::
Builder
target
,
bool
isBootstrap
);
schema
::
Value
::
Builder
target
,
bool
isBootstrap
);
// Interprets the value expression and initializes `target` with the result.
// Interprets the value expression and initializes `target` with the result.
kj
::
Maybe
<
DynamicValue
::
Reader
>
readConstant
(
DeclName
::
Reader
name
,
bool
isBootstrap
);
// Get the value of the given constant. May return null if some error occurs, which will already
// have been reported.
kj
::
Maybe
<
ListSchema
>
makeListSchemaOf
(
schema
::
Type
::
Reader
elementType
);
// Construct a list schema representing a list of elements of the given type. May return null if
// some error occurs, which will already have been reported.
Orphan
<
List
<
schema
::
Annotation
>>
compileAnnotationApplications
(
List
<
Declaration
::
AnnotationApplication
>::
Reader
annotations
,
kj
::
StringPtr
targetsFlagName
);
};
class
ValueTranslator
{
public
:
class
Resolver
{
public
:
virtual
kj
::
Maybe
<
Schema
>
resolveType
(
uint64_t
id
)
=
0
;
virtual
kj
::
Maybe
<
DynamicValue
::
Reader
>
resolveConstant
(
DeclName
::
Reader
name
)
=
0
;
};
ValueTranslator
(
Resolver
&
resolver
,
const
ErrorReporter
&
errorReporter
,
Orphanage
orphanage
)
:
resolver
(
resolver
),
errorReporter
(
errorReporter
),
orphanage
(
orphanage
)
{}
kj
::
Maybe
<
Orphan
<
DynamicValue
>>
compileValue
(
kj
::
Maybe
<
Orphan
<
DynamicValue
>>
compileValue
(
ValueExpression
::
Reader
src
,
schema
::
Type
::
Reader
type
,
bool
isBootstrap
);
ValueExpression
::
Reader
src
,
schema
::
Type
::
Reader
type
);
// Compile the given value as the given type. Returns null if there was an error, including
// if the value doesn't match the type.
private
:
Resolver
&
resolver
;
const
ErrorReporter
&
errorReporter
;
Orphanage
orphanage
;
Orphan
<
DynamicValue
>
compileValueInner
(
ValueExpression
::
Reader
src
,
schema
::
Type
::
Reader
type
,
Orphan
<
DynamicValue
>
compileValueInner
(
ValueExpression
::
Reader
src
,
schema
::
Type
::
Reader
type
);
bool
isBootstrap
);
// Helper for compileValue().
// Helper for compileValue().
void
fillStructValue
(
DynamicStruct
::
Builder
builder
,
void
fillStructValue
(
DynamicStruct
::
Builder
builder
,
List
<
ValueExpression
::
FieldAssignment
>::
Reader
assignments
,
List
<
ValueExpression
::
FieldAssignment
>::
Reader
assignments
);
bool
isBootstrap
);
// Interprets the given assignments and uses them to fill in the given struct builder.
// Interprets the given assignments and uses them to fill in the given struct builder.
kj
::
String
makeNodeName
(
uint64_t
id
);
kj
::
String
makeNodeName
(
uint64_t
id
);
kj
::
String
makeTypeName
(
schema
::
Type
::
Reader
type
);
kj
::
String
makeTypeName
(
schema
::
Type
::
Reader
type
);
kj
::
Maybe
<
DynamicValue
::
Reader
>
readConstant
(
DeclName
::
Reader
name
,
bool
isBootstrap
,
ValueExpression
::
Reader
errorLocation
);
// Get the value of the given constant. May return null if some error occurs, which will already
// have been reported.
kj
::
Maybe
<
ListSchema
>
makeListSchemaOf
(
schema
::
Type
::
Reader
elementType
);
kj
::
Maybe
<
ListSchema
>
makeListSchemaOf
(
schema
::
Type
::
Reader
elementType
);
// Construct a list schema representing a list of elements of the given type. May return null if
// some error occurs, which will already have been reported.
Orphan
<
List
<
schema
::
Annotation
>>
compileAnnotationApplications
(
List
<
Declaration
::
AnnotationApplication
>::
Reader
annotations
,
kj
::
StringPtr
targetsFlagName
);
};
};
}
// namespace compiler
}
// namespace compiler
...
...
c++/src/capnp/dynamic.c++
View file @
5c851221
...
@@ -1659,6 +1659,19 @@ DynamicStruct::Builder MessageBuilder::getRoot<DynamicStruct>(StructSchema schem
...
@@ -1659,6 +1659,19 @@ DynamicStruct::Builder MessageBuilder::getRoot<DynamicStruct>(StructSchema schem
return
DynamicStruct
::
Builder
(
schema
,
getRoot
(
structSizeFromSchema
(
schema
)));
return
DynamicStruct
::
Builder
(
schema
,
getRoot
(
structSizeFromSchema
(
schema
)));
}
}
template
<>
void
MessageBuilder
::
setRoot
<
DynamicStruct
::
Reader
>
(
DynamicStruct
::
Reader
&&
value
)
{
setRootInternal
(
value
.
reader
);
}
template
<>
void
MessageBuilder
::
setRoot
<
const
DynamicStruct
::
Reader
&>
(
const
DynamicStruct
::
Reader
&
value
)
{
setRootInternal
(
value
.
reader
);
}
template
<>
void
MessageBuilder
::
setRoot
<
DynamicStruct
::
Reader
&>
(
DynamicStruct
::
Reader
&
value
)
{
setRootInternal
(
value
.
reader
);
}
namespace
_
{
// private
namespace
_
{
// private
DynamicStruct
::
Reader
PointerHelpers
<
DynamicStruct
,
Kind
::
UNKNOWN
>::
getDynamic
(
DynamicStruct
::
Reader
PointerHelpers
<
DynamicStruct
,
Kind
::
UNKNOWN
>::
getDynamic
(
...
...
c++/src/capnp/dynamic.h
View file @
5c851221
...
@@ -216,6 +216,8 @@ public:
...
@@ -216,6 +216,8 @@ public:
template
<
typename
T
,
typename
=
kj
::
EnableIf
<
kind
<
FromReader
<
T
>>
()
==
Kind
::
STRUCT
>>
template
<
typename
T
,
typename
=
kj
::
EnableIf
<
kind
<
FromReader
<
T
>>
()
==
Kind
::
STRUCT
>>
inline
Reader
(
T
&&
value
)
:
Reader
(
toDynamic
(
value
))
{}
inline
Reader
(
T
&&
value
)
:
Reader
(
toDynamic
(
value
))
{}
inline
size_t
totalSizeInWords
()
const
{
return
reader
.
totalSize
()
/
::
capnp
::
WORDS
;
}
template
<
typename
T
>
template
<
typename
T
>
typename
T
::
Reader
as
()
const
;
typename
T
::
Reader
as
()
const
;
// Convert the dynamic struct to its compiled-in type.
// Convert the dynamic struct to its compiled-in type.
...
@@ -279,6 +281,8 @@ public:
...
@@ -279,6 +281,8 @@ public:
template
<
typename
T
,
typename
=
kj
::
EnableIf
<
kind
<
FromBuilder
<
T
>>
()
==
Kind
::
STRUCT
>>
template
<
typename
T
,
typename
=
kj
::
EnableIf
<
kind
<
FromBuilder
<
T
>>
()
==
Kind
::
STRUCT
>>
inline
Builder
(
T
&&
value
)
:
Builder
(
toDynamic
(
value
))
{}
inline
Builder
(
T
&&
value
)
:
Builder
(
toDynamic
(
value
))
{}
inline
size_t
totalSizeInWords
()
const
{
return
asReader
().
totalSizeInWords
();
}
template
<
typename
T
>
template
<
typename
T
>
typename
T
::
Builder
as
();
typename
T
::
Builder
as
();
// Cast to a particular struct type.
// Cast to a particular struct type.
...
@@ -926,6 +930,12 @@ template <>
...
@@ -926,6 +930,12 @@ template <>
DynamicStruct
::
Builder
MessageBuilder
::
initRoot
<
DynamicStruct
>
(
StructSchema
schema
);
DynamicStruct
::
Builder
MessageBuilder
::
initRoot
<
DynamicStruct
>
(
StructSchema
schema
);
template
<>
template
<>
DynamicStruct
::
Builder
MessageBuilder
::
getRoot
<
DynamicStruct
>
(
StructSchema
schema
);
DynamicStruct
::
Builder
MessageBuilder
::
getRoot
<
DynamicStruct
>
(
StructSchema
schema
);
template
<>
void
MessageBuilder
::
setRoot
<
DynamicStruct
::
Reader
>
(
DynamicStruct
::
Reader
&&
value
);
template
<>
void
MessageBuilder
::
setRoot
<
const
DynamicStruct
::
Reader
&>
(
const
DynamicStruct
::
Reader
&
value
);
template
<>
void
MessageBuilder
::
setRoot
<
DynamicStruct
::
Reader
&>
(
DynamicStruct
::
Reader
&
value
);
namespace
_
{
// private
namespace
_
{
// private
...
...
c++/src/capnp/schema-parser.c++
View file @
5c851221
...
@@ -67,7 +67,7 @@ size_t findLargestElementBefore(const kj::Vector<T>& vec, const T& key) {
...
@@ -67,7 +67,7 @@ size_t findLargestElementBefore(const kj::Vector<T>& vec, const T& key) {
// =======================================================================================
// =======================================================================================
class
SchemaParser
::
ModuleImpl
:
public
compiler
::
Module
{
class
SchemaParser
::
ModuleImpl
final
:
public
compiler
::
Module
{
public
:
public
:
ModuleImpl
(
const
SchemaParser
&
parser
,
kj
::
Own
<
const
SchemaFile
>&&
file
)
ModuleImpl
(
const
SchemaParser
&
parser
,
kj
::
Own
<
const
SchemaFile
>&&
file
)
:
parser
(
parser
),
file
(
kj
::
mv
(
file
))
{}
:
parser
(
parser
),
file
(
kj
::
mv
(
file
))
{}
...
...
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