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 }