1// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "tools/gn/value_extractors.h"
6
7#include "tools/gn/err.h"
8#include "tools/gn/label.h"
9#include "tools/gn/source_dir.h"
10#include "tools/gn/source_file.h"
11
12namespace {
13
14// This extractor rejects files with system-absolute file paths. If we need
15// that in the future, we'll have to add some flag to control this.
16struct RelativeFileConverter {
17  RelativeFileConverter(const SourceDir& current_dir_in)
18      : current_dir(current_dir_in) {}
19  bool operator()(const Value& v, SourceFile* out, Err* err) const {
20    if (!v.VerifyTypeIs(Value::STRING, err))
21      return false;
22    *out = current_dir.ResolveRelativeFile(v.string_value());
23    if (out->is_system_absolute()) {
24      *err = Err(v, "System-absolute file path.",
25          "You can't list a system-absolute file path here. Please include "
26          "only files in\nthe source tree. Maybe you meant to begin with two "
27          "slashes to indicate an\nabsolute path in the source tree?");
28      return false;
29    }
30    return true;
31  }
32  const SourceDir& current_dir;
33};
34
35struct RelativeDirConverter {
36  RelativeDirConverter(const SourceDir& current_dir_in)
37      : current_dir(current_dir_in) {}
38  bool operator()(const Value& v, SourceDir* out, Err* err) const {
39    if (!v.VerifyTypeIs(Value::STRING, err))
40      return false;
41    *out = current_dir.ResolveRelativeDir(v.string_value());
42    return true;
43  }
44  const SourceDir& current_dir;
45};
46
47struct LabelResolver {
48  LabelResolver(const SourceDir& current_dir_in,
49                const Label& current_toolchain_in)
50      : current_dir(current_dir_in),
51        current_toolchain(current_toolchain_in) {}
52  bool operator()(const Value& v, Label* out, Err* err) const {
53    if (!v.VerifyTypeIs(Value::STRING, err))
54      return false;
55    *out = Label::Resolve(current_dir, current_toolchain, v, err);
56    return !err->has_error();
57  }
58  const SourceDir& current_dir;
59  const Label& current_toolchain;
60};
61
62}  // namespace
63
64bool ExtractListOfStringValues(const Value& value,
65                               std::vector<std::string>* dest,
66                               Err* err) {
67  if (!value.VerifyTypeIs(Value::LIST, err))
68    return false;
69  const std::vector<Value>& input_list = value.list_value();
70  dest->reserve(input_list.size());
71  for (size_t i = 0; i < input_list.size(); i++) {
72    if (!input_list[i].VerifyTypeIs(Value::STRING, err))
73      return false;
74    dest->push_back(input_list[i].string_value());
75  }
76  return true;
77}
78
79bool ExtractListOfRelativeFiles(const Value& value,
80                                const SourceDir& current_dir,
81                                std::vector<SourceFile>* files,
82                                Err* err) {
83  return ListValueExtractor(value, files, err,
84                            RelativeFileConverter(current_dir));
85}
86
87bool ExtractListOfRelativeDirs(const Value& value,
88                               const SourceDir& current_dir,
89                               std::vector<SourceDir>* dest,
90                               Err* err) {
91  return ListValueExtractor(value, dest, err,
92                            RelativeDirConverter(current_dir));
93}
94
95bool ExtractListOfLabels(const Value& value,
96                         const SourceDir& current_dir,
97                         const Label& current_toolchain,
98                         std::vector<Label>* dest,
99                         Err* err) {
100  return ListValueExtractor(value, dest, err,
101                            LabelResolver(current_dir, current_toolchain));
102}
103