salesforce_id 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4898a0b33f8f54372cff05bd0b65c0705c544a8c
4
+ data.tar.gz: c9f1d80e51b4229bc9bd636fb5a684c050494cf6
5
+ SHA512:
6
+ metadata.gz: 4b6885c6be43f1ead7dc991a006278faaad1968b734324eed060b13f9801f7ca8868ca8602735fb1a7c5992b9772a50426d0d8ab96e7c32aae11ff49086b4f88
7
+ data.tar.gz: fe2d8cab75769f2eba6f618a9ab9072e09e3c8938a6d4f633ef5a338afa8926cff19e0e6ff25d7ed6748bb60b6434d06926f73a740bab010ab8e5b7325ddd444
data/.gitignore ADDED
@@ -0,0 +1,30 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ .DS_Store
11
+
12
+ .project
13
+ .directory
14
+ *.swp
15
+ *~
16
+ .DS_Store
17
+ .idea
18
+ .envrc
19
+ .nvmrc
20
+ .ruby-gemset
21
+ .ruby-version
22
+ .rspec-local
23
+ *.backup
24
+ npm-debug.log
25
+
26
+ *.bundle
27
+ *.so
28
+ *.o
29
+ *.a
30
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format progress
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.2
4
+ - 2.2.1
5
+ before_install: gem install bundler -v 1.10.6
6
+ cache: bundler
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in salesforce_id.gemspec
4
+ gemspec
5
+
6
+ gem 'codeclimate-test-reporter', group: :test, require: nil
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Fire-Dragon-DoL
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,86 @@
1
+ # SalesforceId [![Build Status](https://api.travis-ci.org/plataformatec/devise.svg?branch=master)](https://travis-ci.org/Fire-Dragon-DoL/salesforce_id.svg?branch=master) [![Code Climate](https://codeclimate.com/github/Fire-Dragon-DoL/salesforce_id/badges/gpa.svg)](https://codeclimate.com/github/Fire-Dragon-DoL/salesforce_id) [![Test Coverage](https://codeclimate.com/github/Fire-Dragon-DoL/salesforce_id/badges/coverage.svg)](https://codeclimate.com/github/Fire-Dragon-DoL/salesforce_id/coverage)
2
+
3
+ Gem to properly convert from and to 15 characters case sensitive format and
4
+ 18 characters case insensitive format for salesforce record ID.
5
+
6
+ It's implemented as a C library to make the conversion as fast and performant
7
+ as possible.
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'salesforce_id'
15
+ ```
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install salesforce_id
24
+
25
+ ## Usage
26
+
27
+ The gem can be used as easily as:
28
+
29
+ ```ruby
30
+ id15 = "003G000001SUbc4"
31
+ id18 = "003G000001SUbc4IAD"
32
+
33
+ # Convert to insensitive id, 18 characters
34
+ SalesforceId.to_insensitive(id15) == id18 # => true
35
+
36
+ # Convert to sensitive id, 15 characters
37
+ SalesforceId.to_sensitive(id18) == id15 # => true
38
+
39
+ # Check if salesforce id is valid
40
+ SalesforceId.valid?(id15) # => true
41
+ SalesforceId.valid?(id18) # => true
42
+ SalesforceId.valid?("foo") # => false
43
+
44
+ # Fixes casing for case-insensitive ids
45
+ SalesforceId.repair_casing(id18.downcase) == id18 # => true
46
+
47
+ # Check if id is case-sensitive format
48
+ SalesforceId.sensitive?(id15) # => true
49
+ SalesforceId.sensitive?(id18) # => false
50
+ SalesforceId.sensitive?(nil) # => false
51
+
52
+ # Check if id is case-insensitive format
53
+ SalesforceId.insensitive?(id18) # => true
54
+ SalesforceId.insensitive?(id15) # => false
55
+ SalesforceId.insensitive?(nil) # => false
56
+ ```
57
+
58
+ ## Documentation
59
+
60
+ Methods are documented in [salesforce_id_ext.h](https://github.com/Fire-Dragon-DoL/salesforce_id/blob/master/ext/salesforce_id/salesforce_id_ext.h), this file is
61
+ the only public API of the gem, everything else must be considered private.
62
+
63
+ ## Links
64
+
65
+ Some useful links related to this Salesforce ID issue:
66
+
67
+ - [What are salesforce ids composed of](http://salesforce.stackexchange.com/questions/1653/what-are-salesforce-ids-composed-of)
68
+ - [How I can view 18 characters long Salesforce ID in reports?](https://success.salesforce.com/answers?id=90630000000gy8oAAA)
69
+ - [Why does 18-character ID casing matter in a SOQL WHERE clause?](http://salesforce.stackexchange.com/questions/50163/why-does-18-character-id-casing-matter-in-a-soql-where-clause)
70
+ - [Creating a link using an 18 character ID](http://salesforce.stackexchange.com/questions/9568/creating-a-link-using-an-18-character-id/9569#9569)
71
+
72
+ ## Development
73
+
74
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
75
+
76
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
77
+
78
+ ## Contributing
79
+
80
+ Bug reports and pull requests are welcome on GitHub at https://github.com/Fire-Dragon-DoL/salesforce_id.
81
+
82
+
83
+ ## License
84
+
85
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
86
+
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => [:compile, :spec]
7
+ require "rake/extensiontask"
8
+
9
+ task :build => :compile
10
+
11
+ Rake::ExtensionTask.new("salesforce_id") do |ext|
12
+ ext.lib_dir = "lib/salesforce_id"
13
+ end
data/bin/bundler ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'bundler' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('bundler', 'bundler')
data/bin/byebug ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'byebug' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('byebug', 'byebug')
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'cc-tddium-post-worker' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('codeclimate-test-reporter', 'cc-tddium-post-worker')
data/bin/coderay ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'coderay' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('coderay', 'coderay')
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "salesforce_id"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/htmldiff ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'htmldiff' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('diff-lcs', 'htmldiff')
data/bin/ldiff ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'ldiff' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('diff-lcs', 'ldiff')
data/bin/pry ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'pry' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('pry', 'pry')
data/bin/rake ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rake' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('rake', 'rake')
data/bin/rake-compiler ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rake-compiler' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('rake-compiler', 'rake-compiler')
data/bin/rspec ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rspec' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('rspec-core', 'rspec')
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,17 @@
1
+ #include "charmap.h"
2
+ #include <ctype.h>
3
+
4
+ const char CHARMAP[CHARMAP_SIZE] = {
5
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
6
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5'
7
+ };
8
+
9
+ int charmap_index(const char character)
10
+ {
11
+ char upped = toupper(character);
12
+
13
+ for (int index = 0; index < CHARMAP_SIZE; ++index)
14
+ if (CHARMAP[index] == upped) return index;
15
+
16
+ return (-1);
17
+ }
@@ -0,0 +1,10 @@
1
+ #ifndef CHARMAP_H
2
+ #define CHARMAP_H 1
3
+
4
+ #define CHARMAP_SIZE 32
5
+
6
+ extern const char CHARMAP[CHARMAP_SIZE];
7
+
8
+ int charmap_index(const char character);
9
+
10
+ #endif /* CHARMAP_H */
@@ -0,0 +1,5 @@
1
+ require "mkmf"
2
+
3
+ $CFLAGS += " -std=c99"
4
+
5
+ create_makefile("salesforce_id/salesforce_id")
@@ -0,0 +1,19 @@
1
+ #include "insensitive_to_sensitive.h"
2
+ #include "ruby.h"
3
+ #include <string.h>
4
+ #include "salesforce_id_ext.h"
5
+ #include "repair_casing.h"
6
+
7
+ // rb_sId MUST be a string and of size 18
8
+ VALUE insensitive_to_sensitive(VALUE rb_sId)
9
+ {
10
+ const int new_id_size = SALESFORCE_ID_INSENSITIVE_STRING_LENGTH;
11
+ char* id = StringValueCStr(rb_sId);
12
+ char new_id[SALESFORCE_ID_INSENSITIVE_STRING_LENGTH] = {0};
13
+
14
+ memcpy(new_id, id, new_id_size);
15
+ repair_casing(new_id);
16
+ memset(&new_id[15], '\0', sizeof(new_id[0]) * 4u);
17
+
18
+ return rb_str_new2(new_id);
19
+ }
@@ -0,0 +1,8 @@
1
+ #ifndef INSENSITIVE_TO_SENSITIVE_H
2
+ #define INSENSITIVE_TO_SENSITIVE_H 1
3
+
4
+ #include "ruby.h"
5
+
6
+ VALUE insensitive_to_sensitive(VALUE rb_sId);
7
+
8
+ #endif /* INSENSITIVE_TO_SENSITIVE_H */
@@ -0,0 +1,49 @@
1
+ #include "repair_casing.h"
2
+ #include "ruby.h"
3
+ #include <stddef.h>
4
+ #include <string.h>
5
+ #include <ctype.h>
6
+ #include <stdbool.h>
7
+ #include "salesforce_id_ext.h"
8
+ #include "charmap.h"
9
+
10
+ static void chunk_casing(const char character, bool* casing);
11
+
12
+ void repair_casing(char* id)
13
+ {
14
+ const int chunk_index = SALESFORCE_ID_SENSITIVE_LENGTH;
15
+ const size_t casing_size = (size_t)SALESFORCE_ID_SENSITIVE_LENGTH;
16
+ bool casing[SALESFORCE_ID_SENSITIVE_LENGTH] = {false};
17
+
18
+ chunk_casing(id[chunk_index], casing);
19
+ chunk_casing(id[chunk_index + 1], &casing[5]);
20
+ chunk_casing(id[chunk_index + 2], &casing[10]);
21
+
22
+ for (size_t index = 0u; index < casing_size; ++index)
23
+ {
24
+ if (casing[index])
25
+ id[index] = toupper(id[index]);
26
+ else
27
+ id[index] = tolower(id[index]);
28
+ }
29
+
30
+ id[chunk_index] = toupper(id[chunk_index]);
31
+ id[chunk_index + 1] = toupper(id[chunk_index]);
32
+ id[chunk_index + 2] = toupper(id[chunk_index]);
33
+ }
34
+
35
+ // Casing is an array of size 5
36
+ void chunk_casing(const char character, bool* casing)
37
+ {
38
+ const size_t casing_size = 5u;
39
+ int map_index = charmap_index(character);
40
+
41
+ if (map_index < 0)
42
+ {
43
+ rb_raise(rb_eArgError, "Salesforce ID contains invalid character");
44
+ return;
45
+ }
46
+
47
+ for (size_t bit_index = 0u; bit_index < casing_size; ++bit_index)
48
+ casing[bit_index] = (map_index & (1u << bit_index)) != 0u;
49
+ }
@@ -0,0 +1,6 @@
1
+ #ifndef REPAIR_CASING_H
2
+ #define REPAIR_CASING_H 1
3
+
4
+ void repair_casing(char* id);
5
+
6
+ #endif /* REPAIR_CASING_H */
@@ -0,0 +1,151 @@
1
+ #include "salesforce_id_ext.h"
2
+ #include <string.h>
3
+ #include <ctype.h>
4
+ #include <stddef.h>
5
+ #include "repair_casing.h"
6
+ #include "insensitive_to_sensitive.h"
7
+ #include "sensitive_to_insensitive.h"
8
+ #include "validate_id.h"
9
+
10
+ VALUE rb_mSalesforceId;
11
+
12
+ void Init_salesforce_id()
13
+ {
14
+ // Module
15
+ rb_mSalesforceId = rb_define_module("SalesforceId");
16
+
17
+ // Constants
18
+ rb_define_const(
19
+ rb_mSalesforceId,
20
+ "SENSITIVE_SIZE",
21
+ INT2FIX(SALESFORCE_ID_SENSITIVE_LENGTH)
22
+ );
23
+ rb_define_const(
24
+ rb_mSalesforceId,
25
+ "INSENSITIVE_SIZE",
26
+ INT2FIX(SALESFORCE_ID_INSENSITIVE_LENGTH)
27
+ );
28
+
29
+ // Methods
30
+ rb_define_method(
31
+ rb_mSalesforceId,
32
+ "to_sensitive",
33
+ salesforce_id_to_sensitive,
34
+ 1
35
+ );
36
+ rb_define_method(
37
+ rb_mSalesforceId,
38
+ "to_insensitive",
39
+ salesforce_id_to_insensitive,
40
+ 1
41
+ );
42
+ rb_define_method(
43
+ rb_mSalesforceId,
44
+ "valid?",
45
+ salesforce_id_is_valid,
46
+ 1
47
+ );
48
+ rb_define_method(
49
+ rb_mSalesforceId,
50
+ "repair_casing",
51
+ salesforce_insensitive_repair_casing,
52
+ 1
53
+ );
54
+ rb_define_method(
55
+ rb_mSalesforceId,
56
+ "sensitive?",
57
+ salesforce_id_is_sensitive,
58
+ 1
59
+ );
60
+ rb_define_method(
61
+ rb_mSalesforceId,
62
+ "insensitive?",
63
+ salesforce_id_is_insensitive,
64
+ 1
65
+ );
66
+ }
67
+
68
+ // Convert to 15 character case-sensitive id
69
+ VALUE salesforce_id_to_sensitive(VALUE self, VALUE rb_sId)
70
+ {
71
+ VALUE id = rb_obj_as_string(rb_sId);
72
+
73
+ if (!is_id_valid(id))
74
+ {
75
+ rb_raise(rb_eArgError, "Invalid Salesforce ID");
76
+ return Qnil;
77
+ }
78
+
79
+ if (RSTRING_LEN(id) == SALESFORCE_ID_SENSITIVE_LENGTH) return id;
80
+
81
+ return insensitive_to_sensitive(id);
82
+ }
83
+
84
+ // Convert to 18 character case-insensitive id
85
+ VALUE salesforce_id_to_insensitive(VALUE self, VALUE rb_sId)
86
+ {
87
+ VALUE id = rb_obj_as_string(rb_sId);
88
+
89
+ if (!is_id_valid(id))
90
+ {
91
+ rb_raise(rb_eArgError, "Invalid Salesforce ID");
92
+ return Qnil;
93
+ }
94
+
95
+ if (RSTRING_LEN(id) == SALESFORCE_ID_INSENSITIVE_LENGTH) return id;
96
+
97
+ return sensitive_to_insensitive(id);
98
+ }
99
+
100
+ VALUE salesforce_id_is_valid(VALUE self, VALUE rb_sId)
101
+ {
102
+ VALUE id = rb_obj_as_string(rb_sId);
103
+
104
+ if (is_id_valid(id)) return Qtrue;
105
+
106
+ return Qfalse;
107
+ }
108
+
109
+ VALUE salesforce_insensitive_repair_casing(VALUE self, VALUE rb_sId)
110
+ {
111
+ VALUE id = rb_obj_as_string(rb_sId);
112
+
113
+ if (!is_id_valid(id) || RSTRING_LEN(id) != SALESFORCE_ID_INSENSITIVE_LENGTH)
114
+ rb_raise(rb_eArgError, "Salesforce ID is not case-insensitive format");
115
+
116
+ // Start for insensitive characters
117
+ const size_t istart = (size_t)SALESFORCE_ID_SENSITIVE_LENGTH;
118
+ const size_t sensitive_chars = 3u;
119
+ const int new_id_size = SALESFORCE_ID_INSENSITIVE_STRING_LENGTH;
120
+ char* old_id = StringValueCStr(id);
121
+ char new_id[SALESFORCE_ID_INSENSITIVE_STRING_LENGTH] = {0};
122
+
123
+ memcpy(new_id, old_id, new_id_size);
124
+ repair_casing(new_id);
125
+ memcpy(&new_id[istart], &old_id[istart], sizeof(new_id[0]) * sensitive_chars);
126
+
127
+ for (size_t index = 0u; index < sensitive_chars; ++index)
128
+ new_id[istart + index] = toupper(new_id[istart + index]);
129
+
130
+ return rb_str_new2(new_id);
131
+ }
132
+
133
+ VALUE salesforce_id_is_sensitive(VALUE self, VALUE rb_sId)
134
+ {
135
+ VALUE id = rb_obj_as_string(rb_sId);
136
+
137
+ if (is_id_valid(id) && (RSTRING_LEN(id) == SALESFORCE_ID_SENSITIVE_LENGTH))
138
+ return Qtrue;
139
+
140
+ return Qfalse;
141
+ }
142
+
143
+ VALUE salesforce_id_is_insensitive(VALUE self, VALUE rb_sId)
144
+ {
145
+ VALUE id = rb_obj_as_string(rb_sId);
146
+
147
+ if (is_id_valid(id) && (RSTRING_LEN(id) == SALESFORCE_ID_INSENSITIVE_LENGTH))
148
+ return Qtrue;
149
+
150
+ return Qfalse;
151
+ }
@@ -0,0 +1,67 @@
1
+ #ifndef SALESFORCE_ID_H
2
+ #define SALESFORCE_ID_H 1
3
+
4
+ #include "ruby.h"
5
+
6
+ extern VALUE rb_mSalesforceId;
7
+
8
+ #define SALESFORCE_ID_SENSITIVE_LENGTH 15
9
+ #define SALESFORCE_ID_INSENSITIVE_LENGTH 18
10
+ #define SALESFORCE_ID_SENSITIVE_STRING_LENGTH 16
11
+ #define SALESFORCE_ID_INSENSITIVE_STRING_LENGTH 19
12
+
13
+ /*
14
+ * Entry point
15
+ */
16
+ void Init_salesforce_id();
17
+
18
+ /*
19
+ * Converts any valid salesforce ID to case-sensitive version. Raises
20
+ * ArgumentError if ID contains invalid characters or it's not correct length
21
+ * @param rb_sId [String] valid salesforce id
22
+ * @return [String] salesforce id in case-sensitive version
23
+ */
24
+ VALUE salesforce_id_to_sensitive(VALUE self, VALUE rb_sId);
25
+
26
+ /*
27
+ * Converts any valid salesforce ID to case-insensitive version. Raises
28
+ * ArgumentError if ID contains invalid characters or it's not correct length
29
+ * @param rb_sId [String] valid salesforce id
30
+ * @return [String] salesforce id in case-insensitive version
31
+ */
32
+ VALUE salesforce_id_to_insensitive(VALUE self, VALUE rb_sId);
33
+
34
+ /*
35
+ * Performs a deep check of the ID ensuring characters are all valid and length
36
+ * is valid too
37
+ * @param rb_sId [String] salesforce id (valid or not)
38
+ * @return [Boolean] true if the deep check has success and salesforce id is
39
+ * valid
40
+ */
41
+ VALUE salesforce_id_is_valid(VALUE self, VALUE rb_sId);
42
+
43
+ /*
44
+ * Fixes a valid case-insensitive salesforce id casing by using the last 3
45
+ * letters
46
+ * @param rb_sId [String] valid salesforce id in case-insensitive format
47
+ * @return [String] case-insensitive salesforce id with casing fixed, which
48
+ * means you can strip the last 3 characters to obtain the case-sensitive
49
+ * format
50
+ */
51
+ VALUE salesforce_insensitive_repair_casing(VALUE self, VALUE rb_sId);
52
+
53
+ /*
54
+ * Detects if given ID is case-sensitive
55
+ * @param rb_sId [String] salesforce id (valid or not)
56
+ * @return [Boolean] true if passed ID is valid case-sensitive salesforce ID
57
+ */
58
+ VALUE salesforce_id_is_sensitive(VALUE self, VALUE rb_sId);
59
+
60
+ /*
61
+ * Detects if given ID is case-insensitive
62
+ * @param rb_sId [String] salesforce id (valid or not)
63
+ * @return [Boolean] true if passed ID is valid case-insensitive salesforce ID
64
+ */
65
+ VALUE salesforce_id_is_insensitive(VALUE self, VALUE rb_sId);
66
+
67
+ #endif /* SALESFORCE_ID_H */
@@ -0,0 +1,54 @@
1
+ #include "sensitive_to_insensitive.h"
2
+ #include "ruby.h"
3
+ #include <stddef.h>
4
+ #include <string.h>
5
+ #include <stdint.h>
6
+ #include <ctype.h>
7
+ #include "salesforce_id_ext.h"
8
+ #include "charmap.h"
9
+
10
+ static void append_casing_hash(char* id);
11
+ static char char_from_chunk(char* id, size_t chunk);
12
+
13
+ // rb_sId MUST be a string and of size 15
14
+ VALUE sensitive_to_insensitive(VALUE rb_sId)
15
+ {
16
+ const int id_size = SALESFORCE_ID_SENSITIVE_STRING_LENGTH;
17
+ char* id = StringValueCStr(rb_sId);
18
+ char new_id[SALESFORCE_ID_INSENSITIVE_STRING_LENGTH] = {0};
19
+
20
+ memcpy(new_id, id, sizeof(char) * id_size);
21
+ append_casing_hash(new_id);
22
+
23
+ return rb_str_new2(new_id);
24
+ }
25
+
26
+ void append_casing_hash(char* id)
27
+ {
28
+ const int insensitive_index = SALESFORCE_ID_SENSITIVE_LENGTH;
29
+ const size_t chunks = 3u;
30
+ char hash[3] = {'\0', '\0', '\0'};
31
+
32
+ for (size_t chunk = 0u; chunk < chunks; ++chunk)
33
+ hash[chunk] = char_from_chunk(id, chunk);
34
+
35
+ id[insensitive_index] = hash[0];
36
+ id[insensitive_index + 1] = hash[1];
37
+ id[insensitive_index + 2] = hash[2];
38
+ }
39
+
40
+ // Chunk must be within 0 and 2
41
+ char char_from_chunk(char* id, size_t chunk)
42
+ {
43
+ const size_t chars_per_chunk = 5u;
44
+ uint8_t map_index = 0u;
45
+
46
+ for (size_t index = 0u; index < chars_per_chunk; ++index)
47
+ {
48
+ char current = id[(chars_per_chunk * chunk) + index];
49
+
50
+ if (isupper(current)) map_index = (map_index | (1u << index));
51
+ }
52
+
53
+ return CHARMAP[map_index];
54
+ }
@@ -0,0 +1,8 @@
1
+ #ifndef SENSITIVE_TO_INSENSITIVE_H
2
+ #define SENSITIVE_TO_INSENSITIVE_H 1
3
+
4
+ #include "ruby.h"
5
+
6
+ VALUE sensitive_to_insensitive(VALUE rb_sId);
7
+
8
+ #endif /* SENSITIVE_TO_INSENSITIVE_H */
@@ -0,0 +1,18 @@
1
+ #include "validate_id.h"
2
+ #include "ruby.h"
3
+ #include <stdbool.h>
4
+ #include <string.h>
5
+ #include <stddef.h>
6
+ #include "salesforce_id_ext.h"
7
+ #include "charmap.h"
8
+
9
+ // rb_sId MUST be a string
10
+ bool is_id_valid(VALUE rb_sId)
11
+ {
12
+ VALUE id = rb_sId;
13
+
14
+ if (RSTRING_LEN(id) == SALESFORCE_ID_SENSITIVE_LENGTH) return true;
15
+ if (RSTRING_LEN(id) == SALESFORCE_ID_INSENSITIVE_LENGTH) return true;
16
+
17
+ return false;
18
+ }
@@ -0,0 +1,11 @@
1
+ #ifndef VALIDATE_SALESFORCE_ID_H
2
+ #define VALIDATE_SALESFORCE_ID_H 1
3
+
4
+ #include "ruby.h"
5
+ #include <stdbool.h>
6
+
7
+ bool is_id_valid(VALUE rb_sId);
8
+
9
+ #endif /* VALIDATE_SALESFORCE_ID_H */
10
+
11
+
@@ -0,0 +1,3 @@
1
+ module SalesforceId
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,6 @@
1
+ require 'salesforce_id/version'
2
+ require 'salesforce_id/salesforce_id'
3
+
4
+ module SalesforceId
5
+ extend self
6
+ end
@@ -0,0 +1,37 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'salesforce_id/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "salesforce_id"
8
+ spec.version = SalesforceId::VERSION
9
+ spec.authors = ["Fire-Dragon-DoL"]
10
+ spec.email = ["francesco.belladonna@gmail.com"]
11
+
12
+ spec.summary = %q{Gem to handle 15 characters and 18 characters salesforce IDs}
13
+ spec.description = %q{Gem to properly convert from and to 15 characters case sensitive format and 18 characters case insensitive format for salesforce record ID}
14
+ spec.homepage = "https://github.com/Fire-Dragon-DoL/salesforce_id"
15
+
16
+ # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
17
+ # delete this section to allow pushing this gem to any host.
18
+ if spec.respond_to?(:metadata)
19
+ spec.metadata['allowed_push_host'] = "https://rubygems.org"
20
+ else
21
+ raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
22
+ end
23
+
24
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
25
+ spec.bindir = "exe"
26
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
+ spec.require_paths = ["lib"]
28
+ spec.extensions = ["ext/salesforce_id/extconf.rb"]
29
+
30
+ spec.add_development_dependency "bundler", "~> 1.10"
31
+ spec.add_development_dependency "rake", "~> 10.0"
32
+ spec.add_development_dependency "rake-compiler"
33
+ spec.add_development_dependency "rspec"
34
+ spec.add_development_dependency "fuubar"
35
+ spec.add_development_dependency "pry"
36
+ spec.add_development_dependency "pry-byebug"
37
+ end
metadata ADDED
@@ -0,0 +1,179 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: salesforce_id
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Fire-Dragon-DoL
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-10-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake-compiler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: fuubar
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: pry-byebug
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: Gem to properly convert from and to 15 characters case sensitive format
112
+ and 18 characters case insensitive format for salesforce record ID
113
+ email:
114
+ - francesco.belladonna@gmail.com
115
+ executables: []
116
+ extensions:
117
+ - ext/salesforce_id/extconf.rb
118
+ extra_rdoc_files: []
119
+ files:
120
+ - ".gitignore"
121
+ - ".rspec"
122
+ - ".travis.yml"
123
+ - Gemfile
124
+ - LICENSE
125
+ - README.md
126
+ - Rakefile
127
+ - bin/bundler
128
+ - bin/byebug
129
+ - bin/cc-tddium-post-worker
130
+ - bin/coderay
131
+ - bin/console
132
+ - bin/htmldiff
133
+ - bin/ldiff
134
+ - bin/pry
135
+ - bin/rake
136
+ - bin/rake-compiler
137
+ - bin/rspec
138
+ - bin/setup
139
+ - ext/salesforce_id/charmap.c
140
+ - ext/salesforce_id/charmap.h
141
+ - ext/salesforce_id/extconf.rb
142
+ - ext/salesforce_id/insensitive_to_sensitive.c
143
+ - ext/salesforce_id/insensitive_to_sensitive.h
144
+ - ext/salesforce_id/repair_casing.c
145
+ - ext/salesforce_id/repair_casing.h
146
+ - ext/salesforce_id/salesforce_id_ext.c
147
+ - ext/salesforce_id/salesforce_id_ext.h
148
+ - ext/salesforce_id/sensitive_to_insensitive.c
149
+ - ext/salesforce_id/sensitive_to_insensitive.h
150
+ - ext/salesforce_id/validate_id.c
151
+ - ext/salesforce_id/validate_id.h
152
+ - lib/salesforce_id.rb
153
+ - lib/salesforce_id/version.rb
154
+ - salesforce_id.gemspec
155
+ homepage: https://github.com/Fire-Dragon-DoL/salesforce_id
156
+ licenses: []
157
+ metadata:
158
+ allowed_push_host: https://rubygems.org
159
+ post_install_message:
160
+ rdoc_options: []
161
+ require_paths:
162
+ - lib
163
+ required_ruby_version: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - ">="
166
+ - !ruby/object:Gem::Version
167
+ version: '0'
168
+ required_rubygems_version: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - ">="
171
+ - !ruby/object:Gem::Version
172
+ version: '0'
173
+ requirements: []
174
+ rubyforge_project:
175
+ rubygems_version: 2.4.6
176
+ signing_key:
177
+ specification_version: 4
178
+ summary: Gem to handle 15 characters and 18 characters salesforce IDs
179
+ test_files: []