kythe.io@v0.0.68-0.20240422202219-7225dbc01741/kythe/cxx/common/kzip_writer_c_api.cc (about)

     1  /*
     2   * Copyright 2018 The Kythe Authors. All rights reserved.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *   http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  #include "kythe/cxx/common/kzip_writer_c_api.h"
    18  
    19  #include <stddef.h>
    20  #include <stdint.h>
    21  
    22  #include <cstring>
    23  #include <string>
    24  #include <utility>
    25  
    26  #include "absl/log/check.h"
    27  #include "absl/log/log.h"
    28  #include "absl/status/status.h"
    29  #include "absl/status/statusor.h"
    30  #include "absl/strings/string_view.h"
    31  #include "kythe/cxx/common/index_writer.h"
    32  #include "kythe/cxx/common/kzip_encoding.h"
    33  #include "kythe/cxx/common/kzip_writer.h"
    34  #include "kythe/proto/analysis.pb.h"
    35  
    36  using kythe::IndexWriter;
    37  using kythe::KzipEncoding;
    38  
    39  namespace {
    40  
    41  KzipEncoding ToKzipEncoding(int32_t encoding) {
    42    KzipEncoding kzip_encoding = KzipEncoding::kJson;
    43    switch (encoding) {
    44      case KZIP_WRITER_ENCODING_JSON:
    45        kzip_encoding = KzipEncoding::kJson;
    46        break;
    47      case KZIP_WRITER_ENCODING_PROTO:
    48        kzip_encoding = KzipEncoding::kProto;
    49        break;
    50      default:
    51        // fallthrough
    52      case KZIP_WRITER_ENCODING_ALL:
    53        kzip_encoding = kythe::KzipEncoding::kAll;
    54        break;
    55    }
    56    return kzip_encoding;
    57  }
    58  
    59  int32_t CodeFromStatus(const absl::Status& s) {
    60    const absl::StatusCode code = s.code();
    61    LOG(ERROR) << "Status: " << s;
    62    return static_cast<int32_t>(code);
    63  }
    64  
    65  }  // namespace
    66  
    67  KzipWriter* KzipWriter_Create(const char* path, const size_t path_len,
    68                                int32_t encoding, int32_t* create_status) {
    69    CHECK(path != nullptr);
    70    *create_status = 0;
    71    KzipEncoding kzip_encoding = ToKzipEncoding(encoding);
    72    const absl::string_view path_view(path, path_len);
    73  
    74    absl::StatusOr<IndexWriter> writer =
    75        kythe::KzipWriter::Create(path_view, kzip_encoding);
    76    if (!writer.ok()) {
    77      *create_status = CodeFromStatus(writer.status());
    78      return nullptr;
    79    }
    80    return reinterpret_cast<KzipWriter*>(
    81        new kythe::IndexWriter(*std::move(writer)));
    82  }
    83  
    84  void KzipWriter_Delete(KzipWriter* writer) {
    85    // We assume that `writer` was created by `KzipWriter_Create`.
    86    delete reinterpret_cast<IndexWriter*>(writer);
    87  }
    88  
    89  int32_t KzipWriter_Close(KzipWriter* writer) {
    90    const absl::Status status = reinterpret_cast<IndexWriter*>(writer)->Close();
    91    return static_cast<int32_t>(status.code());
    92  }
    93  
    94  int32_t KzipWriter_WriteFile(KzipWriter* writer, const char* content,
    95                               const size_t content_length, char* digest_buffer,
    96                               size_t buffer_length,
    97                               size_t* resulting_digest_size) {
    98    // We assume that `writer` was created by `KzipWriter_Create`.
    99    IndexWriter* w = reinterpret_cast<IndexWriter*>(writer);
   100    auto digest_or = w->WriteFile({content, content_length});
   101    if (!digest_or.ok()) {
   102      return CodeFromStatus(digest_or.status());
   103    }
   104    const std::string& digest = *digest_or;
   105    if (digest.length() > buffer_length) {
   106      LOG(ERROR) << "Digest buffer too small to fit digest: " << digest;
   107      return KZIP_WRITER_BUFFER_TOO_SMALL_ERROR;
   108    }
   109    memcpy(digest_buffer, digest.c_str(), digest.length());
   110    *resulting_digest_size = digest.length();
   111    return 0;
   112  }
   113  
   114  int32_t KzipWriter_WriteUnit(KzipWriter* writer, const char* proto,
   115                               size_t proto_length, char* digest_buffer,
   116                               size_t buffer_length,
   117                               size_t* resulting_digest_size) {
   118    // We assume that `writer` was created by `KzipWriter_Create`.
   119    IndexWriter* w = reinterpret_cast<IndexWriter*>(writer);
   120    kythe::proto::IndexedCompilation unit;
   121    const bool success = unit.ParseFromArray(proto, proto_length);
   122    if (!success) {
   123      LOG(ERROR) << "Protobuf could not be parsed, at len: " << proto_length;
   124      return KZIP_WRITER_PROTO_PARSING_ERROR;
   125    }
   126    absl::StatusOr<std::string> digest_or = w->WriteUnit(unit);
   127    if (!digest_or.ok()) {
   128      return CodeFromStatus(digest_or.status());
   129    }
   130    const auto& digest = *digest_or;
   131    if (digest.length() > buffer_length) {
   132      return KZIP_WRITER_BUFFER_TOO_SMALL_ERROR;
   133    }
   134    memcpy(digest_buffer, digest.c_str(), digest.length());
   135    *resulting_digest_size = digest.length();
   136    return 0;
   137  }